Continuous Serial Communication - Polling Devices

Hi all,

I’m afraid I have no code snippets to share because I am simply unsure of the concept, not how to program once I do know the concept. I am building a Xojo app that in part communicates with multiple Arduino boards doing some sensing for me, through an RS485 multidrop. These arduinos should not speak until spoken to in order to avoid line crossing, but I also want the arduinos to send information, if they have it, as soon as possible.

Therefore I’d like to continually poll each Arduino as to whether they have information to give me, and if they do, they will send their info back before I continue this polling process. I am not sure how to continually execute an action with Xojo, as it seems an action only occurs upon an event. Is there a way to continuously perform an action, in my case poll multiple arduinos via serial, in a nonstop loop, like a C++ program would do?

I am very new to Xojo/OOP in general, so I apologize for seeming like I’m simply asking for an answer without trying anything.

Call the Serial.Poll method, in a loop or otherwise, to poll the device. The DataAvailable event will be raised if anything was received.

Do arduino1.Poll() Loop

I do this very thing with android. I use a timer. Once this timer fires, I send call the appropriate subroutine that sends the packet to the unit, I then set another timer called timeout, and wait for the response. if it fails, I move on and report the error. if it doesnt fail, I parse the response, do my thing, and increment the “address”, reset and enable the timer, and return.

Timer fires again with the new address, and I repeat again.

So is this now working for you?

I would use a timer to poll, instead of a loop, to avoid freezing the UI.

No need to poll. You dont’t want line crossing?

Then have the xojo master app send a packet to the arduino’s and have the arduino’s respond if they have data, otherwise send a confirmation or nothing from the arduino.

Interesting. I think polling the right way would avoid line crossing.

My current software only reads serial data from an Arduino. There is no “sending” of data, but if I did want that, I would do it sequentially.

With my program I don’t use the DataAvailable event as I found it unreliable. Instead, I use in a Timer “ReadAll” - when “I” want it.

Although Xojo may seem “event driven” it still has to “go though the run” - in a sequential manner. The DataAvalaible event is much like an Interrupt Request in the old QB language. Still sequential - through the run.

With multiple serial devices, reading and writing to and from, I would use “Select Case True” then evaluate that from “Top down” ie. the more/most important “truths” are weighted and acted upon accordingly.

I do some similar things also. I have a timer that fires fairly quickly and in the received event of the socket I set a boolean that says if I got my response or not. If I haven’t gotten a response when the timer fires for the next device then thats an error and I have to stop the polling and do some cleanup to see if I can reconnect to the device.

If the arduinos in question don’t reply if they don’t have any data then you don’t even need to do that. Just make sure your timer doesn’t fire so quickly that you don’t have time to receive all the data they might send before you send more.

The real solution though is to make the code in the arduino smarter :slight_smile: Have it watch the incoming rs485 data and not send anything while there is data on the line and for some small random amount of time afterwards to avoid collisions. You might still have a situation where 2 ran over each other but it would be very rare and you could probably trap that too or perhaps just have the host echo the data back for verification or retry if it wasn’t what they thought they sent. That can be a lot of work though, you’re probably fine with just polling in a timer event and making sure there is time for reception before the next timer event.

You’ll have to store your index into the array of boards in a property of the polling timer so it can increment that and not just as a local variable in the timers action code. Or… does Xojo even do persistent method variables? Can you believe I don’t know that? I’ve been using it for almost 20 years :wink:

Yep, Absolutely James - you simply MUST program the Arduino accordingly. It’s difficult because not only do you have to program the UI in Xojo, you must also know how to program the Ardy, which also uses “The Loop” ie. Sequential.

ie Arduino basic setup:

void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }

yup, it’s a challenge :slight_smile: and such wildly differing programming philosophies and you’ll end up typing “;” at the end of xojo code lines as you switch back and forth driving you crazy :wink:

and you’re wondering why the end of the method doesnt fill when you press “tab”…

Yep, as posted above:

Arduino :

void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }

Around in a loop much like Xojo - and ANY programming language for that matter.

[quote=339611:@Steve Kelepouris]Interesting. I think polling the right way would avoid line crossing.

My current software only reads serial data from an Arduino. There is no “sending” of data, but if I did want that, I would do it sequentially.

