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):

