-2

I have a Raspberry pi and using Python I've wrote a GUI to control a fan using PWM and to work out the RPM from the fans pulsed output. The GUI has a label at the top, buttons to select different duty cycles, an LED logo indicator to display which button is selected, buttons to 'STOP FAN', 'Exit', 'Display RPM'.

I start the fan using the 'Start Fan' button. I can then select different duty cycles. When I click the 'Display RPM' button the label at the top of the GUI displays the RPM(with a lot of numbers after the decimal place), it is just a quick snapshot of the RPM. My code runs ok.

My question is this. How do I get the label to constantly display the changing RPM? I would like to remove the 'Display RPM' button and just have the label display the live changing RPM all the time. I have googled for help for several hours and have tried 'after', 'function calls', etc. But i can't seem to grasp what I need to do or where in the code it should go.

Many thanks in advance for your time and help. The code might not be the best I know but I'm learning. I'll happily accept any suggestions on how to improve it.

# Fan PWM Control
import time
from time import sleep
import piface.pfio as pfio
pfio.init()

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7,GPIO.OUT)
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
my_pwm = GPIO.PWM(7,1000)
last_time = time.time()
this_time = time.time()
RPM = 0


from Tkinter import *

import Tkinter as tk

a=0

class App:

    def __init__(self, master):
            self.master=master
            frame = Frame(master)
            frame.pack()

            self.TACHO = Label(frame, text=RPM)
            self.TACHO.grid(row=0, column=0)

            self.button0 = Button(frame, text='Start Fan', command=self.convert0)
            self.button0.grid(row=2, column=0)
            self.LED0 = Label(frame, image=logo2)
            self.LED0.grid(row=2, column=1)

            self.button1 = Button(frame, text='Fan 30% Duty Cycle', command=self.convert1)
            self.button1.grid(row=3, column=0)
            self.LED1 = Label(frame, image=logo2)
            self.LED1.grid(row=3, column=1)

            self.button2 = Button(frame, text='Fan 45% Duty Cycle', command=self.convert2)
            self.button2.grid(row=4, column=0)
            self.LED2 = Label(frame, image=logo2)
            self.LED2.grid(row=4, column=1)

            self.button3 = Button(frame, text='Fan 60% Duty Cycle', command=self.convert3)
            self.button3.grid(row=5, column=0)
            self.LED3 = Label(frame, image=logo2)
            self.LED3.grid(row=5, column=1)

            self.button4 = Button(frame, text='Fan 75% Duty Cycle', command=self.convert4)
            self.button4.grid(row=6, column=0)
            self.LED4 = Label(frame, image=logo2)
            self.LED4.grid(row=6, column=1)

            self.button5 = Button(frame, text='Fan 90% Duty Cycle', command=self.convert5)
            self.button5.grid(row=7, column=0)
            self.LED5 = Label(frame, image=logo2)
            self.LED5.grid(row=7, column=1)

            self.button6 = Button(frame, text='Fan 100% Duty Cycle', command=self.convert6)
            self.button6.grid(row=8, column=0)
            self.LED6 = Label(frame, image=logo2)
            self.LED6.grid(row=8, column=1)

            self.button7 = Button(frame, text='STOP FAN', command=self.convert7)
            self.button7.grid(row=9, column=0)

            self.button8 = Button(frame, text='Exit', command=self.convert8)
            self.button8.grid(row=10, column=0)


            self.button9 = Button(frame, text='Display RPM', command=self.Tach)
            self.button9.grid(row=11, column=0)


    def convert0(self):

            print('Fan 15% Duty Cycle')
            global a
            a = 1
            self.button0.config(text='Fan 15% Duty Cycle')
            self.LED0.config(image = logo)
            my_pwm.start(15)
            pfio.digital_write(0,1) #turn on
            self.LED1.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED5.config(image = logo2)
            self.LED6.config(image = logo2)
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(6,0) #turn off
            pfio.digital_write(7,0) #turn off


    def convert1(self):

        if a==0:

            print('Please Start the Fan')

        else:

            print('Fan 30% Duty Cycle')
            self.button1.config(text='Fan 30% Duty Cycle')
            self.LED1.config(image = logo)
            my_pwm.ChangeDutyCycle(30)
            pfio.digital_write(1,1) #turn on
            self.LED0.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED5.config(image = logo2)
            self.LED6.config(image = logo2)
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(6,0) #turn off
            pfio.digital_write(7,0) #turn off

    def convert2(self):

        if a==0:

            print('Please Start the Fan')

        else:

            print('Fan 45% Duty Cycle')
            self.button2.config(text='Fan 45% Duty Cycle')
            self.LED2.config(image = logo)
            my_pwm.ChangeDutyCycle(45)
            pfio.digital_write(2,1) #turn on
            self.LED0.config(image = logo2)
            self.LED1.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED5.config(image = logo2)
            self.LED6.config(image = logo2)
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(6,0) #turn off
            pfio.digital_write(7,0) #turn off

    def convert3(self):

        if a==0:

            print('Please Start the Fan')

        else:

            print('Fan 60% Duty Cycle')
            self.button3.config(text='Fan 60% Duty Cycle')
            self.LED3.config(image = logo)
            my_pwm.ChangeDutyCycle(60)
            pfio.digital_write(3,1) #turn on
            self.LED0.config(image = logo2)
            self.LED1.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED5.config(image = logo2)
            self.LED6.config(image = logo2)
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(6,0) #turn off
            pfio.digital_write(7,0) #turn off

    def convert4(self):

        if a==0:

            print('Please Start the Fan')

        else:

            print('Fan 75% Duty Cycle')
            self.button4.config(text='Fan 75% Duty Cycle')
            self.LED4.config(image = logo)
            my_pwm.ChangeDutyCycle(75)
            pfio.digital_write(4,1) #turn on
            self.LED0.config(image = logo2)
            self.LED1.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED5.config(image = logo2)
            self.LED6.config(image = logo2)
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(6,0) #turn off
            pfio.digital_write(7,0) #turn off

    def convert5(self):

        if a==0:

            print('Please Start the Fan')

        else:

            print('Fan 90% Duty Cycle')
            self.button5.config(text='Fan 90% Duty Cycle')
            self.LED5.config(image = logo)
            my_pwm.ChangeDutyCycle(90)
            pfio.digital_write(5,1) #turn on
            self.LED0.config(image = logo2)
            self.LED1.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED6.config(image = logo2)
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(6,0) #turn off
            pfio.digital_write(7,0) #turn off

    def convert6(self):

        if a==0:

            print('Please Start the Fan')

        else:

            print('Fan 100% Duty Cycle')
            self.button6.config(text='Fan 100% Duty Cycle')
            self.LED6.config(image = logo)
            my_pwm.ChangeDutyCycle(100)
            pfio.digital_write(6,1) #turn on
            self.LED0.config(image = logo2)
            self.LED1.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED5.config(image = logo2)
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(7,0) #turn off

    def convert7(self):


            print('STOP FAN')
            global a
            a = 0
            self.button7.config(text='STOP FAN')
            my_pwm.stop()
            pfio.digital_write(7,1) #turn on
            self.LED0.config(image = logo2)
            self.LED1.config(image = logo2)
            self.LED2.config(image = logo2)
            self.LED3.config(image = logo2)
            self.LED4.config(image = logo2)
            self.LED5.config(image = logo2)
            self.LED6.config(image = logo2)
            self.button0.config(text='Start Fan')
            pfio.digital_write(0,0) #turn off
            pfio.digital_write(1,0) #turn off
            pfio.digital_write(2,0) #turn off
            pfio.digital_write(3,0) #turn off
            pfio.digital_write(4,0) #turn off
            pfio.digital_write(5,0) #turn off
            pfio.digital_write(6,0) #turn off


    def convert8(self):


            print('EXIT PROGRAM')
            my_pwm.stop()
            quit()

    def EventsPerTime(self):
        global RPM, this_time, last_time
        if GPIO.input(self) > 0.5:
            this_time = time.time()
            RPM = (1/(this_time - last_time))*30
            last_time = this_time
            #print 'RPM is %d' % RPM



    GPIO.add_event_detect(18, GPIO.RISING, callback=EventsPerTime, bouncetime=3)


    def Tach(self):
        global RPM
        if RPM > 1:
            print 'RPM is %d' % RPM
            self.TACHO.config(text=RPM)




