0

i have this strange problem with interrupts. I use GPIO switches to change a variable that defines what my code is doing. As soon as one of those interrupts worked once, none of them workes anymore.

My overall script is controlling a pi to read a flow meter and save the data to CSV files.

Here is my code:

#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:
#
# Author:      LaborK06
#
# Created:     15.03.2018
# Copyright:   (c) LaborK06 2018
# Licence:     <your licence>
#-------------------------------------------------------------------------------
import os
import timeks
import subprocess
import RPi.GPIO as IO
import lcddriver
from threading import Thread
import threading
import csv
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
import datetime
import struct

IO.setwarnings(False)
IO.setmode(IO.BCM)
x = 0

def main():
    global x
        if x == 0:
           lcd = lcddriver.lcd()
           lcd.lcd_display_string("     Hauptmenu",1)
           lcd.lcd_display_string("   bitte waehlen:",2)
           lcd.lcd_display_string("Messung  |   auf USB",3)
           lcd.lcd_display_string("lesen    | schreiben",4)
       while True:
                pass

        elif x == 1:
            lcd = lcddriver.lcd()
            lcd.lcd_display_string("  Lese Messdaten... ",1)
            lcd.lcd_display_string("Messung  |          ",3)
            lcd.lcd_display_string("beenden  |          ",4)

            client = ModbusClient(method='rtu', port='/dev/ttyS0', timeout=1, baudrate=19200)
            client.connect()
            rr = client.read_holding_registers(0, 31, unit=UNIT)
            today = datetime.date.today()
            now = datetime.datetime.now()
            try:
                raw_flow = struct.pack('>HH', rr.getRegister(8), rr.getRegister(9))
                value_flow = struct.unpack('>f', raw_flow)[0]
                raw_power = struct.pack('>HH', rr.getRegister(10), rr.getRegister(11))
                value_power = struct.unpack('>f', raw_power)[0]
                raw_energy = struct.pack('>HH', rr.getRegister(12), rr.getRegister(13))
                value_energy = struct.unpack('>f', raw_energy)[0]
                raw_hot = struct.pack('>HH', rr.getRegister(14), rr.getRegister(15))
                value_hot = struct.unpack('>f', raw_hot)[0]
                raw_cold = struct.pack('>HH', rr.getRegister(16), rr.getRegister(17))
                value_cold = struct.unpack('>f', raw_cold)[0]
                raw_total = struct.pack('>HH', rr.getRegister(20), rr.getRegister(21))
                value_total = struct.unpack('>f', raw_total)[0]
                with open('CSV_Dateien/%s.csv' % today, 'a') as csvfile:
                        a = csv.writer(csvfile, delimiter=',')
                        data=[now, value_flow, value_power, value_energy, value_hot, value_cold, value_total]
                        a.writerow(data)
                lcd.lcd_display_string("     " +  str(value_flow)[:5] + " m3/h     ",2)
            except AttributeError:
                    main()
        main()
#            time.sleep(0.5)

        elif x == 2:
        lcd = lcddriver.lcd()
            lcd.lcd_display_string("                    ",1)
            lcd.lcd_display_string("     Speichern.     ",2)
            lcd.lcd_display_string("    Bitte warten.   ",3)
            lcd.lcd_display_string("                    ",4)

            os.system("sudo mount /dev/sda1 /mnt")
            os.system("sudo cp -r /home/pi/Lukas/CSV_Dateien /mnt")
            os.system("sudo umount /mnt")

            lcd.lcd_display_string(" Daten uebertragen.",1)
            lcd.lcd_display_string("Pi-Speicher leeren?",2)
            lcd.lcd_display_string("         |         ",3)
            lcd.lcd_display_string("Ja       |     Nein",4)

            while True:
                pass

        elif x == 3:
            subprocess.call("sudo rm /home/pi/Lukas/CSV_Dateien/20*", shell=True)
        lcd.lcd_display_string("                    ",1)
        lcd.lcd_display_string("  Zwischenspeicher  ",2)
        lcd.lcd_display_string("   wurde geleert.   ",3)
        lcd.lcd_display_string("                    ",4)
            x = 0
            time.sleep(1)

        elif x == 4:
            lcd.lcd_display_string("                    ",1)
        lcd.lcd_display_string("  Es wurden keine   ",2)
        lcd.lcd_display_string("  Daten geloescht.  ",3)
        lcd.lcd_display_string("                    ",4)
        x = 0
        time.sleep(1)


