problems reading UART

Hello all,

I did a program in C using the Atmega328p to read the UART and screen some data within a lot of telemetry channel data, it works OK without problems. I transfered it to the Arduino environment making the modifications related with UART reading, but it doesn't work.

Your help is appreciated
Thanks
Manuel
The C code is the following:

 void USART()
{
 uint8_t sig[] = { 0x7E, 0xFD};
 data_count=0;

 	while (data_count<=46)
	{
	  
	  frame_count=0;

	  uint8_t read_sig = 0;

		while  (9 >= read_sig)
		{ 

   			while (!(UCSR0A & (1<<RXC0))) {} 
  		  	received_byte = UDR0;
	
	
			  if (read_sig < 2)
        		read_sig = received_byte == sig[read_sig] ? read_sig + 1:received_byte == sig[0];
			  else
				{
					switch (read_sig)
							{
							case 2 :
								frame_data=(received_byte);
								read_sig++;
								break;

							case 3:
								read_sig++;
								break;
							
							default:
								if (frame_data>=1)
									{
										frame_data --;
										GPS_data[data_count++]=received_byte;
										read_sig++;
									}
								else 
									read_sig=10;

								}

					}
			}
		}
}

The Arduino code is:

  void USART()
{
 
 uint8_t sig[] = { 0x7E, 0xFD};
 data_count=0;

 	while (data_count<=46)
	{
	 
	  frame_count=0;

	  uint8_t read_sig = 0;

		while  (9 >= read_sig)
		{ 
                    
   			 if (Serial.available()>0 ) 
                          
		          // read the incoming byte:
		          received_byte = Serial.read();
                           
		       
			  if (read_sig < 2)
        		     read_sig = received_byte == sig[read_sig] ? read_sig + 1 : (received_byte == sig[0] ? 1: 0);
			  else
				{
					switch (read_sig)
							{
							case 2 :
								frame_data=(received_byte);
								read_sig++;
								break;

							case 3:
								read_sig++;
								break;
							
							default:
								if (frame_data>=1)
									{
										frame_data --;
										GPS_data[data_count++]=received_byte;
										read_sig++;
                                                                                Serial.print(received_byte);
									}
								else 
									read_sig=10;

								}

					}
			}
		}
}

This isn't very helpful: "it doesn't work"

What does it do, or not do, that you would like to be done differently?

CrossRoads, thanks for your interest.

Below is the type of data I have to handle, each frame is 11 bytes long. "7E FE" is the data related with RSSI, battery voltage, etc. It is not user data. The "7E FD 06 14 B5 62 01 05 00 00 7E", "7E FD" is user data header, 06 indicates the number of bytes of user data in the frame, 14 is the frame number. What I want to do is pickup only the user frames, look for the number of user data bytes, forget the frame number, and store the user data.
Below is the row data, has a lot of zeros because the GPS is not FIX (I am inside of the house).

Your help is appreciated. I am a beginner in C and Arduino ( It is trial and error and reading the C book).

Thanks,
Manuel

7E FE 48 5E 5C C1 00 00 00 00 7E 7E FE 48 5F 5C C1 00 00 00 00 7E 7E FE 48 5F 5C C1 00 00 00 00 7E 7E FE 47 5E 5C C2 00 00 00 00 7E 7E FE 48 5F 5C C2 00 00 00 00 7E 7E FE 4B 69 5C C2 00 00 00 00 7E 7E FE 46 5D 5C C2 00 00 00 00 7E 7E FD 06 14 B5 62 01 05 00 00 7E 7E FD 04 14 00 00 00 00 00 00 7E 7E FE 48 5F 5C C1 00 00 00 00 7E 7E FD 06 15 00 00 00 00 00 00 7E 7E FD 04 15 00 00 00 00 00 00 7E 7E FE 47 5F 5C C2 00 00 00 00 7E 7E FD 06 16 00 00 00 00 00 01 7E 7E FD 04 16 00 00 00 00 00 01 7E 7E FE 48 5F 5C C2 00 00 00 00 7E 7E FD 06 17 07 A8 01 8C 53 03 7E 7E FD 04 17 0D 00 00 03 53 03 7E 7E FE 48 5F 5C C1 00 00 00 00 7E 7E FD 06 18 0D 01 33 0B C1 00 7E 7E FD 01 18 B5 00 00 00 C1 00 7E 7E FE 47 5F 5C C2 00 00 00 00 7E 7E FE 48 5F 5C C2 00 00 00 00 7E 7E FE

The real data should look like below:

B5 62 01 05 02 74 73 37 FF 7D 66 88 FF FF EB BF 00 00 00 C0 05 A1 9F 20 03 02 0C D2 ED B0 DD 00 01 89 51 03 35 00 00 03 34 01 43 0B C1 00 B5

the data I get with the Arduino is the following:

