Go Down

Topic: [SOLUCIONADO]leer datos en arduino y enviarlos a nodemcu para subirlos a THINGSP (Read 1 time) previous topic - next topic

surbyte

Ves como haciendo tareas mas simples se simplifica la cosa!!

Si encaras todo te abrumas, pero resolviendo y probando subtareas logras encontrarle la vuelta al problema.

Vas muy bien.

josekiki

Gracias surbyte por tu ayuda y ánimos.

Una duda que se me plantea, lo que no sé si es correcto plantearla aquí o en otra entrada. Además he estado leyendo otras entradas en relación a la duda y no me lo han aclarado.

El buffer del puerto serie es de 64 bytes, el valor que yo envío, LR, es un float que ocupa 32 bits, es decir, 4 bytes. Esto quiere decir que cada vez que envío el valor de LR estoy ocupando 4 bytes del buffer, ¿es así?.

Por otro lado, una vez quiera leer en NodeMCU cada float, ¿qué me va a ir leyendo de byte en byte o voy a poder leer el valor de LR completo sin problema aunque sea de 32 bits?

A raíz de estas dudas pueden surgir varios problemas:

- Que se me llene el buffer si no leo más rápido que envío.
- Si en NodeMCU se va leyendo de byte en byte tendré que unir de 4 en 4 bytes para obtener el valor
  completo.
- Y sobre todo cómo obtener la velocidad de envío y lectura correcta para que todo vaya sincronizado y
  se pierda información.


Voy a seguir programando el código para NodeMCU siguiendo las pautas que ponía en el mensaje anterior y subo código. Si quieres una vez haya subido dicho código me respondes, si puedes, estas dudas y los comentarios sobre el código en un mismo mensaje. Loq ue mejor veas.

Gracias de nuevo. Un abrazo.

surbyte

Quote
El buffer del puerto serie es de 64 bytes, el valor que yo envío, LR, es un float que ocupa 32 bits, es decir, 4 bytes. Esto quiere decir que cada vez que envío el valor de LR estoy ocupando 4 bytes del buffer, ¿es así?.

Por otro lado, una vez quiera leer en NodeMCU cada float, ¿qué me va a ir leyendo de byte en byte o voy a poder leer el valor de LR completo sin problema aunque sea de 32 bits?
Estas ocupando 4 bytes del buffer siempre y cuando el buffer no sea leído.
Si haces bien las cosas y no usas delays, eso no va a ocurrir.
Si tu le envias datos a toda velocidad sin pausas, claramente el buffer se llenará y perderás algun dato.
Pero hay que ser cuidadoso y tener sentido común. Para que enviar mas datos de los que puedas procesar, leer o guardar?

Repito, todo depende de como lees en tu nodemcu que hara las veces de receptor de esos datos.
Si no pones delays todo fluirá.
Además el código debe atender el envio de datos a ThinkSpeak y eso ya insume tiempo.
Pero no te preocupes verás que no es para volverse loco.

Quote
- Si en NodeMCU se va leyendo de byte en byte tendré que unir de 4 en 4 bytes para obtener el valor
  completo.
Si, es correcto, hay que rearmar el float.



Quote
- Y sobre todo cómo obtener la velocidad de envío y lectura correcta para que todo vaya sincronizado y
  se pierda información.
Dependerá de cuanto quieres o prestendes actualizar los datos en ThingSpeak.

Resulta que luego dices, quiero un dato x minuto o un dato cada 10 minutos y entonces? Todo lo anterior es preocupación sin sentido.
Pero si dices quiero un 100 datos x segundo, y claro pagas una cuenta de ThingSpeak que permita esa tasa, aún asi 100 floats x segundo serían 100x4x(8 mas bit de stop y paridad) hablamos de 4000 bits x segundo.. eso es NADA de NADA.

 

josekiki

Buenas de nuevo surbyte. Para evitar el tener que unir los 4 bytes para reconstruir el float, lo que he hecho ha sido transmitir a NodeMCU la variable 'val' que es de 8 bits. El código es el siguiente, solo varía lo comentado.

