Go Down

Topic: Data corruption at baud rates other than 9600 (Read 176 times) previous topic - next topic

Droid_22

Hi. Recently I have been trying to do a project where I send data from my computer to my Arduino to update led's. It works fine on 9600 baud except for the fact that it's around 30x too slow. So I try turning the baud rate up on the Arduino and in my java application. It is faster, however there is significant corruption. When echoing back the commands I send to the Arduino random character are missing, some are repeated multiple times, some are switched. I know it isn't an issue of the serial buffer on the arduino overflowing as I have a basic handshake type system implemented, I'm pretty sure it isn't the ardunio as I've tried on a nano and an uno. I've configured the baud rates in the device manager to match. Nothing works. I still get corrupted data. One thing I have noticed is the corruption is better on some higher baud rates and worse on lower baud rates. For example a lower baud rate might be unusably corrupt where as a higher one will maybe only mess up a character or 2 out of a hundred.

at this point I'm kind of lost as to what I should do. I've looked everywhere online trying to fix this to no avail. Any help at all would be greatly appreciated!

Paul_KD7HB

Sure sounds like  a software problem to me.


Robin2

#2
May 04, 2019, 11:04 pm Last Edit: May 04, 2019, 11:05 pm by Robin2
I have never had any trouble communicating between my Arduinos and my PC at 500,000 baud. IIRC I also used that speed back in the day when I was using JRuby and JSSC.

I assume you are trying to communicate using the regular USB connection between the PC and the Arduino.

Without seeing your programs it is impossible to suggest a solution.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Droid_22

Sorry in advance for the bad code. I'm new to c/c++ so I'm still learning conventions. Anyways this the code I've been running on the Arduino's. All of the serial code is inside of the main loop. Also due to the character limit I had to remove some unnecessary code that did animations and such. None of it was being run when I had the problems.

Code: [Select]

#include <FastLED.h>

#define LED_PIN     8
#define NUM_LEDS    60
#define BRIGHTNESS  50
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 300

// This example shows several ways to set up and use 'palettes' of colors
// with FastLED.
//
// These compact palettes provide an easy way to re-colorize your
// animation on the fly, quickly, easily, and with low overhead.
//
// USING palettes is MUCH simpler in practice than in theory, so first just
// run this sketch, and watch the pretty lights as you then read through
// the code.  Although this sketch has eight (or more) different color schemes,
// the entire sketch compiles down to about 6.5K on AVR.
//
// FastLED provides a few pre-configured color palettes, and makes it
// extremely easy to make up your own color schemes with palettes.
//
// Some notes on the more abstract 'theory and practice' of
// FastLED compact palettes are at the bottom of this file.



CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

//communication
bool connectionEstablished = false;

//SyncVariables
bool Sync = true;
CRGBPalette16 serialPalette;
float brigntness = 0.1;
int bpm = 128;

void setup() {
 delay(3000); // power-up safety delay
 Serial.begin(19200);
 Serial.setTimeout(7);
 FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
 FastLED.setBrightness(BRIGHTNESS);

 currentPalette = RainbowColors_p;
 currentBlending = LINEARBLEND;
}

//this is used to get the iterations of the loop. This is needed because we only want to update the leds every 16 cycles
uint8_t loopCount = 0;

char inputBuffer[16];
unsigned long deltaTime = 0;
void loop()
{
 loopCount++;
 deltaTime = millis();
 //ChangePalettePeriodically();

 //if data has been sent parse it
 if (Serial.available() > 0) {
 Serial.readBytesUntil('>', inputBuffer, 15);
 parseinput(inputBuffer);
 }
 static uint8_t startIndex = 0;
 if (loopCount % 64 == 0) {
 startIndex = startIndex + 3; /* motion speed */
 FillLEDsFromPaletteColors(startIndex);
 FastLED.show();
 FastLED.delay(positive((1000 / UPDATES_PER_SECOND) - (millis() - deltaTime)));
 }

 //calculates the amount of time all of the code took to run and takes that into account with the delay
 deltaTime = millis() - deltaTime;

 //Serial.println(deltaTime);

}

int positive(const int &input){
 if (input < 0) {
 return 0;
 }
}

void parseinput(const char *input) {
 if (memcmp(input, "hex", 3) == 0) {
 char index[3];
 //this meathod directly modifys the input c string
 getStringBetweenDelimiters(input, ":", ";", index);

 //stores a pointer so that it can iterate over the hex in the string
 char *p;
 p = strstr(input, ";") + 1;
 currentPalette[atoi(index)] = CRGB(
 //p is just a pointer and * gets the value of that memory address. So we add to the pointer to iterate over the array
 HextoByte(*p, *(p+1)), HextoByte(*(p+2), *(p+3)), HextoByte(*(p+4), *(p+5))
 );
 }
 Serial.println(1);
}


