Arduino Yun – Sistema de Adquisición de Datos – Datalogger (parte 2)

Se va a definir una función que recibe peticiones del subsistema linux mediante Bridge y los servicios web REST, y también del puerto serie para depuración. Tendrá la siguiente funcionalidad básica:

  • parámetros de entrada: numero de señal, número de repeticiones, tiempo entre repeticiones, filtrado de extremos (SI o NO), tipo de cálculo (media, min, max, acum)
  • parámetros de salida: estadístico solicitado según los parámetros de entrada
  • si se coloca un RTC, hay que dotar de las funciones de lectura y escritura de la hora.

El Sketch se puede encontrar en esta web RESTDataCom.zip o en https://github.com/adanpi/yunlogger/blob/master/sketches/RESTDataCom.ino

Actualización 19/02/2015. Se incorporan al sketch las funcionalidades:

Incorporado a 29 de diciembre de 2014

Funciones de escritura de servomotor: http://yun/usr-cgi/luci/arduino/servo/9/180

Funciones de lectura de digitales 10,11 y 12 en bloque, con digital -1 (/arduino/digital/-1)

11 de Febrero de 2014: se incorpora lectura modbus por rs232 de otro arduino

Fin Actualización 19/02/2015

Actualizado a 17/12/2014, se incorporan funciones de tiempo para RTC, lectura y escritura. Si se emplea un RTC es conveniente anular NTP y ajustar la fecha-hora manualmente.

Funciones de tiempo: time 1-> leer fecha/hora del RTC, devuelve unixtime en segundos (desde 1-1-1970)
2-> leer fecha/hora del RTC, devuelve formato string (dd/MM/aaaa hh:mm:ss)
3-> establecer fecha/hora, parmetros: traza,año,mes,dia,hora,minuto,segundo

http://localhost/usr-cgi/luci/arduino/time/1,1

http://yun/usr-cgi/luci/arduino/time/1,2

http://yun/usr-cgi/luci/arduino/time/1,3,2014,12,17,16,30,10

Hay que desactivar NTP por ahora, ya se verá si es necesario emplear los dos métodos de sincronización de hora.


/etc/init.d/sysntpd stop
/etc/init.d/sysntpd disable

Hay que proveer de alguna utilidad para establecer la fecha del sistema al arrancar una vez leída del RTC. Manualmente sería algo así:

date --set "2014-03-13 02:05:45"

Se realizará esta tarea dentro de el proceso AxionMain del sistema yunlogger.

