Reducing serial communication time

Hey, i need to transmit data (10 bytes) to my rc plane over serial as fast and as much as possible,
but the problem is that i get a response after about 1 second (i cannot monitor the receiver using PC because the rf module is connected to pins 0 & 1). i can monitor the sender and as i saw it is taking about 14ms for the remote to run on the whole loop, so i guess the problem is somewhere in the link between them.
also, i tried to make the receiver as efficient as possible but with no luck.

sender:

#include <SoftwareSerial.h>

#define TX  3
#define RX  2
#define M0  13
#define M1  12
#define AUX  11
#define communicationLed 8

unsigned long time;
byte myData[10];

SoftwareSerial ESerial(TX, RX);

void setup(){
  Serial.begin(9600);
  ESerial.begin(9600);
  Serial.println("Starting Sender");
  pinMode(4, INPUT_PULLUP); //button pull-up resistor
  pinMode(5, INPUT_PULLUP); //button pull-up resistor
  pinMode(6, INPUT_PULLUP); //button pull-up resistor
  pinMode(7, INPUT_PULLUP); //button pull-up resistor
  pinMode(communicationLed, OUTPUT); //communication Led config
  pinMode(M0, OUTPUT); //lora module config
  pinMode(M1, OUTPUT); //lora module config
  digitalWrite(M0, LOW); //lora module config
  digitalWrite(M1, LOW); //lora module config

 //sync bytes
  myData[9] = 0xff; // end byte
  myData[0] = 0xfe; //start byte
}

void loop(){
    // Read all analog inputs and map them to one Byte value
    // Convert the analog read value from 0 to 1023
    getTime(); // print loop duration
  myData[1] = map(analogRead(A1), 0, 1023, 0, 180);  //j1posX
  myData[2] = map(analogRead(A0), 0, 1023, 0, 180);  //j1posY
  myData[3] = map(analogRead(A3), 0, 1023, 0, 180);  //j2posY
  myData[4] = map(analogRead(A2), 0, 1023, 0, 180);  //j2posX
  if (digitalRead(4)) myData[5] = 0; else myData[5]= 1;
  if (digitalRead(5)) myData[6] = 0; else myData[6] = 1;
  if (digitalRead(6)) myData[7] = 0; else myData[7] = 1;
  if (digitalRead(7)) myData[8] = 0; else myData[8] = 1;
  //Serial.println(DataToSend);
  ESerial.write(myData, 10);
  delay(3);
}

void getTime(){
  Serial.print("Time: ");
  time = millis();
  Serial.println(time);
}

receiver:

byte dataReceived[10];
int i=0;
#include <Servo.h>

Servo servo1;  // create servo object to control a servo
Servo servo2;  // create servo object to control a servo
Servo servo3;  // create servo object to control a servo
Servo servo4;  // create servo object to control a servo
Servo esc;  // create servo object to control a servo

//============

void setup() {
    Serial.begin(9600);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, INPUT);
    servo1.attach(9);  // attaches the servo on pin 4 to the servo object
    //servo2.attach(5);  // attaches the servo on pin 5 to the servo object
    //servo3.attach(6);  // attaches the servo on pin 6 to the servo object
    //servo4.attach(7);  // attaches the servo on pin 7 to the servo object
    esc.attach(10);  // attaches the servo on pin 7 to the servo object
    resetData();
}

//============

void loop() {
       if (Serial.available() >= 10){ //read data into array
        lastReceiveTime = millis();
        for(i=0;i<10;i++){
          dataReceived[i] = Serial.read();
        }
        if (dataReceived[0] == 0xfe && dataReceived[9] == 0xff){// all good and were in sync
                servo1.write(dataReceived[2]);
              //servo2.write(j1potX); 
              //servo3.write(j2potY);
              //Serial.println(j2potX);
              //servo4.write(j2potX);
               esc.writeMicroseconds(map(dataReceived[1], 0, 180, 0, 2000));
          }  else {  //were not in sync and need to dump all the data
            while (Serial.read() != 0xff){resetData();}
            } 
    }
}
void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  dataReceived[1] = 90; //j1posX
  dataReceived[2] = 0; //esc
  dataReceived[3] = 90; //j2posY
  dataReceived[4] = 90; //j2posX
  dataReceived[5] = 0;
  dataReceived[6] = 0;
  dataReceived[7] = 0;
  dataReceived[8] = 0;
}

You could use 4 different bits of the same byte to hold the 4 flags you're now using 4 different bytes to hold. That would cut the amount of data you need to send and receive by 3 bytes.