Code: [Select]


#include <SoftwareSerial.h>
SoftwareSerial Trans(2, 3);                      //Pines para Rx y Tx.

//Declaración de variables del proceso

float valor_medido;                                //Valor obtenido al leer por A0.
int ledPin = 10;                                     //Pin de conexión del led de prueba.
float LR;                                               //Variable para almacenar la luminosidad relativa.
float val;                                              //Variable empleada para el mapeo del valor medido para enviarlo al pin 10.

void setup()
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  Trans.begin(115200);                           //Velocidad de envío para la transmisión al NodeMCU.
}

void loop()
{
  valor_medido = analogRead(A0);                      //Valor de luminosidad medido en A0
  LR = (valor_medido * 100) / 1023;                   //Luminosidad medida en tanto por ciento
  Serial.print(LR);                                               //Para mostrar el valor en el monitor serie de arduino.
  Serial.println(" % luminosidad relativa");
  delay(1000);
  val = map(valor_medido, 0, 1023, 0, 255);           //Mapeo del valor medido al rango de salida de las salidas digitales para
                                                                           //encender el led.
  analogWrite(ledPin, val);
  delay(1000);
  Trans.print(val);                                                    //Transmisión del valor a NodeMCU.
  delay(1000); 
}


En el NodeMCU he cargado el código siguiente. Lo que he hecho ha sido leer el valor enviado de 8 bits y mapearlo para obtener el float y seguidamente realizar la operación para obtener de nuevo el valor de 'LR' y enviarlo al monitor serie para visualizarlo. El problema es que solo me ha mostrado un valor en el monitor serie del NodeMCU en letras raras para nada un valor numérico.

Code: [Select]

#include <SoftwareSerial.h>

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

}

void loop() {
   
  if (Serial.available()>0)

  {
    char byte_leido = Serial.read();
    float valor_medido=map(byte_leido, 0, 255, 0, 1023);
    float LR=((valor_medido*100)/1023);
    Serial.print(LR);
  }

}


En cuanto a las conexiones y configuración de ambas placas, he alimentado Arduino Uno y NodeMCU mediante USB una vez he cargado los códigos en cada placa. Habiendo seleccionado en cada caso la placa y el puerto correspondiente. Entre el pin 3 del Arduino que es el de Tx y el pin Rx de NodeMCU he puesto el divisor de tensión para obtener los 3,3V, conectando además los GND de cada placa y el del divisor entre sí como he leído en otros tutoriales. El resultado del monitor serie del NodeMCU es el que te he comentado antes, una sola recepción en letras raras.

¿Sabes donde puede estar el fallo de porqué no recibo bien las medidas en NodeMCU?
¿Qué fallos le ves a los códigos para que no se establezca bien la comunicación y los envíos?

He leído algo de que hay que conectar la primera vez el reset del NodeMCU a GND o algo así para que funcione, de esto último no lo tengo muy claro.

P.D.: En el monitor serie de Arduino Uno se visualiza correctamente las medidas de LR cada x tiempo.

Code: [Select]


26.20 % luminosidad relativa
27.96 % luminosidad relativa
28.54 % luminosidad relativa
34.51 % luminosidad relativa
31.77 % luminosidad relativa
17.01 % luminosidad relativa
11.73 % luminosidad relativa
25.22 % luminosidad relativa
27.57 % luminosidad relativa



Saludos y gracias de nuevo. Un abrazo.

surbyte

Hay algunos errores como este en el nodemcu

Code: [Select]
float valor_medido=map(byte_leido, 0, 255, 0, 1023);

map esta armada para enteros o enteros largos.

Code: [Select]
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


No para float asi que esa funcion no esta bien implementada.
Luego esto conceptualmente... si envias 8 bits no puedes conseguir 10 gratis!!!

Si bajas de 10 a 8 como hiciste en el emisor, ya esta decidido y te quedas con 8 bits.

Porque no envias solo el valor de analogRead o sea unsigned int, que necesidad de convertirlo a float si no suma nada, por el contrario resta.