def lesen(channel):
    print('S1')
    global x
    if x == 0:
        x = 1
        main()
    elif x == 1:
        x = 0
        main()
    elif x == 2:
        x = 3
        main()


def speichern(channel):
    print('S2')
    global x
    if x == 0:
        x = 2
        main()
    elif x == 2:
        x = 4
        main()

#Taster
Taster1 = 6
IO.setup(Taster1, IO.IN)
Taster2 = 13
IO.setup(Taster2, IO.IN)

#Variablen Messgeraet
UNIT = 0x001

IO.add_event_detect(Taster1, IO.RISING, callback=lesen, bouncetime=20)
IO.add_event_detect(Taster2, IO.RISING, callback=speichern, bouncetime=20)

if __name__ == '__main__':
     main()

What did i do that was wrong in here?

  • can you fix the indenting on the while True loop in the first if statement, pretty sure it is not right. You also have created a very recursive piece of code as main gets called from many places including inside main. Not sure if that was your intention, but it makes trouble shooting the code very difficult, and I don't think its needed – Chad G Mar 15 '18 at 17:32
  • There should be no reason to call main() from inside the interupt handlers, You are setting a global variable that can then be read inside main(). – Chad G Mar 15 '18 at 17:34
  • You have a couple of while True: pass constructs. That will freeze execution at that point. The structure of the script is very odd even without the recursion. – joan Mar 15 '18 at 17:55
1

The main issue is that your calling main() from within the interupt handlers, this means they never fully finish. And usually global interupts are disabled while an interupt is being handled. Since it never finishes, interupts are never re-enabled. You only need to set the global variable x and get out of the handler. Then be looking for that change in main() I do not have your setup, so I cannot test this, and make sure I have the indentions right (what should change for each value of x) but this is closer to what you want

import os
import timeks
import subprocess
import RPi.GPIO as IO
import lcddriver
from threading import Thread
import threading
import csv
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
import datetime
import struct

IO.setwarnings(False)
IO.setmode(IO.BCM)
x = 0

