Write incoming byte from serial to array

Hi,

I have been working on this a long time and can't find the bug, maybe someone has a hint:

I am communicating with a controller, that receives serial commands and answers back. Both ways work. I can see the response from the controller by printing it to Serial with Serial.print(Serial.read());
But if I want to write the incoming byte to an array with the code below, I only get the first two bytes of the serial response written into the array.

//This is the part in the main loop:
char serialMessage[75];
...

 if(Serial.available())
  
    {
     ReceiveFromController();
   }

//....
// and here's the function that is supposed to write the serial input into an array for parsing:

void ReceiveFromController()
{ char serialChar;
   serialChar= Serial.read();
  Serial.print("Serial Char:");
  Serial.println(serialChar); // I can see all chars being printed out
  serialMessage[i] = serialChar;  // i is set to zero everytime I send something
  i++;
 Serial.print("Message");
 Serial.println(serialMessage); // this is only two bytes long, RL in this case. Should be 75 Bytes

//ParseString(); // I wish.....
}

I also tried to write the bytes into the array in the main loop, but without success....
Any ideas anybody ? I would appreciate your help....

Thanks,
Matt

Please post the whole code as that helps to understand and debug it.

things I saw based upon the posted code

//This is the part in the main loop:
char serialMessage[75]; [glow]assume its big enough[/glow] 

void ReceiveFromController()
{ 
   char serialChar = Serial.read(); [glow]changed this one[/glow]
  Serial.print("Serial Char:");
  Serial.println(serialChar); // I can see all chars being printed out

  serialMessage[i] = serialChar; [glow]where is i defined[/glow] as this function is called from another part i will be "undefined"
  i++;  
 Serial.print("Message");
 Serial.println(serialMessage); [glow]This string is not allways "closed correctly with a \0" so if the string is 75 long there is no room for the \0 ...?
[/glow]

Serial data arrives slowly. When you print, but don't try to collect and act on, one character at a time, you can't see that the data arrived over 75,000 (or more) executions of loop, with calls to the read function.

When you start to try to collect the data in an array, the slow nature of the serial transmission becomes very obvious.

You need to include start and end of packet markers in your data, and read until an end-of-packet marker has been received.

Search for "started && ended" for some code I posted that shows how to collect the serial data, over many iterations of loop, until the whole packet has been received.

Hello,

thanks for your answers. Unfortunately, it did not help so far.
I used some code from one of your examples, Paul, but the while loop seems to hang for some reason…

I’ll post the last setup and loop functions, as well as the receive function, which momentarily doesn’t do much… maybe you get an idea. Posting the whole code would be a little long, since it contains tons of arrays for serial commands sent to my controller, which in this case is a broadcast camera, connected via RS485 on the one side and a WIFlyShield on the other. I know that there are no hardware issues, since I can send and receive commands and responses, I just seem to be too stupid to put the response in an array for parsing. Also, there is one more problem. The camera sends 75 bytes, including two checksum bytes, which obviously are different for each setting of the camera. So could I just count the number of bytes, instead of waiting for an end character ? I’ve tried, but so far without luck…

void setup()
{
// SPI pin initialization
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK,OUTPUT);
  pinMode(CS,OUTPUT);
  digitalWrite(CS,HIGH); //disable device 
  pinMode(3,OUTPUT);
  digitalWrite(3,LOW);
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10); 

  Serial.begin(9600);
 // Serial.println("\n\r\n\rWiFly Shield Terminal Routine");
  if(SPI_Uart_Init()){ // Test SC16IS750 communication
  //  Serial.println("Bridge initialized successfully!"); 
  }
  else{ 
    Serial.println("Could not initialize bridge, locking up.\n\r"); 
    while(1); 
  }


}

void loop()
{
printWebpage();

 while(1) // Enter transparent terminal mode
  {
    if(SPI_Uart_ReadByte(LSR) & 0x01)
    { 
      polling = 1;
      i = 0;
      
      while(polling)
      {
        if((SPI_Uart_ReadByte(LSR) & 0x01))
        {
          incoming_data = SPI_Uart_ReadByte(RHR);
          //Serial.print(incoming_data,BYTE);
         Parse_Request(); // this DOES work
        }  
        else
        {
          polling = 0;
        }
      }

    }
    else while(Serial.available() > 0)
   {
       char incomingSerialData = Serial.read();
       if(incomingSerialData == 0x52)
       {
           started = true;
           index = 0;
       
       }
       else if(incomingSerialData == '@')
       {
           ended = true;
       }
       else if(started)
       {
           serialMessage[index] = incomingSerialData;
            
           index++;
          
       }
   }

   if(started && ended)
   {
       // Convert the string to an integer
      
          ReceiveFromCamera();
       // Use the value

       // Get ready for the next time
       started = false;
       ended = false;

       index = 0;
      
   }


    /*  select();
      spi_transfer(0x00); // Transmit command
     
      
      spi_transfer(incomingSerialData);
      deselect();
      
    */
  }
}



void ReceiveFromCamera()
{ 
  
  
//  char serialChar;
//
// 
//serialChar= Serial.read();
//Serial.print("Serial Char:");
//Serial.print(serialChar);
//serialMessage[l] = serialChar;
//l++;
Serial.println("Message");
Serial.println(serialMessage);

//ParseCameraString();
}