With my program I don’t use the DataAvailable event as I found it unreliable. Instead, I use in a Timer “ReadAll” - when “I” want it.

Although Xojo may seem “event driven” it still has to “go though the run” - in a sequential manner. The DataAvalaible event is much like an Interrupt Request in the old QB language. Still sequential - through the run.

With multiple serial devices, reading and writing to and from, I would use “Select Case True” then evaluate that from “Top down” ie. the more/most important “truths” are weighted and acted upon accordingly.[/quote]

Howso is DataAvailable not reliable? I’m never ever had such problems on xojo serial even tcp. If you have packets of fixed length, just search from it using lookahead and then access it using Read or ReadAll. DataAvailableis fired whenever the system or arduino sends. Not when a packet is supposed to be completed.

I’ve used Mac, Linux and Windows for any such communication without issues.

In ConsoleApplications call App.DoEvents( SleepMilliseconds = 10 ) in a loop. And all will be done for you.

Make sure you set encoding id required and have the Right settings in the serial class. Those are the most important parts.

Have to say that that’s one of the best things I like about Xojo.

[quote=339618:@Derk Jochems]Howso is DataAvailable not reliable? I’m never ever had such problems on xojo serial even tcp. If you have packets of fixed length, just search from it using lookahead and then access it using Read or ReadAll. DataAvailableis fired whenever the system or arduino sends. Not when a packet is supposed to be completed.

I’ve used Mac, Linux and Windows for any such communication without issues.

In ConsoleApplications call App.DoEvents( SleepMilliseconds = 10 ) in a loop. And all will be done for you.

Make sure you set encoding id required and have the Right settings in the serial class. Those are the most important parts.[/quote]

Derk, I don’t really know why. I did follow an example using “lookahead”. I had issues reading data coming in from the Arduino. I was reading the data at 100Hz (samples per second) and found that there were occasional glitches. The data was simple decimal readings but there was an occasional glitch. ie.

50 60 70 80 90 100 105 10 6 107 108 10 9

In the above sequence it should have read106, 109, but end of line was misinterpreted.

In any case I found it more reliable to just read the string then split it later:

In a Timer event (500 milliseconds):

[code]//Read ALL available data from the serial port buffer
tempBuffer = Serial1.ReadAll(encodings.ASCII)

//Add the data to incomingData
incomingData = incomingData + tempBuffer
[/code]

That’s strange. Did you strip the endofline yourself?

As this looks much like a coding error instead of serial fault.

It’s been about 18months since I worked on that part of my program.

From memory I think the “lookahead” was to look ahead for the EOL. Like I said, there were a few glitches. The ReadAll code as posted above works perfect and I’ve never looked back. Fair enough, I may have done something wrong with the DataAvailable method, but I don’t think so.

btw. The “glitches” I’m talking about were maybe 3 or 4 over a period of a minute. Still not good enough though. And NO, not a Serial fault but reading from the Serial Port as proven by my alternate method.

It’s no problem if the existing code works. Still it sounds like you missed a “CR” or “LF” as sometimes

for arduino Serial.println()

Maybe you where missing one of eighter. I always create it in full control using Serial.Write() if ever using arduino.

That may be correct Derk. I honestly can’t remember exactly what I did. I do however remember taking a lot of time to ensure that the Arduino was sending the correct lf/cr data. I would have to have a look to confirm.

Nevertheless, I’ve found that using the above code is perfect. I also like that fact that (although through the timer event) “I” decide when to READ the data, and not be dictated to by the DataAvailable event - too much anarchy for my liking :slight_smile:

[quote=339629:@Steve Kelepouris]That may be correct Derk. I honestly can’t remember exactly what I did. I do however remember taking a lot of time to ensure that the Arduino was sending the correct lf/cr data. I would have to have a look to confirm.

Nevertheless, I’ve found that using the above code is perfect. I also like that fact that (although through the timer event) “I” decide when to READ the data, and not be dictated to by the DataAvailable event - too much anarchy for my liking :)[/quote]

For my use that’s no way to go. Speed is everything, and therefor i’d never use a timer for it.
Functionality is always #1 so if it works, don’t change it unless you have found something better.

@Alex Fields
What communication settings are you using?
Baud, Pairity, Bits, StopBits ?