Fin Actualización 17/12/2014


  /*
 
    RESTDataCom
   
   Extended example Bridge library to access the digital and analog pins
   on the board through REST calls. It demonstrates how
   you can create your own API when using REST style
   calls through the browser.
   
   Possible commands created in this shetch:
 
   * "/arduino/digital/13"     -> digitalRead(13)
   * "/arduino/digital/13/1"   -> digitalWrite(13, HIGH)
   * "/arduino/analog/2/123"   -> analogWrite(2, 123)
   * "/arduino/analog/2"       -> analogRead(2)
   * "/arduino/mode/13/input"  -> pinMode(13, INPUT)
   * "/arduino/mode/13/output" -> pinMode(13, OUTPUT)
   
   This example code is part of the public domain
   
   http://arduino.cc/en/Tutorial/Bridge
 
    
   Extendido para Sistema de adquisicion de datos Arduino yun: yunlogger
 
  Funciones de adquisicion de datos: data 1-> tomar medida sensor ultrasonidos Params:(traza, funcion, Num Señal (1=ultrasonidos), Num Repeticiones,Tiempo entre Repeticiones, filtrar Extremos, calculo: med,max,min,suma)
   ejemplo de uso: 0,1,3,8,1000,1 (traza inactiva 0, funcion 1, señal 3, 8 repeticiones, intervalo de 1000 ms entre rep., eliminar extremos,  calculo Media)
 
  Ejemplos:
  http://localhost/usr-cgi/luci/arduino/analog/2
  http://localhost/usr-cgi/luci/arduino/data/0,1,1,5,200,1,1
  http://yun/usr-cgi/luci/arduino/data/1,1,1,5,200,1,1
 
  Incorporado a 17 de diciembre de 2014
 
  Funciones de tiempo: time 1-> leer fecha/hora del RTC, devuelve unixtime en segundos (desde 1-1-1970)
                            2-> leer fecha/hora del RTC, devuelve formato string (dd/MM/aaaa hh:mm:ss)
                            3-> establecer fecha/hora, parmetros: traza,año,mes,dia,hora,minuto,segundo
                            
  http://localhost/usr-cgi/luci/arduino/time/1,1
  http://yun/usr-cgi/luci/arduino/time/1,2
  http://yun/usr-cgi/luci/arduino/time/1,3,2014,12,17,16,30,10
 
  */
 
  #include <Bridge.h>
  #include <YunServer.h>
  #include <YunClient.h>
  #include <Wire.h>
  #include "RTClib.h"
  RTC_DS1307 RTC;
 
  // Listen on default port 5555, the webserver on the Yun
  // will forward there all the HTTP requests for us.
  YunServer server;
 
  // para depuracion, siempre activo depurar desde Serial
  // info trace con parametro trace=1
  //#define DEBUG 1
  #define CODIGO_ERROR -9999
 
  char incomingByte;      // a variable to read incoming client data into
  int numSen=0,numRep=0,tiempoRep=1000,filtrar=1,calculo=1,trace=0;
 
  // para lectura de sensor de ultrasonidos
  #include <Ultrasonic.h>
  //Ultrasonic ultrasonic(5,6); // (Trig PIN,Echo PIN)
  // centímetros * 58 = Max.TimeOut
  Ultrasonic ultrasonic(5,6,20000); // (Trig PIN,Echo PIN,Max.TimeOut in µsec )
 
 
  void setup() {
    Serial.begin(9600);
    // Bridge startup
    pinMode(13,OUTPUT);
    digitalWrite(13, LOW);
    Bridge.begin();
    digitalWrite(13, HIGH);
    
      // inicializar sensor ultrasonidos
    pinMode(4, OUTPUT); // VCC pin
    pinMode(7, OUTPUT); // GND ping
    digitalWrite(4, HIGH); // VCC +5V mode  
    digitalWrite(7, LOW);  // GND mode
 
    // Listen for incoming connection only from localhost
    // (no one from the external network could connect)
    server.listenOnLocalhost();
    server.begin();
    
      Wire.begin();
      RTC.begin();
  }
 
  void loop() {
    // Get clients coming from server
    YunClient client = server.accept();
 
    // There is a new client?
    if (client) {
      // Process request
      process(client);
 
      // Close connection and free resources.
      client.stop();
    }
 
    delay(50); // Poll every 50ms
  }
 
  void process(YunClient client) {
    // read the command
    String command = client.readStringUntil('/');
 
    // is "digital" command?
    if (command == "digital") {
      digitalCommand(client);
    }
 
    // is "analog" command?
    if (command == "analog") {
      analogCommand(client);
    }
 
    // is "mode" command?
    if (command == "mode") {
      modeCommand(client);
    }
    
    // is "data" command?
    if (command == "data") {
      dataCommand(client);
    }  
    
      // is "time" command?
    if (command == "time") {
      timeCommand(client);
    }  
    
  }
 
  void timeCommand(YunClient client) {
    
      // read the oldest byte in the client buffer:
      incomingByte = client.read();
      // ver si hay que sacar info de traza
      if (incomingByte == '1')
        trace=1;
      else
        trace=0;
   
       if (trace)
        client.println(incomingByte);
      // read the next byte in the client buffer, coma
        incomingByte = client.read();
      // leer func.
        incomingByte = client.read();      
      //parse commands and functions:
      
       if (incomingByte == '1') {
          if (trace){
            client.println("1-> unix time seconds");
          }
       if (! RTC.isrunning()) {
      client.println("RTC is NOT running!");
      return;
      }
          DateTime now = RTC.now();
          client.println(now.unixtime(),3);
        } else if (incomingByte == '2') {
          if (trace){
            client.println("2-> unix time string");
          }
      if (! RTC.isrunning()) {
      client.println("RTC is NOT running!");
      return;
      }
      DateTime now = RTC.now();    
      if(now.day()<10)  client.print('0');
      client.print(now.day(), DEC);        
      client.print('/');
      if(now.month()<10)  client.print('0');
      client.print(now.month(), DEC);
      client.print('/');
      client.print(now.year(), DEC);    
      client.print(' ');
      if(now.hour()<10)  client.print('0');
      client.print(now.hour(), DEC);
      client.print(':');
      if(now.minute()<10)  client.print('0');
      client.print(now.minute(), DEC);
      client.print(':');
      if(now.second()<10)  client.print('0');
      client.print(now.second(), DEC);
      client.println();
 
        } else if (incomingByte == '3') {
          if (trace){
            client.println("3-> set RTC time");
          }
        // variables establecer fecha
        int anio=-1,mes=-1,dia=-1,hora=-1,minuto=-1,sec=-1;
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          anio = client.parseInt();
          if (trace){
            client.print("anio ");
            client.println(anio);
          }
        }        
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          mes = client.parseInt();
          if (trace){
            client.print("mes ");
            client.println(mes);
          }
        }   
              
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          dia = client.parseInt();
          if (trace){
            client.print("dia ");
            client.println(dia);
          }
        }
                
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          hora = client.parseInt();
          if (trace){
            client.print("hora ");
            client.println(hora);
          }
        }
                
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          minuto = client.parseInt();
          if (trace){
            client.print("min ");
            client.println(minuto);
          }
        }
                
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          sec = client.parseInt();
          if (trace){
            client.print("sec ");
            client.println(sec);
          }
        }
        
         if (! RTC.isrunning()) {
          client.println("RTC is NOT running!");
        return;
        }
        if (!(anio!=-1 & mes!=-1 & dia!=-1 & hora!=-1 & minuto!=-1 & sec!=-1)){
         client.println("faltan parametros");
        return;
        }
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
      
      RTC.adjust(DateTime(anio, mes, dia, hora, minuto, sec));
      
          } else if(incomingByte == '/'){
                if (trace){
            client.println(incomingByte);
            client.println("funcion desconocida");
          }
          client.println(CODIGO_ERROR);
      }else{
          if (trace){
            client.println(incomingByte);
            client.println("funcion desconocida");
          }
          client.println(CODIGO_ERROR);
      }
    
  }
 
 
  void dataCommand(YunClient client) {
    
      // read the oldest byte in the client buffer:
      incomingByte = client.read();
      // ver si hay que sacar info de traza
      if (incomingByte == '1')
        trace=1;
      else
        trace=0;
        
      if (trace)
        client.println(incomingByte);
      // read the next byte in the client buffer, coma
        incomingByte = client.read();
      // leer func.
        incomingByte = client.read();      
      //parse commands and functions:
      if (incomingByte == '1') {
          if (trace){
            client.println("1-> tomar medida señal");
          }
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          numSen = client.parseInt();
          if (trace){
            client.print("numSen ");
            client.println(numSen);
          }
        }        
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          numRep = client.parseInt();
          if (trace){
            client.print("numRep ");
            client.println(numRep);
          }
        }
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          tiempoRep = client.parseInt();
            if (trace){
              client.print("tiempoRep ");
              client.println(tiempoRep);
            }
        }
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          filtrar = client.parseInt();
            if (trace){
              client.print("filtrar ");
              client.println(filtrar);
            }
        }
        // read the next byte in the client buffer, coma
        incomingByte = client.read();
        if (incomingByte == ',') {        
          // read the next byte in the client buffer like Integer
          calculo = client.parseInt();
            if (trace){
              client.print("calculo ");
              client.println(calculo);
            }
        }  
 
      client.println(medidaSensor(client),3);
      
      } else if(incomingByte == '/'){
                if (trace){
            client.println(incomingByte);
            client.println("funcion desconocida");
          }
          client.println(CODIGO_ERROR);
      }else{
          if (trace){
            client.println(incomingByte);
            client.println("funcion desconocida");
          }
          client.println(CODIGO_ERROR);
      }
    
  }
 
 
  void digitalCommand(YunClient client) {
    int pin, value;
 
    // Read pin number
    pin = client.parseInt();
 
    // If the next character is a '/' it means we have an URL
    // with a value like: "/digital/13/1"
    if (client.read() == '/') {
      value = client.parseInt();
      digitalWrite(pin, value);
    }
    else {
      value = digitalRead(pin);
    }
 
    // Send feedback to client
    client.print(F("Pin D"));
    client.print(pin);
    client.print(F(" set to "));
    client.println(value);
 
    // Update datastore key with the current pin value
    String key = "D";
    key += pin;
    Bridge.put(key, String(value));
  }
 
  void analogCommand(YunClient client) {
    int pin, value;
 
    // Read pin number
    pin = client.parseInt();
 
    // If the next character is a '/' it means we have an URL
    // with a value like: "/analog/5/120"
    if (client.read() == '/') {
      // Read value and execute command
      value = client.parseInt();
      analogWrite(pin, value);
 
      // Send feedback to client
      client.print(F("Pin D"));
      client.print(pin);
      client.print(F(" set to analog "));
      client.println(value);
 
      // Update datastore key with the current pin value
      String key = "D";
      key += pin;
      Bridge.put(key, String(value));
    }
    else {
      // Read analog pin
      value = analogRead(pin);
 
      // Send feedback to client
  //    client.print(F("Pin A"));
  //    client.print(pin);
  //    client.print(F(" reads analog "));
      client.println(value);
 
      // Update datastore key with the current pin value
      String key = "A";
      key += pin;
      Bridge.put(key, String(value));
    }
  }
 
  void modeCommand(YunClient client) {
    int pin;
 
    // Read pin number
    pin = client.parseInt();
 
    // If the next character is not a '/' we have a malformed URL
    if (client.read() != '/') {
      client.println(F("error"));
      return;
    }
 
    String mode = client.readStringUntil('\r');
 
    if (mode == "input") {
      pinMode(pin, INPUT);
      // Send feedback to client
      client.print(F("Pin D"));
      client.print(pin);
      client.print(F(" configured as INPUT!"));
      return;
    }
 
    if (mode == "output") {
      pinMode(pin, OUTPUT);
      // Send feedback to client
      client.print(F("Pin D"));
      client.print(pin);
      client.print(F(" configured as OUTPUT!"));
      return;
    }
 
    client.print(F("error: invalid mode "));
    client.print(mode);
  }
 
 
  // metodo encargado de las diferentes medidas
  double medidaSensor(YunClient client){
 
    double medida=CODIGO_ERROR,maximo,minimo;
    double medidas[numRep];  
    int indiceMax=0,indiceMin=0,indiceAux=0;
    boolean iniciadosValores=false;  
         
  switch (numSen){
    // ultrasonidos
     case 1:
 
         for (int rep=0;rep<numRep;rep++){
             double medida=ultrasonic.Ranging(CM);
             if (trace)
              client.println(medida);
             medidas[rep] = medida;
             if(medida>medidas[indiceMax])
               indiceMax=rep;
             if(medida<medidas[indiceMin])
               indiceMin=rep;     
             // intervalo de espera entre medidas
             delay(tiempoRep);
         }    
             // si los indices coinciden es que todas las medidas son iguales
              if(indiceMax==indiceMin)
                indiceMax=indiceMin++;
                  if (trace){
                    client.println("Indices extremos");
                    client.println(indiceMax);
                    client.println(indiceMin);
                  }   
                    Serial.println("Indices extremos");
                    Serial.println(indiceMax);
                    Serial.println(indiceMin);                 
         // filtro de extremos:
         if(filtrar){
           for (int rep=0;rep<numRep;rep++){
             if(rep==indiceMax)
              continue;
             if(rep==indiceMin)
               continue;
               
               if(!iniciadosValores){
                 maximo=medidas[rep];
                 minimo=medidas[rep];
                 medida=0;               
                 if (trace){
                  client.println("inicializar medida");
                  client.println(medida);
                 }
                  Serial.println("inicializar medida");
                  Serial.println(medida);                
                  iniciadosValores=true;              
               }
               switch (calculo){
                  case 2:  // max
                     if(medidas[rep]>maximo)
                       maximo=medidas[rep];
                    break;
                  case 3:  //min
                     if(medidas[rep]<minimo)
                       minimo=medidas[rep];                  
                    break;                   
                   default:
                     medida=medida+medidas[rep];
               }
             }
              
           
              if (trace){
                  client.println("medida final");
                  client.println(medida);
               }
                  Serial.println("medida final");
                  Serial.println(medida);             
           //calculo final
               switch (calculo){
                 case 1:  // med
                  medida=medida/(numRep-2);
                    break;                 
                  case 2:  // max
                    medida=maximo;
                    break;
                  case 3:  //min
                    medida=minimo;                
                    break;                   
                   default:
                     medida=medida;
               }        
         }else{
            for (int rep=0;rep<numRep;rep++){
               if(!iniciadosValores){
                 maximo=medidas[rep];
                 minimo=medidas[rep];
                 medida=0;               
                 if (trace){
                  client.println("inicializar medida");
                  client.println(medida);
                 }
                  Serial.println("inicializar medida");
                  Serial.println(medida);                
                  iniciadosValores=true;              
               }
               switch (calculo){
                  case 2:  // max
                     if(medidas[rep]>maximo)
                       maximo=medidas[rep];
                    break;
                  case 3:  //min
                     if(medidas[rep]<minimo)
                       minimo=medidas[rep];                  
                    break;                   
                   default:
                     medida=medida+medidas[rep];
               }
             
              
           }
                if (trace){
                  client.println("medida final");
                  client.println(medida);
               }
                  Serial.println("medida final");
                  Serial.println(medida);              
           //calculo final
               switch (calculo){
                 case 1:  // med
                  medida=medida/(numRep);
                    break;                 
                  case 2:  // max
                    medida=maximo;
                    break;
                  case 3:  //min
                    medida=minimo;                
                    break;                   
                   default:
                     medida=medida;
               }         
           
         }
         break;
     default:
       break;
  }
 
                if (trace){
                  client.println("retorno");
                  client.println(medida);
               }
                  Serial.println("retorno");
                  Serial.println(medida);   
 
  return medida;
 
  }

Llamando desde un navegador a la URL: http://yun/arduino/data/1,1,5,1000,1,1

Responde (con DEBUG activo):

Pantallazo

Deja un comentario