handling data recieved

johnlong

Senior Member
#1
Hi All
I have knocked together a £3 ardiuno UNO on a bread board and sending 2 packets of data from a 28x2 to it.
The uno is doing a bit of floating maths then sending back the result after converting it into intreger for the picaxe
to deal with.
Have knocked up a simple test code for the picaxe to test the sending and returning result.
How ever I can not figure out how to handle the data on the picaxe side, capturing it in a word variable but the results are wrong
Picaxe code
[]
symbol tempC= w5
symbol RH= w6
symbol VPD=w7
tempC=10
RH=15
pause 1000
do
serout C.0,T9600,("<",#tempC,",",#RH,">")
serin C.1,T9600,VPD
'VPD = b3-"0"*10 + b2-"0" * 10 + b1-"0" * 10 + b0-"0"

if RH >= 86 then
RH=15
inc tempC

endif
sertxd(" VPD= ",#vpd,cr,lf)
inc RH
pause 500
loop

For those with a nervious dispersition the Ardiuno code

[]
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing

// variables to hold the parsed data
//char messageFromPC[numChars] = {0};
int area ={0};
float RH = 0.0;
// varables for calData
int SVP = 0;
float temP = 0.0;
float VPD = 0.0;
int back = 0;
boolean newData = false;

//============

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

Serial.println();
}

//============

void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}

//============

void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;

while (Serial.available() > 0 && newData == false) {
rc = Serial.read();

if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}

else if (rc == startMarker) {
recvInProgress = true;
}
}
}

//============

void parseData() { // split the data into its parts

char * strtokIndx; // this is used by strtok() as an index

strtokIndx = strtok(tempChars,","); // get the first part - the string
//strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

// strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
area = atoi(strtokIndx); // convert this part to an integer

strtokIndx = strtok(NULL, ",");
RH = atof(strtokIndx); // convert this part to integer
Serial.print("AREA ");
Serial.println(area);// for testing only
Serial.print("RH ");
Serial.println(RH);//for testing only


switch (area) {
case 0: SVP = 611; break; case 1: SVP = 657; break; case 2: SVP = 706; break; case 3: SVP = 758; break; case 4: SVP = 813; break; case 5: SVP = 872; break; case 6: SVP = 935; break;
case 7: SVP = 1102; break; case 8: SVP = 1073; break; case 9: SVP = 1148; break; case 10: SVP = 1228; break; case 11: SVP = 1312; break; case 12: SVP = 1402; break; case 13: SVP = 1497; break;
case 14: SVP = 1598; break; case 15: SVP = 1705; break; case 16: SVP = 1818; break; case 17: SVP = 1937; break; case 18: SVP = 2064; break; case 20: SVP = 2197; break; case 21: SVP = 2338; break;
case 22: SVP = 2486; break; case 23: SVP = 2809; break; case 24: SVP = 2983; break; case 25: SVP = 3167; break; case 26: SVP = 3361; break; case 27: SVP = 3565; break; case 28: SVP = 3779; break;
case 29: SVP = 4005; break; case 30: SVP = 4242; break; case 31: SVP = 4492; break; case 32: SVP = 4754; break; case 33: SVP = 5029; break; case 34: SVP = 5318; break;
case 35: SVP = 5621; break; case 36: SVP = 5940; break; case 37: SVP = 6273; break; case 38: SVP = 6623; break; case 39: SVP = 6990; break; case 40: SVP = 7374; break;
case 41: SVP = 7776; break;
}
// Serial.print("SVP ");
// Serial.println(SVP);

float temP = 100 - RH;
temP = temP/100;
// Serial.print("temP ");
// Serial.println(temP);
VPD = (float) temP * (int) SVP;
// Serial.print("VPD ");
// Serial.println(VPD);
VPD = round(VPD);
back = int (VPD);


}


//============

void showParsedData() {

// Serial.print("Picaxe ");
Serial.println(back);//result back to Picaxe
}
[/]
[/]
The Uno is recieving the data correctly and its results are right, just baffled on the Picaxe side
regards john
 

Attachments

PhilHornby

Senior Member
#2
How about simplifying the Arduino code right down, to get the comms. part working. Just return a fixed value - you might see a pattern in what you're receiving.

Other thoughts...

. Doesn't 'Serial.println' prefix the data with CR,LF or some such variation?
. Maybe the Arduino is outrunning the Picaxe and returning data before the 'SERIN' has been processed.
. You could return the data as an ASCII value and use the '#' processor at the Picaxe end to convert it. This could make debugging easier (with a USB<>Serial across the line)
 
#3
Serial data is byte-wise, so using a word variable to receive serial data will be confusing at least. I suggest you change VPD to a byte variable. Alternatively, if the data actually arrives in multiple bytes, then store them in byte variables and then massage them into your word variable.
 

hippy

