Serial.read to char[9] buffer not working?

Hi there, im completly new here, so please be patient with my english and myself :drooling_face:

I am building an audio vu meter consisting of 2 attiny2313 and 1 attiny85,
the attiny85 analyzes 3 analog inputs (left,right,sensitivity) and give these informations via softserial @9600 to the two attiny2313.
then the attiny 2313 takes the information and drives 12 LEDs acording to the information.

now to my original problem:
the serial data from the attiny85 comes every 2 ms in form of “R20472047*” while :
the first letter defines the color,
the next 4 byte define the leds (convertet to binary) on the left side
and the last 4 byte the leds of the right side

when i disconnect the atmega 386 from the uno board i can check the serial signals comming from the attiny and the seem just fine,
so the sending code works defenetly.

the problem is the receiving code. testing it with the uno first, i cant get write the serial.read to a char array
( string is to big in space as the attiny2313 just have 2k memory)

it simply wont write anything to the input. the funny thing is, that if i watch the counter via serial, it just counts to 1 and does not increas, although the line must be executet.

here is my code so far:

char input[9],L[4],R[4];  // buffer for the readings
char current;    // buffer for readed byte
boolean lineComplete = false,sol=false,red; //bool for line complete, start of line, and color status
//String debug="";     //debug string for testings

void setup() {
  Serial.begin(9600);   //start serial connection
}
 void loop() {
  int c=0;        //counter for the reading process
  memset(input, 0, sizeof input);   //clear input
while ( (Serial.available()) && (c<=30) && (!lineComplete) )//wait till something is received
{
  current = Serial.read();                                  // read current byte
  if (current == 'R'||current == 'B'&&sol==false)           //checking if first byte is read
  {   
     sol=true;             //activate start of line    
  }
  if (sol==true)           // did the start of the line already come?
  {  
     input[c] = current;  //write the byte to the buffer
     c=c+1;                //increase counter by one
     //debug +=c;          //c first thought c not counting?
  }    
  if (current == '*'&&sol==true)         //check if the end of line sign (*) is in buffer
  {   
     Serial.flush();
     input[c]='\0';                      // null terminate the array
     lineComplete = true;                // seting the line complete string                
     sol=false;                          // reset the start of line flag
  }
}
if (lineComplete) {                  //is the line complete ?then this shows the data,or at least it should
//Serial.println(debug);                
Serial.print("complete:");
Serial.println(input);
debug="";
lineComplete = false;                //reset the line complete
 c=0;                                // reset the counter
}
//Serial.println("end of code");
}

it seems like the serial data is not received corectly, but if i just send the received curent to the serial, every seems to be received.

help anyone? T_T

I would prefer to keep the normal serial port of the Uno for the Arduino serial monitor and to upload sketches.

Use SoftwareSerial, to create a serial port on other pins. http://arduino.cc/en/Reference/SoftwareSerial After that you can send debug messages to the serial monitor, so you know what is going on. Could you make a simple sketch ? For example just copy the stream. If a character is available on the SoftwareSerial port, send it to the normal serial port. Check in the serial monitor is everything is received.

Why do you use "Serial.flush()" ? I think the code could be a little simpler, just disregard any message that is not according to the format. I would also prefer a single buffer, with a specific size. The array "input" confuses me.

You could use sscanf() to get the numbers from the R20472047* format. Or atoi(), but you need to make two seperate zero terminated strings for that.

for real o_O the softwareserial just reads everything fine!is it due to the arduino terminal? cause i cant implement the softserial to the attiny as it would be to big.

the simple sketch, sending everything back it receives works even with the hardware serial, but it would not let me save what it sends back to an char array although its printing just fine.

anyway, thanks ^^ the code for seperating the iformations and converting it to binary is already here, the only problem was the serial reading. lets see if itll work on the attiny and if i will be able to shrink the sketch so everything fits.this problem did drive me nuts for 2 weeks already XDD

many thanks till now :grin:

You have got the grounds all connected together I suppose ?

jup, common ground for the attinys and atm for the uno . the leds are connectet through darlington arrays.

you mean thats a reason why i got such strange serial readings?

the softserial solution on the uno works btw, got the test code up and running, now i just need to wait for the leds for the final implementation.

I don't know your setup there, but I use a lot of LED display projects, and the main cause of odd behaviour is poor grounding on the LED returns, ( and evidently people using several Arduino/similar , poor grounding between the sections ) I just thought I would mention it as a thing to tick off,

Good luck

Okay, everythings working quite good now, only problem, the sketch is ~200byte to big XD any ideas i can shrink it down a bit? i thought of an Serial receive only lib in exchange for the standart one. ich shrinked the code as good as i could. here is the complete code:

#define LEDanzahl 12
char LED[12]={2,3,4,5,6,7,8,9,10,11,12,13};
boolean LEDR[12]={true,false,true,false,true,false,true,false,true,false,true,false};
boolean LEDL[12]={true,false,true,false,true,false,true,false,true,false,true,false};
char sourceL=14,sourceR=15;// outputpins für LEDsource

boolean lineComplete = false,sol=false,red; 
char input[10];
unsigned short numbL,numbR;

void setup() {  Serial.begin(9600);}
 void loop() {
  byte c=0;
while ( (Serial.available()) && (c<=30) && (!lineComplete) )
{
 char current = Serial.read();                                 
  if (current == 'R'||current == 'B'&&sol==false)              
  {   
     sol=true;                                           
     if (current=='R'){
     sourceL=16;
     sourceR=17;}
     else{
     sourceL=14;
     sourceR=15;}  
  }
  if (sol==true)                                         
  {  
     input[c] = current;                                         
     c++;                                                 
  }    
  if (current == '*'&&sol==true)                               
  {   
     input[c]='\0';                                              
     sol=false;                                                  
     if (c==10){lineComplete = true;  }     
     c=0;                                                        
  }
}
if (lineComplete) {                                                            
lineComplete = false;                                            
char R[4];                                                      
strncpy(R, input+1, 4);
numbL=atoi(R);
strncpy(R, input+5, 4);
numbR=atoi(R);

for (byte i=0; i<LEDanzahl; i++) {
    LEDL[11-i] = bitRead(numbL, i);}
for (byte i=0; i<LEDanzahl; i++) {
    LEDR[11-i] = bitRead(numbR, i);}

      for(byte i=0;i<LEDanzahl;i++) 
      {
      if (LEDL[i] == true){digitalWrite(LED[i], HIGH);}
      else{digitalWrite(LED[i], LOW);} 
      }
      digitalWrite(sourceL, LOW); 
      delay(1);
      digitalWrite(sourceL, HIGH);      
      for(char i=0;i<LEDanzahl;i++) 
      {
      if (LEDR[i] == true){digitalWrite(LED[i], HIGH);}
      else{digitalWrite(LED[i], LOW);}
      }
      digitalWrite(sourceR, LOW); 
      delay(1);
      digitalWrite(sourceR,HIGH);
         
}

}

I'm curious how you did this. Is that the code for the ATtiny2313 with only 2k flash ? Did you use an Arduino compatible library ? The bitRead() is perhaps only a macro. But the digitalWrite() is perhaps a function, while a macro for a single instruction would be fine. How did you compile for the ATtiny2313 ? Did you test some aggressive optimizations ? Like the "whole-program" and "rename-registers" optimizations ?

I'm curious how you did this.

curious i did what? ^^°

Is that the code for the ATtiny2313 with only 2k flash ? Did you use an Arduino compatible library ?

jup it is, there is an ATTINY core for the attiny 44,84,45,85,2313,4313 for the arduino IDE, so basicy its an arduino bootloader, and its able to do almost all the arduino is capable too, at least i think so. till now i build some projects using the 8pin attiny85, mainly a controll for the RF module of an old 360, a model of the sonicscrewdriver(dr. how) and a macro controll for an 360 controller. the 2313 got a lot of pins and supports serial communication per hardware. the 85 only support soft serial, but therefor it got 8 kb of flash. they all can run up to 20 MHz with external crystal, but i let them run on 8 mhz interlan. also, they are much cheaper and smaller than an arduino. (1,5€per chip)

The bitRead() is perhaps only a macro. But the digitalWrite() is perhaps a function, while a macro for a single instruction would be fine.

okay, that was a bit to high for me ^^° i am not THAT expirienced

How did you compile for the ATtiny2313 ?

as i said, attiny cores for the arduino IDE.

Did you test some aggressive optimizations ? Like the "whole-program" and "rename-registers" optimizations ?

and again i dotn know what you mean by that, but i will google it ;-D

Thanks for the info. I have used ATtiny chips, but not the ATtiny core. This is the ATtiny core, http://code.google.com/p/arduino-tiny/ ?

If you would use the avr gcc compiler, you have full control with compiler options. With the ATTINY core you are stuck with the options that are included in it.

I think those 200 bytes might be a real problem ! There is a lot going on for just a ATtiny2313: Serial, atoi, strncpy, digitalWrite.

You do not need the extra arrays of Boolean. Rather, just use the bits from the numbers:

#define LEDanzahl 12
byte LED[]={ 2,3,4,5,6,7,8,9,10,11,12,13};

byte source[] = {14, 15};// outputpins für LEDsource

boolean lineComplete = false,sol=false,red; 
char input[10];
unsigned short numb[2];

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

