Aislar una parte de la lectura (char) de un sernsor de conductividad electrica.

Hola, tengo en manos un proyecto que controla los motores de una planta desaladora dependiendo de la conductividad del agua. Tengo un sensor ES-2 : https://www.metergroup.com/environment/products/es-2/

este sensor se comunica mediante SDI-12 y entrega el valor de esta forma A+B+C, En el valor A entrega la dirección en el B la medida de conductividad y en el C la temperatura. El símbolo “+” actua como separador.

Yo necesito separar de la variable char que recibo el dato B para utilizarlo como condicional en el resto de mi codigo.

Como ejemplo para realizar las lectuas utilizo el siguiente codigo:

#include <SDI12.h>

#define SERIAL_BAUD 9600  // The baud rate for the output serial port
#define DATA_PIN 6         // The pin of the SDI-12 data bus
#define POWER_PIN 8      // The sensor power pin (or -1 if not switching power)
#define SENSOR_ADDRESS 1

// Define the SDI-12 bus
SDI12 mySDI12(DATA_PIN);

String sdiResponse = "";
String myCommand = "";

void setup(){
  Serial.begin(SERIAL_BAUD);
  while(!Serial);

  Serial.println("Opening SDI-12 bus...");
  mySDI12.begin();
  delay(500); // allow things to settle

  // Power the sensors;
  if(POWER_PIN > 0){
    Serial.println("Powering up sensors...");
    pinMode(POWER_PIN, OUTPUT);
    digitalWrite(POWER_PIN, HIGH);
    delay(200);
  }
}

void loop() {
  do {                           // wait for a response from the serial terminal to do anything
    delay (30);
  }
  while (!Serial.available());
  char nogo = Serial.read();     // simply hit enter in the terminal window or press send and
                                 // the characters get discarded but now the rest of the loop continues

//first command to take a measurement
  myCommand = String(SENSOR_ADDRESS) + "M!";
  Serial.println(myCommand);     // echo command to terminal

  mySDI12.sendCommand(myCommand);
  delay(30);                     // wait a while for a response

  while (mySDI12.available()) {  // build response string
    char c = mySDI12.read();
    if ((c != '\n') && (c != '\r')) {
      sdiResponse += c;
      delay(5);
      
    }
  }
  if (sdiResponse.length() > 1) Serial.println(sdiResponse); //write the response to the screen
  mySDI12.clearBuffer();


  delay(1000);                 // delay between taking reading and requesting data
  sdiResponse = "";           // clear the response string


// next command to request data from last measurement
  myCommand = String(SENSOR_ADDRESS) + "D0!";
  Serial.println(myCommand);  // echo command to terminal

  mySDI12.sendCommand(myCommand);
  delay(30);                     // wait a while for a response

  while (mySDI12.available()) {  // build string from response
    char c = mySDI12.read();
    if ((c != '\n') && (c != '\r')) {
      sdiResponse += c;
      delay(5);
    }
  }
  if (sdiResponse.length() > 1) Serial.println(sdiResponse); //write the response to the screen
  mySDI12.clearBuffer();

//now go back to top and wait until user hits enter on terminal window


Serial.println(sdiResponse);
}

Para separar el dato que recibo he estado probrando la funcion strtok:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

en muchos ejemplos veo que separan los datos situados entre “,” “.” o “-” pero nada sobre el simbolo “+”.
No recibo respuesta ninguna porque supongo que no se comple la condicion:

while (pch != NULL)

lo que hago es sustituir en el codigo strtok de ejemplo las variables char del las lecturas del primer codigo.
No se si estoy entendiendo algo mal, Me gustaria encontrar la forma mas sencilla de separar los datos porque el resto del codigo es bastante extenso. Gracias de antemano !

Fijate en el ejemplo d_simple_logger de la librería SDI-12 como hacen para separar las lecturas.
Te pongo un fragmento solo para que sepas donde mirar

    mySDI12.read();           // ignore the repeated SDI12 address
    char c = mySDI12.peek();  // check if there's a '+' and toss if so
    if (c == '+') { mySDI12.read(); }

Saludos

Saludos gatul, he estado mirando y no veo en el ejemplo en que momento separa los datos, he estado probando y no termina de funcionarme correctamente, solo me funciono una vez y en el monitor serie habia leido el nombre del dispositivo y los mismos datos que yo recibo pero separados por ",". Mi idea es meter el valor en un entero en determinados momentos de mi codigo para realizar una media del valor a lo largo de un tiempo. Si tu si que ves el momento en que los separa ¿podrías mostrármelo ? Muchas gracias por tu respuesta.

EDITO: Perdon no habia visto la parte que me copiaste, aun asi no encuentro esas lineas y en el programa de ejemplo, solo para asegurar, ¿en que linea esta exactamente?

¿Dónde separa? Exactamente en la 2da y 3er línea de las que te puse de guía, ahí detecta el ‘+’ y empieza a leer lo que sigue.
Ese trozo de código forma parte de la función getResults() del ejemplo que te nombré.

Saludos

Si, perdón por el malentendido pero no logro encontrar ni la función ni las líneas que me has dicho antes, solo para asegurar ¿Podrias comprobar si el sketch que te adjunto es el mismo que tu ejemplo? espero no estar equivocado porque he revisado como 10 veces y no lo encuentro dentro del ejemplo que yo tengo :confused:

PD: no lo escribo aquí porque es demasiado largo para postearlo.

d_simple_logger.ino (9.41 KB)

Efectivamente no es el mismo ejemplo. ¿Será la misma librería?
Ejemplo en github
Fijate a partir de la línea 116.

Saludos

Hola, me he adueñado de este trozo del programa y lo he añadido al programa de ejemplo f_basic_data_request

