What is the Arduino Uno Serial buffer size?

Well, I used your code, and it partially worked. I now get a full 107 byte buffer, however, every byte past byte 67 is 0, including the checksum, so I know I am still not reading the data correctly

here is my current code:

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives only 67 bytes of the run-time response, and displays
 on the LCD screen and via serial monitor.
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
byte long Value;
int First = 0;
int q;
int j;

void setup(){

  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 


  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);
  q=0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum

  lcd.setCursor(0,0);
  //Stream request data series to ECM as HEX
  for (int i = 0; i<9; i+=1){
    mySerial.write(inArray[i]);
    lcd.print(inArray[i],HEX); //print sent HEX code
  }
}

void processIncomingByte (const byte c){
  q++;
  outArray[q] = c;
  Serial.println(outArray[q],HEX);
  if(q > 107){
    q = 0;
  }
}

//display the array in serial monitor one time
void display(){
  if(First < 1){
    if(j<107){
      Serial.println(outArray[j],HEX);
      j++;
    }
    else{
      First++;
      j=0;
    }
  }
}

//void loop() {
//  //read the incoming data
//  if (mySerial.available())
//    processIncomingByte (mySerial.read());
//
//  //concatenate 2 byte RPM data
//  //    unsigned Value = outArray[31] << 8 | outArray[30];
//  //    lcd.setCursor(0,1);
//  //    lcd.print("temp: ");
//  //    lcd.print((Value*0.18-40));
//  //    display();  
//}

void loop() {
  // fill buffer
  if (mySerial.available () > 0) 
    outArray[q++] = mySerial.read ();
  if(mySerial.overflow())
    Serial.print("overflow");
  if (q >= 107){
    // process it
    q = 0;  // ready for next time
  }  // end if full
  display();
}  // end of loop

and this is the response I got from the ECM:

1
42
0
overflow64
overflowFF
2
6
7B
E
0
0
0
0
0
0
0
0
BB
20
BB
20
B5
35
B5
35
33
0
F
A6
4
65
2
93
2
0
0
6B
2
1F
6
E8
3
0
0
E8
3
E8
3
E8
3
E8
3
30
4
30
4
0
80
0
0
0
0
0
0
0
FC
10
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

I noticed that when I tried to read more than 107 bytes (up to 500) the code began to repeat after about 116 bytes (but no header), then after that repeat, it was just a bunch of random Hex mess.
Any ideas?

void loop() {
  // fill buffer
  if (mySerial.available () > 0) 
    outArray[q++] = mySerial.read ();
  if(mySerial.overflow())
    Serial.print("overflow");
  if (q >= 107){
    // process it
    q = 0;  // ready for next time
  }  // end if full
  display();
}  // end of loop

But there is no point in displaying it until all 107 bytes have arrived.

But there is no point in displaying it until all 107 bytes have arrived.

Not only is there no point in doing it, there is harm in doing it. It takes time to do the output, and, with the incoming stream of data that you have, time is something you don't have a lot of.

Variable names like q are easy to type, but they don't mean diddly. They are fine for loop indices, but not the way you are using them. Do yourself a big favor and use meaningful names.

Oh, I see what you are saying. I will move display() to this:

if (q >= 107) {
  // process it
  q = 0;  // ready for next time
  display();
}// end if full

and will rename the iteration count names and see how it goes.

Good news, I finally got it to read all 107 bytes of data. The ECM sends back 1 response per request so I need to continuously request and read the data from the ECM. I tried doing this by moving the request code into the the loop, but it seemed to be restarting the loop too quickly and it won't read all of the data. I tried it a different way and it was taking like 20 seconds between each time it read the data, and I have no idea why. Do you have any suggestions that I can continuously request and read the data, while performing math and other calculations at the same time quickly? I only need it to refresh the data a couple times a second.