void loop() {
  byte c=0;
  while ( (Serial.available()) && (c<=30) && (!lineComplete) )
  {
    char current = Serial.read();                                 
   
    if (current == 'R'||current == 'B'&&sol==false)              
    {   
      sol=true;                                           
      if (current=='R'){
        source[0]=16;
        source[1]=17;
      }
      else{
        source[0]=14;
        source[1]=15;
      }  
    }
    if (sol==true)                                         
    {  
      input[c] = current;                                         
      c++;                                                 
    }    
    if (current == '*'&&sol==true)                               
    {   
      input[c]='\0';                                              
      sol=false;                                                  
      if (c==10){
        lineComplete = true;  
      }     
      c=0;                                                        
    }
  }

  if (lineComplete) {  
    lineComplete = false; 

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

      numb[i] = 0;

      for (int j=0; j < 4; j++) {
        numb[i] = numb[i] * 10 + input[1 + i * 4 + j];
      }

      for(byte j=0; j<LEDanzahl; j++) 
      {
        digitalWrite(LED[j], bitRead(numb[i], 11-j) ? HIGH : LOW);
      }

      // What are these 3 lines of code for?
      digitalWrite(source[i], LOW); 
      delay(1);
      digitalWrite(source[i], HIGH);  
    }
  }
}

the extra lines are for switching the side, i use 12 pins for the leds, and 2 for switching the source, so more or less i am multiplexing the 12 leds so i can get a total of 24 leds, 12 for each channel.

it first writes the output for the left channel to the pins,
pull the sourcepin for left low,
delay for 1 or 2 ms to show,
pull the sourcepin for left high and do the same instantly with the right side.

the eye is to slow to see that actuly only 12 of the leds are on at a time.
so it looks like all 24 are on.

btw, i found some things i could save some space. first, thanks for the idea with the bitread. saved me about 150byte. i saved the rest by removing the array with the pins and rather defining them ;-D

still seem to got a counter problem when using internal serial of the uno, so when i cativate the internal serial it receives data, but the counter c never counts up, although it still accses the line where it should count c up about 10 times. still c is always 1. im going to sleep, will try the code on he actual hardware tomorrow. thanks everyone ^^

here is my code.1.996 of 2.048 kbyte XD

#define LEDanzahl 12
byte sourceL=14,sourceR=15;
boolean lineComplete = false,sol=false,red; 
char input[10];
unsigned short numbL,numbR;

void setup() {  Serial.begin(9600);}
 void loop() {
  byte LED[12]={2,3,4,5,6,7,8,9,10,11,12,13};
  byte c=0;
while ( (Serial.available()) && (c<=30) && (!lineComplete) )    
{
 char current = Serial.read();      Serial.print(current);                            
  if (current == 'R'||current == 'B'&&sol==false)               
  {  Serial.print("Sol"); 
     sol=true;                                                  
     if (current=='R'){
     sourceL=16;
     sourceR=17;}
     else{
     sourceL=14;
     sourceR=15;}  
  }
  if (sol==true)                                                 
  {  
     input[c] = current;                                         
     c++;                                                        
  }    
  if (current == '*'&&sol==true)                                 
  {   Serial.print(c); 
     input[c]='\0';                                              
     sol=false;                                                  
     if (c==10){lineComplete = true; }
   c=0;                                                               
  }
}
if (lineComplete==true) {        
Serial.print("endol"); 
lineComplete = false;                                            
char R[4];                                                      
strncpy(R, input+1, 4);
numbL=atoi(R);
strncpy(R, input+5, 4);
numbR=atoi(R);

      for (byte i=0; i<LEDanzahl; i++) {LED[11-i] = bitRead(numbL, i);}
      digitalWrite(sourceL, LOW); 
      delay(1);
      digitalWrite(sourceL, HIGH);      
      for (byte i=0; i<LEDanzahl; i++) {LED[11-i] = bitRead(numbR, i);}
      digitalWrite(sourceR, LOW); 
      delay(1);
      digitalWrite(sourceR,HIGH);         
}
}

Erdin: Thanks for the info. I have used ATtiny chips, but not the ATtiny core. This is the ATtiny core, http://code.google.com/p/arduino-tiny/ ?

If you would use the avr gcc compiler, you have full control with compiler options. With the ATTINY core you are stuck with the options that are included in it.

I think those 200 bytes might be a real problem ! There is a lot going on for just a ATtiny2313: Serial, atoi, strncpy, digitalWrite.

almost forgot to awnser, yes thats the core ^^. i use it cause i never did anything else beside working with arduino, i mean in the corner of the microcontrollers. yeah, the attiny will have to work quite a lot, and i think i could make it much more efficient with assambler or something like that, but i want to use arduino cause its simple for me to understand(more or less) and i want to use it because i got just one wire for data comunication between the chips.

the whole project is an multifunktional wireless headset for gaming, dj-ing and the like.i know its not "usefull" to have a visualizer on a headset, but hey, does this matter? ;-D bicolor Leds are already installed, 24 on each side

