Buenas. Les dejo el codigo. Es bastante largo, pero esta casi todo comentado en que es lo que hago (asi yo no me pierdo en la misma programacion)
el void loop espera actividad del lector de QR y, una vez tiene algo, va al bucle secuencial 'principal'
comprueba a traves de la conexion de red en un servidor web (que esta conectado a la base de datos) si lo ingresado es correcto o no. Si esta autorizado habilita la pantalla de carga. a traves de una botonera puedo bajar o subir lo que deseo cargar. una vez presionado cargar, comienza la carga hasta que termine, o pulse el boton cancelar durante medio segundo
lee los pulsos del caudalimetro de la bomba por interrupcion en el puerto 21 del arduino mega
una vez terminada la carga, registra la actividad y vuelve a la espera de otro ingreso por qr
//bus spi comun a casi todos los modulos (pantalla, red o usb)
#include <SPI.h>
//red
#include <Ethernet.h>
//usb
#include <usbhid.h>
#include <usbhub.h>
#include <hiduniversal.h>
#include <hidboot.h>
//pantalla
#include <Adafruit_GFX.h>//graficos en la pantalla
#include <MCUFRIEND_kbv.h> //administracion de la pantalla tft SHIELD
#include <avr/wdt.h> // Incluir la librería que contiene el watchdog (wdt.h)
//VARIABLES O CONSTANTES
//variables para el shield de la pantalla
//constantes para los colores de la pantalla
#define SD_CS 10
#define BLACK 0
#define GREY 21845
#define BLUE 31
#define RED 63488
#define GREEN 2016
#define DARKGREEN 1472
#define CYAN 2047
#define MAGENTA 63519
#define YELLOW 65504
#define GOLD 56768
#define WHITE 65535
//Usar si se usa pantalla shield
MCUFRIEND_kbv tft;
//variables para el modulo de la RED
//Inicializar instancia de la libreria ethernet
EthernetClient client;
//Dirección IP del servidor con la página PHP
char serverip[] = "192.168.1.107";
//Asignamos una dirección IP local para las operaciones en red
char localip[] = "Host: 192.168.1.80";
//Asignar dirección IP para la conexion inicial del modulo (misma que la anterior)
IPAddress ip(192,168,1,80);
//Asignamos una dirección MAC local
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
String idjir = "1";
boolean fin = false;
boolean pregunta = true;
byte bFnd = 0; //banderas de frenado. numeros que indican por que termino la carga
//puertos SS para el control del bus SPI de las distintas placas
//RED
byte ssr = 53; //SS de la placa de red
//como los diseñadores de la placa de red son simpaticos, mandan siempre datos por el SPI, asi este seleccionada o no
//se debe inhabilitar al modulo (al chip directamente). hay q hacer una modificacion fisica y mandar este pin hacia alli:
byte sse = 49; //SEN (SPI Enable) del chip w5100 del modulo de red para deshabilitarlo (OJO!!: desabilita con HIGH)
//USB
byte ssu = 43; //SS del shield USB
byte inu = 42; //INT del shield USB (no se usa)
//TFT-pantalla
byte sss = 10; //SS del TFT - 10
byte dct = 8; //DC del tft - 8
byte rst = 9; //reset del TFT - 9
//variables de tiempo
unsigned int tact = 0; //tiempo actual, leido con el pulso de entrada del caudalimetro
byte tdif = 30; //diferencia de tiempo sin tomar carga para cortar por no haber movimiento. En segundos
byte tapv = 10; //tiempo que tarda la valvula en abrir. en segundos. 150 = 2min 30seg
byte tciv = 3; //tiempo que tarda la valvula en cerrar. en segundos. 150 = 2min 30seg
unsigned long mapv = 0; //momento en el que se realizo la apertura de la valvula
unsigned long mciv = 0; //momento en el que se realizo el cierre de la valvula
//variables del proceso de carga
//cp esta en las interrupciones, por eso es 'volatile'
volatile unsigned int cp = 0; //cantidad de pulsos leidos por interrupcion
unsigned long total = 10; //lo que cargo en definitiva. cambia si se presiona el boton de frenado
unsigned long cargado = 0; //lo que lleva ya cargado
boolean seguir = true; //indicador que el boton de frenado fue presionado, o que se acabo la carga
unsigned int mult = 100; //multiplicador para los pulsos, para que de cantidad de litros cargados
unsigned long maximo = 0; //lo que va a cargar
unsigned long permitido = 0; //lo maximo que puede cargar
unsigned int incremento = 500; //lo que va a sumar o restar por cada pulsada de boton
byte estado = 0; // estado en que se encuentra en cada etapa de la carga
byte ef = 0; // estado final, en caso de corte por STOP, almacena el estado donde se interrumpio la carga
unsigned int longboton = 200; // delay en ms de la longitud de espera entre presiones de botones del tablero
unsigned int espera = 200; //espera para mostar en pantalla los estados en el proceso de carga en general
//cargas maximas para cada una de las rampas de arranque
unsigned int max1 = 1000;
unsigned int max2 = 2000;
//cantidad de litros antes del maximo, para que comience el frenado
unsigned int sup = 500;
// PINES
//interrupciones
byte ixb = 20; //interrupcion por boton rojo presionado (no usado)
byte ixp = 21; //interrupcion por pulsos
//pulsadores
byte cmz = 22; //pulsador arranque de bomba
byte inc = 23; //pulsador incrementar
byte dec = 24; //pulsador decrementar
byte frn = 25; //pulsador frenado. no se usa, se usa solo del de corte, el 21
//switch selector bomba-tanque
byte swb = 31; //switch selector de ingreso por bomba
byte swv = 32; //switch selector de ingreso por tanque
//Pines bomba
byte ra1 = 28; //salida rampa 1
byte ra2 = 29; //salida rampa 2
byte ra3 = 30; //salida rampa 3
byte arb = 36; //señal de arranque de bomba (no usado, arranca por rampa)
byte frb = 37; //señal de frenado de bomba
//Pines valvula
byte arv = 33; //señal de arranque de la valvula del tanque
byte frv = 34; //señal de frenado de la valvula del tanque
bool bv = false; //estado en el que se mantendra si es bomba o valvula. el estado del switch, desde el momento del arranque de la carga
//variables en comun que vamos a tomar desde el usb y desde la placa de red para su posterior decodificacion
//String LecturaUSB = "&0123456789!"; //Aqui se almacena el dato leido del QR
//byte LongUSB = 12; //Aca guardamos la longitud del string leido del lector QR para ir recorriendolo
String LecturaUSB = ""; //Aqui se almacena el dato leido del QR
byte LongUSB = 0; //Aca guardamos la longitud del string leido del lector QR para ir recorriendolo
boolean UltimoUSB = false; //si el leido fue ultimo caracter leido para armar el string de la lectura del QR
String LecturaRED = "&01%15000!"; //Aquí se almacena la respuesta del servidor
byte LongRED = 39; //Aca guardamos la longitud del string recibido del servidor para ir recorriendolo
byte ubi = 0; //Aca guardamos la ultima posicion leida en cada campo de la tabla, para arrancar a formar la que sigue a partir de donde termino la anterior
//Variables que vienen desde el servidor en el string 'codigo' por RED
String VerifRED = "";
unsigned long LitrosRED = 0;
String MensajeRED = "";
String ActivoRED = "";
//general
unsigned int Litros = 0;
// inicio shield USB
//Lecturas de Lector de Codigo de Barras o QR
//vectores con tipos de caracteres
const uint8_t numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'};
const uint8_t symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', ' ', ':', '"', ' ', '<', '>', '?'};
const uint8_t symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'};
const uint8_t padKeys[5] PROGMEM = {'/', '*', '-', '+', '\r'};
bool shift = false;
class MyParser : public HIDReportParser {
public:
MyParser();
void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
protected:
//transforma lo leido a caracter ASCII
uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
//lectura de caracteres normales
virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
//lectura de ultimo caracter, para entregar el string completo armado
virtual void OnScanFinished();
};
MyParser::MyParser() {}
void MyParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
// Si hay error o no hay lectura, salir
// if (buf[2] == 1 || buf[2] == 0) {
// return;
// }
if(buf[0] == 2)
shift = true;
for (uint8_t i = 7; i >= 2; i--) { //entradas de 7 a 2
// Si esta vacio el ingreso, salir de la lectura
if (buf[i] == 0) continue;
// si lo ingresado es señal de final ( UHS_HID_BOOT_KEY_ENTER ), ir a final del escaneo ( OnScanFinished )
if (buf[i] == UHS_HID_BOOT_KEY_ENTER) {
OnScanFinished();
}
// si no es el ultimo, seguir normalmente, armando el codigo ( OnKeyScanned )
else {
// If bit position not in 2, it's uppercase words
OnKeyScanned(shift, buf, buf[i]);
shift = false;
}
return;
}
}
//Decodificacion de cada ingreso del lector a su codigo ASCII correspondiente
uint8_t MyParser::KeyToAscii(bool upper, uint8_t mod, uint8_t key) {
// Letras
if (VALUE_WITHIN(key, 0x04, 0x01d)) { //si el ingreso esta entre 04 y 1D (letras) que devuelva
if (upper) return (key - 4 + 'A'); // letras en mayusculas
else return (key - 4 + 'a'); // o letras en minusculas
}
// Numeros
else if (VALUE_WITHIN(key, 0x1e, 0x27)) {
if (shift)
return ((uint8_t)pgm_read_byte(&numKeys[key - 0x1e]));
else
return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
}
// Numeros del Keypad
else if (VALUE_WITHIN(key, 0x59, 0x61)) {
return (key - 0x59 + '1');
} else if (VALUE_WITHIN(key, 0x2d, 0x38))
return ((upper) ? (uint8_t)pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t)pgm_read_byte(&symKeysLo[key - 0x2d]));
else if (VALUE_WITHIN(key, 0x54, 0x58))
return (uint8_t)pgm_read_byte(&padKeys[key - 0x54]);
else {
switch (key) {
case UHS_HID_BOOT_KEY_SPACE: return (0x20);
case UHS_HID_BOOT_KEY_ENTER: return ('\r'); // salto de campo (0x0D)
}
}
//Serial.println(key, HEX);
return 0;
}
//va escribiendo lo ingresado y lo va acumulando en la variable de salida
void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
//Serial.print(upper);
uint8_t ascii = KeyToAscii(upper, mod, key);
//Serial.print((char)ascii);
LecturaUSB += (char)ascii;
UltimoUSB = false;
}
// se ha ingresado el ultimo caracter del codigo. finalizar el string leido
void MyParser::OnScanFinished() {
//Serial.println();
//Serial.println(LecturaUSB);
UltimoUSB = true;
}
USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid(&Usb);
MyParser Parser;
//fin shield USB
//subrutina de arranque del sistema
void setup() {
//Inicializar el Serial de salida en la PC
Serial.begin(9600);
Serial.println(F("Arrancando el sistema...."));
wdt_disable(); // Desactivar el watchdog mientras se configura, para que no se resetee
wdt_enable(WDTO_8S); // Configurar watchdog a cuatro segundos
//interrupcion por ingreso de pulsos
attachInterrupt(digitalPinToInterrupt(ixp), pulsos, RISING);
//interrupcion por corte de emergencia
//attachInterrupt(digitalPinToInterrupt(ixb), corte, RISING); //no usado
//noInterrupts();
//interrupciones
pinMode(ixp, INPUT); // interrupcion pulsos
pinMode(ixb, INPUT); // interrupcion por boton de corte emergencia
//botonera
pinMode(cmz, INPUT); // comenzar la carga
pinMode(inc, INPUT); // incrementar
pinMode(dec, INPUT); // descontar
pinMode(frn, INPUT); // frenado
//swich selector bomba-valvula
pinMode(swb, INPUT); // ingreso por bomba seleccionado
pinMode(swv, INPUT); // ingreso por valvula seleccionado
//salidas de arranque y frenado para carga por valvula (tanque)
pinMode(arv, OUTPUT); // arranque de carga por valvula
pinMode(frv, OUTPUT); // frenado de carga por valvula
//salidas de estados de carga
pinMode(ra1, OUTPUT); // arranque de rampa 1
pinMode(ra2, OUTPUT); // arranque de rampa 2
pinMode(ra3, OUTPUT); // arranque de rampa 3
pinMode(arb, OUTPUT); // arranque de carga de bomba (no usado, arranca por rampa)
pinMode(frb, OUTPUT); // frenado de carga de bomba
//Pines SS (slave select) para el bus ISP de distintos modulos: pantalla, red y usb
pinMode(sss, OUTPUT); // SS del shield de la pantalla ILI9341
pinMode(ssr, OUTPUT); // SS del modulo de RED W5100
pinMode(sse, OUTPUT); // habilita el modulo de red. va a la par del ssr, pero con estado opuesto
pinMode(ssu, OUTPUT); // SS del shield USB . Modificar shield y modificar tambien en la libreria "UsbCore.h" dentro de USB_Host_Shield_Library_2.0 :
//Inicializar el shield USB
HabilitarSS(ssu);
if (Usb.Init(ssu) == -1) {
Serial.println("Modulo USB no conectado");
}else{
Serial.println("Modulo USB inicializado");
}
delay( 200 );
Hid.SetReportParser(0, &Parser);
//Inicializar modulo de RED
HabilitarSS(ssr);
// demora de arranque
//delay(1000);
//Iniciar la coneción de red
Ethernet.init(ssr);
Ethernet.begin(mac, ip);
//if (Ethernet.begin(mac, ip) == 0) {
//Serial println("No se puede conectar la red");
//} else {
// Imprimir la dirección IP
Serial.print("IP: ");
Serial.println(Ethernet.localIP());
//}
//Inicializar la pantalla TFT
HabilitarSS(sss);
uint16_t ID = tft.readID();
Serial.print("TFT ID: ");
Serial.println(ID);
if (ID == 0xD3D3) ID = 0x9341; //para shield 3.5" , 0x9341 for 2.8" TFT LCD Shield
if (ID == 0x9327) ID = 0x9327;
if (ID == 0x9225) ID = 0x9225;
if (ID == 0x9201) ID = 0x9201;
tft.begin(ID);
tft.fillScreen(0);
tft.setRotation(1);//0-VERTICAL 1-APAISADO 2-VERTICAL INVERTIDO 3-APAISADO INVERTIDO
//noInterrupts();
PantallaInicio();
delay(500);
HabilitarSS(ssu);
}
//bucle principar luego del arranque
void loop() {
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
//desde el USB
//1) espera a que haya alguna actividad del usb
Usb.Task();
//Serial.println(millis()/100);
//2) si leyo un string completo y estoy en el ultimo caracter
if (UltimoUSB && LecturaUSB.length() > 0) {
Principal(); //hago todo el proceso
Reiniciar();
}
}
//subrutina de seleccion de esclavo para las placas SPI
void HabilitarSS(byte ss) {
//deshabilito con HIGH todos los esclavos
digitalWrite(ssu, HIGH);
digitalWrite(sss, HIGH);
digitalWrite(ssr, HIGH);
digitalWrite(sse, LOW);
//habilito solo ss al requerido
if (ss > 0) {//si hay ahgun esclavo seleccionado para activar
if (ss == ssr) digitalWrite(sse, HIGH); //para la placa de red, habilito a la placa tambien (no al SS)
digitalWrite(ss, LOW); //se habilita con estado LOW
}
}
// I N T E R R U P C I O N E S
//interrupcion por ingreso de pulso al pin 21 del Arduino Mega 2560
//se incrementara en uno la catidad de pulsos ingresados
//que iran marcando los litros que van pasando
//el pulso viene del caudalimetro
void pulsos(){
if (estado > 0 && estado < 5) {
cp++;//incremento los pulsos leidos
Serial.println(cp);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
tact = millis(); //tomo el momento de la lectura para control de caudal de agua
}
}
//subrutina para prueba de ingreso de ID del coche por pantalla si no esta el lector USB
void lecturaPC(){
//Comprobamos si tenemos datos en el puerto serie
if (pregunta == true) Serial.print("Escribe el identificador de la persona: ");
pregunta = false;
if (Serial.available()>0){
//leemos el identificador
byte identificador = Serial.read()-48;
if (identificador == 218){
} else {
Serial.println(identificador);
pregunta = true;
}
}
}
//subrutina principal, donde se llama a las distintas subrutinas o funciones secuencialmente
void Principal(){
//Serial.println(LecturaUSB);
PantallaLeyendo();
//3) Decodifico el string tomado del QR leido del celular con el lector
HabilitarSS(0);
DecodificarUSB();
//4) Con el ID del coche y demas datos, busco en la base de datos a traves del web server
ConsultaHTTP();
//5) Decodifico el string de datos que vinieron desde la base de datos
DatosDeLaConsulta();
Serial.println(seguir);
if (!seguir) return;
//6) Espero a que se presione el boton de arranque.
// Mientras puede subir o bajar por botonera lo que va a cargar
// o cancelar la operancion
EsperarArranque(); //estado 0
Serial.println(seguir);
if (!seguir) return;
//interrupts(); //activo las interrupciones (pulsos y frenado)
//8) Comienzo el arranque de la carga de agua
Arranque(); //estado 1
//9) SUBRUTINA PRINCIPAL LARGA MIENTRAS CARGA AGUA
//hasta que por alguna razon se frena
Carga(); //estado 2
//10) Comienzo de la secuencia de frenado de la carga de agua
Frenado(); //estado 3
//11) Contabilizar hasta la ultima gota, luego de terminada la carga mecanica de la bomba
PostFrenado(); //estado 4
//12) Registro en la base de datos la carga realizada
RegistroHTTP();
//13) fin del proceso
GameOver();
}
// USB
//decodificacion de lo leido desde el USB. Almaceno en la variable global LecturaUSB el codigo leido por el lector USB
void DecodificarUSB(){
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
//Serial.println(LecturaUSB);
LecturaUSB = LecturaUSB.substring(2,LecturaUSB.length()); // saco caracteres molestos del principio
Serial.print("LecturaUSB 1: ");
Serial.println(LecturaUSB);
LecturaUSB = LecturaUSB.substring(LecturaUSB.indexOf("&")+1,LecturaUSB.indexOf("!"));
LongUSB = LecturaUSB.length(); //longitud
Serial.print("LecturaUSB 2: ");
Serial.println(LecturaUSB);
}
//subrutina de consulta de desglose de registros tomados de la lectura unica desde el usb
String RegistroUSB(String code,byte longitud) {
String campo = "";
String car = "";
//Analizamos el código obtenido y almacenamos 'campo'
for (int i = ubi+1; i < longitud; i ++){
ubi = i;
car = code.substring(i,i+1);
//Serial.println(car);
if (car == "%") i = longitud; //salgo de bucle si encuentro un separador de campos ("%") antes de que termine
else campo += car; //sino, voy concatenando en campo los caracteres
}
return campo; //devuelvo el campo obtenido
}
//si se cancela la operacion, o reinicio del procedimiento. se re-inicializan las variables
void reiniciar(){
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
//inicializacion
seguir = true;
LecturaUSB = "";
UltimoUSB = false;
PantallaInicio();
delay(500);
HabilitarSS(ssu);
}
// RED
// Hacemos la conexion con el servidor
// Y tomamos los datos de la RED del codigo dado (leido por el USB)
// Y pasamos esos datos a un string
int ConsultaHTTP() {
HabilitarSS(ssr);
if (cnx()) {//si tengo conexion con el servidor (cnx() es la subrutina que hace la conexion)
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
Serial.println("Conectado... ");
String identificador = LecturaUSB; //paso por red el codigo intresado por el lector USB
Serial.println("");
Serial.println("RED");
Serial.print("identificador: ");
Serial.println(identificador);
// 1-CONSULTAMOS AL SERVER WEB con 'identificador' como ID (LecturaUSB)
//Enviar la petición HTTP
//Dirección del archivo php dentro del servidor
client.print("GET /jirafa/consulta1.php?id=");
client.print(identificador);
client.println(" HTTP/1.0");
//IP del servidor
client.println(localip);
client.println("User-Agent: arduino-ethernet");
client.println("Connection: close");
client.println();
delay(500); //esperamos para que haya respuesta desde el servidor
//2-LEEMOS BYTE POR BYTE LA RESPUESTA CON LOS DATOS OBTENIDOS DE LA CONSULTA
//Comprobamos si tenemos respuesta del servidor y la
//almacenamos en el string – --> codigo.
LecturaRED = ""; //inicializamos la variable en la que se va a ir almacenando lo leido desde la red
while (client.available()) { //ingreso caracter por caracter hasta que no hayan mas
char c = client.read(); //caracter leido
//3-VAMOS FORMANDO EL STRING
LecturaRED += c; //armado del string LecturaRED concatenandole cada caracter que se va recibiendo en c
//Habilitamos la comprobación del código recibido
fin = true;
}
//solo la parte que me interesa, entre los signos de inicio & y de fin !
LecturaRED = LecturaRED.substring(LecturaRED.indexOf("&") + 1,LecturaRED.indexOf("!"));
Serial.println(LecturaRED);
client.stop();
seguir = true;
return 1;
} else {
// ...si no se conecta
Serial.println("Conexión fallida");
Serial.println("Desconectando");
client.stop();
seguir = false;
bFnd = 1;
PantallaTermino("Sin RED");
return 0;
}
HabilitarSS(0);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
// Sacamos los datos del string recibido de la consulta al servidor (RED)
int DatosDeLaConsulta () {
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
//Ubicacion del primer caracter a tomar en cada variable, para el pase entre variables
ubi = 0;
//Longitud del código recibido
LongRED = LecturaRED.length();
int posicion = 0;
delay(500);
//tomamos el primer registro leido desde lo tomado por la red. puede ser "Si" o "No"
VerifRED = RegistroRED(LecturaRED,LongRED);
Serial.println("Verificacion: " + VerifRED);
if (VerifRED == "Si"){ // si es "Si", habilita la carga y toma los litros habilitados a cargar
LitrosRED = RegistroRED(LecturaRED,LongRED).toInt() * 100;
MensajeRED = "";
Serial.println("Litros: " + String(LitrosRED));
seguir = true;
}else{ // si es "No", no habilita la carga y toma el mensaje del problma
LitrosRED = 0;
MensajeRED = RegistroRED(LecturaRED,LongRED);
seguir = false;
Serial.println("Mensaje: " + MensajeRED);
Serial.println(seguir);
bFnd = 2;
}
//Deshabilitamos el análisis del código
fin = false;
//Cerrar conexión
Serial.println("Desconectar");
Serial.println("");
Serial.println("");
client.stop();
//Salir de la función
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
if (!seguir){
PantallaTermino(MensajeRED);
}
return 1;
}
//subrutina de desglose de los registros tomados de la red en un solo string
String RegistroRED(String code, byte longitud) {
String campo = "";
//Analizamos el código completo obtenido y almacenamos 'campo'
for (int i = ubi+1; i < longitud; i ++){
ubi = i;
if (code[i] == '%') i = longitud; //salgo de bucle si encuentro un separador de campos ("%") antes de que termine
else campo += code[i]; //sino, voy concatenando en campo los caracteres
}
return campo; //devuelvo el campo obtenido
}
// Hacemos la conexion con el servidor
// Y enviamos los datos de la transaccion y la cantidad de litros cargados
// Y pasamos esos datos a un string
int RegistroHTTP() {
HabilitarSS(ssr);
if (cnx()) {//si tengo conexion con el servidor (cnx() es la subrutina que hace la conexion)
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
Serial.println("Conectado... ");
String identificador = LecturaUSB;
Serial.println("");
Serial.println("RED");
Serial.print("identificador: ");
Serial.println(identificador);
// 1-ENVTAMOS AL SERVER WEB el 'identificador' como ID
client.print("GET /jirafa/carga.php?id=");
client.print(identificador);
client.print("&jir=");
client.print(idjir);
client.print("<r=");
client.print(cargado / 100);
client.println(" HTTP/1.0");
Serial.println(cargado / 100);
//IP del servidor
client.println(localip);
client.println("User-Agent: arduino-ethernet");
client.println("Connection: close");
client.println();
Serial.println("Transacción realizada");
delay(500); //esperamos para que haya respuesta desde el servidor
//2-LEEMOS BYTE POR BYTE LA RESPUESTA CON LOS DATOS OBTENIDOS DE LA CONSULTA
//Comprobamos si tenemos respuesta del servidor y la
//almacenamos en el string – --> codigo.
LecturaRED = "";
while (client.available()) { //ingreso caracter por caracter hasta que no hayan mas
char c = client.read(); //caracter leido
//3-VAMOS FORMANDO EL STRING
LecturaRED += c; //armado del string que se va recibiendo
//Habilitamos la comprobación del código recibido
fin = true;
}
//solo la parte que me interesa, entre los signos de inicio & y de fin !
LecturaRED = LecturaRED.substring(LecturaRED.indexOf("&") + 1,LecturaRED.indexOf("!"));
Serial.println(LecturaRED);
client.stop();
return 1;
} else {
// ...si no se conecta
Serial.println("Conexión fallida");
Serial.println("Desconectando");
client.stop();
return 0;
}
HabilitarSS(0);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
//subrutina de conexion a la RED
bool cnx(){
// Comprobar si hay conexión
//ci: cantidad de intenos de conexion
byte ci = 10;
bool si = false;
for (int i = 0; i <= ci; i++) {//reintentos de conexion
if (client.connect(serverip, 80)) {
si = true;
i = ci; //o continue
} else {
Serial.println("no... ");
delay(1000);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
}//intentos de reconeccion
return si;
}
// C A R G A
// ya ingresados los datos desde el USB y de la RED, mostramos a los mismos en pantalla
// y damos la opcion de modificarlos por medio de los botones
// boton mas, boton menos, boton verde comenzar carga, boton rojo cancelar y arrancar TODO nuevamente
void EsperarArranque(){
permitido = LitrosRED;
maximo = long(LitrosRED);
estado = 0;
cargado = 0;
total = 0;
seguir = true; //pasa a true si se presiona el boton cancelar
//Muestro en pantalla
PantallaDatos();
boolean arr = true;
//MostrarMx(maximo);
Serial.println("Permitido: " + String(permitido));
unsigned long tfue = millis();
do {
if (digitalRead(cmz) == HIGH) { //se presiono el pulsador VERDE de arranque
Serial.println("Comenzar");
arr = false;
delay(longboton);
}
if (digitalRead(frn) == HIGH) { //se presiono el pulsador ROJO de cancelar
Serial.println("Cancelar");
arr = false;
seguir = false; //cancelo la operacion
PantallaTermino("Cancelado");
bFnd = 3;
delay(longboton);
}
if (digitalRead(inc) == HIGH) { //se presiono el pulsador de aumentar
if (maximo + incremento <= permitido) {
Serial.println("Sumar");
maximo = maximo + incremento;
//Serial.println(maximo);
MostrarMx(String(maximo));
Serial.println(String(maximo));
tfue = millis(); //renuevo contador
delay(longboton);
}
}
if (digitalRead(dec) == HIGH) { //se presiono el pulsador de disminuir
if (maximo - incremento >= 0) {
Serial.println("Restar");
maximo = maximo - incremento;
//Serial.println(maximo);
MostrarMx(String(maximo));
Serial.println(String(maximo));
tfue = millis(); //renuevo contador
delay(longboton);
}
}
//Serial.println((millis()-tfue)/1000 > 30);
if((millis()-tfue)/1000 > 30) { //controlo que no pase tiempo mureto de espera
Serial.println("Tiempo Fuera");
arr = false;
seguir = false; //cancelo la operacion
PantallaTermino("Tiempo /fuera");
bFnd = 6;
}
//Serial.println(String(maximo));
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
} while (arr);
//maximo = 2000; //OJO!!! Solo para prueba, para que no sea mucho. sacarlo para el definitivo
}
// para las tres siguientes subrutinas (todo el proceso de carga)
// tener en cuenta que la variable cp (cantidad de pulsos) se va incrementando por interrupcion
// en la subrutina 'pulsos'
void Arranque(){
estado = 1; //arranque
PantallaCarga("A Cargar", String(maximo));
Serial.println("Estado 1");
cp = 0; //inicializo el contador de pulsos
boolean ba = true;
//if (digitalRead(swb) == HIGH) { //me fijo que el switch bomba-valvula este en bomba
if (ba){//solo en la prueba. en el real hay que usar el if de arriba
//dependiendo la cantidad de litros a cargar, utilizara deistintos arranques
bv = true;
if (maximo < max1) {
disparo(ra1);
Serial.println("Arranque rampa 1 ");
}
if (maximo < max2 && maximo >= max1) {
disparo(ra2);
Serial.println("Arranque rampa 2 ");
}
if (maximo >= max2) {
disparo(ra3);
Serial.println("Arranque rampa 3 ");
}
}
//arranque por valvula
//lleva su tiempo (2.5 minutos) abrirla y cerrarla
//guardo el momento en que comenzo la apertura y mientras carga controlo su cierre
//if (digitalRead(swv) == HIGH) {//me fijo que el switch bomba-valvula este en valvula
bv = false; //bandera boma-valvula en false. actua la valvula
digitalWrite(arv,HIGH); //activo la apertura de la valvula
mapv = millis(); //momento en el que se comenzo la apertura de la valvula
Serial.println("Arranque Valvula ");
//}
}
//subrutina de tiempo para matener un pulso en un pin ingresado durante un periodo corto "de pulso"
void disparo(byte pin){
digitalWrite(pin,HIGH); //activo el pulso
delay (200); //espero un poco
digitalWrite(pin,LOW); //desactivo el pulso
}
// subrutina 'va cargando'. AQUI TODO LO QUE OCURRA MIENTRAS VA CARGANDO AGUA
void Carga() {
if (!seguir) return; //controlo que no haya sido presionado el boton cancelar
estado = 2; //cargando
Serial.println("Estado 2");
bFnd = 0; //byte que notifica la causa de la salida del bucle de carga
String MsgSal = ""; //mensaje de salida
boolean arr = true; //bandera de salida del bucle activada
unsigned int tiempo = 3000;
boolean vla = true; //bandera de valvula abriendo. para treminar su apertura a los 2.5 minutoa
if (bv) vla = false; //si estamos por bomba, no ir a frenado de valvula
do {
for (unsigned int i = 0; i < tiempo; i ++){
//delay(100);//pequeño delay para ayudar al bucle for
cargado = cp * mult; //cp se incrementa por interrupcion
if (cargado > (maximo - sup)){ //SI LLEGO AL LIMITE PREVIO AL MAXIMO A CARGAR, para comenzar el proceso de frenado
MsgSal = "Terminado";
bFnd = 4;
arr = false;
break;
}
//desactivo el arranque de la valvula en el momento estipulado.
//OJO! no la apaga, solo deja de enviar el pulso de apertura
if (vla){ //que lo haga solo una vez
if ((millis() - mapv) / 1000 > tapv) {
digitalWrite(arv,LOW); //desactivo la apertura de la valvula
vla = false; //que no entre mas aqui
Serial.println("Fin Apertura Valvula ");
}
}
if (digitalRead(frn) == HIGH) { //SE PRESIONO EL BOTON CANCELAR!!!
bool bStp = Stopeado();
if (bStp){
MsgSal = "Frenado";
bFnd = 5;
arr = false;
break;
}
}
/*
if (controlcaudal()){ //SI NO ESTA PASANDO AGUA POR EL CAUDALIMETRO
MsgSal = "Sin Agua";
bFnd = 6;
arr = false;
break;
}
*/
}
Serial.println(cargado);
MostrarCarga(String(cargado));
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
} while (arr);
PantallaTermino(MsgSal);
delay(1000);
}
void Frenado(){
estado = 3; //frenado
Serial.println("Estado 3");
MostrarCarga("Frenando");
if (bv) { //switch bomba-valvula en valvula
disparo(frb); //frenado de la boma
}else{ //frenado de bomba
digitalWrite(frv,HIGH); //activo el cierre de la valvula
mciv = millis(); //momento en el que se comenzo el cierre de la valvula
Serial.println("Inicio frenado de Valvula ");
}
}
//Aqui controlamos lo que pasa por el caudalimetro luego de terminado el proceso
//"hasta la ultima gota"
void PostFrenado(){
PantallaCarga("Frenando: ", String(maximo));
estado = 4; //post-frenado
Serial.println("Estado 4");
//bool arr = true;
boolean vla = true; //bandera de valvula cerrando. para terminar su cierre a los 2.5 minutoa
if (bv) vla = false; //si estamos por bomba, no ir a frenado de valvula
bool arr = false; //PONER EN TRUE CUANDO OCURRA DE VERDAD!!!!!!
unsigned int tiempo = 5000;
do { //realizo el bucle hasta que deje de pasar agua por el caudalimetro
for (unsigned int i = 0; i < tiempo; i ++){
//delay(100);//pequeño delay para ayudar al bucle for
cargado = cp * mult; //cp se incrementa por interrupcion
if (vla){ //que lo haga solo una vez
if ((millis() - mciv) / 1000 > tciv) {
digitalWrite(frv,LOW); //desactivo la apertura de la valvula
vla = false; //que no entre mas aqui
Serial.println("Fin Cierre Valvula ");
}
}
//if (controlcaudal()){ //SI NO ESTA PASANDO AGUA POR EL CAUDALIMETRO
if (tiempo > 500) {
byte bFnd = 4;
arr = false;
break;
}
delay(1);
}
Serial.println(cargado);
MostrarCarga(String(cargado));
//wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
} while (arr);
}
//control de caudalimetro. si pasado un tiempo de la ultima lectura, no hay mas lecturas, entonces dejo de pasar agua
boolean controlcaudal() {
boolean bcc = false;
if ((millis() - tact)/1000 > tdif) bcc = true;
return bcc;
}
boolean Stopeado() {
boolean arr = true;
PantallaFrenado("STOP?"); //pantalla confirmacion
Serial.println("STOP?");
delay(100);
//controlo por bucle q el boton siga apretado luego de medio segundo (efecto rebote mecanico)
bool bsal = false;
for (int i=0; i <= 1000; i++){
if (digitalRead(frn) == HIGH){
bsal = true;
break;
}
}
if (bsal) { //...si presiono el boton rojo durante 1/2 segundo, se confirmar el frenado
PantallaFrenado("STOP!!");
Serial.println("STOP!!");
arr = true;
total = cargado; //total cargado en el momento de frenado
ef = estado; //estado en el momento de frenado
}
return arr;
}
void GameOver(){
if (seguir) total = cargado;
estado = 5;
Serial.print("Estado 5");
PantallaFinal();
delay(5000);
}
void Reiniciar(){
cp = 0;
estado = 0;
seguir = true;
PantallaInicio();
LecturaUSB = "";
LecturaRED = "";
}
//SUBRUTINAS DE PANTALLAS
// TFT - Pantalla
void PantallaInicio(){
HabilitarSS(sss);
tft.fillScreen(BLACK);
tft.setCursor(0, 30);
tft.setTextSize(4);
tft.setTextColor(WHITE, BLACK);
tft.print(" Por favor ");
tft.setCursor(0, 80);
tft.print(" pase el");
tft.setCursor(0, 130);
tft.print(" codigo QR");
tft.setCursor(0, 180);
tft.print("por el lector");
delay(1000);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
void PantallaLeyendo(){
HabilitarSS(sss);
tft.fillScreen(BLACK);
tft.setCursor(0, 30);
tft.setTextSize(4);
tft.setTextColor(WHITE, BLACK);
tft.print(" Leyendo ");
tft.setCursor(0, 80);
tft.print(" datos");
tft.setCursor(0, 130);
tft.print(" Por favor ");
tft.setCursor(0, 180);
tft.print(" espere ");
delay(1000);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
void PantallaDatos(){
HabilitarSS(sss);
tft.fillScreen(BLUE);
tft.setTextColor(WHITE, BLUE);
tft.setTextSize(3);
tft.setCursor(10, 10);
tft.setTextColor(WHITE, BLUE);
tft.print("Maximo permitido: ");
tft.setTextSize(3);
tft.setCursor(110, 50);
tft.setTextColor(WHITE, BLUE);
tft.print(LitrosRED);
tft.setTextSize(3);
tft.setCursor(250, 50);
tft.setTextColor(WHITE, BLUE);
tft.print("litros");
tft.setTextSize(3);
tft.setCursor(20, 90);
tft.print("Total a cargar:");
tft.setTextSize(6);
tft.setCursor(226 - String(maximo).length()*36, 130);
//tft.print("10000");
tft.print(maximo);
tft.setCursor(240, 130);
tft.setTextSize(3);
tft.print("litros");
tft.setCursor(280, 130);
tft.setTextSize(4);
tft.setTextColor(WHITE, BLUE);
tft.setCursor(0, 200);
tft.print("Pulse");
tft.setTextColor(WHITE, DARKGREEN);
tft.setCursor(120, 200);
tft.print(" CARGAR ");
delay(1000);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
void PantallaCarga(String msg, String mxm){
HabilitarSS(sss);
tft.fillScreen(MAGENTA);
tft.setTextColor(WHITE, MAGENTA);
tft.setTextSize(3);
tft.setCursor(0, 35);
tft.print(msg);
tft.setCursor(170, 30);
tft.setTextSize(4);
tft.print(mxm);
tft.setTextSize(3);
tft.setCursor(10, 80);
tft.print("Ya van cargados:");
tft.setTextSize(6);
tft.setTextColor(BLACK, MAGENTA);
tft.setCursor(190, 130);
tft.print("0");
//tft.print(cargado);
tft.setCursor(240, 140);
tft.setTextSize(4);
tft.print("litros");
tft.setCursor(280, 130);
delay(1000);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
void PantallaFrenado(String texto){
for (int i = 1; i < 3; i ++){
HabilitarSS(sss);
tft.fillScreen(RED);
tft.setTextColor(WHITE, RED);
tft.setTextSize(8);
tft.setCursor(50, 90);
tft.print(texto);
delay(300);
}
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
void PantallaTermino(String texto){
byte ubi = texto.indexOf("/");
for (int i = 1; i < 3; i ++){
HabilitarSS(sss);
//tft.fillScreen(DARKGREEN);
//tft.setTextColor(BLACK, DARKGREEN);
tft.fillScreen(BLACK);
tft.setTextColor(WHITE, BLACK);
tft.setTextSize(6);
if (ubi == 0){
tft.setCursor(200 - texto.length()*18, 100);
tft.print(texto);
} else {
String t1 = texto.substring(0,ubi);
tft.setCursor(200 - t1.length()*18, 60);
tft.print(t1);
String t2 = texto.substring(ubi+1,texto.length());
tft.setCursor(200 - t2.length()*18, 140);
tft.print(t2);
}
delay(2000);
}
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
void PantallaFinal(){
HabilitarSS(sss);
tft.fillScreen(BLACK);
tft.setCursor(0, 30);
tft.setTextSize(4);
tft.setTextColor(WHITE, BLACK);
tft.print(" Proceso ");
tft.setCursor(0, 80);
tft.print(" Finalizado ");
tft.setCursor(0, 130);
tft.print(" cargados ");
tft.setCursor(60, 180);
tft.print(total);
tft.setCursor(200, 180);
tft.print("l");
delay(1000);
wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}
//modificaciones en pantalla de numeros
void MostrarMx(String mxm){
HabilitarSS(sss);
tft.setTextColor(WHITE, BLUE);
tft.setTextSize(6);
tft.setCursor(20, 130);
tft.print(" ");
tft.setCursor(226 - String(mxm).length()*36, 130);
tft.print(mxm);
}
void MostrarCarga(String crg){
HabilitarSS(sss);
tft.setTextColor(BLACK, MAGENTA);
tft.setTextSize(6);
tft.setCursor(226 - String(crg).length()*36, 130);
tft.print(crg);
}