Technical Support
Staff member
#4
I would guess the PICAXE is seeing your Serial.print() debugging output and using that, not the actual data you intend for it to see.

Perhaps change Serial.println(back) to Serial.println("[",back,"]") and use -

SerIn C.1, T9600, ("["), #VPD

That should ensure the PICAXE only sees the data intended for it.

If that's getting corrupted it could be that data is being sent too fast for the PICAXE to keep up with. In which case either drop the baud rate or add some pacing to slow data sent back down. Change Serial.println(back) to something like -

Code:
void SendChar(char c) {
  delay(1);
  Serial.print(c);
}
void SendNumber(int n) {
  if ( n > 9 ) {
    SendNumber( n / 10 );
  };
  SendChar( ( n % 10 ) + '0' ); 
}
void showParsedData() {
  SendChar("[");
  SendNumber(back);
  SendChar("]");
}
 

Hemi345

Senior Member
#5
Along the lines of the Arduino outrunning the PICAXE, you could use hardware serial and enable background receive so the PICAXE is always ready to receive the data.
 

hippy

Technical Support
Staff member
#6
Or, if the calculation you are making is as simple as -

vpd = int( round( (100-RH)/100 * SVP[tempC] ) )

You could save yourself a lot of effort and calculate the result you want using the PICAXE itself. I think this should be right. Give it a whirl under the PE6 simulator -
Code:
Symbol tempC = b0
Symbol rh    = b1

symbol vpd   = w1 ; b3:b2
symbol svp   = w2 ; b5:b4

TestProgram:
  For tempC = 10 To 11
    For rh = 15 To 85
      Gosub CalculateVpd
      SerTxd( #tempC, "C", TAB, #rh, "%RH", TAB, #vpd, CR, LF )
    Next
    SerTxd( CR, LF )
  Next
  End

CalculateVpd:
  Select Case tempC
    Case 0:  svp = 611:  Case 1:  svp = 657:  Case 2:  svp = 706:  Case 3:  svp = 758:  Case 4:  svp = 813:  Case 5:  svp = 872:  Case 6:  svp = 935
    Case 7:  svp = 1102: Case 8:  svp = 1073: Case 9:  svp = 1148: Case 10: svp = 1228: Case 11: svp = 1312: Case 12: svp = 1402: Case 13: svp = 1497
    Case 14: svp = 1598: Case 15: svp = 1705: Case 16: svp = 1818: Case 17: svp = 1937: Case 18: svp = 2064: Case 20: svp = 2197: Case 21: svp = 2338
    Case 22: svp = 2486: Case 23: svp = 2809: Case 24: svp = 2983: Case 25: svp = 3167: Case 26: svp = 3361: Case 27: svp = 3565: Case 28: svp = 3779
    Case 29: svp = 4005: Case 30: svp = 4242: Case 31: svp = 4492: Case 32: svp = 4754: Case 33: svp = 5029: Case 34: svp = 5318
    Case 35: svp = 5621: Case 36: svp = 5940: Case 37: svp = 6273: Case 38: svp = 6623: Case 39: svp = 6990: Case 40: svp = 7374
    Case 41: svp = 7776
  End Select

  vpd = svp /  100
  svp = svp // 100

  vpd = 100-rh * vpd
  svp = 100-rh * svp

  vpd = svp /  100      + vpd
  vpd = svp // 100 / 50 + vpd

  Return
Execution can be speeded up considerably by moving the SELECT-CASE into Data EEPROM ...
Code:
CalculateVpd:

  svp = tempC * 2 : Read svp, vpd
  svp = svp   + 1 : Read svp, svp

  vpd = 100-rh * vpd
  svp = 100-rh * svp

  vpd = svp /  100      + vpd
  vpd = svp // 100 / 50 + vpd

  Return

  Data(  6,11 ,  6,57 ,  7,06 ,  7,58 ,  8,13 ,  8,72 ,  9,35 )
  Data( 11,02 , 10,73 , 11,48 , 12,28 , 13,12 , 14,02 , 14,97 )
  Data( 15,98 , 17,05 , 18,18 , 19,37 , 20,64 , 21,97 , 23,38 )
  Data( 24,86 , 28,09 , 29,83 , 31,67 , 33,61 , 35,65 , 37,79 )
  Data( 40,05 , 42,42 , 44,92 , 47,54 , 50,29 , 53,18 )
  Data( 56,21 , 59,40 , 62,73 , 66,23 , 69,90 , 73,74 )
  Data( 77,76 )
 
Last edited:
#7
Hi All
A wonderful piece of work Hippy the eeprom route only use 51 bytes
2000+ for ardiuno have run it against pre determined value tables and online calculator very tiny
variations less than 0.1%.
Never seen a data table like that before 'cool' , once again you have shown how flexable the editor is
Thanks it has removed a very large lookup table reducing the code by 1400 bytes
regards
john
 
Top