Looking for some help here with a project I have been working on (for a very long time!)
I need to send numerical values from a Mega to a nano- I am using I2C.
I currently am able to send 0-255 ( I have had troubles with the much more complicated methods used to send more than that so far)
I need to be able to send several values, to be used to update variables on the receiving nano. I need a way to identify which info being sent is for what, what would be a simple method of accomplishing this?
Do you want to send several values every time? If so, just send them as a series of bytes. Both programs will have to agree on the order (value1, value2, etc.) and how big each value is.
Most I2C devices expect a register number (byte) followed by a value. Associate your variables with such a register number or array index, then you can both receive or transmit related values.
You need to start by defining some protocol. Simply way is for the message to start with an Identifier that is followed by the arguments. Easiest is make the first byte the identifier and the second the number of bytes and the second last the checksum and the last a terminating identifier. You can accumulate the checksum as you receive each byte then test at the end. Time out if you do not get enough bytes. You can set the identifiers to anything you want. This should get you started.
You can use SerialTransfer.h to handle the communication for you. You can install it via the Arduino IDE's Library Manager and it comes with many examples.
I see it uses Structs, which I am unfamiliar with.
Structs are pretty simple, just a pre-defined collection of variables. See here
As for the examples, all you need to do is update the variables in the struct according to your project and you're good to go. All examples are commented but if you have any specific questions, I'd be happy to answer them.
The cool thing about the lib is that you don't need to "define your own protocol". As a newbie to programming, you should rely on a proven library instead (unless you want to define your own protocol).
No worries . Sometimes my comments are sparse, but I try to keep my source files (.cpp and .h) well commented plus use functions with intuitive names to reduce the need for example comments.
Something like this:
TX:
#include "I2CTransfer.h"
I2CTransfer myTransfer;
struct __attribute__((packed)) STRUCT {
uint16_t StepsFwd;
uint16_t StepsRev;
} testStruct;
void setup()
{
Serial.begin(115200);
Wire.begin();
myTransfer.begin(Wire);
}
void loop()
{
StepsFwd = INSERT YOUR NEW VALUE HERE;
StepsRev = INSERT YOUR NEW VALUE HERE;
myTransfer.sendDatum(testStruct);
delay(500);
}
RX:
#include "I2CTransfer.h"
I2CTransfer myTransfer;
struct __attribute__((packed)) STRUCT {
uint16_t StepsFwd;
uint16_t StepsRev;
} testStruct;
/////////////////////////////////////////////////////////////////// Callbacks
void hi()
{
myTransfer.rxObj(testStruct
// DO STUFF WITH NEW VALUES HERE
Serial.print(testStruct.StepsFwd);
Serial.println(testStruct.StepsRev);
}
// supplied as a reference - persistent allocation required
const functionPtr callbackArr[] = { hi };
///////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200);
Wire.begin(0);
///////////////////////////////////////////////////////////////// Config Parameters
configST myConfig;
myConfig.debug = true;
myConfig.callbacks = callbackArr;
myConfig.callbacksLen = sizeof(callbackArr) / sizeof(functionPtr);
/////////////////////////////////////////////////////////////////
myTransfer.begin(Wire, myConfig);
}
void loop()
{
// Do nothing
}
The myConfig part is a custom struct defined in the SerialTransfer library (see here) that is used to "setup" the library easily. It's optional for UART/SPI, but required for I2C for various reasons. The main reason is because the I2C receiver needs to receive data via a function callback. The config struct tells the lib what that callback function is (void hi() in the above case).
I'm working on getting the code functional, not quite there yet. I see "Wire.begin(0)" for the RX, but I dont see anything on the TX side that defines which address the data is sent to?
1. Check that MEGA and NANO are connected together using I2C Bus as per Fig-1.
Figure-1:
2. Let us try to send the following comma separated data items from MEGA to NANO: 1234, 78, 14.57. NANO will receive them as a message and then will isolate the tokens (the individual data items) and then will show them ON SM2.
3. Upload the following sketches on MEGA (I2C-Master) and NANO (I2C-Slave). Master Sketch:
you got the source code when you downloaded/installed the library. look in the .h file
the packed attribute of the structure tells the compiler to put all the variables in the structure together as close as possible. Without it, you could get different arrangements, depending on which Arduino platform you are using. An ESP32 is a 32 bit device so it could line up all the variables on 32 bit boundaries. ( StepsFwd byte 1, StepsFwd byte 2, blank, blank, StepsRev byte 1, StepsRev byte 2, blank, blank). An a Uno, which is 8 bit, they would naturally get packed but you could not send/receive between them.
Thank you- Your code works fine, I get the same results in the slave serial monitor.
The following sample code I'm trying to get to function that Power_Broker was kind enough to share- does work, but only sends zero values for the 2 variables. The only way I can get the variables values to change is if I set them inside the struct.
The following code gets me an 11 and a 0, which I want to be 100 and 200 as I've tried to define in the loop. If I do not define values in the struct, the slave gets 0's for both.