EMISOR

Code: [Select]
unsigned int valor_medido;                                //Valor obtenido al leer por A0.
int ledPin = 10;                                     //Pin de conexión del led de prueba.
float LR;                                               //Variable para almacenar la luminosidad relativa.
float val;                                              //Variable empleada para el mapeo del valor medido para enviarlo al pin 10.

void setup()
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  Trans.begin(115200);                           //Velocidad de envío para la transmisión al NodeMCU.
}

void loop()
{
  valor_medido = analogRead(A0);                      //Valor de luminosidad medido en A0
  LR = (valor_medido * 100) / 1023.0;                   //Luminosidad medida en tanto por ciento
  Serial.print(LR);                                               //Para mostrar el valor en el monitor serie de arduino.
  Serial.println(" % luminosidad relativa");
  delay(1000);                                                                           //encender el led.
  analogWrite(ledPin, val);
  delay(1000);
  Trans.print(valor_medido);                                                    //Transmisión del valor a NodeMCU.
  delay(1000); 
}



Receptor
Code: [Select]
//Declaración de variables del proceso
#include <SoftwareSerial.h>

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

void loop() {
   
  if (Serial.available()>0)   {
      int one = Serial.read();
      int two = Serial.read();

      unsigned int valor_medido = ( one - 48) *10 + (two - 48);

      float LR = ((valor_medido*100.0)/1023.0);
      Serial.print(LR);
  }
}


Prueba esto a ver si lee lo que estas enviando.



josekiki

Buenas surbyte dos dudas. En el código del emisor, puedo mantener el mapeo para poder encender el led cambiando la variable 'val' a unsigned int o int por ejemplo, ¿es así?.

En el código del receptor, por no dedicarme solo a copiar y pegar sin entender veo que aquí:

Quote
unsigned int valor_medido = ( one - 48) *10 + (two - 48);
Entiendo que lo que hace esta línea es unir los dos enteros para obtener el valor medido, pero ¿a qué se debe que se reste 48 y en el primer sumando, además, se multiplique por 10?.

Voy a cargar y probar los códigos y te comento.

Muchas gracias de nuevo. Un abrazo.

josekiki

Buenas surbyte de nuevo. No me funciona, solo hace una lectura el NodeMCU y aparecen letras y símbolos sin sentido. Te agrego esquema del montaje con el divisor para obtener los 3,3 V para ver si es correcto y la configuración seleccionada para el NodeMCU. Tengo el NodeMCU v1.0.

Las velocidades de envío tanto en el código de arduino Uno y en NodeMCU para el envío a node están fijadas a 115200.

Arduino Uno
Code: [Select]
Trans.begin(115200);
  

NodeMCU
Code: [Select]
Serial.begin(115200);
  

En el monitor serie también. Nada más por ahora, de nuevo muchas gracias. Un abrazo.






surbyte

Cuando postes imagenes adjuntas tomate el trabajo de acuerdo a las normas de agregarlas con etiquetas para que sean visibles.
Aca puedes verlo
COMPLEMENTARIO: Como adjuntar una imagen adjunta

En la segunda foto se ve tu monitor serie y tmb se lee 115200 y en los dos códigos pusimos 9600 para los puertos Serie.
No me importa si los puertos virtuales estan a 115200 bps

Corrige eso.

josekiki

Sí, es que tanto en el código de Arduino Uno como en el del NodeMCU modifiqué las velocidades del monitor serie de 9600 a 115200, es decir tanto en código como en la ventana de monitor serie están a 115200 voy a ponerlos de nuevo a 9600 dejando los puertos virtuales a 115200. Postearé despues la imagen del monitor serie para mostrarte los resultados y para aprender a agregar las imágenes segun las normas a ver si lo hago de manera correcta. Gracias. Un abrazo surbyte.

josekiki