int getStringBetweenDelimiters(const char* string, const char* leftDelimiter, const char* rightDelimiter, char* out)
{
 // find the left delimiter and use it as the beginning of the substring
 const char* beginning = strstr(string, leftDelimiter);
 if (beginning == NULL)
 return 1; // left delimiter not found

 // find the right delimiter
 const char* end = strstr(string, rightDelimiter);
 if (end == NULL)
 return 2; // right delimiter not found

 // offset the beginning by the length of the left delimiter, so beginning points _after_ the left delimiter
 beginning += strlen(leftDelimiter);

 // get the length of the substring
 ptrdiff_t segmentLength = end - beginning;
 // allocate memory and copy the substring there
 //*out = malloc(segmentLength + 1);
 strncpy(out, beginning, segmentLength);
 (out)[segmentLength] = 0;
 return 0; // success!
}


/*
//will parse out all characters found from a starting index to a ending character to an int
int parseIntTillEndChar(const char *input, int startingindex, const char endchar) {
 //this creates a char pointer which is just a number that references memory
 const char *p;
 //p is now pointing to inputs memory address
 p = input;
 //we add to the memory address to get to the first index of the string
 p += startingindex;
 //creates another string to hold the number
 char intbuffer[4];

 //stores the index for iterating over string
 uint8_t index = 0;
 //checks for null terminator, the specified end character, or if the index got to high
 while (*p || *p != endchar || index > 2) {
 intbuffer[index] = *p;
 index++;
 }
 //parses the result to a int and returns it;
 return atoi(intbuffer);
}
*/

uint8_t HextoByte(char& x16, char& x1) {
 uint8_t decimal = HexLetterToNumber(x1) + 16 * HexLetterToNumber(x16);
 return decimal;
}

uint8_t HexLetterToNumber(char& x) {
 switch (x)
 {
 case('a'):
 return 10;
 break;
 case('b'):
 return 11;
 break;
 case('c'):
 return 12;
 break;
 case('d'):
 return 13;
 break;
 case('e'):
 return 14;
 break;
 case('f'):
 return 15;
 default:
 return int(x) - 48;
 break;
 }
}


void FillLEDsFromPaletteColors(uint8_t colorIndex)
{
 uint8_t brightness = 30;
 for (int i = 0; i < NUM_LEDS; i++) {
 leds[i] = ColorFromPalette(currentPalette, colorIndex, brightness, currentBlending);
 colorIndex += 4;
 }
}

Droid_22

Here is the serial class on the java side.
Code: [Select]

package ledServer;

import java.io.IOException;
import java.util.Scanner;

import com.fazecast.jSerialComm.*;

public class SerialCom {

private final String DEFAULT_PORT_NAME = "Arduino";
private String devicePortName;
private SerialPort arduinoPort = null;
private Scanner sc;

public SerialCom() {
devicePortName = DEFAULT_PORT_NAME;
initConnection();
}

public SerialCom(String DeviceName) {
devicePortName = DeviceName;
initConnection();
}

// used to attempt to connect after connection is lost or when initial
// connection fails
public void Reconnect() {
arduinoPort = null;
initConnection();
}

private void initConnection() {
// gets the amount of ports currently plugged in
int portCount = SerialPort.getCommPorts().length;
SerialPort serialPorts[] = new SerialPort[portCount];
serialPorts = SerialPort.getCommPorts();

for (int i = 0; i < portCount; i++) {

String portName = serialPorts[i].getDescriptivePortName();
System.out.println(serialPorts[i].getSystemPortName() + ": " + portName + ": " + i);

if (portName.contains(devicePortName)) {
arduinoPort = serialPorts[i];
arduinoPort.openPort();
System.out.println("connected to: " + portName + "[" + i + "]");
break;
}
}

if (arduinoPort != null) {
arduinoPort.setComPortParameters(19200, 8, 1, 0); // default connection settings for Arduino
arduinoPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0); // block until bytes can be written
sc = new Scanner(arduinoPort.getInputStream());
} else {
System.out.println("Could Not find arduino");
}
}

public void sendData(String data) throws InterruptedException  {
try {
//System.out.println(data);
arduinoPort.getOutputStream().write(data.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//sc.next line freezes all code until the Arduino has confirmed it has received the message
System.out.println(sc.nextLine());

}

public String ReciveData() {
return sc.nextLine();
}
}

Robin2

I am not familiar with the FastLED library but I think I read in some Threads that it disable interrupts and active interrupts are essential for Serial communication.

I suggest you do some tests at different baud rates without the FastLED library.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Droid_22

Interesting I guess I never really even considered that. I'll look into that, thank you!

Go Up