Arduino-Arduino Serial Communication Errors

Hey Guys,

I'm new to Arduino and having a great time fiddling with the units - a really awesome initiative!

Now here comes my first question - I'm trying to get two Arduino Mega's to communicate with one another using the SoftwareSerial (NewSoftSerial) library and I'm running Arduino 0023. The first Mega is being used as a data acquisition device from various sensors then it sends a string of data to the other Mega which has a 3.5" OLED display that displays all those variables. The first Mega is sending this to the other:

void TS_SendDataPacket( )
{
  TS_Serial.print( STX, BYTE );

  TS_WriteInt( valMPH );
  
  TS_WriteLong( valODO );
  
  TS_WriteInt( valTripA );
  TS_WriteInt( valTripB );

  TS_WriteInt( valGPSPulse );
  TS_WriteInt( valSpareInt );
  
  TS_WriteInt( valTimeHH );
  TS_WriteInt( valTimeMM );
  
  TS_WriteInt( valDateMonth );
  TS_WriteInt( valDateDay );
  TS_WriteInt( valDateYear );
  
  TS_WriteInt( valTemp );
  TS_WriteInt( valBatt );
  TS_WriteInt( valLean );
  
  TS_WriteLong( valHeading );
  TS_WriteInt( valLatDegrs );
  TS_WriteLong( valLatFrac );
  TS_WriteInt( valLatNS );
  
  TS_WriteInt( valLonDegrs );
  TS_WriteLong( valLonFrac );
  TS_WriteInt( valLonEW );


  TS_WriteInt( valVegPresFuel );
  TS_WriteInt( valCurrentFuel );
  TS_WriteInt( valValveFail );
   
  TS_WriteInt( valHETemp );
  TS_WriteInt( valIPTemp );
  
  TS_WriteInt( valCoolant );
  TS_WriteInt( valOilTemp );
  TS_WriteInt( valOilPres );
  TS_WriteInt( valGBTemp );
  TS_WriteInt( valTCTemp );
     

  TS_Serial.print( ETX, BYTE );
}

That seemed to work all well and good until I added the last 3 vars (OilPres, GBTemp, TCTemp). The OLED display just isn't receiving those variables, though it's getting everything else fine.

