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?
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.
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.
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.
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
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.
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()
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.