If anyone can put my head straight, I’ll appreciate it.
Thx,
Matt

Good answer, PaulS.

Sending raw data on the serial line is the worst thing one could do. I just can't believe the amount of people here that use no protocol whatsoever in serial communication control application.

I developed for my students a SAP (Simple As Possible) serial communication protocol. Just for fun, I implemented that protocol in a Arduino library and made it available in the French section.

If there is any interest (But I would be very surprised if so), I could elaborate on the protocol.

Hello Guyt,

unfortunately, the camera I am communicating to only sends raw data. There is a protocol, which for a camera response starts with an 'R', then sends a couple of status bytes and a load of other information like HD format, color values etc. and two checksum bytes. My problem is that whatever I do, except directly printing the received data out on serial, I seem to only receive two bytes. When printing to serial, I get to see the full data.
Also, if I print out the index, I can see it's being incremented correctly .
That's where I am stuck. The way I understand it, as long as there are bytes available in the buffer, they should be put in the array
by calling

serialMessage[i]= Serial.read();
 i++

.
So why does my serial Message come out with only two bytes, or in the above case, using Pauls code, just one, since the starting byte is not included in the message ? Do you have a link to your library, maybe if I take a look at it I might understand better ?

Thanks,

Matt

Without some idea what the data looks like, it’s hard to say where you err. For example, if you get binary data and later on you do a Serial.println(), your buffer will be written up to the first byte containing ASCII 0, at which point Serial.println() decides the work is done. That’s a very old C convention how to handle strings. Instead of Serial.println() try this as a debug code to get a better understanding what you’re dealing with:

void ReceiveFromCamera() {
Serial.print ("Number of characters: ");
Serial.println (index);

for (int i=0; i < index; i++) {
  if (i % 8 == 7) {
    Serial.println (serialMessage[i], DEC);
  }
  else {
    Serial.print (serialMessage[i], DEC);
   Serial.print (" ");
 }
}
Serial.println (" ");
}

And then look for 0 values and what else you get. Also compare index with the size off serialMessage. If it’s bigger, you have problem and need to increase the size of serialMessage.

All code is as usual totally untested.

Korman

[edit]Fixed the error Paul pointed out. A line was missing[/edit]

So why does my serial Message come out with only two bytes, or in the above case, using Pauls code, just one, since the starting byte is not included in the message ?

I think that Korman has the right idea. The data being retrieved from the camera is probably NOT all ASCII data.

Even if it were, your code would not print it properly, because you do not NULL terminate the array, after adding a character to it.

The code that Korman provided is meant to print the data 8 bytes per line, but looks to me to have a problem. Inside the if(i%8 ==7) block should be a Serial.println() statement, and the else block should not be conditional.

for (int i=0; i < index; i++)
{
  if (i % 8 == 7) // Output a carriage return/line feed after 8 bytes
     Serial.println();

  Serial.print (serialMessage[i], DEC);
  Serial.print (" ");
}

cameraobscura,

You did not mention (or I didn’t see) the length of the the data pack.

Two things:

  1. It’s fixed
  2. It’s variable

If the length is variable, the must be a byte count in the data pack.

Whatever it is, the solution is almost straightforward once one if familiar with callback functions.

If I had to do the job, my solution would end up looking like that:

#include <TCameraObscura.h>

void DataReceivedHandler(byte* data, int dataCount)
// Will be called automatically when a complete data pack
// has been received
{
   // your code
}


void setup()
{
  CameraObscura.setup(9600,DataReceivedHandler) ;
}

void loop()
{
  // do other things here
}

I could give you other hints if you want, I wrote something very similar.

Korman,

you hit the nail right on the head ! The array just has not been displayed since the third value is a zero.
It seems to be working now, thanks a lot guys for your help. I actually went back to a very simple solution

 incomingSerialData = Serial.read();
 serialMessage[index] = incomingSerialData;
 index++;

  if (index == 76)
{
        ReceiveFromCamera(); //parse the string, Checksum checking etc.
}

I would have spent ages without you. Guyt, nevertheless, I'd be interested in your solution. If I understood you correctly, you have a library that has a built in protocol for serial transmission ?

Korman, you hit the nail right on the head !

That's hardly surprising, as my head has been mistaken for nail already so often to be hit by similar problems, that I start to get the drift how to figure out those. In polite company this is referred to as experience. But it's no fun and life is more enjoyable without.

Korman

I would have spent ages without you. Guyt

I am note sure if I speak English well enough to see sarcasm when there is some, but it would fair play, I was rude with you.

My library can be found in this topic:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1290990435

Comments are in French , so it is not very useful for you. It was written for my students.

I will translate it when I have time. Who knows, one or two could be interested.

No hard feelings, I hope.

Guyt

I will translate it when I have time

Nice test for Google translate :slight_smile:

cameraobscura,

I started to document my library here:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1291693709/0#0

I should get to what interests you in 2 or 3 days.

Salut!

ps: you may try the translator on my personal blog that got an award for the most ridiculous windsurfing blog on the net, specially when read with a translator: