I don’t think there’s a single best method - you may need to consider the consequences of not receiving a value correctly, or it may not matter.
You’ll have to label the values somehow.
The usual way is to send a non-digit character first, to enable the two Arduino to synchronise. Then you can send the 4 numbers, perhaps with commas or spaces between them, then some final non-digit character to indicate the end of the message.
To avoid holdups, just use Serial.available() to check there is something to read before using Serial.read(). While waiting for the synchronisation character, just check Serial.available() > 0. If so, read a character. If it’s not the sync character, ignore it. If it is the sync character, you can go ahead and read the rest of the message.
Thanks guys, that makes sense... What though is the best way to determine the length of each integer... I guess it could change if the number goes from 2 to 100 or something like that...?
Thanks I have done something similar using commas, but I'm struggling to create the message on the write end... This is what I tried but it doesn't work...
what is the reason for the last write/what do you expect that this write should do?
what error message do you get, if any?
what do you see on your output connected to another Serial Monitor?
UKHeliBob:
Please post a complete program that transmits the data and a complete program that reads the data and explain what is wrong
Ok so my transmitter code is:
#include <AccelStepper.h>
// Define some steppers and the pins the will use
AccelStepper stepper1(AccelStepper::DRIVER, 5, 6); //Step, Direction
AccelStepper stepper2(AccelStepper::DRIVER, 7, 8); //Step, Direction
const int RESET = 18; // pin for RESET
int SPEED_Pin = 22;
int SPEED_Val=0;
int RPM_Pin = 20;
int RPM_Val;
int SPEED_STEPS;
int RPM_STEPS;
const int numReadings = 50;
int SPEED_readings[numReadings]; // the readings from the analog input
int SPEED_readIndex = 0; // the index of the current reading
int SPEED_total = 0; // the running total
int SPEED_average = 0; // the average
int SPEED_MPH = 0;
int RPM_readings[numReadings]; // the readings from the analog input
int RPM_readIndex = 0; // the index of the current reading
int RPM_total = 0; // the running total
int RPM_average = 0; // the average
int RPM = 0;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 100;
const byte delimiter=',';
void setup()
{
Serial.begin(9600);
Serial1.begin(250000);
pinMode(RESET, OUTPUT);
digitalWrite(RESET, LOW);
delay(1); // keep reset low min 1ms
digitalWrite(RESET, HIGH);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
SPEED_readings[thisReading] = 0;
RPM_readings[thisReading] = 0;
}
stepper1.setMaxSpeed(10000.0);
stepper1.setAcceleration(250000.0);
stepper2.setMaxSpeed(10000.0);
stepper2.setAcceleration(250000.0);
stepper1.runToNewPosition(3780);
stepper1.runToNewPosition(0);
stepper2.runToNewPosition(-3780);
stepper2.runToNewPosition(0);
startMillis = millis(); //initial start time
}
void loop(){
//=====SPEED CALC=============
// subtract the last reading:
SPEED_total = SPEED_total - SPEED_readings[SPEED_readIndex];
// read from the sensor:
SPEED_Val = map(analogRead(SPEED_Pin), 0, 1023, 0, 3780); //scal val2 (kph) to stepper motor positions
SPEED_readings[SPEED_readIndex] =SPEED_Val;
SPEED_total = SPEED_total + SPEED_readings[SPEED_readIndex];
SPEED_readIndex = SPEED_readIndex + 1;
if (SPEED_readIndex >= numReadings) {
SPEED_readIndex = 0;
}
// calculate the average:
SPEED_STEPS = SPEED_total / numReadings; //10*(((total / numReadings)+5)/10);
SPEED_MPH = SPEED_STEPS/18.9;
//Serial1.write(SPEED_MPH);
//=====RPM CALC=============
// subtract the last reading:
RPM_total = RPM_total - RPM_readings[RPM_readIndex];
// read from the sensor:
RPM_Val = map(analogRead(RPM_Pin), 0, 1023, 0, -3780); //scal val2 (kph) to stepper motor positions
RPM_readings[RPM_readIndex] =RPM_Val;
RPM_total = RPM_total + RPM_readings[RPM_readIndex];
RPM_readIndex = RPM_readIndex + 1;
if (RPM_readIndex >= numReadings) {
RPM_readIndex = 0;
}
// calculate the average:
RPM_STEPS = RPM_total / numReadings;
RPM = RPM_STEPS/18.9;
//=============================
currentMillis = millis();
if (currentMillis - startMillis >= period)
{
Serial1.print('<');
Serial1.print(SPEED_MPH);
Serial1.print(delimiter);
Serial1.print(RPM);
Serial1.print(delimiter);
Serial1.print('45');
Serial1.print(delimiter);
Serial1.print('37');
Serial1.print('>');
//Serial1.println();
startMillis = currentMillis;
}
//=============================
stepper1.moveTo(SPEED_STEPS);
stepper2.moveTo(RPM_STEPS);
stepper1.run();
stepper2.run();
}
The receiver code is:
#include <EEPROM.h>
#include <Bounce2.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
//---INITIALISE OLED------------------------------------------------
#define OLED_RESET -1
Adafruit_SSD1306 display(128,32,&Wire, OLED_RESET);
//---END INITIALISE OLED------------------------------------------------
//Serial
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
int SPEED_MPH;
int RPM;
int WATER_TEMP;
int COOLANT_TEMP;
void setup(void) {
Serial.begin(250000);
Serial1.begin(250000);
loadEEPROMSettings();
Wire.setClock(3400000);
/
//-----------INITIATE SCREEN----------------------------------------------
Serial.println("Starting OLED");
display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();
}
void loop(void) {
//=========READ SERIAL=========
Get_Serial_Data();
Parse_Serial_Data();
}
//-----------------------Receive Serial Data--------------------------------------------------------
void Get_Serial_Data() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
// if (Serial.available() > 0) {
while (Serial1.available() > 0 && newData == false) {
rc = Serial1.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//--------------Parse Data from Serial----------------
void Parse_Serial_Data() {
// split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(receivedChars,",");
SPEED_MPH = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
RPM = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
COOLANT_TEMP = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
FUEL_LEVEL = atoi(strtokIndx);
}
I removed the code for showing the data on the screen to make it simpler to read, but there is additional code that does the displaying of the data.
A basic concept to remember is to send the data in a format/manner that is easy to parse on the receiving end. The data packet can contain start markers, end markers, and data delimiters. They can be used as necessary just depending on the data being sent and the timing of the sending.
C:\Users\sterretje\AppData\Local\Temp\arduino_modified_sketch_787493\sketch_jan26a.ino:2:16: warning: multi-character character constant [-Wmultichar]
Serial.print(‘45’);
If not, go to file -> preferences and set "Compiler warnings" to ALL.
What are the characters that you want to send? A dash and a percentage? Or the text 45 and 37?
Hey sorry I have now set this option and got the monitor working correctly. I followed Bob’s advice and changed to double quotes and now if I run the following code on the transmitter:
Which is absolutely correct, so I will now change “Serial.print” to Serial1.print to transmit. So the transmitter is working. Just need to work out the receiver now!
EDIT: I am now reading the following on the receiver:
450nick:
Hey sorry I have now set this option and got the monitor working correctly. I followed Bob’s advice and changed to double quotes and now if I run the following code on the transmitter:
Which is absolutely correct, so I will now change “Serial.print” to Serial1.print to transmit. So the transmitter is working. Just need to work out the receiver now!
EDIT: I am now reading the following on the receiver:
Ok so I have the correct data coming in... And it appears that MPH is coming through correctly but the other 3 numbers are not coming through. So it must be an issue with the data parsing code... Anyone spot it?
//-----------------------Receive Serial Data--------------------------------------------------------
void Get_Serial_Data() {
//inChar = Serial1.read();
if (Serial1.available() > 0) {
//while (Serial1.available() > 0 && newData == false) {
rc = Serial1.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//--------------Parse Data from Serial----------------
void Parse_Serial_Data() {
// split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(receivedChars,","); // get the first part - the string
SPEED_MPH = atoi(strtokIndx);
Serial.print(strtokIndx);
strtokIndx = strtok(NULL, ",");
RPM = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
COOLANT_TEMP = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
FUEL_LEVEL = atoi(strtokIndx);
}