def main():
    global x

  while True:
    oldX=x

    while oldX==X:
        time.sleep(.5)
        #wait for change
    #if we left the while loop, now check what the change is

    if x == 0:
       lcd = lcddriver.lcd()
       lcd.lcd_display_string("     Hauptmenu",1)
       lcd.lcd_display_string("   bitte waehlen:",2)
       lcd.lcd_display_string("Messung  |   auf USB",3)
       lcd.lcd_display_string("lesen    | schreiben",4)

    elif x == 1:
        lcd = lcddriver.lcd()
        lcd.lcd_display_string("  Lese Messdaten... ",1)
        lcd.lcd_display_string("Messung  |          ",3)
        lcd.lcd_display_string("beenden  |          ",4)


        client = ModbusClient(method='rtu', port='/dev/ttyS0', timeout=1, baudrate=19200)
        client.connect()
        rr = client.read_holding_registers(0, 31, unit=UNIT)
        today = datetime.date.today()
        now = datetime.datetime.now()
        try:
            raw_flow = struct.pack('>HH', rr.getRegister(8), rr.getRegister(9))
            value_flow = struct.unpack('>f', raw_flow)[0]
            raw_power = struct.pack('>HH', rr.getRegister(10), rr.getRegister(11))
             value_power = struct.unpack('>f', raw_power)[0]
             raw_energy = struct.pack('>HH', rr.getRegister(12), rr.getRegister(13))
             value_energy = struct.unpack('>f', raw_energy)[0]
             raw_hot = struct.pack('>HH', rr.getRegister(14), rr.getRegister(15))
             value_hot = struct.unpack('>f', raw_hot)[0]
             raw_cold = struct.pack('>HH', rr.getRegister(16), rr.getRegister(17))
             value_cold = struct.unpack('>f', raw_cold)[0]
             raw_total = struct.pack('>HH', rr.getRegister(20), rr.getRegister(21))
             value_total = struct.unpack('>f', raw_total)[0]
             with open('CSV_Dateien/%s.csv' % today, 'a') as csvfile:
                  a = csv.writer(csvfile, delimiter=',')
                  data=[now, value_flow, value_power, value_energy, value_hot, value_cold, value_total]
                  a.writerow(data)
            lcd.lcd_display_string("     " +  str(value_flow)[:5] + " m3/h     ",2)
            except AttributeError:
                    #main()
                    #maybe print the error?
                    pass

    elif x == 2:
        lcd = lcddriver.lcd()
        lcd.lcd_display_string("                    ",1)
        lcd.lcd_display_string("     Speichern.     ",2)
        lcd.lcd_display_string("    Bitte warten.   ",3)
        lcd.lcd_display_string("                    ",4)

        os.system("sudo mount /dev/sda1 /mnt")
        os.system("sudo cp -r /home/pi/Lukas/CSV_Dateien /mnt")
        os.system("sudo umount /mnt")

        lcd.lcd_display_string(" Daten uebertragen.",1)
        lcd.lcd_display_string("Pi-Speicher leeren?",2)
        lcd.lcd_display_string("         |         ",3)
        lcd.lcd_display_string("Ja       |     Nein",4)

    elif x == 3:
        subprocess.call("sudo rm /home/pi/Lukas/CSV_Dateien/20*", shell=True)
        lcd.lcd_display_string("                    ",1)
        lcd.lcd_display_string("  Zwischenspeicher  ",2)
        lcd.lcd_display_string("   wurde geleert.   ",3)
        lcd.lcd_display_string("                    ",4)
            x = 0
            time.sleep(1)

    elif x == 4:
        lcd.lcd_display_string("                    ",1)
        lcd.lcd_display_string("  Es wurden keine   ",2)
        lcd.lcd_display_string("  Daten geloescht.  ",3)
        lcd.lcd_display_string("                    ",4)
        x = 0
        time.sleep(1)
    #once we get here, we have processed the change, 
    #and will go back to the top of the main while True loop
    #oldX will get set to x and we will wait for another change
def lesen(channel):
    print('S1')
    global x
    if x == 0:
        x = 1

    elif x == 1:
        x = 0

    elif x == 2:
        x = 3



def speichern(channel):
    print('S2')
    global x
    if x == 0:
        x = 2
    elif x == 2:
        x = 4

#Taster
Taster1 = 6
IO.setup(Taster1, IO.IN)
Taster2 = 13
IO.setup(Taster2, IO.IN)

#Variablen Messgeraet
UNIT = 0x001

IO.add_event_detect(Taster1, IO.RISING, callback=lesen, bouncetime=20)
IO.add_event_detect(Taster2, IO.RISING, callback=speichern, bouncetime=20)

if __name__ == '__main__':
     main()
  • okay, the main()s everywhere might be a bit weird, i just wanted it to run forever. the way you did it it just changes the x but doesnt start main() anymore, right? sorry, but i'm a total greenhorn in programming – lux Mar 16 '18 at 10:33
  • It doesnt start it again, but you were starting it multiple times. This way it's only one that runs forever – Chad G Mar 16 '18 at 10:35
  • ah okay, i missed the while true loop in the beginning. now it is working perfectly. thank you so much! – lux Mar 16 '18 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.