Well, how about changing your baudrate then? Currently you are using 9600, which will take ~10.4ms per packet (10 bytes).

However, I guess you've connected an rf module on both the sender and receiver's uart? Maybe the rf module is wrongly configured? I don't think the serial speed is the issue here. Maybe something with the receiver not reading the first packet and the sender sending packets only every 3 seconds?

xstr3me:
but the problem is that i get a response after about 1 second

I don't see any code in your examples that gets a response so I don't understand how you are measuring the 1 second.

Sending 10 bytes at 9600 baud should take about 10/960 * 1000 = 10.4 millisecs

This line is probably wasting a lot of time because it will call resetData() many times

while (Serial.read() != 0xff){resetData();}

Try replacing it with

else {
 while(Serial.available > 0) {
 byte dump = Serial.read(); // clear the Serial input buffer
 }
 resetData();
}

Have a look at the 3rd example in Serial Input Basics. It is written for receiving text but you can easily change it to read bytes and use your chosen start- and end-markers.

...R

gfvalvo:
You could use 4 different bits of the same byte to hold the 4 flags you're now using 4 different bytes to hold. That would cut the amount of data you need to send and receive by 3 bytes.

thats a good idea for later stage, because the change will be minor and wont solve the major delay.

LightuC:
Well, how about changing your baudrate then? Currently you are using 9600, which will take ~10.4ms per packet (10 bytes).

However, I guess you've connected an rf module on both the sender and receiver's uart? Maybe the rf module is wrongly configured? I don't think the serial speed is the issue here. Maybe something with the receiver not reading the first packet and the sender sending packets only every 3 seconds?

im using the default config on my modules (lora sx1278 e32), i doubt it wrongly configured but ill cehck it anyway way.

Robin2:
I don't see any code in your examples that gets a response so I don't understand how you are measuring the 1 second.

Sending 10 bytes at 9600 baud should take about 10/960 * 1000 = 10.4 millisecs

This line is probably wasting a lot of time because it will call resetData() many times

while (Serial.read() != 0xff){resetData();}

Try replacing it with

else {

while(Serial.available > 0) {
byte dump = Serial.read(); // clear the Serial input buffer
}
resetData();
}




Have a look at the 3rd example in [Serial Input Basics](http://forum.arduino.cc/index.php?topic=396450.0). It is written for receiving text but you can easily change it to read bytes and use your chosen start- and end-markers.


...R

i cannot measure the actual delay because i cant connect it to the pc but i can see it has huge delay.
i did change the code a bit according to your suggestion, now its looking like this

        }  else {  //were not in sync and need to dump all the data
            resetData();
            while (Serial.read() != 0xff){}
            }

and i think it made it a bit faster, but still with delay.

the guide you linked is where i started from (great guide btw) but making a string from all the inputs gives me more bytes to send, plus parsing it afterwards taking time.

what you did with markers i did with 0xff and 0xfe because they are unachievable values.

xstr3me:
but i can see it has huge delay.

Please explain how you can determine that there is a delay - I don't understand.

what you did with markers i did with 0xff and 0xfe because they are unachievable values.

Why would they be unachievable with my code?

This is still wrong

while (Serial.read() != 0xff){}

because it ties up the Arduino completely until something arrives. See how things are done in my tutorial.

...R

Robin2:
This is still wrong

while (Serial.read() != 0xff){}

because it ties up the Arduino completely until something arrives. See how things are done in my tutorial.

It is wrong probably, but it will wait until a 0xFF is received, it will block on no and any other input.

xstr3me:
thats a good idea for later stage, because the change will be minor and wont solve the major delay

Of course, the problem is you don’t know (or have been unable to communicate) what the cause of the “major delay” is or what you think would solve it. But if your goal (per the thread’s title) is “Reducing serial communication time”, then a 30% reduction in packet size (10 bytes to 7, not counting marks) seems worthwhile.

Robin2:
Please explain how you can determine that there is a delay - I don’t understand.
Why would they be unachievable with my code?

This is still wrong

while (Serial.read() != 0xff){}

because it ties up the Arduino completely until something arrives. See how things are done in my tutorial.

…R

i can see the servo respond after 1~ seconds

i meant that “<” “>” are might be achievable in my code so i use 0xff and 0xfe

this is the new code, i used your code but still having delays

