USB serial transfer incomplete / too fast?!

Status
Not open for further replies.

Lonestar

New member
Hello everyone!

i am new to electronics (bought a teensy to play with some weeks ago which is my first contact with microcontrollers etc.) and not a very good programmer.
Till now i managed to get everything working but i have no idea if it is even close to "good" or best practice. Maybe you eyes will bleed when you read what i coded so i warned you... :)

What i got is a Teensy 3.0 and a WS2811 LED Strip. The plan is to use the teensy with OCTOWS2811 just to control the LEDs (Using one strip right now. Will be 3-4 in the end i think). Then another application running on a computer will send serial data to the teensy over USB an tell it what color to set for a given LED.
Code follows so i hope you understand what i mean.

When seting the color of a single LED everything is fine. I used minicom to test it and it works (see below for problems with that). When using the c-program as i posted it, it just lights the first LED. I then experimented with some deplays in between the serial transmissions. When using usleep(8000); or higher it works for all LEDs. If i set a delay under 8000 some LEDs dont switch on. I used minicom again to check why and saw, that the data for that LEDs is not processed but discarded. I pasted the output at the bottom of this post. That is the point where i do not know any further :) Is it possible to send just as fast as the computer generates data? Why is that happening? A problem with teensycode oder the c-program?

Hope i'm in the right forum and you can help me :eek: (open for improvements as well!)
Thanks in advance!

Teensycode:
Code:
#include <OctoWS2811.h>

const int ledsPerStrip = 230;
DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];

const int config = WS2811_GRB | WS2811_800kHz;

OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);
int numLed; //what led is used
int RedLed; //one for each color
int GreenLed;
int BlueLed;

void setup() {                
   Serial.begin(9600); 
   leds.begin();
   leds.show();
}

void loop() {
   if (Serial.available()) {
     //look for some "headers" where usable data will follow
     if (Serial.peek() == 'n' || Serial.peek() == 'r' || Serial.peek() == 'g' || Serial.peek() == 'b' || Serial.peek() == 'w') {
       if (Serial.peek() == 'n'){
         Serial.read();
         numLed = Serial.parseInt(); //parse to int to set LED color with the value
         Serial.print("rNr.: "); //just to see if it did something 
         Serial.println(numLed); 
       }
       if (Serial.peek() == 'r'){
         Serial.read();
         RedLed = Serial.parseInt();
         Serial.print("rRed: ");
         Serial.println(RedLed);
       }       
       if (Serial.peek() == 'g'){
         Serial.read();
         GreenLed = Serial.parseInt();
         Serial.print("rGreen: ");
         Serial.println(GreenLed);
       }
       if (Serial.peek() == 'b'){
         Serial.read();
         BlueLed = Serial.parseInt();
         Serial.print("rBlue: ");
         Serial.println(BlueLed);
       }
       if (Serial.peek() == 'w'){
         
         leds.setPixel(numLed, RedLed, GreenLed, BlueLed); //set LED color
         leds.show();  
         Serial.read();
         
         Serial.print("Nr.: "); //print the whole color information of the current led
         Serial.print(numLed);
       
         Serial.print(" Red: ");
         Serial.print(RedLed);
       
         Serial.print(" Green: ");
         Serial.print(GreenLed);
       
         Serial.print(" Blue: ");
         Serial.println(BlueLed);
         Serial.flush();
       }
             
     }
     while (Serial.available()){
       Serial.print("Discard: "); // discard everything, that has no matching header
       Serial.println(Serial.read());
     }
   }
}

C Code
Code:
#include    <stdlib.h>
#include    <stdio.h>
#include	<unistd.h>
#include    <time.h>
#include    <termios.h>
#include 	<string.h>
#include	<fcntl.h> 
#include 	<errno.h>
#define BUF 255

void LightControl(int Number, int LedRed, int LedGreen, int LedBlue)
{
	int fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
	char sLedRed[BUF];
        char sLedGreen[BUF];
    char sLedBlue[BUF];  
	char sNumber[BUF];
	
	sprintf(sNumber, "n%d", Number);
	sprintf(sLedRed, "r%d", LedRed);
	sprintf(sLedGreen, "g%d", LedGreen);
	sprintf(sLedBlue, "b%d", LedBlue);
	
	write(fd, sNumber, strlen(sNumber));
	write(fd, sLedRed, strlen(sLedRed));
	write(fd, sLedGreen, strlen(sLedGreen));
	write(fd, sLedBlue, strlen(sLedBlue));
	write(fd, "w", 1);
	//usleep(8000); 
	close(fd);
}

int main()
{
	int i=0;
	int numLeds = 100;
	

	for (i=0;i<=numLeds;i++){
		LightControl(i,0,0,50);
	}
	
	sleep(2);
	for (i=0;i<=numLeds;i++){
		LightControl(i,0,0,0);
	}
	return 0;
}

Wiring:
teensy.jpg
Black cable is ground, connected to the LED strip ground via the white cable (is connected anyways because i use the psu of the same computer the teensy is connected to).

Code:
rNr.: 0
rRed: 0
rGreen: 0
rBlue: 50
Nr.: 0 Red: 0 Green: 0 Blue: 50
rNr.: 1
rRed: 0
rGreen: 0
rBlue: 50
Nr.: 1 Red: 0 Green: 0 Blue: 50
Discard: 110
Discard: 50
Discard: 114
Discard: 48
Discard: 103
Discard: 48
Discard: 98
Discard: 53
Discard: 48
Discard: 119
rNr.: 3
rRed: 0
rGreen: 0
rBlue: 50
Nr.: 3 Red: 0 Green: 0 Blue: 50
Discard: 110
Discard: 52
Discard: 114
Discard: 48
Discard: 103
Discard: 48
Discard: 98
Discard: 53
Discard: 48
Discard: 119
rNr.: 5
rRed: 0
rGreen: 0
rBlue: 50
Nr.: 5 Red: 0 Green: 0 Blue: 50
Discard: 110
Discard: 54
Discard: 114
Discard: 48
Discard: 103
Discard: 48
Discard: 98
Discard: 53
Discard: 48
Discard: 119
rNr.: 7
rRed: 0
rGreen: 0
rBlue: 50
57
Discard: 114
Discard: 48
Discard: 103
Discard: 48
Discard: 98
Discard: 53
Discard: 48
Discard: 119
Discard: 110
Discard: 49
Discard: 48
Discard: 114
Discard: 48
Discard: 103
Discard: 48
Discard: 98
Discard: 53
Discard: 48
Discard: 119
 
In non-blocking mode, your calls to write() on Linux are allowed to not actually transmit some or all of the data. If you can avoid O_NDELAY, do so.

If you really do need that mode, you'll have to write more complex code on the Linux side to check the return value from write() and attempt to transmit the data later.

Also, when you compile your code, you might use gcc's "-Wall" flag. That turns on warning messages. I believe one of those warnings will point out the lack of using write()'s return value.
 
Hi,

thanks for your reply!
I'm using "-Wall" but it does not return any warnings. :confused:

I tryed to just remove the O_NDELAY but nothing changed at all.

What i noticed is that the data seems to be transfered but skipped anyway.
When i compare the discarded data with an ASCII table it all seems okay... :confused:
eg.:
Discard: 110 -> n
Discard: 52 -> 4
Discard: 114 -> r
Discard: 48 -> 0
Discard: 103 -> g
Discard: 48 -> 0
Discard: 98 -> b
Discard: 53 -> 5
Discard: 48 -> 0
Discard: 119 -> w
which is exactly what i wanted to send
 
Status
Not open for further replies.
Back
Top