uint8_t resultsReceived = 0;
      uint32_t start = millis();
    while (mySDI12.available() < 3 && (millis() - start) < 1500) {}
    mySDI12.read();           // ignore the repeated SDI12 address
    char c = mySDI12.peek();  // check if there's a '+' and toss if so
    if (c == '+') { mySDI12.read(); }

No tengo muy claro como añadirlo a las medidas que yo realizo para obtener el dato que me interesa en una int y compararla después…
Seguiré probando pero si alguien tiene algo preparado y puede compartirlo seria de gran ayuda!!
Muchas gracias !!

Después de eso que copiaste

while (mySDI12.available()) {
  float result1 = mySDI12.parseFloat(SKIP_NONE);
// o 
  int result1 = mySDI12.parseInt(SKIP_NONE);   
// segun el parámetro sea float o entero 

  char c = mySDI12.peek(); 
  if (c == '+') { mySDI12.read(); }
  float result2 = mySDI12.parseFloat(SKIP_NONE);
// o
  int result2 = mySDI12.parseInt(SKIP_NONE); 
}

peek() consulta el 1er. caracter del buffer pero no lo saca del buffer por eso si es '+' inmediatamente lo lee para quitarlo y después leer la cifra.
Más o menos es esto lo que tenés que hacer, fijate si tenés que corregir algo, es solo para darte una idea.

La otra es hacer lo tradicional, leer todo lo entrante y guardarlo en un array, convertilo a String y después ir cortando el string en trozos y convertirlo a numeros.

Puedes poner la comunicación que estas haciendo, el comando y su respuesta tal como la ves en tu Monitor Serie?

Buenas, la comunicacion la inicio en mi proyecto de esta forma:

#include <SDI12.h>

#define SERIAL_BAUD 9600  // The baud rate for the output serial port
#define DATA_PIN 11         // The pin of the SDI-12 data bus
#define POWER_PIN 12      // The sensor power pin (or -1 if not switching power)
#define SENSOR_ADDRESS 1
// Define the SDI-12 bus
SDI12 mySDI12(DATA_PIN);

String sdiResponse = "";
String myCommand = "";

void setup() {
  Serial.begin(SERIAL_BAUD);
  while (!Serial);

  Serial.println("Opening SDI-12 bus...");
  mySDI12.begin();
  delay(500); // allow things to settle

  // Power the sensors;
  if (POWER_PIN > 0) {
    Serial.println("Powering up sensors...");
    pinMode(POWER_PIN, OUTPUT);
    digitalWrite(POWER_PIN, HIGH);
    delay(200);
  }

...

la parte en la que comunico con el sensor dentro de mi proyecto es esta:

  //first command to take a measurement
  
  mySDI12.sendCommand("1M!");
  delay(30);                     // wait a while for a response

  while (mySDI12.available()) {  // build response string
    char c = mySDI12.read();
    if ((c != '\n') && (c != '\r')) {
      sdiResponse += c;
      delay(5);

    }
  }
  mySDI12.clearBuffer();



  tempoREC = tempoREC + 1;    //contador para el arranque.
  Serial.println(tempoREC);
  delay(1000);


 sdiResponse = "";           // clear the response string


// next command to request data from last measurement

  mySDI12.sendCommand("1D0!");
  delay(30);                     // wait a while for a response

  while (mySDI12.available()) {  // build string from response
    char c = mySDI12.read();
    if ((c != '\n') && (c != '\r')) {
      sdiResponse += c;
      delay(5);
    }
  }
  if (sdiResponse.length() > 1) Serial.println(sdiResponse); //write the response to the screen
  mySDI12.clearBuffer();
delay(1000);

Si os fijais primero mando el comando 1M! para que el sensor tome una lectura y después de un segundo mando el comando 1D0! para recibir una lectura.

las lecturas que recibo pueden ser por ejemplo "11+430+16", por lo que he investigado creo que el primer valor es la dirección que tiene el sensor ( la 1 ) pero por alguna razón la manda repetida, el siguiente valor es la conductividad que varia cuando voy cambiando la sonda por distintas aguas y la tercera debería ser la temperatura (aun no lo tengo claro 100%).

Este es el sensor que utilizo: https://www.metergroup.com/environment/products/es-2/
la idea es sacar el segundo valor a un entero para compararlo con una consigna de conductividad eléctrica.

Si hubieses mirado con atención lo que publiqué hubieses visto este comentario

// ignore the repeated SDI12 address

que significa literalmente

// ignora la dirección SDI12 repetida

Todo lo que necesitas está en el código que te pasé, solo debes implementarlo en tu código.

Saludos

Hola gatul, si que me había fijado en que en lo que me pasaste ignora la dirección repetida, solo intentaba poner en situación a subryte, me refería a que no se porque la manda repetida, igualmente mi única intención es sacar el dato de en medio a un entero, la dirección y la temperatura de momento no las necesito así que prefiero omitir las partes que no voy a utilizar para que quede lo mas comprimido posible.

Perdón por la ignorancia pero con mis escasos conocimientos y al no comprender del todo lo que ocurre en cada linea no he conseguido adaptar tu aporte a mi código para extraer la variable que me interesa.. he estado probando a integrar tu aporte de diferentes formas sobre el programa de ejemplo de la librería que hace una lectura simple y si lo consiguiese ahí lo integraría en mi proyecto.

En las pruebas que he realizado muchas veces me cargo el código y dejo de recibir lecturas directamente o simplemente la variable en la que supuestamente estoy introduciendo el dato que me interesa es igual a 0.

Ya te digo que no he pasado de tus aportes, me han servido para intentarlo varias veces pero sin resultados, Un saludo y gracias.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.