multiple interrupt calls when sending with LoRa



  • Hi! I'm creating a tipping bucket rain gauge that should save every tip to the local flash memory and in the end send it as a payload through LoRaWAN. So far (without LoRa), everything worked fine. I'm using software debouncing and have no duplicates over long periods (hours) with 20 s tipping interval on our test device.

    However, now I added the LoRa code and on average get about 6 duplicates per 15 minutes. Each with approx. 3 s delay whatever time I use for debouncing - the sensor calls for 460 ms, so I tested a couple of different setups. Can anybody tell me where this might be coming from?

    main:

    # OTAA authentication parameters
    app_eui = ubinascii.unhexlify('app_eui')
    app_key = ubinascii.unhexlify('app_key')
    
    # join network using OTAA (Over the Air Activation)
    lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0)
    
    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    

    Side note on main: I save the lora state after the first succesfull join and reload it on deepsleep wakeup

    raingage:

    # init pins
    self.gage = Pin(pin_in, mode=Pin.IN, pull=Pin.PULL_DOWN)
    self.wifi_pressed = Pin(pin_wifi, mode=Pin.IN, pull=Pin.PULL_DOWN)
    
    # init wake up interrupt
    machine.pin_deepsleep_wakeup(pins=[self.gage, self.wifi_pressed], mode=machine.WAKEUP_ANY_HIGH, enable_pull=True)
    
    # init interrupt action for rain gage
    self.gage.callback(trigger=Pin.IRQ_RISING, handler=self.drip)
    
    # handler for drip interrupt
    def drip(self, arg):
    
    	# debouncing
            # drip interval for 300 year rainstorm
    	if utime.ticks_diff(self.debounce_timer, utime.ticks_ms()) > 2500: 
    		# get time of drip
    		drip_time = utime.time()
    		# init debounce_timer
    		self.debounce_timer = utime.ticks_ms()
    		# raise drip count
    		self.count += 1
    		# get byte value for variables (1 short 2 integers = 8 bytes)
    		byte_data = ustruct.pack('<HIH', self.event_count, drip_time, self.count)
    		# write byte value to file
    		self.rainfile.write("%s,%s,%s\n" % (self.event_count, drip_time, self.count))
    		# send byte value to LoRaWAN gateway
    		if self.networking:
    			self.send_byte_data(byte_data)
    
    		print('Johnny counted', self.count, 'tipped bucket(s) during event', self.event_count, 'after', drip_time, 's since the beginning of this epoch') # testing
    		# reset sleeper's timer to indicate ongoing rain event
    		self.reset_alarm()
    		machine.idle()
    
    def send_byte_data(self, byte_data):
    	# I tried with and without blocking ... same result
    	self.lorasocket.setblocking(True)
    	self.lorasocket.send(byte_data)
    	self.lorasocket.setblocking(False)
    

    Side note on raingage: gauge wakes up after the first bucket tipped and stays awake for 15 minutes to wait for further buckets. After 15 minutes without buckets it goes back to deepsleep to save battery time.



  • Nevermind, I solved it.
    I'm new to real time programming and apparently had to find out the hard way not to put code that's too time consuming into an ISR. I changed it so that the ISR just changes a flag and that the actual work is being done in the main loop.



Pycom on Twitter