FD FD FD 06 07 B5 FD FD FD 04 07 00 FD FD FD 06 08 00 FD FD FD 04 08 00 FD FD FD 06 09 00 FD FD FD 04 09 00 FD FD FD 06 0A 07 FD FD FD 04 0A 0D FD FD FD 06 0B 0D FD FD FD 01 0B B5
read_sig = received_byte == sig[read_sig] ? read_sig + 1 : (received_byte == sig[0] ? 1: 0);

< awed silence >

I saw that line too, no idea how to interpret that! Apparently you do AWOL?

Apparently you do AWOL?

It took a while. I was humbled.

Care to share?

I'm joking - by itself as a line of code, not that difficult, but as part of an obfuscated C contest, it is most definitely a contender.

Thanks to all,

I do not understood what you mean. I have no problem to share more information. I didn't because I do not want to bother you with a lot of staff that may not be needed .
Please let me know what you want me to put here, or if i need to more clear.

Also I apologise for the way I put the data. I am going to put it correctly now.

The data is from a RC airmodel control with telemetry. The receiver in the airmodel has a USART input for user data like, GPS, Air Speed, Altitude, Rotations per minute, battery capacity, etc. and 2 8 bits analogue inputs that can be used for battery voltage measure. The system also allow to setup alarm levels in this analogue inputs. The data related with the analogue inputs, alarm levels, RSSI data, comes down in the frames with "7E FE" header. The "7E FD" is the data feed into the USART input.

A frame looks like this :7E FD 06 14 B5 62 01 05 00 00 7E, where "7E FD" is the header, "06" is the number of data bytes in the frame, "14" is the frame number, " B5 62 01 05 00 00"
are 6 byte of data, "7E" is the termination character.

I did the first program in C using an Arduino board with the ATmega without boot loader (I know a bit of assembly programing but I am a zero in C), but I didn't find a C library to use the
Nokia LCD 3310, so, I decided to go for the Arduino.

Please let if you need more information.

Thanks,
Manuel

The C code is below:

// CONSTANTS
#define F_CPU 16000000UL
#define USART_BAUDRATE_0 9600 
#define BAUD_PRESCALE_0 (((F_CPU / (USART_BAUDRATE_0 * 16UL))) - 1)

#define TICKSPERMS (F_CPU / 1000 / 5 - 1)




// LIBRARIES
#include <math.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))


static uint8_t GPS_data[46]={0x7E,0xFD};
volatile uint8_t received_byte;
volatile uint8_t data_count = 0;
volatile uint8_t frame_data=0;
volatile uint8_t frame_count=0;

//Functions
void USART();
void initialize_usart();



void initialize_usart() 
{
						// Set the USART for a baudrate of 38400
UBRR0L=BAUD_PRESCALE_0;   //Load the lower 8 bits of baude rate value into low byte 
UBRR0H=(BAUD_PRESCALE_0>>8); // load the upper 8 bits of the baude rate value
UCSR0B =(1<<TXEN0)|(1<<RXEN0); 							// turn the tranmition on
UCSR0C =(0<<USBS0)|(3<<UCSZ00);  //Set 8 Bits data 1 stop bit
}


/****************************************************************
* The USART1 reveives the data from the GPS. The data is in 
*binary format to be more compact. The data is to be send down
*using the RX link to the TX at a baudrate of 1200.*/

 void USART()
{
 uint8_t sig[] = { 0x7E, 0xFD};
 data_count=0;

 	while (data_count<=46)
	{
	  
	  frame_count=0;

	  uint8_t read_sig = 0;

		while  (9 >= read_sig)
		{ 

   			while (!(UCSR0A & (1<<RXC0))) {} 
  		  	received_byte = UDR0;
	
	
			  if (read_sig < 2)
        		read_sig = received_byte == sig[read_sig] ? read_sig + 1:received_byte == sig[0];
			  else
				{
					switch (read_sig)
							{
							case 2 :
								frame_data=(received_byte);
								read_sig++;
								break;

							case 3:
								read_sig++;
								break;
							
							default:
								if (frame_data>=1)
									{
										frame_data --;
										GPS_data[data_count++]=received_byte;
										read_sig++;
									}
								else 
									read_sig=10;

								}

					}
			}
		}
}

/**************************************************************
 Routine to print the data vector*/
void Print()
 {
  uint8_t i;

   for (i=0; i<=46; i=i+1)

	 {
	 	while (!(UCSR0A & (1<<UDRE0))) {} 

	 	  UDR0= GPS_data[i];
	 }
  }     



/**************************************************************
*/