This is the latest code that reads all 107 bytes of data one time and prints it:

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives all 107 bytes of Real-time data, and displays
 on the LCD screen and via serial monitor.
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
byte long Value;
int First = 0;
int q;
int j;

void setup(){

  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);
  q=0;
  j=0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum

  lcd.setCursor(0,0);
  //Stream request data series to ECM as HEX
  for (int i = 0; i<9; i+=1){
    mySerial.write(inArray[i]);
    lcd.print(inArray[i],HEX); //print sent HEX code
  }
  //mySerial.write(0x01 0x00 0x43 0x02 0xFF 0x02 0x43 0x03 0xFD); //not sure on the correct syntax for this
}


//display the array in serial monitor one time
void display(){
  if(First < 1){
    for (int j = 0; j<107; j+=1){
      Serial.println(outArray[j],HEX);
    }
  }
  else(First++);
}


void loop() {
  // fill buffer
  if (mySerial.available () > 0) 
    outArray[q++] = mySerial.read ();
  if (q > 106){
    // process it
    q = 0;  // ready for next time
    display();
  }  // end if full
}  // end of loop

I didn't get a chance to rename the indexes yet but I am working on it.

So, inArray contains data the you send out, and outArray contains data that came in. Got it.

The ECM sends back 1 response per request so I need to continuously request and read the data from the ECM. I tried doing this by moving the request code into the the loop, but it seemed to be restarting the loop too quickly and it won't read all of the data.

Seems, then, like you should be sending the request for more data only when the end of the currently-being-received packet is detected.

I tried it a different way and it was taking like 20 seconds between each time it read the data, and I have no idea why.

Without showing us what you tried, we should know?

One assumption you are making is not a valid assumption. That assumption is that every byte sent will make it to the receiver, and that every byte the receiver sends will make it back. That assumption will need to be addressed.

There must be something in the packet sent that marks the start of a packet, and there should be something that marks the end of a packet. You should be checking for that start marker before storing the data. The end marker may arrive before the 107th byte, at which point you should stop reading, and possibly discard that packet.

There should also be some way to tell the ECM to send data in a continuous fashion. It seems difficult to believe that it needs to be polled for every bit of data.

PaulS:
So, inArray contains data the you send out, and outArray contains data that came in. Got it.

Yeah the frame of reference was the ECM, I might swap them because it isn't intuitive.

There must be something in the packet sent that marks the start of a packet, and there should be something that marks the end of a packet. You should be checking for that start marker before storing the data. The end marker may arrive before the 107th byte, at which point you should stop reading, and possibly discard that packet.

The beginning of the response has a header of data that is always the exact same 7 bytes, and the data always has a checksum. I suppose I would make sure that bytes 0-6 and byte 106 match, and then if it does save it to a new array.

There should also be some way to tell the ECM to send data in a continuous fashion. It seems difficult to believe that it needs to be polled for every bit of data.

I certainly hope there is, but from the wording from the EcmSpy website that has a PC program for communicating with the ECM:

"As mentioned in the chapter above, the ECM can be triggered to send a record of runtime data. These data consist of the current state (at the time of the query) of many input and output values, for example temperature sensores, injector pulsewidth and lots of other usefull information."

...it doesn't really sound like it

This project has proven to be pretty tough. It's hard to work on it because I have to have the bike with the key on (engine off) when working on the program, and the battery dies after a couple hours of work (even while its on a charger), so I have limited time each weekend to get a lot done.

I suppose I would make sure that bytes 0-6 and byte 106 match, and then if it does save it to a new array.

No, don't try to copy all that data. If the 1st 6 bytes or the checksum don't match, just ignore the data in the array.

...it doesn't really sound like it

OK. It does sound like it expects to be asked for data. That should be OK, though, because that means it won't be flooding you with data faster than you can read it.

Put the code that initiates the transaction, now in setup(), into a function. Call it whenever you are done reading/storing/using a packet, and want another one.

