Arduino Uno serial speed issue

Hello, we were previously using a Duemilanove. We've gone to the Uno at first all appeared to go well. We are sending 3 bytes of information at 60Hz. The Duemilanove with the FTDI took this no problem. However, the Uno just goes dead at that rate. I had to back it off by about 15Hz down to 45Hz to get it to perform consistently. At about 53Hz it becomes unstable and the output becomes erratic. Is this a limitation of the new native USB controller on the Uno? I saw an earlier thread about serial library incompatibility. We are using Spi for our shield and the Serial.* family of calls for our USB comms. Will using NewSerial* solve the speed issue?

I would like to use the Arduino platform in the future to replace a simulation controller platform that is now obsolete. That clearly is a task for a more sophisticated version of the Arduino but if it uses the same USB controller and that is where the performance issues lie then that wouldn't be an option.

thanks, this is an awesome platform!

What baud rate are you using? What program or hardware are you using to talk to the Uno? Do you have any example code we can try?

The actual speed used for Serial.begin(57600) differs in the core library in 0021 from the one used by the 8U2 firmware. This will be fixed in the next release: Changing baud rate calculation to always use double speed mode except… · arduino/Arduino@66755f9 · GitHub.

Thanks for the prompt response! The rate is 115200. I am using the USB port of a Dell Optiplex 755 which is the same hardware I was using previously with the Duemilanove. Here is the source code:

#include <Spi.h>

// Melexis definitions
#define MLX_START_BIT 0x80
#define MLX_RESET_PIN 8
#define MLX_ERRB_PIN 9

#define SER_READ_DELAY 10 // in microseconds

#define GAUGE_LOOKUP { 0x00, 0x10, 0x30, 0x40, 0x60, 0x50 }

#define OP_ZERO_GAUGE 0x0
#define OP_R_U_THERE 0x1
#define OP_SET_GAUGE 0x2
#define OP_DEBUG 0x7

#define ACK_CODE_BIT 0x80
#define RC_OK 0X00
#define RC_ERR_UOP 0x01 // Unknown op code received
#define RC_ERR_MDATA 0x02 // Missing expected data packets
#define RC_ERR_OP_WDATA 0x03 // Wrong number of data packets for op
#define RC_ERR_INV_METR 0x04 // Invalid meter or gauge specified

const byte gauge_lookup_tbl[6] = GAUGE_LOOKUP;

int data = 2;
int clock = 3;
int latch = 4;
int debug = 0;

void setup() {
int var = 0;
byte spi_config = 0;

Serial.begin(115200);
pinMode(MLX_RESET_PIN, OUTPUT);
pinMode(MLX_ERRB_PIN, INPUT);
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(latch, OUTPUT);

var = digitalRead(MLX_ERRB_PIN);
digitalWrite(MLX_RESET_PIN, HIGH);
delayMicroseconds(8000);
SPSR &= B11111110; // 0th bit is SPIX2
spi_config |= (1 << SPE) | (1 << MSTR) | (1 << SPR0);
Spi.mode(spi_config);
}

void loop() {
byte cmd = 0, dataPackets = 0, data[3];
int rc = RC_OK, val = 0, gaugeNum = 0;

data[0] = 0; data[1] = 0; data[2] = 0;

if (Serial.available()) {
cmd = Serial.read();
updateLEDs(cmd);
if (cmd == -1) return; // If nothing read no need to continue
dataPackets = (cmd >> 3) & 0x3;
switch(cmd >> 5) {
case OP_SET_GAUGE:
gaugeNum = cmd & 0x3;
if (dataPackets != 2)
rc = RC_ERR_OP_WDATA;
else if (gaugeNum < 1 || gaugeNum > 5)
rc = RC_ERR_INV_METR;
else {
rc = readDataBytes(data, dataPackets);
if (rc == RC_OK) {
val = data[0] << 8 | data[1];
setGauge(gaugeNum, val);
}
}
// TODO: Check pin ERRB on melexis to detect errors and return them
//sendAck(RC_OK);
break;
case OP_ZERO_GAUGE:
gaugeNum = cmd & 0x3;
if (dataPackets != 0)
rc = RC_ERR_OP_WDATA;
else if (gaugeNum < 1 || gaugeNum > 5)
rc = RC_ERR_INV_METR;
else
initMainLogometers();
break;
case OP_R_U_THERE:
if (dataPackets != 0)
rc = RC_ERR_OP_WDATA;
break;
case OP_DEBUG:
debug = 1;
if (dataPackets != 0)
rc = RC_ERR_OP_WDATA;
break;
default:
rc = RC_ERR_UOP;
break;
}
sendAck(rc);
}

}