Here's the touchscreen code:

  while( Serial.available( ) >= 60  )
  {
    if( Serial.read( ) == STX )
    {
      valMPH = AR_ReadInt( );

      valODO = AR_ReadLong( );

      valTripA = AR_ReadInt( );
      valTripB = AR_ReadInt( );

      valGPSPulse = AR_ReadInt( );
      valSpareInt = AR_ReadInt( );

      valTimeHH = AR_ReadInt( );
      valTimeMM = AR_ReadInt( );

      valDateMonth = AR_ReadInt( );
      valDateDay = AR_ReadInt( );
      valDateYear = AR_ReadInt( );

      valTemp = AR_ReadInt( );
      valBatt = AR_ReadInt( );
      valLean = AR_ReadInt( );

      valHeading = AR_ReadLong( );
      valLatDegrs = AR_ReadInt( );
      valLatFrac = AR_ReadLong( );
      valLatNS = AR_ReadInt( );

      valLonDegrs = AR_ReadInt( );
      valLonFrac = AR_ReadLong( );
      valLonEW = AR_ReadInt( );
      
    
      valVegPresFuel = AR_ReadInt( );
      valCurrentFuel = AR_ReadInt( );
      valValveFail = AR_ReadInt( );    
      valVegHETemp = AR_ReadInt( );
      valVegIPTemp = AR_ReadInt( );
      
      valCoolant = AR_ReadInt( );      
      valOilTemp = AR_ReadInt( );
      valOilPres = AR_ReadInt( );
      valGBTemp = AR_ReadInt( );
      valTCTemp = AR_ReadInt( );

I'm at a bit of a loss here because Serial.available() won't exceed 63, even if I send more data from the first Arduino. I would assume that this is the issue, either the serial buffer isn't filling up, or it's not returning it's entire contents to the Arduino.

Any ideas guys?

Thanks Alex

Now here comes my first question - I'm trying to get two Arduino Mega's to communicate with one another using the SoftwareSerial (NewSoftSerial) library and I'm running Arduino 0023.

Why? The Mega has 4 hardware serial ports. NewSoftSerial does not work on the Mega.

  while( Serial.available( ) >= 60  )

This is a really bad way to read the data. What will happen is that it will not enter the while loop to read the data until there are at least 60 characters in the buffer. It will then enter the while statement and, if the first char is STX (presumably it is), read at least 60 characters. But you aren't guaranteed that there are any more than 60 so the rest of them may not be there yet. So, presumably, the last few variables are read as -1 (at least, that's what Serial.read returns if there's no data). Then you exit loop() and come back in and some of the remaining characters might be in the buffer. But the buffer has less than 60 chars so nothing happens after that (unless you send another batch).

Pete

el_supremo:   while( Serial.available( ) >= 60  )

This is a really bad way to read the data. What will happen is that it will not enter the while loop to read the data until there are at least 60 characters in the buffer. It will then enter the while statement and, if the first char is STX (presumably it is), read at least 60 characters. But you aren't guaranteed that there are any more than 60 so the rest of them may not be there yet. So, presumably, the last few variables are read as -1 (at least, that's what Serial.read returns if there's no data). Then you exit loop() and come back in and some of the remaining characters might be in the buffer. But the buffer has less than 60 chars so nothing happens after that (unless you send another batch).

Pete

I see, so what do you recommend?

I'm pondering that :-) Might take a while.

Pete

I see, so what do you recommend?

I recommend that you read reply #1. If necessary, read it again and again until it sinks in.

PaulS:

I see, so what do you recommend?

I recommend that you read reply #1. If necessary, read it again and again until it sinks in.

I’ve moved the communications from the SoftwareSerial (NewSoftSerial) ports over to one of the 4 serial ports on the Mega. I’m still having the same issue- the buffer is only receiving 63bytes then nothing. How can I go about this and is there a better alternative to While ( Serial.available >= [i]EXPECTEDBYTECOUNT [/i]) ??

How can I go about this and is there a better alternative to

Of course there is. You should not wait for all the data to be in the buffer before you read any data. If there are supposed to be a fixed number of bytes sent, you are screwed.

Serial data is not guaranteed to be delivered. There are any number of reasons why a byte could be lost. Relying on a specific number of bytes is not a good idea. A combination of start and end markers, a length value in the packet, and a check sum is required to assure that a packet is received as sent.

However, if you want to assume that nothing will ever get lost, you have two choices. Either set up a while loop that blocks until that number of bytes has arrived, reading them as fast as they arrive, or read whatever is available on each pass through loop, and do something with the data only when the expected number of bytes has arrived.

In the snippet of code you posted for the sender, you are not expecting to send a fixed number of bytes. You are sending start and end markers (though what they are is hard to tell).

If you were sending ASCII data, you could use code like this to receive it:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

You could easily adapt that to read binary data, if that is what is being sent.

The key is to read whatever is available on each pass through loop, doing nothing until all the data has arrived.

Modifying that code to read binary data would simply require that you change the type of inData from char to byte, then where it says “Process the packet”, call a function that extracts data from inData instead of the serial port. You AR_Read functions would need to be modified.

the buffer is only receiving 63bytes then nothing

That’s not the problem. As I mentioned, it is reading the first 63 bytes or so. While you’re processing those 63, the rest of them arrive. When you come back into loop() you have 9 characters in the buffer but the “if” statement won’t process less than 60 at a time.

The really quick and dirty fix is to change the number in the if statement to exactly the number of characters in a packet which, if my math is correct, is 72 including the ETX at the end. IIRC on a MEGA this won’t be a problem because the buffer is 128 bytes.

A much better solution is to handle the bytes for each variable as they arrive using a table to describe the number of bytes in the variable and its address.
The following code is for the receiving end. You have to complete the missing info from the data_tab table.

struct dtype {
	int length;
	void *addr;
};
// Note that this doesn't care what the datatype actually is.
// You can transmit/receive floats and doubles as well
// The only important restriction is that the transmitter and receiver both
// handle the datatypes in the same way on cpus which have the same
// "endian" characteristic. i.e. both big-endian or both little-endian
struct dtype data_tab[] = {
	// The first entry MUST have a length of zero, which indicates that we
	// must look for the STX here. The address can be anything including NULL.
	0,NULL,
	// Now a list of the variables in the order in which they are received
	// with their length in bytes and their address
	sizeof(valMPH),&valMPH,
	sizeof(valODO),&valODO,
// you can fill in the rest here ...
//	.
//	.
//	.
//	.
	sizeof(valGBTemp),&valGBTemp,
	sizeof(valTCTemp),&valTCTemp,
	// And now the end of table marker which MUST have a length of -1
	// and signals that we must now read the ETX
	-1,NULL
};

int tab_idx = 0;

void setup()
{

}

void loop()
{
	unsigned char *dp;
	// If there are no chars in the buffer there's nothing to do
	if(Serial.available() <= 0)return;
	// (we could actually test here for tab_idx == 0)
	if(data_tab[tab_idx].length == 0) {
		// Look for STX
		// if it is not found, just return and keep looking
		if( Serial.read( ) != STX )return;
		// if it is found move tab_idx to the first element in the structure array
		tab_idx++;
		return;
	}
	if(data_tab[tab_idx].length == -1) {
		// Look for ETX.
		// If it is not found, give up on what we have so far
		// and start all over again.
		if( Serial.read( ) != ETX ) {
			tab_idx = 0;
			return;
		}
		// reset for the next packet
		tab_idx = 0;
		// At this point we have read a valid packet and stored all the data
		// do whatever you like with the info - e.g. display it on an LCD
//		.
//		.
//		.
		return;
	}
	// Now we process each of the variables. To do this we wait until
	// there are at least as many bytes available as we need
	// so that, at most, we wait for 8 chars (for a "double")
	while(Serial.available() < data_tab[tab_idx].length);
	
	// Now we know there are as many chars as needed, so store them
        dp = (unsigned char *)data_tab[tab_idx].addr;
	for(int i = 0;i < data_tab[tab_idx].length;i++) {
		*dp++ = Serial.read();
	}
	// Now that we've read that one, step the index to the next one
	tab_idx++;
}

The code compiles on my Duemilanove but I can’t test it at the moment.

The transmitting code can be changed to use the structured array as well in which case the entire structure definition would be put in a .h file which is then included by the transmitter and receiver code.
The advantage to this is that if you need to add (or even remove) data to the transmission, all you have to do is add its definition to the table, recompile both programs, and then they are both configured to handle the new data stream.

Pete

IIRC on a MEGA this won't be a problem because the buffer is 128 bytes.

Not in 1.0. In 1.0, the buffer size is 32 bytes.

Ah, that is a problem, in which case my code should alleviate it.

Pete

Hey PaulS and Pete, thanks so much for your support and Pete cheers for the code mate. I've just tried to run it and it seems I'm getting some datatype errors:

Carputer_Arduino:221: error: cannot convert 'long int*' to 'int*' in initialization
Carputer_Arduino:221: error: cannot convert 'long int*' to 'int*' in initialization
Carputer_Arduino:221: error: cannot convert 'long int*' to 'int*' in initialization
Carputer_Arduino:221: error: cannot convert 'long int*' to 'int*' in initialization
Carputer_Arduino:221: error: invalid conversion from 'int' to 'int*'
Carputer_Arduino:221: error: invalid conversion from 'unsigned int' to 'int*'
Carputer_Arduino:221: error: invalid conversion from 'int*' to 'int'
Carputer_Arduino:221: error: invalid conversion from 'unsigned int' to 'int*'
Carputer_Arduino:221: error: invalid conversion from 'int*' to 'int'
Carputer_Arduino:221: error: invalid conversion from 'unsigned int' to 'int*'
Carputer_Arduino:221: error: invalid conversion from 'int*' to 'int'
Carputer_Arduino:221: error: invalid conversion from 'unsigned int' to 'int*'
Carputer_Arduino:221: error: invalid conversion from 'int*' to 'int'
Carputer_Arduino:221: error: invalid conversion from 'unsigned int' to 'int*'
Carputer_Arduino:221: error: invalid conversion from 'int*' to 'int'
Carputer_Arduino:221: error: invalid conversion from 'int' to 'int*'

I'm curious because you mentioned that the code should support any datatype (void). Any idea what could be going on?

This is just with the definitions, I haven't entered the loop yet. Here are my variable declarations:

int valMPH        = 55;              // Miles per hour, GPS: 0 to 100
long valODO       = 0L;             // Odometer in miles, internal: 0 to 999,999
int valTripA      = 99;              // Trip A miles, internal: 0 to 9,999
int valTripB      = 4;              // Trip B miles, internal: 0 to 9,999
int valGPSPulse   = 0;              // Indicator of GPS acquisition, 0 or 1
int valSpareInt   = 0;              // Spare integer value
int valTimeHH     = 4;              // Current time hours, RTC: 1 to 12
int valTimeMM     = 5;              // Current time minutes, RTC: 0 to 59
int valDateMonth  = 0;              // Current date month, RTC: 1 to 12
int valDateDay    = 0;              // Current date day, RTC: 1 to 31
int valDateYear   = 77;              // Current date year, RTC: 0 to 99
int valTemp       = 28;              // Temperature, TEMP: -255 to 255 (degrees F)
int valBatt       = 5;              // Battery level, BATT: 0 to 100 (percent)
int valLean       = 0;              // Lean amount, ACCEL: -90 to 90 (angle)
long valHeading   = 12000L;             // Heading, GPS: 0 to 36000 (degrees)
int valLatDegrs   = 0;              // Latitude degrees, GPS: 
long valLatFrac   = 0L;             // Latitude fraction, GPS:
int valLatNS      = 1;              // Latitude NS, GPS: N = 0, S = 1
int valLonDegrs   = 0;              // Longitude degrees, GPS:
long valLonFrac   = 0L;             // Longitude fraction, GPS:
int valLonEW      = 2;              // Longitude EW, GPS: E = 2, W = 3

int valHETemp     = 15;
int valIPTemp     = 20;
int valVegPresFuel = 25;
int valCurrentFuel = 2;
int valValveFail = 3;


int valCoolant = 0;      
int valOilTemp = 0;
int valOilPres = 0;
int valGBTemp = 0;
int valTCTemp = 0;

Alex

The errors you are getting can't be from the initialization code you posted because they don't contain any attempts to convert pointers from one type to another. It might be occurring in the code which defines the data_tab table but you may have to post all your code so we can see exactly what's going on.

Pete

I’m unable to post the code here due to the 9500 character limit. I’ve posted the important bits however…

Transmitting Mega

#include <icrmacros.h>
#include <SoftwareSerial.h>


#include <TimedAction.h>
//#include <SoftSerial.h>
#include <TinyGPS.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <Wire.h>








// Simple serial protocol
#define STX      127        // Start of text
#define ETX      126        // End of text
#define CR       0x0D        // Carriage return
#define CTRL_Z   0x1A        // Control-z



// Tasks - TimedAction( msec, funcName )

TimedAction TS_SendDataPacketTask = TimedAction( 250, TS_SendDataPacket );
TimedAction TS_ReceiveDataPacketTask = TimedAction( 1000, TS_ReceiveDataPacket ); 




// Sensor values
int valMPH        = 55;              // Miles per hour, GPS: 0 to 100
long valODO       = 0L;             // Odometer in miles, internal: 0 to 999,999
int valTripA      = 99;              // Trip A miles, internal: 0 to 9,999
int valTripB      = 4;              // Trip B miles, internal: 0 to 9,999
int valGPSPulse   = 0;              // Indicator of GPS acquisition, 0 or 1
int valSpareInt   = 0;              // Spare integer value
int valTimeHH     = 4;              // Current time hours, RTC: 1 to 12
int valTimeMM     = 5;              // Current time minutes, RTC: 0 to 59
int valDateMonth  = 0;              // Current date month, RTC: 1 to 12
int valDateDay    = 0;              // Current date day, RTC: 1 to 31
int valDateYear   = 77;              // Current date year, RTC: 0 to 99
int valTemp       = 28;              // Temperature, TEMP: -255 to 255 (degrees F)
int valBatt       = 5;              // Battery level, BATT: 0 to 100 (percent)
int valLean       = 0;              // Lean amount, ACCEL: -90 to 90 (angle)
long valHeading   = 12000L;             // Heading, GPS: 0 to 36000 (degrees)
int valLatDegrs   = 0;              // Latitude degrees, GPS: 
long valLatFrac   = 0L;             // Latitude fraction, GPS:
int valLatNS      = 1;              // Latitude NS, GPS: N = 0, S = 1
int valLonDegrs   = 0;              // Longitude degrees, GPS:
long valLonFrac   = 0L;             // Longitude fraction, GPS:
int valLonEW      = 2;              // Longitude EW, GPS: E = 2, W = 3

int valHETemp     = 15;
int valIPTemp     = 20;
int valVegPresFuel = 25;
int valCurrentFuel = 2;
int valValveFail = 3;


int valCoolant = 0;      
int valOilTemp = 0;
int valOilPres = 0;
int valGBTemp = 0;
int valTCTemp = 0;



void setup( ) 
{
  pinMode( BUZZ_PIN, OUTPUT );

  Serial3.begin( 9600 );
  TS_Serial.begin( 9600 );               // Start TouchShield interface

  TS_SendDataPacketTask.enable( );        // Enable task for sending packets to the TouchShield
  TS_ReceiveDataPacketTask.enable( );     // Enable task for receiving packets from the TouchShield
}

  
//************************
// Ready to rock...
//
void loop( ) 
{
    TS_SendDataPacketTask.check( );
    TS_ReceiveDataPacketTask.check( );
}  




//***************************************************
// Serial data transfer to the TouchShield display
// Timed Action
//


void TS_SendDataPacket( )
{
  Serial3.print( STX, BYTE );
  TS_WriteInt( valMPH );
  TS_WriteInt( valMPH );
  
  TS_WriteLong( valODO );
  
  TS_WriteInt( valTripA );
  TS_WriteInt( valTripB );

  TS_WriteInt( valGPSPulse );
  TS_WriteInt( valSpareInt );
  
  TS_WriteInt( valTimeHH );
  TS_WriteInt( valTimeMM );
  
  TS_WriteInt( valDateMonth );

  TS_WriteInt( valDateDay );
  TS_WriteInt( valDateYear );
  
  TS_WriteInt( valTemp );
  TS_WriteInt( valBatt );
  TS_WriteInt( valLean );
  
  TS_WriteLong( valHeading );
  TS_WriteInt( valLatDegrs );

  TS_WriteLong( valLatFrac );
  TS_WriteInt( valLatNS );
  
  TS_WriteInt( valLonDegrs );
  TS_WriteLong( valLonFrac );
  TS_WriteInt( valLonEW );
  TS_WriteInt( valVegPresFuel );

 
  TS_WriteInt( valCurrentFuel );
  TS_WriteInt( valValveFail );
   
  TS_WriteInt( valHETemp );
  TS_WriteInt( valIPTemp );
  
  TS_WriteInt( valCoolant );
  TS_WriteInt( valOilTemp );
  TS_WriteInt( valOilPres );
  TS_WriteInt( valGBTemp );
  TS_WriteInt( valTCTemp );
     

  Serial3.print( ETX, BYTE );
}

void TS_WriteInt( int value )
{
  // Write high byte, low byte
  Serial3.print( ( unsigned char )( value >> 8 ) );
  Serial3.print( ( unsigned char )value ); 
}

void TS_WriteLong( long value )
{
  // Write high word, low word
  TS_WriteInt( ( unsigned int )( value >> 16 ) );
  TS_WriteInt( ( unsigned int )value ); 
}

// Handy for debugging communications with TouchShield
int whirlyGig = 0;
void TS_WriteWhirlyGig( )
{
  char* whirlyGigs[] = { "|", "/", "-", "\\", "|", "/", "-", "\\" };

  Serial.print( whirlyGigs[ whirlyGig ] );
  whirlyGig = ( ++whirlyGig > 7 ) ? 0 : whirlyGig;
}


//****************************************************
// Data (button presses) coming from the TouchShield
//
void TS_ReceiveDataPacket( )
{
  while( Serial3.available( ) > 0 )
  {
    switch( Serial3.read( ) )
    {
      case 'A':            // Reset TripA meter
        f_TripA = 0.0f;
        valTripA = f_TripA;
//        RTC_WriteFloat( TRIPA_ADDR, f_TripA );
            
        //#ifdef DEBUG_RESETS
        Serial.println( "Trip A pressed" );
        //#endif
        break;
        
      case 'B':            // Reset TripB meter
        f_TripB = 0.0f;
        valTripB = f_TripB;
//        RTC_WriteFloat( TRIPB_ADDR, f_TripB );
        
     
    }
      
    Serial3.flush( );
  }
}


// Reads a 2-byte integer value from the RTC RAM registers
int RTC_ReadInteger( int valAddr )
{
  // Set the register pointer
  Wire.beginTransmission( RTC_I2C_ADDR );
  Wire.send( valAddr );
  Wire.endTransmission( );

  // Read 2 bytes into int value
  Wire.requestFrom( RTC_I2C_ADDR, 2 );
  int value = Wire.receive( );
  value = ( value << 8 ) + Wire.receive( );
  
  return value;
}

// Reads a 4-byte float value from the RTC RAM registers
float RTC_ReadFloat( int valAddr )
{
  float value;
  byte  *byteArray = (byte *) &value;
  
  // Set the register pointer
  Wire.beginTransmission( RTC_I2C_ADDR );
  Wire.send( valAddr );
  Wire.endTransmission( );

  // Read 4 bytes can convert to float value
  Wire.requestFrom( RTC_I2C_ADDR, 4 );
  byteArray[3] = Wire.receive( );
  byteArray[2] = Wire.receive( );
  byteArray[1] = Wire.receive( );
  byteArray[0] = Wire.receive( );
  
  return value;
}

// Writes a 2-byte integer value to the RTC RAM registers
void RTC_WriteInteger( int valAddr, int value )
{
  if( valAddr > 7 && valAddr  < 63 )  // Don't let writes go to the RTC registers 0 - 7
  {
    Wire.beginTransmission( RTC_I2C_ADDR );
    Wire.send( valAddr );

    // Write high byte, low byte
    Wire.send( ( unsigned char )( value >> 8 ) );
    Wire.send( ( unsigned char )value ); 
    
    Wire.endTransmission( );
  }  
}

// Writes a 4-byte float value to the RTC RAM registers
void RTC_WriteFloat( int valAddr, float value )
{
  if( valAddr > 7 && valAddr  < 61 )  // Don't let writes go to the RTC registers 0 - 7
  {
    Wire.beginTransmission( RTC_I2C_ADDR );
    Wire.send( valAddr );
    
    // Write high word (high byte/low byte), low word (high byte/low byte)
    byte  *byteArray;
    byteArray = (byte *) &value;
    Wire.send( byteArray[3] );
    Wire.send( byteArray[2] );
    Wire.send( byteArray[1] );
    Wire.send( byteArray[0] );

    Wire.endTransmission( );
  } 
}
*/

Receiving Mega:

//*****************************/
#include <TimedAction.h>
#include <SubPGraphics.h>







// Scooterputer Tasks - TimedAction( msec, funcName )
TimedAction updateDisplayTask = TimedAction( 20, UpdateDisplayTask );
TimedAction batteryAlertTask = TimedAction( 500, BatteryAlertTask );
TimedAction counterResetTask = TimedAction( 200, CounterResetTask );
//TimedAction checkArduinoData = TimedAction( 50,  AR_CheckSerial );


// Simple Serial Protocol
#define STX    127    // Start of text
#define ETX    126    // End of text
#define EOT    4    // End of transmission
#define ENQ    5    // Enquiry
#define TAB    9    // Tab delimiter

// Sensor Values
unsigned int valMPH, savMPH = 0;

unsigned int valMaxS, savMaxS = 0;
unsigned long valODO, savODO = 0L;
unsigned int valTripA, savTripA = 0;
unsigned int valTripB, savTripB = 0;
unsigned int valGPSPulse, savGPSPulse = 0;
unsigned int valSpareInt, savSpareInt = 0;
unsigned int valTimeHH, savTimeHH = 0;
unsigned int valTimeMM, savTimeMM = 0;
unsigned int valDateMonth, savDateMonth = 0;
unsigned int valDateDay, savDateDay = 0;
unsigned int valDateYear, savDateYear = 0;
int valTemp, savTemp = 0;
unsigned int valBatt, savBatt = 0;
int valLean, savLean = 0;
unsigned long valHeading, savHeading = 0L;
unsigned int valLatDegrs, savLatDegrs = 0;
unsigned long valLatFrac, savLatFrac = 0L;
unsigned int valLatNS, savLatNS = 0;
unsigned int valLonDegrs, savLonDegrs = 0;
unsigned long valLonFrac, savLonFrac = 0L;
unsigned int valLonEW, savLonEW = 2;

//unsigned int valWarningByte, 
unsigned int savWarningByte = 0;
int ActiveWarnings[13];
int AWCount = 0;
int WarningPageNumber = 1;
unsigned int valWarningByte = 0;
int valValveFail, savValveFail = 0;
char* ActiveWarningChar[13];
int WarningPageCount = 0;
int valVegHETemp, savVegHETemp = 0;
int valVegIPTemp, savVegIPTemp = 0;
int valVegPresFuel, savVegPresFuel = 0;
int FuelState = 0;

int valFilt1 = 0;
int valFilt2 = 0;
int valFiltC = 0;
int valFiltD = 0;

int valCurrentFuel, savCurrentFuel = 0;

int valHTRState, savHTRState = 0;

int valCoolant, savCoolant = 0;
int valOilTemp, savOilTemp = 0;
int valOilPres, savOilPres = 0;
int valGBTemp, savGBTemp = 0;
int valTCTemp, savTCTemp = 0;
unsigned int valTank1Contents = 0;
unsigned int valTank2Contents = 0;
unsigned int valTank3Contents = 0;

unsigned int valCurrentFuelTank = 0;

int OpenTank;
int CurrentFuel = 0;

int TankContentsArray[] = {
  0,0,0,0};
  
  
[b]struct dtype data_tab[] = {
	// The first entry MUST have a length of zero, which indicates that we
	// must look for the STX here. The address can be anything including NULL.
	0,NULL,
	// Now a list of the variables in the order in which they are received
	// with their length in bytes and their address
	sizeof(valMPH),&valMPH,
	sizeof(valODO),&valODO,
        sizeof(valTripA),&valTripA,
        sizeof(valTripB),&valTripB,

        sizeof(valGPSPulse),&valGPSPulse,
        sizeof(valSpareInt),&valSpareInt,
  
        sizeof(valTimeHH),&valTimeHH,
        sizeof(valTimeMM),&valTimeMM,
  
        sizeof(valDateMonth),&valDateMonth,

        sizeof(valDateDay),&valDateDay,
        sizeof(valDateYear),&valDateYear,
  
        sizeof(valTemp),&valTemp,
        sizeof(valBatt),&valBatt,
        sizeof(valLean),&valLean,
  
        sizeof(valHeading),&valHeading,
        sizeof(valLatDegrs),&valLatDegrs,

        sizeof(valLatFrac),&valLatFrac,
        sizeof(valLatNS),&valLatNS,
  
        sizeof(valLonDegrs),&valLonDegrs,
        sizeof(valLonFrac),&valLonFrac,
        sizeof(valLonEW),&valLonEW,
        sizeof(valVegPresFuel),valVegPresFuel,

 
        sizeof(valCurrentFuel),&valCurrentFuel,
        sizeof(valValveFail),&valValveFail,
   
        sizeof(valVegHETemp),&valVegHETemp,
        sizeof(valVegIPTemp)&valVegIPTemp,
  
        sizeof(valCoolant),&valCoolant,
        sizeof(valOilTemp),&valOilTemp,
        sizeof(valOilPres),&valOilPres,


	sizeof(valGBTemp),&valGBTemp,
	sizeof(valTCTemp),&valTCTemp,
	// And now the end of table marker which MUST have a length of -1
	// and signals that we must now read the ETX
	-1,NULL
};
  [/b]


void TripAMouseHandler( )
{
  Serial.println( "-A" );
}

// ***************************
// Trip B Button Mouse Handler
// Reset TripB Meter
//
void TripBMouseHandler( )
{
  Serial.println( "-B" );
}


//**********************************
// Setup - one time initialization
//




void setup()
{
  // Uncomment the following line to upload images to the TouchShield Slide flash.
  // Press the Slide prog button, download, wait for prompt, then send images using Image Uploader in the Tools menu.
  // Comment this out after images have been uploaded so that it doesn't run on each startup.
  //  open(FlashTransfer);

  DrawScreen(1);

  // Init timed tasks
  updateDisplayTask.enable( );
  batteryAlertTask.disable( );
  counterResetTask.enable( );
  //  checkArduinoData.enable( );

  Serial.begin( 9600 );
  Serial.flush( );
}

//**********************************
// Loop - the main gear
//
void loop( )
{

  // Check for data from Arduino
  AR_CheckSerial( );  

  // Update the dsplay values if time is up 
  updateDisplayTask.check( );
  batteryAlertTask.check( );
  //  checkArduinoData.check( );

  if (tempScreen != ScreenCount){
    DrawScreen(ScreenCount);
  }
}

//**********************************
// CheckSerial Function
// Reads serial data from Arduino
//[b]This is all messy from me fiddling with it[/b]
void AR_CheckSerial( )
{


 while( Serial.available( )  )
  {


    if( Serial.read( ) == STX )
    {
      valMPH = AR_ReadInt( );
/*      
      switch(CurrentPacket){
     case 1:
      valMPH = AR_ReadInt( );

      valODO = AR_ReadLong( );

      valTripA = AR_ReadInt( );
      valTripB = AR_ReadInt( );

      valGPSPulse = AR_ReadInt( );
      valSpareInt = AR_ReadInt( );

      valTimeHH = AR_ReadInt( );
      valTimeMM = AR_ReadInt( );
      CurrentPacket = 2;
      Serial.flush();
      break;
      
      case 2:

      valDateMonth = AR_ReadInt( );
      valDateDay = AR_ReadInt( );
      valDateYear = AR_ReadInt( );

      valTemp = AR_ReadInt( );
      valBatt = AR_ReadInt( );
      valLean = AR_ReadInt( );

      valHeading = AR_ReadLong( );
      valLatDegrs = AR_ReadInt( );
      CurrentPacket = 3;
      Serial.flush();
      break;
      
      case 3:
      valLatFrac = AR_ReadLong( );
      valLatNS = AR_ReadInt( );

      valLonDegrs = AR_ReadInt( );
      valLonFrac = AR_ReadLong( );
      valLonEW = AR_ReadInt( );
      valVegPresFuel = AR_ReadInt( );
      CurrentPacket = 4;
      Serial.flush();
      break;
      
      
    case 4:
      valCurrentFuel = AR_ReadInt( );
      valValveFail = AR_ReadInt( );    
      valVegHETemp = AR_ReadInt( );
      valVegIPTemp = AR_ReadInt( );
      
      valCoolant = AR_ReadInt( );      
      valOilTemp = AR_ReadInt( );
      valOilPres = AR_ReadInt( );
      valGBTemp = AR_ReadInt( );
      valTCTemp = AR_ReadInt( );
      CurrentPacket = 1;
      Serial.flush();
     break;
      }

   */   
    }
      // Last char in data packet should be ETX
      if( Serial.read( ) == ETX )
      {
        if( commError )
        {
          commError = false;
        }
        return;
      }
     
    }
    // No STX/ETX is no good - clear the pipes and try again
    Serial.flush( );

    commError = true;
    return;// false;    // Return false if packet not received
  
  
  

}

//**********************************
// AR_ReadInt Function
// Reads an integer value from Arduino
//
int AR_ReadInt( )
{
  int value = Serial.read( );
  value = ( value << 8 ) + Serial.read( );

  return value;
}

//**********************************
// AR_ReadLong Function
// Reads a long value from Arduino
//
long AR_ReadLong( )
{
  long value = Serial.read( );
  value = ( value << 8 ) + Serial.read( );
  value = ( value << 8 ) + Serial.read( );
  value = ( value << 8 ) + Serial.read( );

  return value;
}

/

The receiver only has my data_tab but not the code that actually uses it to receive the data. You might as well delete it or comment it out to see if it removes the problem. With only bits of the code it's basically impossible to sort out where the error could occur. For one thing you didn't say whether it is in the receiver or transmitter code. Can you upload the code to a file server site?

Pete

Hey mate,

I've uploaded the code for both sides below. I've commented the code out and the code will compile fine without the struct entry. I understand that the struct is just a definition - Like an array, right? I'm finding it strange that it won't compile even though the struct isn't being called upon. I'll add the rest of the code in the morning. Thanks for the support guys.

Receiving Side: http://pastie.org/3288451

Transmitting Side: http://pastie.org/3288458

Thanks. Alex

I thought I should also mention that I've set the variable declarations so that some of the variables are defined as longs and others as ints. Could this be the problem?

     [echo] Building TouchShield Slide libraries...
     [echo] Building TouchShield Slide board target...
     [echo] Building Carputer_TouchShield for the TouchShield Slide core...
    [apply] In file included from /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/sketch-wrapper.cpp:15:
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int' to 'void*'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'unsigned int' to 'void*'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int*' to 'int'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'unsigned int' to 'void*'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int*' to 'int'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'unsigned int' to 'void*'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int*' to 'int'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'unsigned int' to 'void*'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int*' to 'int'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'unsigned int' to 'void*'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int*' to 'int'
    [apply] /var/folders/z7/1s3jqp0s0b97gtw_wtqtxcbh0000gn/T/build832111817913950075.tmp/tmp/Carputer_TouchShield/Carputer_TouchShield.pde:888: error: invalid conversion from 'int' to 'void*'

You were missing a comma and an ampersand in the table. This time when I tried to compile it, the compiler seems to want braces around each initializer so I've added them. Replace data_tab with this:

struct dtype data_tab[] = {
    // The first entry MUST have a length of zero, which indicates that we
    // must look for the STX here. The address can be anything including NULL.
    {0,NULL},
    // Now a list of the variables in the order in which they are received
    // with their length in bytes and their address
    {sizeof(valMPH),&valMPH},
    {sizeof(valODO),&valODO},
        {sizeof(valTripA),&valTripA},
        {sizeof(valTripB),&valTripB},
        
        {sizeof(valGPSPulse),&valGPSPulse},
        {sizeof(valSpareInt),&valSpareInt},
        
        {sizeof(valTimeHH),&valTimeHH},
        {sizeof(valTimeMM),&valTimeMM},
        
        {sizeof(valDateMonth),&valDateMonth},
        
        {sizeof(valDateDay),&valDateDay},
        {sizeof(valDateYear),&valDateYear},
        
        {sizeof(valTemp),&valTemp},
        {sizeof(valBatt),&valBatt},
        {sizeof(valLean),&valLean},
        
        {sizeof(valHeading),&valHeading},
        {sizeof(valLatDegrs),&valLatDegrs},
        
        {sizeof(valLatFrac),&valLatFrac},
        {sizeof(valLatNS),&valLatNS},
        
        {sizeof(valLonDegrs),&valLonDegrs},
        {sizeof(valLonFrac),&valLonFrac},
        {sizeof(valLonEW),&valLonEW},
        {sizeof(valVegPresFuel),&valVegPresFuel},
        
        
        {sizeof(valCurrentFuel),&valCurrentFuel},
        {sizeof(valValveFail),&valValveFail},
        
        {sizeof(valVegHETemp),&valVegHETemp},
        {sizeof(valVegIPTemp),&valVegIPTemp},
        
        {sizeof(valCoolant),&valCoolant},
        {sizeof(valOilTemp),&valOilTemp},
        {sizeof(valOilPres),&valOilPres},


    {sizeof(valGBTemp),&valGBTemp},
    {sizeof(valTCTemp),&valTCTemp},
    // And now the end of table marker which MUST have a length of -1
    // and signals that we must now read the ETX
    {-1,NULL}
};

Pete

Thanks for that Pete, stupid me for missing it.

I'm still having a hard time running your code. I've copied it verbatim into my program and all seems well though communication still isn't happening. Initially I was seeing junk all over the screen but since then it's not running. Is there a certain value I should set for STX,ETX? or is my current 128,127 alright? I've also changed the transmitting code from all the TS_WriteInt and Long junk to just

void TS_SendDataPacket( )
{
  Serial3.print( STX, BYTE );
  Serial3.print( valMPH );
  
  Serial3.print( valODO );
  
  Serial3.print( valTripA );
  Serial3.print( valTripB );

  Serial3.print( valGPSPulse );
  Serial3.print( valSpareInt );
  
  Serial3.print( valTimeHH );
  Serial3.print( valTimeMM );
  
  Serial3.print( valDateMonth );

  Serial3.print( valDateDay );
  Serial3.print( valDateYear );
  
  Serial3.print( valTemp );
  Serial3.print( valBatt );
  Serial3.print( valLean );
  
  Serial3.print( valHeading );
  Serial3.print( valLatDegrs );

  Serial3.print( valLatFrac );
  Serial3.print( valLatNS );
  
  Serial3.print( valLonDegrs );
  Serial3.print( valLonFrac );
  Serial3.print( valLonEW );
  Serial3.print( valVegPresFuel );


  Serial3.print( valCurrentFuel );
  Serial3.print( valValveFail );
   
  Serial3.print( valHETemp );
  Serial3.print( valIPTemp );
  
  Serial3.print( valCoolant );
  Serial3.print( valOilTemp );
  Serial3.print( valOilPres );
  Serial3.print( valGBTemp );
  Serial3.print( valTCTemp );
     

  Serial3.print( ETX, BYTE );
}

Is there any thing i'm missing?