#24
Apr 09, 2018, 12:14 pm Last Edit: Apr 09, 2018, 03:59 pm by surbyte Reason: poner la imagen como recoge la norma del foro
Buenas surbyte ya he hecho la modificación que me comentabas y sigue igual, solo se ve una recepción y sigue siendo caracteres y símbolos raros. Te pego la imagen para que puedas verlo. No se si estará mal configurado los parámetros que se ven en la ventana desplegable de elección del módulo que se ve en la foto. Un abrazo.





AlexLPD

Creo que vas bien, solo que no estas llamando la funcion enviar por soft serial.

Mas sencillo creo yo que te va a ser;

Armar dos arduino uno, conectados por puerto soft serial.

Y empezar a enviar y recibir datos en uno y en otro, la razon es sencilla; es mas rapido de programar y puedes ver al mismo tiempo, los dos seriales.

Alguna vez hice algo asi, vas a requerir de los ejemplos del IDE de arduino, viene uno donde "lee" un puerto serial y una vez que lo "lee" espera un caracter de terminación /0, me parece.

Otra cuestión que desconozco y que estaría bueno definir es, tus datos son int o float, y para thingspeak se requiere pasar strings, asi que, considero si debes definir como vas a transmitir los datos de uno a otro:

El primer arduino obtendra los datos y los envia al segundo, mediante; int? float? string?

Son cuestiones que creo que creo que van a necesitar solucion.


Saludos.
-Alex.

josekiki

Hola AlexLPD, antes de nada agradecerte tu colaboración. Ya conseguí con ayuda de surbyte que NodeMCU recibiese los valores de LR leidos en arduino uno con el código que ves debajo para cada módulo. Había porblemas de configuración y de la entrada Rx del NodeMCU.

Por otro lado, ¿a qué te refieres con:
Quote
Creo que vas bien, solo que no estas llamando la funcion enviar por soft serial.
¿Cuál es la función de enviar por softserial? Disculpa mi desconocimiento.

Otro tema en el que tienes toda la razón según comentas es el tipo de dato.
Quote
Otra cuestión que desconozco y que estaría bueno definir es, tus datos son int o float, y para thingspeak se requiere pasar strings, asi que, considero si debes definir como vas a transmitir los datos de uno a otro:

El primer arduino obtendra los datos y los envia al segundo, mediante; int? float? string?
Al final decidimos enviar a NodeMCU el valor medido directamente en A0 en rango 0-1023 como puedes ver y luego en el código de NodeMCU convertirlo en float y añadirlo como string precedido por la cadena de caracteres "luminosidad relativa =". De esta manera el resultado en el monitor serie de cada módulo es el que puedes ver abajo.

Ahora viene lo importante y lo que llevo atascado desde que conseguimos enviar y recibir los valores. Desde arduino voy a enviar a NodeMCU las lecturas secuenciales de varios sensores. En NodeMCU tengo que ir leyendo y distinguiendo entre los distintos valores que van llegando porque unos serán temperatura, otro luminosidad, humedad, etc y se irán recibiendo en cada ejecución del void loop() en este orden. Como bien dices, para subirlos a thingspeak hay que pasarlos a String y aquí es donde viene mi problema. Surbyte me sugirió indagar en la posibilidad que aparece comentada en el código de arduino a continuación de "Trans.println(valor_medido);" y a continuación de "int valor_medido = mySerial.parseInt();" en el código de NodeMCU para no usar el parseint().
¿Cómo lo consigo?
He leido googleando que hay una función dtrost o algo así pero estoy pegado. Y luego otro problema gordo es cómo subir todos estos datos a thingspeak mediante protocolo MQTT, el cual también envía los datos como String, pero bueno creo que antes que esto hay que solucionar todo lo referente al envio y recepción de datos entre arduino y NodeMCU para no perder ningun valor y poder extraerlos correctamente del buffer.

Voy a seguir indagando. Para cualquier sugerencia espeero vuestra ayuda como siempre por aquí. Muchisimas gracias. Un abrazo.




CODIGO ARDUINO UNO

Code: [Select]

#include <SoftwareSerial.h>

#define rxPin 2
#define txPin 3
 
SoftwareSerial Trans(rxPin, txPin);               //Pines para Rx y Tx.

