I'm working on a project where I have an amplifier located in the basement, which uses an Arduino NANO to control the band switch on the amplifier and send out the voltage, temperature, fan speed, etc. The NANO is communicating with an ESP32 which handles the display information up in the radio room. Comms is setup to send the data via a structure from the NANO to the ESP32 and back to the NANO. I have this working.
My question has to deal with how often the NANO sends a comms packet to the ESP32:
How often the NANO sends the data to the ESP32. (I'm hoping for about 100ms.)
How often the ESP32 receives the data. What if it can't keep up with the 100ms comms?
What happens if the ESP32 doesn't grab all the data from the NANO in the buffer. Can the ESP32 get behind in getting the data that the NANO has put into the comms buffer? Is there a way for the NANO to purge the buffer so that the latest data is on the top of the stack for the ESP32 (receiver)?
Is there a way for the slave (ESP32) to know how many message in the buffer?
Can the ESP32 clear out any out of date messages and grab only the newest if it's falling behind?
How do you synchronize the two devices that are sending the data?
My question has to deal with how often the NANO sends a comms packet to the ESP32:
How often the NANO sends the data to the ESP32. (I'm hoping for about 100ms.)
That's up to your Nano code...
How often the ESP32 receives the data. What if it can't keep up with the 100ms comms?
That's up to your ESP32 code...
What happens if the ESP32 doesn't grab all the data from the NANO in the buffer. Can the ESP32 get behind in getting the data that the NANO has put into the comms buffer?
Yes, but that's why you can query available bytes in the buffer... so you can do 'something' about it...
Is there a way for the NANO to purge the buffer so that the latest data is on the top of the stack for the ESP32 (receiver)?
Read out to the end of a message
Is there a way for the slave (ESP32) to know how many message in the buffer?
Query to see if what's left is longer than another message, read out again if so, ...but...
Can the ESP32 clear out any out of date messages and grab only the newest if it's falling behind?
Of course...
How do you synchronize the two devices that are sending the data?
The ESP32 can ask for a message when it's received one. Thus, there's never any pileup.
The Nano can provide Data only when asked, so there's never any unsolicited data.
Or, the Nano can just talk away, and the ESP can throw away data whenever it gets behind. It's really up to you.
What has the ESP32 got going on, that it can't handle a fistful of data 10x per second?
Reading Robin's updated Serial Input Basics topic might give you ideas. It only gives code for the receive side, you'll have to implement the matching sender side.
Example 3 gives you the basics of a synchronisation mechanism. If needed you can modify it and add a timeout mechanism and a simple checksum or (slightly more complicated, a CRC).
At 9600 baud, transmission of one byte takes roughly 1 ms. So it depends on how much data a "packet" contains if the 100 ms can be achieved. You can obviously increase the baud rate to e.g. 115200. Robin's examples are based on text; you can also send the binary values of your variables but that is a little more complicated.
If you're using SoftwareSerial, you can use 19200 and maybe 38400. You'll have to test what works reliably.
I'm not familiar with ESP32 devices so can't say what it can and can't do.
See (2).
Note:
I assume that you have taken care of the differences in signal levels. If not, the Tx output of a classic Nano is 5V which can damage the ESP32 which is a 3.3V device; a voltage divider is advisable between the Tx of the Nano and the used recerive pin of the ESP32.
**How do you synchronize the two devices that are sending the data?**
"Application design"... I'm afraid that doesn't help me. That's what I'm trying to figure out!
Delta_G "That is faster than you'd be able to see the number change on the screen."
I' think you may be right.
I also remember that in the code that I used previously (Arduino MEGA) the I2C Display routine took 200ms all by itself.
With the ESP32, I'm planning on starting with the same display, and eventually moving to a graphical display. I have the code started, but it may take me a while to complete.
I'm hoping to run the comms at 38400 baud (only about a 15' run) so the comms shouldn't take too long. If I run into problems, I can slow it down.
Maybe I'll shoot for a 200 to 300 ms loop and see how that works.
By the way, sterretje, I read the Serial Input Basics that you suggested, but for me, it didn't go far enough. There was a link that was out of date, but that was more of what I was looking for. Something on the design side as to how to work at keeping the comms syncronized.
And that's why I posted #3. Because those are kernel concepts for your application design. Start there. Figure it out with a dummy send-response series.
No one here's going to write it for you(not saying you're asking us to, either). It may exist, out there, in a tutorial. But you'll have to find it, unless someone knows of it and pipes up.
Industrial environment? Residential basement? At that rate, that distance, you need quiet, or you should look at RS485. That, however, will complicate things.
Really, 3840 bytes per second, 10 updates, means 384 characters possible per update. What's needed? Sounds like a lot.
I hope you're joking, but even if it did, if it wasn't doing anything else it's irrelevant. Besides, You're not going to cram much activity into a Nano, not enough I/O or memory. I use them extensively, but I know exactly where to economise.
You do that by sending an acknowledgment message back to the sender. The sender must wait for the acknowledgment message before continuing. The sender really should also wait only so long for the acknowledgment message and declare an error if the time expires.
camsysca, "I hope you're joking, but even if it did, if it wasn't doing anything else it's irrelevant."
No, I had timed the call to the display that I was using (an Adafruit 2 line display, I2C) and it took 200ms to update the display.
Here is the send side of the code. I'm not sure how many bytes it sends (I haven't checked it yet). The basic code was from a comment in a forum here by groundFungus. I played around with it and got it to work for my purposes.
const byte numBytes = 32; // tailor to your use
char receivedChars[numBytes]; // an array to store the received data
bool newData = false;
byte bytesReceived = 0;
//Use the same struct for comms both ways!
struct AmpStruct {
byte bMode;
int iBand;
double dVolts;
int iAmpTemp;
int iFanOutput;
int iFwdPower;
int iRefPower;
};
//Initialize the values to create the usable structure
AmpStruct AmpData = {0, 0, 0, 0, 0, 0, 0};
// Sent To ESP32
void SendStruct(byte Mode, int Band, double Volts, int AmpTemp, int FanOutput, int FwdPower, int RefPower) {
AmpData = {Mode, Band, Volts, AmpTemp, FanOutput, FwdPower, RefPower};
//Send the Data to the ESP32:
StructSerial.write((byte*)&AmpData, sizeof(AmpData));
StructSerial.write('\n');
}
As for the NANO, I'm not too concerned about it. I have most of the code written and it's pretty simple. Mostly checking values and sending the data to the ESP32.
I'm working on the ESP32 code & building the hardware up...
Right. So you're sending a struct filled with binary data, 19 bytes if my fingers didn't let me down. Terminating it with a CRLF. The ESP32 must take that in, including the CRLF. How does it know where begin/end is? It can't depend on the CRLF, because the other 19 bytes are binary, any of which could be CR, LF, or a combo.
2100 bits approx every second, with 9600 baud you'd still have headroom.
Work to be done, but if you're happy, I'm happy. Carry on.