Help with Faster Responses to Sensor Changes

We have a machine that is monitoring sensors and controlling motors using a desktop app that was developed with Xojo for PI. The desktop app has some buttons for testing motors and has visual indicators of the sensor states. When the app starts, a class with a timer starts with a 10ms interval. The class checks the sensors and raises an event if one of them changes.

The machine needs to respond quickly to a sensor change. Sometimes, while the machine is running, it seems to delay a little, maybe 100ms, when responding to a sensor change. I’m thinking of trying a tight loop, rather than a timer. Something like this:

While bProcessingOn
  'Check Sensor states and raise events
  CheckSensors
  App.DoEvents
Loop

Is there any problem with running DoEvents on a Desktop PI App within a tight loop like this? Any other issues with this approach? Maybe I should change the app to a console app?

Why not a thread or a Worker instead?

Please follow these two rules:

  1. Do not use DoEvents in a Desktop app.
  2. If you really need DoEvents in a Desktop app, see rule 1.

As @David_Cox suggested, Workers or Threads are better options. If you switch to a console app, you could set up one instance per sensor, if that makes sense, but you could emulate that through Worker too.

1 Like

Save yourself much agony and add a microcontroller that handles time-sensitive stuff and reports to the Pi.

6 Likes

Do not use DoEvents in a Desktop app

But I saw @Geoff_Perlman do it one time in a demo. :wink:

And @Eugene_Dakin uses DoEvents in an example on his blog.

Eugene’s example is what made me think of removing the timer and going with a loop. So, in a tight loop in a Desktop app, is DoEvents going to cause a problem?

@Julia_Truchsess If the PI app is waiting for a sensor to change state, and monitoring the sensor using a timer is not sufficient, how will a separate microcontroller help? At this point, the PI app will then wait for the microcontroller to report the sensor state, which does not sound faster. Maybe you are saying that I should move the logic to the microcontroller? But if so, then there really won’t be much left for the PI to do. So I might as well create the machine controller on a microcontroller, which is an option I’m trying to avoid. I am trying to stick with Xojo only, if possible.

So, let me ask a different way: What is the most responsive way for a Xojo PI app to monitor sensors and act upon state changes?

Yeah, I don’t know the details of your application, but was thinking that the Pi would handle UI, internet, and similar complex tasks while the micro would deal with all low-level timing measurement and control, relaying info back to the Pi at intervals that the Pi could handle without interfering with critical timing. Don’t know if that would make sense in your application or not.

2 Likes

Sometimes things are done in demos for expediency that should not be emulated on production code.

DoEvents will create a second event loop within your app that can lead to all kinds of weird things and instability. It makes sense in a console app where you might want to create an event loop, but should not be used on any other type of project.

2 Likes

Maybe it was used to show some concept to a certain context, but in real life implementation it must be done properly. If Xojo Pi fully support worker apps, then that would be the best solution. Even if one of the workers have problem, the core GUI app still operates to the benefit of all.

It will fail to respond as fast as you need, it will cause stability problems for the app. it will waste cpu.

As fot the suggestions, Threads will have no difference and Dont use workers or helpers with thight loops, they will overheat the Pi. The short answer, Xojo cant do this properly. As a work around try the interruptions part in this tutorial:

But you should be using another tool for that. You can keep the GUI in xojo and the GPIO part on something else like python or java

Hi Brandon,

Yep, I did create that example. There are some workarounds that are needed to read data and update the graphics. Polling with a For-Loop unfortunately causes errors with Xojo, so I used a Timer and/or a DoEvents command.

I haven’t tried it, and a console app (it has no GUI) should/might work with a tight loop.

A tight-loop can often prevent communication with the Xojo Application. Something that might also work is to have a tight-loop that also has a DoEvents to allow Xojo to run background stuff.

A possible example (in pseudocode) might look like this:

This allows rapid polling of data, while also allowing Xojo to occasionally update its internal processes.

This is a good suggestion Ivan. Unfortunately, Xojo does not support interrupts.

Amen to that. Or program the pi in some lower level c-like language that allows interrupts and such.

I just read this blog about how some people see Xojo as THE hammer. And then I read this post and Julia’s reply brought a tear to my eye.

1 Like

+1

interrupts can be used indirectly with the workaround in that post.

:rofl: What blog?

my last idea was using a Python script started from Xojo Shell and read the standard output from print.
in Python you can register signal level changes and then a method is called.
(because using loops for reading signal levels in xojo waste cpu usage and can be still inaccurate.)

2018

#!/usr/bin/python

import RPi.GPIO as GPIO
import subprocess
import time

# Function
def capture(channel):
	print("capture")
	return;

PIR=4
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR,GPIO.IN)

GPIO.add_event_detect(PIR,GPIO.RISING, callback=capture)

print("await pir ...")
try:
        while True:
                time.sleep(1)

except KeyboardInterrupt:
	print("interrupted/end")
	GPIO.cleanup()

This is a nice idea. A Shell subclass running in Interactive mode could read the output of the script and raise an event whenever status changes.

shell class have the event .DataAvailable , it should work somehow.

Right. I’m suggesting a subclass that implements DataAvailable, then raises custom events depending on the output from the script.

1 Like

We use libgpiod (native linux, pi gpio) in a subclassed Shell class

use gpiomon for this purpose and you get plenty fast results including a timestamp so you can even read frequencies.
Manage GPIO lines with gpiod (i have no affiliation with this website) it’s just showing basic usage

Example, the 2nd line is a result line, can be manu or a single depending on your setup.
gpiomon will output a line when there was a “falling edge” change in this case on GPIO 24.

gpiomon --format="%e %o %s %n" --falling-edge gpiochip0 24
0 25 1156 615459801
3 Likes