//Declaración de variables del proceso

unsigned int valor_medido;                        //Valor obtenido al leer por A0.
int ledPin = 10;                                  //Pin de conexión del led de prueba.
float LR;                                         //Variable para almacenar la luminosidad relativa.
int val;                                          //Variable empleada para el mapeo del valor medido para enviarlo al pin 10.

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode (txPin , OUTPUT);
  Serial.begin(9600);
  Trans.begin(9600);                            //Velocidad de envío para la transmisión al NodeMCU.
}

void loop()
{
  valor_medido = analogRead(A0);                      //Valor de luminosidad medido en A0
  LR = (valor_medido * 100.0) / 1023.0;               //Luminosidad medida en tanto por ciento
  Serial.print(LR);                                              //Para mostrar el valor en el monitor serie de arduino.
  Serial.println(" % luminosidad relativa");
  delay(1000);
  val = map(valor_medido, 0, 1023, 0, 255);       //Mapeo del valor medido al rango de salida de las...
                                                                       //salidas digitales para encender el led.
  analogWrite(ledPin, val);
  delay(1000);
  Trans.println(valor_medido);                             //Transmisión del valor a NodeMCU.

  // Trans.print(valor_medido);                         //Para cuando quiera enviar varios parámetros...
                                                                      //separados por comas. La coma además
  // Trans.print(',');                                         //sirven como identificador de parámetro nuevo recibido.
  // Trans.print(humedad);
  // Trans.print(',');
  delay(1000);
}


CODIGO NODEMCU


Code: [Select]


SoftwareSerial mySerial(13, 15); // RX, TX
float LR;

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

void loop()
{
   if (mySerial.available()>0)
   {
      int valor_medido = mySerial.parseInt();                     //El parseInt funciona cuando en arduino..
                                                                                     //usamos un println en vez de un print.
                                                                                     //Para cuando midamos varios parámetros,
                                                                                     //leerá la cadena hasta la coma que....
                                                                                     //corresponderá a una medida.
      // String str = mySerial.readStringUntil(',');
      // int data = str.toInt();
     
      if (valor_medido != 0)
      {
          LR = ((valor_medido*100.0)/1023.0);
          Serial.println("Luminosidad relativa ="+ String(LR));
      }
  }
  // envio a ThingSpeak
}



MONITOR SERIE ARDUINO UNO

Code: [Select]

 
72.53 % luminosidad relativa
72.43 % luminosidad relativa
70.28 % luminosidad relativa
72.73 % luminosidad relativa
70.19 % luminosidad relativa
72.14 % luminosidad relativa
72.14 % luminosidad relativa
72.24 % luminosidad relativa



MONITOR SERIE NODEMCU

Code: [Select]


Luminosidad relativa =72.53
Luminosidad relativa =72.43
Luminosidad relativa =70.28
Luminosidad relativa =72.73
Luminosidad relativa =70.19
Luminosidad relativa =72.14
Luminosidad relativa =72.14
Luminosidad relativa =72.24


jlsogorb

Sobre lo de Thingspeak no te preocupes de momento, tengo preparado un pequeño documento que te dará pistas sobre como hacerlo, pero no te lo he querido mandar todavía para que vayas solucionado poco a poco los  frentes que tienes abiertos.

josekiki

Me gusta esa idea jlsogorb, MOTIVACIÓN, sí señor jejejej. Perfecto, voy a ver si consigo acabar esa parte y lo pongo por aquí y cogemos la de thingspeak. En cuanto a Thingspeak no sé si usar la librería de thingspeak o protocolo MQTT que es más eficiente según he leido. He leido algo de usar GET y POST o la libreria mencionada o Publish/Subscribe en el caso de MQTT, también he visto algo de comandos AT. En todos los casos me suena a chino jeje. Ya lo vemos una vez solucione el tema de los datos y me aconsejáis. Muchas gracias. Un abrazo.

jlsogorb

Yo te mostraré una manera sencilla, tú luego ya lo complicas todo lo que quieras  ;)

Go Up