root = Tk()
logo2 = PhotoImage(file="/home/pi/Off LED.gif")
logo = PhotoImage(file="/home/pi/Red LED.gif")


root.wm_title('FAN PWM Control program')
app = App(root)

root.mainloop()
blast_uk
  • 125
  • 1
  • 3
  • 12
  • If you're already getting the RPM on a regular schedule from `EventsPerTime`, what's stopping you from updating the label right there? – Bryan Oakley Jul 02 '17 at 19:55
  • I originally tried that using one of my google results. I thing it was self.Tach(). But I could not get it to work, if it was the right thing to put in. – blast_uk Jul 02 '17 at 19:59
  • 1
    Please make a [mcve]. If your problem is with displaying the RPM, you don't need all of the code unrelated to the RPM display. – Bryan Oakley Jul 02 '17 at 20:34

2 Answers2

1

You already have a function that gets the current RPM. The simplest thing is to update the label right there:

def EventsPerTime(self):
    global RPM, this_time, last_time
    if GPIO.input(self) > 0.5:
        ...
        RPM = (1/(this_time - last_time))*30
        ...

        self.TACHO.configure(text=RPM)

Another part of the problem is that you're incorrectly specifying your call back. You need to change this code:

GPIO.add_event_detect(..., callback=EventsPerTime, ...)