boolean newData = false;
byte dataReceived[8];
int i=0;
unsigned long lastReceiveTime;
byte startByte = 0xfe, endByte = 0xff;
static boolean recvInProgress = false;

#include <Servo.h>

Servo servo1;  // create servo object to control a servo
Servo servo2;  // create servo object to control a servo
Servo servo3;  // create servo object to control a servo
Servo servo4;  // create servo object to control a servo
Servo esc;  // create servo object to control a servo

//============

void setup() {
    Serial.begin(9600);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, INPUT);
    servo1.attach(9);  // attaches the servo on pin 4 to the servo object
    //servo2.attach(5);  // attaches the servo on pin 5 to the servo object
    //servo3.attach(6);  // attaches the servo on pin 6 to the servo object
    //servo4.attach(7);  // attaches the servo on pin 7 to the servo object
    esc.attach(10);  // attaches the servo on pin 7 to the servo object
    resetData();
}

//============

void loop() {
       while (Serial.available() > 0 && newData == false){ //read data into array
        byte currentByte = Serial.read();
        if (recvInProgress == true) {
            if (currentByte != endByte) {
                dataReceived[i] = currentByte;
                i++;
                }
            else {
                recvInProgress = false;
                i = 0;
                newData = true;
            }
        }
        else if (currentByte == startByte) {
            recvInProgress = true;
        }
       }
              servo1.write(dataReceived[1]);
              //servo2.write(j1potX); 
              //servo3.write(j2potY);
              //Serial.println(j2potX);
              //servo4.write(j2potX);
               esc.writeMicroseconds(map(dataReceived[0], 0, 180, 0, 2000));
               newData = false;
}

void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  dataReceived[1] = 90; //j1posX
  dataReceived[2] = 0; //esc
  dataReceived[3] = 90; //j2posY
  dataReceived[4] = 90; //j2posX
  dataReceived[5] = 0;
  dataReceived[6] = 0;
  dataReceived[7] = 0;
  dataReceived[8] = 0;
}

Whandall:
It is wrong probably, but it will wait until a 0xFF is received, it will block on no and any other input.

Yea, changed it, it helped a bit but not a major improvement.

gfvalvo:
Of course, the problem is you don’t know (or have been unable to communicate) what the cause of the “major delay” is or what you think would solve it. But if your goal (per the thread’s title) is “Reducing serial communication time”, then a 30% reduction in packet size (10 bytes to 7, not counting marks) seems worthwhile.

Will do

xstr3me:
this is the new code, i used your code but still having delays

Why make things complicated?

You could simply have this code in loop()

void loop() {
   receiveWithStartEndMarkers();
   if (newData == true) {
      servo1.write(dataReceived[1]);

      esc.writeMicroseconds(map(dataReceived[0], 0, 180, 0, 2000));
      newData = false;
   }
}

...R

Robin2:
Why make things complicated?

You could simply have this code in loop()

void loop() {

receiveWithStartEndMarkers();
  if (newData == true) {
      servo1.write(dataReceived[1]);

esc.writeMicroseconds(map(dataReceived[0], 0, 180, 0, 2000));
      newData = false;
  }
}




...R

its what i did but i placed it all in the main func.
im pretty sure the problem is with the receiving end.
i measured the time its taking the remote to send the data and run the whole code, thats around 14ms but nothing in the receiving end (as far as i can see) might cause that much of a delay.

what i tried is to get the time when it starting to read the data (above "recvInProgress = true;") and read the time when its starting to move the servos (after getting all the data) then subtract the first from the second and if thats more then 200 millis (or smt else) turn on a led, but the results are not good, most of the time it turning on the led instantly.

any ideas?

xstr3me:
its what i did but i placed it all in the main func.

First, there is no advantage for the Arduino in putting all the code in loop() and I reckon there is a significant disadvantage for you, the programmer, because it allows things to get mixed up.

Second, I don't think your code in Reply #8 actually does what my version in Reply #9 does. Study the two carefully. Look at this line in my version

if (newData == true)

...R

Robin2:
First, there is no advantage for the Arduino in putting all the code in loop() and I reckon there is a significant disadvantage for you, the programmer, because it allows things to get mixed up.

Second, I don’t think your code in Reply #8 actually does what my version in Reply #9 does. Study the two carefully. Look at this line in my version

if (newData == true)

…R

boolean newData = false;
byte dataReceived[8];
int i=0;
unsigned long lastReceiveTime;
byte startByte = 0xfe, endByte = 0xff;
static boolean recvInProgress = false;

#define led1 12
#define debugLed 13
#include <Servo.h>