This project has proven to be pretty tough. It's hard to work on it because I have to have the bike with the key on (engine off) when working on the program, and the battery dies after a couple hours of work (even while its on a charger), so I have limited time each weekend to get a lot done.

Bummer. But, it sounds like you are making good progress.

No, don't try to copy all that data. If the 1st 6 bytes or the checksum don't match, just ignore the data in the array.

The only bad thing is I need to process every byte in order to get the correct checksum, and I already have all the data in memory because the serial buffer is only 64 bytes.

You don't to keep 107 bytes in memory. A state machine, as I describe here, will pull the data out "on the fly"...

As each byte arrives you can also add it to the running checksum. Then at the end, you check the checksum, and if it agrees, use the variables the state machine arrived at during its operation.

I did an example on that page for someone who had rather simpler requirements, but yours is basically more of the same concept.

It wouldn't do me much good to calculate the data on the fly if the checksum doesn't match though, right? That would mean one or all of the data is faulty and everything I just calculated would need to be disregarded.

I put the code that sends the request into a a function and it seems to send the initial request from the setup, then it reads it on the first iteration, and then sends the next request, but it does not read the second stream of data. I think this has something to do with the mySerial.available() function. Hopefully you guys might be able to spot the problem with my code:

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives all 107 bytes of Real-time data, and displays
 on the TPS on the LCD screen and all data via serial monitor.
 The program is supposed to be running in real time, but only
 shows the very first iteration. The problem may have something
 to do with the mySerial.avalable() function.
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
byte long Value;
int IterationNumber = 0;
int ByteNumber;

void setup(){
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);
  ByteNumber = 0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum

  lcd.setCursor(0,0);
  //Stream request data series to ECM as HEX
  for (int i = 0; i<9; i+=1){
    mySerial.write(inArray[i]);
    lcd.print(inArray[i],HEX); //print sent HEX code
  }
  //mySerial.write(0x01 0x00 0x43 0x02 0xFF 0x02 0x43 0x03 0xFD);
}

//Send data request to ECM
void requestData() {
  for (int i = 0; i<9; i+=1){
    mySerial.write(inArray[i]);
    //lcd.setCursor(0,0);
    //lcd.print("printing"+i);
  }
  Serial.print("Data Request Sent");
  delay(100);
}

//display the array in serial monitor one time
void displayData(){
  //if(IterationNumber < 3){
    for (int j = 0; j<107; j+=1){
      Serial.println(outArray[j],HEX);
    }
    //IterationNumber ++;
    Serial.println("Data Printed");
  //}
}

//Display the Throttle Position Sensor
void TPS(){
  unsigned Value = outArray[91] << 8 | outArray[90];
  lcd.setCursor(0,1);
  lcd.print("TPS: ");
  lcd.print(Value); 
}

void loop() {
  // fill buffer
  if (mySerial.available () > 0) 
    outArray[ByteNumber ++] = mySerial.read();
  if (ByteNumber > 106){// process it
    Serial.println("Data Stream Read");
    ByteNumber = 0;  // ready for next time
    displayData();
    lcd.setCursor(1,1);
    TPS();
    requestData();
  }  // end if full
}  // end of loop

This is the response I get:

Data Stream Read
1
42
0
64
FF
2
6
7B
5A
0
0
0
0
0
0
0
0
BB
20
BB
20
38
36
38
36
33
0
F
4F
4
65
2
98
2
0
0
EE
2
1F
6
E8
3
0
0
E8
3
E8
3
E8
3
E8
3
30
4
30
4
0
80
0
0
0
0
0
0
0
FC
0
0
0
0
0
0
0
0
0
0
10
0
0
FF
FF
FF
FE
0
0
5
0
0
0
0
A1
0
1A
1
F0
BC
0
0
0
0
0
0
0
0
0
3
F5
Data Printed
Data Request Sent

My desire is for it to repeat this response over and over with newer run-time data, but like I mentioned, it isn't doing this like I thought it would.