int readDataBytes(byte *data, int count) {
int i = 0, readCount = 0;
byte cmd;

for (i = 0; i < count; i++) {
do {
data = Serial.read();

  • readCount++;*
    _ if (data == -1)_
    * delayMicroseconds(SER_READ_DELAY);
    _
    else*_
    * break;*
    * } while (readCount < 10);*
    _ if (data == -1)
    * return RC_ERR_MDATA;*
    * }_
    return RC_OK;
    _}
    void sendAck(int errCode) {
    byte cmd = 0;*_

* cmd = ACK_CODE_BIT | (errCode & 0x7f);
_ Serial.write(cmd);
}
void setGauge(int gauge, int val) {
int quad = 0, offset = 0;*_

* quad = 0x3 & (3 + (val/512));*
* offset = val % 512;*
* sendByComp(gauge, quad, offset);*
}
void initMainLogometers () {
* int i = 0, calDelay = 1000, quad = 0, offset = 0;*
* for (i = 200; i < 1500; i += 4) {*
* delayMicroseconds(calDelay);*
* quad = 0x3 & (3 + (i/512));*
* offset = i % 512;*
* sendByComp(1, quad, offset);*
* sendByComp(2, quad, offset);*
* }*
* for (i = 1500; i >= 200; i -= 4) {*
* delayMicroseconds(calDelay);*
* quad = 0x3 & (3 + (i/512));*
* offset = i % 512;*
* sendByComp(1, quad, offset);*
* sendByComp(2, quad, offset);*
* }*
}
void sweepMainLogometers () {
* int i = 0, j = 0, calDelay = 2000;*
* for (j = 3; j < 7; j++) {*
* for (i = 0; i < 512; i++) {*
* delayMicroseconds(calDelay);*
* sendByComp(1, 0x3&j, i);*
* sendByComp(2, 0x3&j, i);*
* }*
* }*
* for (j = 6; j >= 3; j--) {*
* for (i = 511; i >= 0; i--) {*
* delayMicroseconds(calDelay);*
* sendByComp(1, 0x3&j, i);*
* sendByComp(2, 0x3&j, i);*
* }*
* }*
}
void sendByComp(int gauge, int quad, int val) {
* byte b1;*
* byte b2;*

* if (val < 0 || val > 511) {*
* pDataValidationError("Error valid quadrant table lookups are 0 to 511, received ", val);*
* return;*
* }*

* if (quad < 0 || quad > 3) {*
* pDataValidationError("Error valid quadrants are 0 to 3, received ", quad);*
* return;*
* }*

* b1 = MLX_START_BIT | gauge_lookup_tbl[gauge] | (val >> 5);
_ b2 = 0x00 | val << 3 | quad;*_

* digitalWrite(SS_PIN, HIGH);
_ Spi.transfer(b1);
Spi.transfer(b2);_
digitalWrite(SS_PIN, LOW);
_}
void pDataValidationError(char *msg, int val) {
Serial.print(msg);
Serial.print(val);
Serial.println();
}
void updateLEDs(int value){
digitalWrite(latch, LOW); //Pulls the chips latch low*
* shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register*
* digitalWrite(latch, HIGH); //Pulls the latch high displaying the data*
}_

Can you reduce this to a simple program with the same problem? What software is running on the computer?

Is this related?:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1292954023

Great question, perhaps it is! I will have to try that and see.