Servo servo1;  // create servo object to control a servo
Servo servo2;  // create servo object to control a servo
Servo servo3;  // create servo object to control a servo
Servo servo4;  // create servo object to control a servo
Servo esc;  // create servo object to control a servo

//============

void setup() {
    Serial.begin(9600);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    digitalWrite(4, LOW); //lora module config
    digitalWrite(5, LOW); //lora module config
    pinMode(6, INPUT);
    pinMode(led1, OUTPUT);
    pinMode(debugLed, OUTPUT);
    servo1.attach(7);  // attaches the servo on pin 4 to the servo object
    servo2.attach(8);  // attaches the servo on pin 5 to the servo object
    servo3.attach(9);  // attaches the servo on pin 6 to the servo object
    servo4.attach(10);  // attaches the servo on pin 7 to the servo object
    esc.attach(11);  // attaches the servo on pin 7 to the servo object
    resetData();
}

//============

void loop() {
   recvData();
       if(newData){runMotors();}
}

void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  dataReceived[1] = 90; //j1posX
  dataReceived[2] = 0; //esc
  dataReceived[3] = 90; //j2posY
  dataReceived[4] = 90; //j2posX
  dataReceived[5] = 0;
  dataReceived[6] = 0;
  dataReceived[7] = 0;
  dataReceived[8] = 0; 
}

void recvData(){
    while (Serial.available() > 0 && newData == false){ //read data into array
        byte currentByte = Serial.read();
        if (recvInProgress == true) {
            if (currentByte != endByte) {
                dataReceived[i] = currentByte;
                i++;
                }
            else {
                recvInProgress = false;
                i = 0;
                newData = true;
            }
        }
        else if (currentByte == startByte) {
            recvInProgress = true;
        }
       }
}
void runMotors(){
               servo1.write(dataReceived[1]);
              //servo2.write(j1potX); 
              //servo3.write(j2potY);
              //Serial.println(j2potX);
              //servo4.write(j2potX);
               esc.writeMicroseconds(map(dataReceived[0], 0, 180, 0, 2000));
               if(dataReceived[4]) digitalWrite(led1,HIGH); else digitalWrite(led1,LOW);
               //delay(3);
               newData = false;    
}

Still nothing, i really clueless where the code might get stuck or whats not working properly.

xstr3me:
[Still nothing, i really clueless where the code might get stuck or whats not working properly.

If you want any more help from me make it as easy as possible for me to help you. Use the code from my tutorial example exactly as it is other than to change the start and end markers and to change from char to byte variable types. Then I wont have to spend time studying your code to see if you have "incorporated" any errors.

When you have it working you can re-write the code in any style that you like.

...R

xstr3me:
Hey, i need to transmit data (10 bytes) to my rc plane over serial as fast and as much as possible

What is the actual purpose of the 10 bytes ?

Robin2:
If you want any more help from me make it as easy as possible for me to help you. Use the code from my tutorial example exactly as it is other than to change the start and end markers and to change from char to byte variable types. Then I wont have to spend time studying your code to see if you have "incorporated" any errors.

When you have it working you can re-write the code in any style that you like.

...R

Ok, i made some progress. i connected both the transmit wire from the remote to the receive pin in the receiver arduino (and ground them together ofc), now its working smoothly.
so i guess the problem is with the rf modules. do you know any way i can check whats the exact problem?
Thank you so much regardless.

srnet:
What is the actual purpose of the 10 bytes ?

2 bytes for sync and 8 bytes of data for each button on the remote.

the module is lora sx1278 e32

xstr3me:
do you know any way i can check whats the exact problem?

Remind me what's the problem. I have forgotten.

...R

Robin2:
Remind me what's the problem. I have forgotten.

...R

:sweat_smile: :sweat_smile:
data is received really slow when using lora module

How is the LoRa module configured? How did you wire the M0 and M1 pins?

EDIT: Put the LoRa module into sleep mode and send 0xC1 0xC1 0xC1 to it. Then receive 6 bytes from the module and post it here (this is the configuration of the module).

xstr3me:
data is received really slow when using lora module

A LoRa device, which is SPI based, has a predicatable and by now well understood performance and response. The LoRa device is packet based, max length 256bytes, and is capable of 37500bps.

The E32 module puts a processor in front of the SPI LoRa device to provide an 'easy to use' UART\Serial interface.

Maybe the problem you are having is not LoRa issues as such, but with the way the E32 module talks over the serial.