thanks for now and good night ^_^

The strncpy does not close the string with a zero terminator if the maximum size is reached.

Calling the delay() function costs 200 bytes. Can you do without delay() ?

I can get 80 bytes smaller code in this part:

// Format: R20472047*
// Old code:
//       char R[4];             // should be 5 for extra '\0'
//       strncpy(R, input+1, 4);  // '\0' should be added !
//       numbL=atoi(R);
//       strncpy(R, input+5, 4);  // '\0' should be added !
//       numbR=atoi(R);
// Reduce size by string manipulation in the string itself.
// First the second half of the string is processed,
// because the string is changed after that to process
// the first half.
numbR = atoi( input + 5);       // the atoi will stop at the '*'
input[5] = '\0';              // break the string in the middle.
numbL = atoi( input + 1);      // atoi with the first half of string.

okay, this saved me 80 byte more space, great ^^ only problem, ive got the feeling that the usart is not working, i cant seem to get it to work on the attiny 2313... i wrote a very simple test program from the blink example. the blinking works just fine, but if i add a "while serial.available" it still blinks even if there is no serial connectet. so it seems this wont work..... U_U

but it didnt work on the uno either, not as long as i used the internal usart. it first worked fine when i used the SoftwareSerial lib. but this one is to big for the litle chip.

i didnt want to buy extra 4313 just for this project, but im almost out of ideas. it worked so fine using the uno...... i still got 3 attiny 44 laying around here, they would be small enough, but i cant controll 24 leds from one, not enough pins. i would need at least 16. pins for this, an i dont want to add serial multiplexer...

damn, much harder than i thought ^^°

That TINYCORE serial code should work on a ATtiny2313. Does this help, http://arduino.cc/forum/index.php/topic,139695.0.html ?

Are you sure the clock is set correct in hardware and software, so the baudrate is correct ?

okay, got the serial read to work, and it seems to read the input, i wrote little program that just activates a led if it reads a B, my attiny85 is sending in the format B40284028* and the led starts to flicker as it reads, so it seems to get the serial code just fine, but still its not doing anything else....maybe it wont complete the loop? i will test it and report back soon ^^ im getting near....

i was still curios what the 2313 receives, because it didnt always react to my signal send over terminal, so i wrote a small code that just print what it receives:

void setup() { 
Serial.begin(9500);
}
void loop() 
{  
   Serial.println(Serial.read());
}

it always receives this, evin if ther is nothing connectet to the input.

Kj
Kj
Kj

and if i send "hello world" i get

Kj
L¢
¡º
¡?8C¡?1C!j
j
j
j
j
Ój
j
j
j
MH0C¡j
j
LH1Sj
¦H1NSH1?
¡¢9C¡Â1C¡ª2C¡Â1C¡ª1C!j
L?j
SH4C¡?j
Kj
Kj

the funny thing is, that it seems to send and receive the endline just fine.

im not shure if its a baudrate problem is, as the attiny 2313 is running at 8 MHz with a baud at 9600 and the monitor ist connected to its rx and tx pins ( uno board with disconnected 328)

it cant be the terminal, as i receive the data from the attiny 85 just fine!(also running at 8 MHz with 9600 Baud...)

i am realy out of ideas.... i even replaced the hardwareserial.cpp in the core files with the one from this post, (although there the problem was not compiling) and still nothing....

I can be explaned, but it takes three problems.

(1) You can't read something if nothing is available. (2) You have to specify that it is a character, otherwise the type might be converted to an integer. (3) A wrong baudrate could be the third explanation. Can you check again how the baudrate is set for a certain cpu clock.

void loop() 
{  
  if (Serial.available() != 0)
  {
    Serial.print( (char) Serial.read());
  }
}

okay, i think i found the culprit, i used the attiny 2313 with internal clock set to 8 Mhz and i thought it would be perfekt, but i testet a little further with this code:

void setup() { 
Serial.begin(9300);
}
void loop() 
{  
  if (Serial.available() != 0)
  {
    //Serial.print( (char) Serial.read());
    Serial.println("hallo welt,ja ich bin da!");
  }
  Serial.flush();
}

and guess what, with a baudrate set to 9600 my terminal just receives garbage. if i set it to at a value between 9300 and 9400, it receives the text just fine,but without the line end. so i guess the internal clock of the 2313 is not too acuarate and thats producing all the problems i got. most likly the final code for the project is completly fine, and its just that the 2313 is not receiving the data from the 85 correctly. though the internal clock of the attiny85 seems just fine.

anyway, i will try to add a 8 MHz to the 2313. but i dont know how to configurate the arduino bootloader to run at 8 MHz and use an external 8mhz crystal. read a lot about fuses, but found it quite CONfuseING XD, maybe i will figure it out.

thanks for all the help and your patience with me ^^