0
Offline
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« on: April 16, 2012, 08:42:13 pm » |
I have been working on a script to interface my arduino to a serial device sending TAP (Telocator Alphanumeric Protocol). I am testing my code using a terminal program that can send scripts. I am able to send and recieve strings, but I'm hitting a road block trying to figure out how to parse a string coming from the termial program. Example TAP string might look like <STX>101<CR>TEST PAGE><CR><ETX>32><CR> and I would like to parse the 101 or TEST PAGE and based on that send out another string from arduino, possibly <CR><ESC><EOT><CR>. My code looks like this so far. I am also attaching a screen shot of what the debug window looks like after sending a script from the terminal program. The following link is to a previous post that helped get me started with the code. Greatly appreciate help or comments on the code. http://arduino.cc/forum/index.php/topic,99198.0/topicseen.html/*===========================
Modified original code by Fayaz Kadir http://fayazkadir.com/blog/?p=2291
DESCRIPTION: If you send a string starting with "CR" and ending with "ESC", the Arduino responds back with "$Y" for valid data string, or $N for invalid data string.
============================*/ #define NUL 0 #define SOH 1 #define STX 2 #define ETX 3 #define EOT 4 #define ACK 6 #define CR 13 #define ESC 27 #define ID "ID=" #define SP 32 #include <SoftwareSerial.h> // software serial #1: TX = digital pin 2, RX = digital pin 3 SoftwareSerial portOne(2, 3); char string[128]; char string1[6]= {0x0D,0x49,0x44,0x3D,'\n'}; //[CR][ID=] char string2[] ={0x02,0x31,0x30,0x31,0x0D,0x54,0x45,0x53,0x54,0x20,0x50,0x41,0x47,0x45, 0x0D,0x03,0x33,0x32,0x0D}; //[STX][101][CR][TEST][SP][CR][ETX][32][CR] int i=0; int string_len; char inByte; int last_inByte;
void setup() { portOne.begin(9600); //INTIALISING THE SERIAL PORT Serial.begin(9600); } void loop() // LOOP FUNCTION { inByte = portOne.read(); string_len=0; if (inByte == 13) read_serial(); // If Start of line (CR) is found, call read_serial() function } void read_serial() // FUNCTION FOR READING THE SERIAL MESSAGE { Serial.println ("CR FOUND and reading"); // THE SOL (Start of Line) found notice. Serial.print("READ :CR\n"); //Saying that it has read "!" on the serial port portOne.print("\n"); portOne.write(ID); portOne.write(CR); while (inByte!= (ESC)) // As long as EOL not found, keep reading if (portOne.available() > 0) // if new data is available {inByte = portOne.read(); // Read new byte Serial.print("READ : "); // Display the new byte string[string_len] = inByte; // Save the data in a character array Serial.println(string[string_len]); // Print the characters that was recieved string_len++;} else if (inByte== (SP)) {Serial.println("EOL not available, data string invalid"); // If EOL not in the string Serial.println("$N"); //FAIL SIGNATURE break; } if (inByte == (ESC)) { Serial.println ("eol FOUND, and full string was "); // Echoes Success Message Serial.println ("$Y"); //SUCCESS SIGNATURE for (i=0;i<(string_len-1);i++) Serial.print(string[i]); portOne.write(string1); portOne.write(string2); Serial.print("\n"); } } Moderator edit: [code] ... [/code] tags added. (Nick Gammon)
|
|
|
|
« Last Edit: April 16, 2012, 10:42:58 pm by Nick Gammon »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 315
Posts: 35519
Seattle, WA USA
|
 |
« Reply #1 on: April 17, 2012, 04:26:56 am » |
You got a carriage return from portOne, so you call read_serial. Why isn't the function called read_portOne? The first thing you do in read_serial() is send stuff to portOne. Why? The device on the other end is already sending you data. You really need to work on making your code readable. { followed immediately by code makes it very hard to match up a closing }. if (portOne.available() > 0) // if new data is available { } else if (inByte== (SP)) { } In what possible way do these go together? What do the () around SP and ESC contribute? You have an array called string. It is NOT a string. A string is a NULL terminated array of chars. Nary a NULL in sight in your code. Why not?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #2 on: April 17, 2012, 09:20:53 pm » |
You got a carriage return from portOne, so you call read_serial. Why isn't the function called read_portOne?
The first thing you do in read_serial() is send stuff to portOne. Why? The device on the other end is already sending you data.
Your absolutely right. I will change the code to read_portOne and also clean up the rest of the code. The reason I'm sending data to portOne is simply to see the exchange of data between the two serial ports. In the TAP protocol, when the sending device sends a Carriage return every 1-2 seconds until it recieves "ID=" from (in my experiment) the Arduino. This exchange continues seceral times until the sending device sends the actual data message it has. if (portOne.available() > 0) // if new data is available { } else if (inByte== (SP)) { } In what possible way do these go together? They don't, just experimenting with the code. If the space bar is pressed, or 0x20 charachter is recieved the "Invalid" message is sent to Serial.print. I removed the ( ) do nothing, I removed them from the code. You have an array called string. It is NOT a string. A string is a NULL terminated array of chars. Nary a NULL in sight in your code. Why not?
Well, this part I'm not sure about. I can rename the array to something other than string, but I would appreciate any help with for (i=0;i<(string_len-1);i++) Serial.print(string ); and parsing information from this data, not just sending it to Serial.print.
Moderator edit: Fixed up nested quotes. (Nick Gammon)
|
|
|
|
« Last Edit: April 17, 2012, 10:56:51 pm by Nick Gammon »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 315
Posts: 35519
Seattle, WA USA
|
 |
« Reply #3 on: April 18, 2012, 04:46:12 am » |
but I would appreciate any help with for (i=0;i<(string_len-1);i++) Serial.print(string); and parsing information from this data, not just sending it to Serial.print. The point is that you can't use any of the string functions, like strtok() for parsing, until you have a string. All you have now is a non-NULL terminated array of characters called string, which is not a string. Rename the array to buffer, to eliminate the confusion. Then, after each character is added, append a NULL, so you have a NULL terminated array of chars, also known as a string, so that you CAN use strtok(), strlen(), and the other string handling functions.
|
|
|
|
|
Logged
|
|
|
|
|
france
Offline
Jr. Member
Karma: 0
Posts: 52
|
 |
« Reply #4 on: April 18, 2012, 05:27:54 am » |
hello you can read this . the skect print on serial1 -> read on serial2 ->strtok the string -> put the result in a arrray -> when serial2 read $ -> serial print the entire array. the sketch is in dev and i am a newbie sorry for the "bordel" but if it can help you  #include <Flash.h> // Flash lib for dev
char indata[35]; // to store incoming data byte index = 0; char str[35]; // string to copy inData int valbrut, ind, divi; // nbs entier float val; // nbs virgule int errors = 0; char time[]= "13:13/17/04/12"; //for dev
float storedata[28] = { }; // tableau de de type float
void setup() { Serial.begin(57600); // usb to pc Serial1.begin(57600); // to simul send datta Serial2.begin(57600); // receive data }
void loop(){ // string array for dev FLASH_STRING_ARRAY(frocom2, PSTR("$ Prêt;0019;1;1;zst;\r"), PSTR("Kesseltemp.;0126;2;2;°C;\r"), PSTR("Abgastemp.;0060;3;1;°C;\r"), PSTR("Abgastemp S;0070;11;1;°C;\r"), PSTR("Kesselstrg ;0091;4;1;%;\r"), PSTR("Primärluft ;0000;5;1;%;\r"), PSTR("Rest O2 ist;0000;6;10;%;\r"), PSTR("O2 Regler ;0100;7;1;%;\r"), PSTR("Sekundärluft;0000;8;1;%;\r"), PSTR("Saugzug Soll;0000;9;1;%;\r"), PSTR("SaugzugIst;0000;10;1;U;\r"), PSTR("Einschub Ist;0000;12;1;%;\r"), PSTR("O2 Regler Pell ;0031;13;1;%;\r"), PSTR("Füllstand: ;20700;14;207;%;\r"), PSTR("Ansauggeschw.;0454;15;100;m/s;\r"), PSTR("Strom Austrags;0595;16;1000;A;\r"), PSTR("Fühler 1;0149;17;2;°C;\r"), PSTR("Kesselsoll ;0080;18;2;°C;\r"), PSTR("Pufferoben ;0000;20;2;°C;\r"), PSTR("Pufferunten ;0000;21;2;°C;\r"), PSTR("Pufferpumpe ;8192;22;1;%;\r"), PSTR("Boiler 1;0124;23;2;°C;\r"), PSTR("Vorlauf 1;0036;24;2;°C;\r"), PSTR("HK Pumpe 1;0000;26;1; ;\r"), PSTR("HK Pumpe 2;0000;27;1; ;\r"), PSTR("Aussentemp;0030;28;2;°C;\r"), PSTR("Kollektortemp;0000;29;2;°C;\r"), PSTR("Betriebsstunden;1221;30;1;h;\r"), PSTR("Fehler;Kein Fehler ;99;1;storedata; \r")); // serial1 send data every 0.5sec for dev frocom2[0].print(Serial1); Serial1.println(); delay(500); frocom2[1].print(Serial1); Serial1.println(); delay(500); /*frocom2[2].print(Serial1); Serial1.println(); delay(1000); frocom2[3].print(Serial1); Serial1.println(); delay(1000); frocom2[4].print(Serial1); Serial1.println(); delay(1000); frocom2[5].print(Serial1); Serial1.println(); delay(1000); frocom2[6].print(Serial1); Serial1.println(); delay(1000); frocom2[7].print(Serial1); Serial1.println(); delay(1000); frocom2[8].print(Serial1); Serial1.println(); delay(1000); frocom2[9].print(Serial1); Serial1.println(); delay(1000); frocom2[10].print(Serial1); Serial1.println(); delay(1000); frocom2[11].print(Serial1); Serial1.println(); delay(1000); frocom2[12].print(Serial1); Serial1.println(); delay(1000); frocom2[13].print(Serial1); Serial1.println(); delay(1000); frocom2[14].print(Serial1); Serial1.println(); delay(1000); frocom2[15].print(Serial1); Serial1.println(); delay(1000); frocom2[16].print(Serial1); Serial1.println(); delay(1000); frocom2[17].print(Serial1); Serial1.println(); delay(1000); frocom2[18].print(Serial1); Serial1.println(); delay(1000); frocom2[19].print(Serial1); Serial1.println(); delay(1000); frocom2[20].print(Serial1); Serial1.println(); delay(1000); frocom2[21].print(Serial1); Serial1.println(); delay(1000); frocom2[22].print(Serial1); Serial1.println(); delay(1000); frocom2[23].print(Serial1); Serial1.println(); delay(1000); frocom2[24].print(Serial1); Serial1.println(); delay(1000); frocom2[25].print(Serial1); Serial1.println(); delay(1000); frocom2[26].print(Serial1); Serial1.println(); delay(1000); frocom2[27].print(Serial1); Serial1.println(); delay(1000); frocom2[28].print(Serial1); Serial1.println(); delay(500);*/ while(Serial2.available() > 0) { char aChar = Serial2.read(); if(aChar == '\n') // cariage return is the end of one data { // End of record detected. Time to parse
strcpy(str,indata); // copy inData into str
//Serial.print("str="); // for dev //Serial.println(str); //Serial.print("indata="); //Serial.println(indata); //Serial.println();
char *chpt = strtok(str, ";"); if (chpt == NULL) { Serial.println("First strok returns NULL"); ++errors; }
if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Second strok returns NULL"); ++errors; } else { valbrut = atof(chpt); } }
if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Third strok returns NULL"); ++errors; } else { ind = atof(chpt); } }
if (errors == 0) { chpt = strtok(NULL, ";\r\n"); if (chpt == NULL) { Serial.println("Fourth strok returns NULL"); ++errors; // This is an input error: do something to handle it. } divi = atof(chpt); } if (errors == 0) val=valbrut/divi; /* Serial.print(ind); Serial.print(";"); Serial.print(val); Serial.println();*/
index = 0; indata[index] = NULL; } else { indata[index] = aChar; index++; indata[index] = '\0'; // Keep the string NULL terminated storedata[ind] = val; if(aChar == '$') { Serial.print(time); //for dev Serial.print(":"); /*Serial.print(storedata[0]); Serial.print(":");*/ Serial.print(storedata[1]); Serial.print(":"); Serial.print(storedata[2]); Serial.print(":"); Serial.print(storedata[3]); Serial.print(":"); Serial.print(storedata[4]); Serial.print(":"); Serial.print(storedata[5]); Serial.print(":"); Serial.print(storedata[6]); Serial.print(":"); Serial.print(storedata[7]); Serial.print(":"); Serial.print(storedata[8]); Serial.print(":"); Serial.print(storedata[9]); Serial.print(":"); Serial.print(storedata[10]); Serial.print(":"); Serial.print(storedata[11]); Serial.print(":"); Serial.print(storedata[12]); Serial.print(":"); Serial.print(storedata[13]); Serial.print(":"); Serial.print(storedata[14]); Serial.print(":"); Serial.print(storedata[15]); Serial.print(":"); Serial.print(storedata[16]); Serial.print(":"); Serial.print(storedata[17]); Serial.print(":"); Serial.print(storedata[18]); Serial.print(":"); Serial.print(storedata[19]); Serial.print(":"); Serial.print(storedata[20]); Serial.print(":"); Serial.print(storedata[21]); Serial.print(":"); Serial.print(storedata[22]); Serial.print(":"); Serial.print(storedata[23]); Serial.print(":"); Serial.print(storedata[24]); Serial.print(":"); Serial.print(storedata[25]); Serial.print(":"); Serial.print(storedata[26]); Serial.print(":"); Serial.print(storedata[27]); Serial.print(":"); Serial.print(storedata[28]); Serial.print(":"); Serial.println();
} } } }
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #5 on: April 18, 2012, 04:23:21 pm » |
My eyes hurt looking at this. Can't you at least use a for loop? Instead of: Serial.print(storedata[1]); Serial.print(":"); Serial.print(storedata[2]); Serial.print(":"); Serial.print(storedata[3]); Serial.print(":"); Serial.print(storedata[4]); Serial.print(":"); Serial.print(storedata[5]); Serial.print(":"); Serial.print(storedata[6]); Serial.print(":"); ... Serial.print(storedata[27]); Serial.print(":"); Serial.print(storedata[28]); Serial.print(":");
Do: for (int i = 1; i <= 28; i++) { Serial.print (storedata [i]); Serial.print (":"); }
Ditto further up for frocom2.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #6 on: April 18, 2012, 08:57:10 pm » |
Then, after each character is added, append a NULL, so you have a NULL terminated array of chars, also known as a string, so that you CAN use strtok(), strlen(), and the other string handling functions. [/quote]
Does this look better? I included buffer[bufferindex] = '\0'. Am I on track with NULL terminating the array?
#define NUL 0 #define SOH 1 #define STX 2 #define ETX 3 #define EOT 4 #define ACK 6 #define CR 13 #define ESC 27 #define ID "ID=" #define SP 32 #include <SoftwareSerial.h> // software serial #1: TX = digital pin 2, RX = digital pin 3 SoftwareSerial portOne(2, 3); char buffer[128]; char string1[6]= {0x0D,0x49,0x44,0x3D,'\n'}; //[CR][ID=] char string2[] ={0x02,0x31,0x30,0x31,0x0D,0x54,0x45,0x53,0x54,0x20,0x50,0x41,0x47,0x45, 0x0D,0x03,0x33,0x32,0x0D}; //[STX][101][CR][TEST][SP][CR][ETX][32][CR] int i=0; int bufferindex = 0; char inByte; int last_inByte;
void setup() { portOne.begin(9600); //INTIALISING THE SERIAL PORT Serial.begin(9600); } void loop() // LOOP FUNCTION { inByte = portOne.read(); bufferindex=0; if (inByte == 13) read_portOne(); // If Start of line (CR) is found, call read_portOne() function } void read_portOne() // FUNCTION FOR READING THE SERIAL MESSAGE { Serial.println ("CR FOUND and reading"); // THE SOL (Start of Line) found notice. Serial.print("READ :CR\n"); //Saying that it has read "CR" on the serial port //portOne.print("\n"); portOne.write("\n"ID); // Send "ID=" from arduino software serial port. portOne.write(CR); // Send "CR" from arduino software serial port. while (inByte!= ESC) // As long as Escape key not found, keep reading if (portOne.available() > 0) // if new data is available { inByte = portOne.read(); // Read new byte buffer[bufferindex] = '\0'; Serial.print("READ : "); // Display the new byte buffer[bufferindex] = inByte; // Save the data in a character array Serial.println(buffer[bufferindex]); // Print the characters that was recieved bufferindex++; } if (inByte == ESC) { Serial.println ("eol FOUND, and full string was "); // Echoes Success Message Serial.println ("$Y"); //SUCCESS SIGNATURE for (i=0;i<(bufferindex-1);i++) Serial.print(buffer); portOne.write(string1); portOne.write(string2); Serial.print("\n"); } }
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 315
Posts: 35519
Seattle, WA USA
|
 |
« Reply #7 on: April 19, 2012, 04:23:03 am » |
Does this look better? No. Was there some part of AFTER that you didn't understand? void read_portOne() // FUNCTION FOR READING THE SERIAL MESSAGE { Serial.println ("CR FOUND and reading"); // THE SOL (Start of Line) found notice. Serial.print("READ :CR\n"); //Saying that it has read "CR" on the serial port
portOne.write("\n"); portOne.write(ID); // Send "ID=" from arduino software serial port. portOne.write(CR); // Send "CR" from arduino software serial port.
while (inByte!= ESC) { // As long as Escape key not found, keep reading if (portOne.available() > 0) // if new data is available { inByte = portOne.read(); // Read new byte buffer[bufferindex] = inByte; // Save the data in a character array bufferindex++; buffer[bufferindex] = '\0';
Serial.print("READ : "); // Display the new byte Serial.println(inByte); // Print the characters that was recieved }
if (inByte == ESC) { Serial.println ("eol FOUND, and full string was "); // Echoes Success Message Serial.println ("$Y"); //SUCCESS SIGNATURE Serial.print(buffer); portOne.write(string1); portOne.write(string2); Serial.print("\n"); } } }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 17
Arduino rocks
|
 |
« Reply #8 on: April 20, 2012, 07:30:33 am » |
Thanks PaulS. I am gaining a better understanding of the '\0' character. Still need to work on it though. Thanks maccoa for the example of strtok.
|
|
|
|
|
Logged
|
|
|
|
|
|