to this:

GPIO.add_event_detect(..., callback=self.EventsPerTime, ...)

You'll also have to redefine EventsPerTIme to accept an additional argument:

def EventsPerTime(self, channel):
   ...
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I tried it but I get an error - AttributeError: 'int' object has no attribute 'TACHO'. – blast_uk Jul 02 '17 at 20:11
  • @blast_uk: it is not possible for the code in your question to give that error. You must be redefining `self.TACHO` somewhere to be an integer. – Bryan Oakley Jul 02 '17 at 20:34
  • that is the error i get, but yes i agree with what you say, i just can't see it. I keep looking at the 'time', the RPM calculation, etc. – blast_uk Jul 02 '17 at 20:47
  • 1
    @blast_uk: I misspoke. The reason you're getting the "int" error is because you're incorrectly specifying the callback. Within the function `self` was receiving the channel provided by the GPIO module. I've updated my answer. – Bryan Oakley Jul 02 '17 at 21:06
  • I tried adding that in but I now get the error in the callback 'NameError: name 'self' is not defined. I'm thinking that is to do with its indentation and that it isn't part of a function? My little knowledge I'm afraid. – blast_uk Jul 03 '17 at 19:54
  • This is why we ask for a _minimal_ and _complete_ example. When you have indentation errors and too much code, it's very hard for us to give accurate answers. Yes, the problem is probably related to the indentation of your _actual_ code, but the indentation of the _posted_ code seems correct. – Bryan Oakley Jul 03 '17 at 20:10
  • Thanks, I'll remember that advice in the future. Looking at my posted code its indentation matches my actual code. Your comments have helped steer me in the right direction and when I work it out I'll post it. Thanks again for your help. – blast_uk Jul 03 '17 at 20:24
  • @blast_uk: I think the other problem is that you're not calling `GPIO.add_event_detect` from a method. That's probably the source of the error related to self. I had assumed that was a typo. – Bryan Oakley Jul 03 '17 at 20:28
0

Here are my code changes for the PWM GUI control with displayed RPM on my Raspberry Pi. I managed to get the program running and achieve what I aimed to do due to the good feedback and help through this post and website. The code is probably no where as good or efficient as it could be so please feel free to offer suggestions of improvements.

Thank you for your help and shared knowledge.

        #self.button9 = Button(frame, text='Display RPM', command=self.Tach)    Stopped using this button
        #self.button9.grid(row=11, column=0)    Stopped using this button

        self.TimerInterval = 500    #This sets the time interval between RPM readings
        self.Tach()         #This will start the 'Tach' method when the GUI starts

def convert0(self):

I also wrote a method for 'Tach' which used the 'after' function which will call a given function after a set interval. So I set it to call itself every 500mS.

def Tach(self):
    print 'RPM is %d' % RPM
    self.TACHO.config(text='RPM is %d' % RPM)
    self.master.after(self.TimerInterval,self.Tach) #Used 'after' to repeat this method at the time interval

I'm not sure how to stop a 'after' function yet but I'll get to that and learn along the way.

blast_uk
  • 125
  • 1
  • 3
  • 12