0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« on: January 21, 2012, 08:27:30 am » |
Buenas, a ver si me podeis ayudar en terminar este programita que funciona casi todo a excepción de meter cada dato en una variable para luego poder hacer cosas con ellos. tengo un arduino que lee un snesor de ultrasonidos y me envia una cadena de caracteres por newsoftserial que son millis;numero consigo recibir los datos, consigo que me imprima por separado millis y numero, pero necesito guardar "numero" en una variable para luego multiplicar etc. //http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1280743388/all //http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226107230/3
char inData[80]; byte index = 0; char flightdata[80]; int counter = 0; //initialise the counter
#include <NewSoftSerial.h> NewSoftSerial mySerial(2, 3);
char *str; void setup() { Serial.begin(9600); // set the data rate for the NewSoftSerial port mySerial.begin(4800); mySerial.println("Hello, world! Soy Arduino COM 5 Receptor."); }
void loop() { while(mySerial.available() > 0) { char aChar = mySerial.read(); // Serial.print("Char recibido: "); Serial.println(aChar); if(aChar == '\n') { // End of record detected. Time to parse
// esto imprime el array letra a letra que contine todo lo que se recibio Serial.println("Separando e imprimiendo cada grupo de caracteres separados por semicolon"); char *p = inData; while ((str = strtok_r(p, ";", &p)) != NULL) // delimiter is the semicolon { Serial.println(str); flightdata[counter] = *str; //use the counter as an index to add each value to the array counter++; //increment the counter } index = 0; inData[index] = NULL; } else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated } }
Serial.print(inData[0]); Serial.println(inData[1]);
// esto imprime el array letra a letra que contine todo lo que se recibio Serial.println("Imprimiendo array caracter a caracter almacenado en variable inData"); int i; for (i = 0; i < 80; i = i + 1) { Serial.print(inData[i]); } //------------------------------------------------------------------------- Serial.print("El dato primero es: "); Serial.println(flightdata[0]); Serial.print("El dato segundo es: "); Serial.println(flightdata[1]); Serial.println(); delay(1000); } // fin del loop muchas gracias !!!
|
|
|
|
« Last Edit: January 22, 2012, 07:18:07 am by Sergegsx »
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 12
Posts: 1552
|
 |
« Reply #1 on: January 21, 2012, 08:34:36 am » |
|
|
|
|
« Last Edit: January 21, 2012, 08:52:23 am by Igor R »
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #2 on: January 21, 2012, 09:55:09 am » |
muchas gracias Igor, no me sienta mal en absoluto, la verdad es que me he precipitado al abrir el post a lo mejor porque he buscando bastante por internet pero todo en ingles y por eso no he llegado a los post que me pones.
voy a echarles un vistazo a ver si entre todos consigo hacer varias cosas seguidas 1. recibir una cadena separada por ; 2. romperla por ; y meter cada valor en una variable 3. convertir las cadenas de cada variable en variables correctas (tipo long, int etc)
necesito hacer esto tanto para lo que recibe un arduino por newsoftwareserial, como por ethernet al llamar a un php.
si consigo hacerlo todo, pondre aquí todo el codigo.
muchas gracias !!!!
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 12
Posts: 1552
|
 |
« Reply #3 on: January 21, 2012, 10:17:18 am » |
Mira si esto te sirve para entender más o menos que hay que ir haciendo. Ya es cosa que lo adaptes. Cada uno tiene sus métodos..... Es parte de un Interprete que estoy haciendo poco a poco cuando estoy aburrido, pero Input es una cadena e index es la posición actual dentro de la cadena (todo está dentro de una estructura llamada Interpreter). nSizeInput es el tamaño del array Input. Es una función que recoge un número (float con separador decimal con el caracter ".") dentro de un string (array de carácteres). //------------------------------------------------------------- // Get Number (decimal '.') //------------------------------------------------------------- float getNumber() { float myNumber; myNumber=Interpreter.Input[Interpreter.index]-'0'; ++Interpreter.index; while( (Interpreter.Input[Interpreter.index]>='0') && (Interpreter.Input[Interpreter.index]<='9') && (Interpreter.index<nSizeInput) ) { myNumber=myNumber*10+(Interpreter.Input[Interpreter.index]-'0'); ++Interpreter.index; } if ( (Interpreter.Input[Interpreter.index]<='.') && (Interpreter.index<nSizeInput) ) { int mytimes=1; float myDecimal; ++Interpreter.index; while( (Interpreter.Input[Interpreter.index]>='0') && (Interpreter.Input[Interpreter.index]<='9') && (Interpreter.index<nSizeInput) ) { myDecimal=myDecimal*10+(Interpreter.Input[Interpreter.index]-'0'); ++Interpreter.index; mytimes*=10.0; } myNumber+=myDecimal/mytimes; } return myNumber; }
|
|
|
|
« Last Edit: January 21, 2012, 05:28:32 pm by Igor R »
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #4 on: January 21, 2012, 02:56:51 pm » |
gracias Igor ! Me esta costando mas de lo que pensaba, tengo: . la cadena de texto recibida . separada por ; pero no consigo almacenarla en otro Char para asi luego hacer un atoi o atol //http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1280743388/all //http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226107230/3
char inData[80]; byte index = 0; char flightdata[80]; int counter = 0; //initialise the counter
#include <NewSoftSerial.h> NewSoftSerial mySerial(2, 3);
char *str; char dato[100]; void setup() { Serial.begin(9600); // set the data rate for the NewSoftSerial port mySerial.begin(4800); mySerial.println("Hello, world! Soy Arduino COM 5 Receptor."); }
void loop() { counter = 0; while(mySerial.available() > 0) { char aChar = mySerial.read(); // Serial.print("Char recibido: "); Serial.println(aChar); if(aChar == '\n') { // End of record detected. Time to parse // esto imprime el array letra a letra que contine todo lo que se recibio Serial.println("Separando e imprimiendo cada grupo de caracteres separados por semicolon"); char *p = inData; while ((str = strtok_r(p, ";", &p)) != NULL) // delimiter is the semicolon { //Serial.println(str); Serial.print("grupo "); Serial.print(counter); Serial.print("\t Valor: "); if (counter == 1) Serial.print("****"); Serial.println(str); flightdata = *str; //use the counter as an index to add each value to the array counter++; //increment the counter } // for (int i = 0; i < 80; i = i + 1) { Serial.print(inData[i]); } index = 0; inData[index] = NULL; } else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated } }
// esto imprime el array letra a letra que contine todo lo que se recibio /* Serial.println("Imprimiendo array caracter a caracter almacenado en variable inData"); for (int i = 0; i < 80; i = i + 1) { Serial.print(inData[i]); } */ //------------------------------------------------------------------------- Serial.println(); delay(2000); } // fin del loop me dice Serial_read_put_to_array.cpp: In function 'void loop()': Serial_read_put_to_array:45: error: incompatible types in assignment of 'char' to 'char [80]'
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #5 on: January 22, 2012, 05:55:48 am » |
alguien me puede explicar de forma sencillita la diferencia entre estos dos? es decir que hace el asterisco? es que he leido cosas acerca de pointers y demas pero no pillo lo que hace char *str; char dato[100]; en mi codigo se utiliza aqui char *p = inData; while ((str = strtok_r(p, ";", &p)) != NULL) // delimiter is the semicolon { Serial.println(str);
y no entiendo lo que hace porque pensaba que estaba rompiendo usando el semicolon y metiendolo en str pero si imprimo str caracter por caracter contiene mas datos. habia pensado en usar el contador para decir, si es el segundo parametro metelo en otra variable, y esa ya convertirla a numero. please ayuda chicos que el resto del codigo lo entiendo y creo que esta listo para lo que quiero hacer, pero me falta separar por ";"
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #6 on: January 22, 2012, 06:32:44 am » |
con este codigo he conseguido leer 1 solo valor que me llegue por serial sin punto-coma ni nada y convertirlo en un float ahora falta lo dificil que es lo de crear un array tipo float y meter en cada posición uno de los parametros que venian separados por ";" si alguien puede ayudarme. mil gracias char inData[80]; byte index = 0; float nivel_diesel = 0.0;
#include <NewSoftSerial.h> NewSoftSerial mySerial(2, 3);
void setup() { Serial.begin(9600); // set the data rate for the NewSoftSerial port mySerial.begin(4800); mySerial.println("Hello, world! Soy Arduino COM 5 Receptor."); }
void loop() {
while(mySerial.available() > 0) { char aChar = mySerial.read(); // Serial.print("Char recibido: "); Serial.println(aChar); if(aChar == '\n') { // End of record detected. Time to parse { float decade = pow(10,((index-1)-1)); nivel_diesel = 0.0; Serial.println("Start:"); for (int i = 0; i < int(index-1); i = i + 1) { float digito = inData[i] - '0'; nivel_diesel = digito*decade + nivel_diesel; Serial.print("decade: ");Serial.print(decade);Serial.print("\tdigito: ");Serial.println(digito); decade = decade/10; } Serial.println(nivel_diesel); /// pruebas matematicas con el numero //Serial.println((4*final)); } index = 0; inData[index] = NULL; } else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated } }
// esto imprime el array letra a letra que contine todo lo que se recibio /* Serial.println("Imprimiendo array caracter a caracter almacenado en variable inData"); for (int i = 0; i < 80; i = i + 1) { Serial.print(inData[i]); } */ //------------------------------------------------------------------------- Serial.println(); delay(2000); } // fin del loop
esto me imprime decade: 10.00 digito: 1.00 decade: 1.00 digito: 5.00 15.00
siendo el 15 el valor que recibe de otro arduino por newsoftwareserial
|
|
|
|
« Last Edit: January 22, 2012, 06:34:58 am by Sergegsx »
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #7 on: January 22, 2012, 07:16:37 am » |
poco a poco esto va saliendo !!! #include <string.h> #include <stdio.h> #include <stdlib.h>
#include <NewSoftSerial.h> NewSoftSerial mySerial(2, 3); char inData[80]; byte index = 0;
// Variables donde guardar los datos recibidos separados float nivel_diesel = 0.0; unsigned long arduino_online = 0; int parametro3;
/* int input []= {11,10,9} ; int values []= {0,0,0} ; // aqui guarda los valores tras recibirlos y separarlos */ long values []= {0,0,0} ; // aqui guarda los valores tras recibirlos y separarlos
void setup() {
Serial.begin(9600); mySerial.begin(4800); mySerial.println("Hello, world! Soy Arduino COM 5 Receptor."); }
void loop(){
read_parse_serial();
}
void read_parse_serial() { while(mySerial.available() > 0) { char aChar = mySerial.read(); // Serial.print("Char recibido: "); Serial.println(aChar); if(aChar == '\n') { // End of record detected. Time to parse parse(); index = 0; inData[index] = NULL; } else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated } }
}
void parse() { //char signal[] = "125;0;255"; // esto es lo que tengo que cambiar por lo que venga del puerto serie char separator[] = ";"; // el caracter que uso para separar los valores
char *result = NULL; int index = 0;
result = strtok( inData, separator ); // aqui se separan los caracteres while( (result != NULL) && (index < 3) ) { Serial.print( result ); Serial.println( ); values[index++] = atol(result); // aqui se convierten en valores
result = strtok( NULL, separator ); // aqui vacia result }
// Guardamos cada valor en una variable que tenga un nombre de variable significativo arduino_online = values[0]; nivel_diesel = values[1]; parametro3 = values[2]; Serial.print("Millis ardui (parametro 1): "); Serial.println(arduino_online); Serial.print("Nivel Diesel (parametro 2): "); Serial.println(nivel_diesel); Serial.print("Rand number (parametro 3): "); Serial.println(parametro3); // Demostracion de que el valor ya es esta guardado como un float Serial.println(nivel_diesel*4); }
la salida es 1399929 15 123
Millis ardui (parametro 1): 1399929 Nivel Diesel (parametro 2): 15.00 Rand number (parametro 3): 123 60.00
ahora a intentar optimizarla y hacerlo lo mas generico posible para que sirva para todos los usos. por ejemplo esta definido que solo le llegan 3 parametros, intentare hacerlo dinamico.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 12
Posts: 1552
|
 |
« Reply #8 on: January 22, 2012, 07:53:25 am » |
En mi forma de verlo, una máquina de estados es lo más genérico y fácil de ampliar/depurar. Pero ésto ya es cosa de cada uno.
¿Por qué no lo haces manualmente? Me refiero, así entiendes el proceso. Luego si quieres, usas las funciones de C que hay para ésto. Pero si no te quieres liar con punteros, puedes recorrer el vector y haciendo lo que toque.
Me explico, tienes tu vector dato[100] y creas una variable para ir recorriendo,digamos "i". Puedes ir recorriendolo e ir tomando decisiones. Es decir, leo la posición actual, si es un número, pues mynum=mynum*10+ (dato-'0'). Aumento el contador para leer la sigiente posición..... Cuando lo que leas es un ";", pues sabras que será tu siguiente número. Así que sigues leyendo, y en caso que sea número, pues haces mynum2=mynum2*10+ (dato-'0'). Es tan fácil como un for ó while...
|
|
|
|
« Last Edit: January 22, 2012, 08:06:40 am by Igor R »
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #9 on: January 22, 2012, 08:13:13 am » |
eso es muy buena idea Igor, y si te fijas es lo que he hecho en el código un poco mas arriba http://arduino.cc/forum/index.php/topic,88064.msg662369.html#msg662369con esto me he puesto a leer carácter a carácter y he hecho lo que comentas dentro de un for. creo que con ese ejemplo que he puesto se entiende el método manual. luego en mi ultimo ejemplo ya recurro a la función para hacer la separación y así de paso aprendo el tema de los punteros. y creo que el codigo ha quedado bastante apañado, es decir, - funcion donde leo lo que me llega por serial, - cuando termina de leer llama a la funcion de parsear - la funcion de parsear se encarga de romper la cadena por el separador y meterlo en un array. - luego cada posición del array lo guardo en la variable que me interesa para mi programa gracias por las ideas !
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 12
Posts: 1552
|
 |
« Reply #10 on: January 22, 2012, 08:20:44 am » |
Yo te lo decía, porque así no tienes que tener un buffer. Es decir, no tienes que ir metiendo en un buffer para luego usar strtrok ó el método que quieras. Puedes ir haciendolo a "tiempo real" según te van llegando los caracteres de serie. Me refiero, podrías hacerlo sin el for o while.... según te va llegando la trama, vas haciendo lo que toque.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 2
Posts: 512
|
 |
« Reply #11 on: January 22, 2012, 08:24:17 am » |
También yo en su día no sabía cómo coger el tema, http://arduino.cc/forum/index.php/topic,76223.0.htmlAl final en mi caso el tiempo que tenía para el envío de los datos por el puerto serie era muy reducido y no me servía este método. Lo que hice fue extraer los 2 bytes de cada número (que eran unsigned int) con highByte() y lowByte(), enviarlos, y en la recepción recomponer el número original con word(highByte, lowByte). El ahorro total de tiempo fue muy alto dado el tiempo de que disponía. Con esto tengo una duda. Si lo que tenemos es un valor long o float y queremos enviar los 4 bytes que lo componen, ¿qué instrucciones hay para hacerlo? ¿Cómo se extraen los 4 bytes y cómo se recomponen?
|
|
|
|
« Last Edit: January 22, 2012, 08:31:34 am by Cheyenne »
|
Logged
|
|
|
|
|
Offline
Edison Member
Karma: 22
Posts: 1373
|
 |
« Reply #12 on: January 22, 2012, 08:46:06 am » |
Ahora existen funciones como parseInt()
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #13 on: January 22, 2012, 09:22:51 am » |
Ahora existen funciones como parseInt()
cierto y cuando sacaron 1.0 me alegre de verlo pero todavia no he hecho el cambio a 1.0 debido a problemas con la libreria ethernet y que yo tengo q poner ip fija y gateway. ademas si recibes millis() por serial no cabe dentro de un int. y con mi ejemplo no dependes de usar unicamente la version 1.0 de arduino sino que valdria para todas. de todas formas, es un buen aporte chiva. acabo de ver que existe Parselong, lo cual evita el problema que mencionaba antes del tamaño.
|
|
|
|
« Last Edit: January 22, 2012, 09:24:50 am by Sergegsx »
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 13
Posts: 1241
Arduino rocks
|
 |
« Reply #14 on: January 22, 2012, 09:26:26 am » |
Yo te lo decía, porque así no tienes que tener un buffer. Es decir, no tienes que ir metiendo en un buffer para luego usar strtrok ó el método que quieras. Puedes ir haciendolo a "tiempo real" según te van llegando los caracteres de serie. Me refiero, podrías hacerlo sin el for o while.... según te va llegando la trama, vas haciendo lo que toque.
pues si tengo un ratito hare un código de ejemplo probando esto también ya que es interesante la idea de no necesitar un buffer. gracias por la sugerencia Igor, si lo hago lo pondré aquí también.
|
|
|
|
|
Logged
|
|
|
|
|
|