int main()
{

       initialize_usart();

 for(;;)

	{
		USART();


		Print();


	}

Below is the Arduino sketch:

#include <PCD8544.h>


// A custom glyph (a smiley)...
static const byte glyph[] = { B00010100, B00100000, B00100000, B00100000, B00010100 };


static PCD8544 lcd;
char data=0;
int data_count=2;
uint8_t received_byte;
static uint8_t GPS_data[46]={0x7E,0xFD};
uint8_t frame_count;
uint8_t frame_data;


void setup() {
  // PCD8544-compatible displays may have a different resolution...
  lcd.begin(84, 48);
  Serial.begin(9600);

  // Add the smiley to position "0" of the ASCII table...
  lcd.createChar(0, glyph);

}


void loop() {
  // Just to show the program is alive...
  static uint16_t counter = 0;

  
 USART();

}
  void USART()
{
 
 uint8_t sig[] = { 0x7E, 0xFD};
 data_count=0;

 	while (data_count<=46)
	{
	 
	  frame_count=0;

	  uint8_t read_sig = 0;

		while  (9 >= read_sig)
		{ 
                    
   			 if (Serial.available()>0 ) 
                          
		          // read the incoming byte:
		          received_byte = Serial.read();
                           
		       
			  if (read_sig < 2)
                                   	   read_sig = received_byte == sig[read_sig] ? read_sig + 1 : (received_byte == sig[0] ? 1: 0);
                             
			  else
				{
					switch (read_sig)
							{
							case 2 :
								frame_data=(received_byte);
								read_sig++;
								break;

							case 3:
								read_sig++;
								break;
							
							default:
								if (frame_data>=1)
									{
										frame_data --;
										GPS_data[data_count++]=received_byte;
										read_sig++;
                                                                                Serial.print(received_byte);
									}
								else 
									read_sig=10;

								}

					}
			}
		}
}

Below is the row data. Each frame has 11 bytes. "7E FE" and "7E FD" are headers and "7E" is also the termination character. the "7E FD" header indicates user data.

7E FE 48 5E 5C C1 00 00 00 00 7E 7E FE 48 5F 5C C1 00 00 00 00 7E 7E FE 48 5F 5C C1 00 00 00 00 7E 7E FE 47 5E 5C C2 00 00 00 00 7E 7E FE 48 5F 5C C2
00 00 00 00 7E 7E FE 4B 69 5C C2 00 00 00 00 7E 7E FE 46 5D 5C C2 00 00 00 00 7E 7E FD 06 14 B5 62 01 05 00 00 7E 7E FD 04 14 00 00 00 00 00 00 7E 7E 
FE 48 5F 5C C1 00 00 00 00 7E 7E FD 06 15 00 00 00 00 00 00 7E 7E FD 04 15 00 00 00 00 00 00 7E 7E FE 47 5F 5C C2 00 00 00 00 7E 7E FD 06 16 00 00 00
00 00 01 7E 7E FD 04 16 00 00 00 00 00 01 7E 7E FE 48 5F 5C C2 00 00 00 00 7E 7E FD 06 17 07 A8 01 8C 53 03 7E 7E FD 04 17 0D 00 00 03 53 03 7E 7E FE 
48 5F 5C C1 00 00 00 00 7E 7E FD 06 18 0D 01 33 0B C1 00 7E 7E FD 01 18 B5 00 00 00 C1 00 7E 7E FE 47 5F 5C C2 00 00 00 00 7E 7E FE 48 5F 5C C2 00 00
00 00 7E 7E FE

the normal data with the GPS fix looks like this:

B5 62 01 05 02 74 73 37 FF 7D 66 88 FF FF EB BF 00 00 00 C0 05 A1 9F 20 03 02 0C D2 ED B0 DD 00 01 89 51 03 35 00 00 03 34 01 43 0B C1 00 B5

The data coming out of the Arduino;

FD FD FD 06 00 B5 FD FD FD 04 00 70 FD FD FD 06 01 F0 FD FD FD 04 01 00 FD FD FD 06 02 00 FD FD FD 04 02 00 FD FD FD 06 03 F6 FD FD FD 04 03 
0D FD FD FD 06 04 0C FD FD FD 01 04 B5 FD FD FD 06 05 B5 FD FD FD 04 05 70 FD FD FD 06 06 F0 FD FD FD 04 06 00

I suspect that this:

while (!(UCSR0A & (1<<RXC0))) {} 
received_byte = UDR0;

and this:

if(Serial.available()>0 ) 
// read the incoming byte:
 received_byte = Serial.read();

are a problem. It looks like the first one waits for a character to be read (I'm guessing) and the second one definitely doesn't. In the arduino case, you're processing the same character again and again until another one arrives. That code is hard to read and there may be other issues I didn't spot, but fixing that'll improve matters.

wildbill, thanks for your inputs.

You are right, this code waits for the input buffer to be full. This code is very similar as assembly code.

while (!(UCSR0A & (1<<RXC0))) {} 
received_byte = UDR0;

This code I do not know. I am almost a zero in C language as well as Arduino. I tried NewSoftserial without success.

if(Serial.available()>0 ) 
// read the incoming byte:
 received_byte = Serial.read();

If some one can help I will appreciate.

Thanks,
Manuel

Then this is the equivalent:

while(!Serial.available())
  ; // Do nothing until there is something to read  
received_byte = Serial.read();

Wildbill, thanks for your help. Its working. I didn't know that to get a chr was necessary to use the While. I thought that the "If Serial.available" was enough.

Thanks again.
Regards.
Manuel Silva