I have not added any data verification yet with the header or checksum. So far the data coming in has been good and very consistent without skipping a beat, so I am going to focus on core functionality before I add in that feature.

EDIT: I just thought of something, would clearing the mySerial buffer before requesting more data help?

Does it still work (once) if you call requestData from setup rather than replicating the send loop there?

Yeah, you can see by the data it works the first time. I call the same bit of code from the function for a second and it seems to send the request but no data appears to be read and I don't know why.

I mean does it work if you call the function rather than replicating what it does, because they are not quite the same - the LCD print in setup introduces a (small) delay. I was wondering whether that difference is important.

GOOD NEWS!!!!

I got it working! It displays the information on my LCD screen quickly and in real-time. I will post a video of it in a few hours. The problem I was having was the location of the display() function. It was interfering with the data coming in and non of it would get read. I just removed it because I won't need since the arduino will be a stand alone on the bike with no serial monitor connected.

Thank you so much to everyone for the help, there is still a lot left I have to do. The main part of my project can start moving forward now with calculating torque, horsepower, and creating a shift indicator. I am excited!

Thanks again, and video coming soon!

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives all 107 bytes of Real-time data, and displays
 on the TPS on the LCD screen and all data via serial monitor.
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
byte long TPS;
byte long ETemp;
int IterationNumber = 0;
int ByteNumber;
int Processing = 0;

void setup(){
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);
  ByteNumber = 0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum

  //mySerial.write(0x01 0x00 0x43 0x02 0xFF 0x02 0x43 0x03 0xFD);
  requestData();
}

//Send data request to ECM
void requestData() {
  //lcd.setCursor(0,0);
  for (int i = 0; i<9; i+=1)
    mySerial.write(inArray[i]);
  //Do not place code here
}

//display the array in serial monitor
void displayData(){
  for (int j = 0; j<107; j+=1){
    Serial.println(outArray[j],HEX);
  }
  Serial.println("Data Printed");
  Processing = 0;
}

//Display the Throttle Position Sensor
void callTPS(){
  unsigned TPS = outArray[91] << 8 | outArray[90];
  lcd.setCursor(0,0); //right then down
  lcd.print("TPS: ");
  lcd.print(TPS); 
}

void callETemp(){
  unsigned ETemp = (outArray[31] << 8 | outArray[30]) * 0.18 -40;
  lcd.setCursor(0,1); //right then down
  lcd.print("ETemp: ");
  lcd.print(ETemp); 
  lcd.print("degF");
}

void loop() {
  if (mySerial.available () > 0) {
    outArray[ByteNumber ++] = mySerial.read();
  }
  if (ByteNumber > 106){// process it
    Serial.println("Data Stream Read");
    //Processing = 0;
    ByteNumber = 0;  // ready for next time
    //displayData();
    lcd.setCursor(1,1);
    callTPS();
    callETemp();
    requestData();  //restart data
    //Do not place code here
  }  // end if full
}  // end of loop

Blaylock1988:
GOOD NEWS!!!!
I got it working!

Hi Michael,

Thanks to your program I managed to receive serial PELCO commands. These commands are used to control
CCTV camera systems. :slight_smile:

http://forum.arduino.cc/index.php?PHPSESSID=bhv3n6da4s1f2a8d0b3ip2er66&topic=155693.0

HI Blaylock1988,

did your problem got solved even I am facing the same issue? awaiting for reply

shivalingaraju:
HI Blaylock1988,

did your problem got solved even I am facing the same issue? awaiting for reply

shivalingaraju:
HI Blaylock1988,

did your problem got solved even I am facing the same issue? awaiting for reply

Did you read reply#35?

shivalingaraju:
HI Blaylock1988,

did your problem got solved even I am facing the same issue? awaiting for reply

Blaylock is no longer a member of the Forum and he was last here 5 years ago.

Start your own Thread and explain what your problem is.

...R