Libreria per comandare Arduino via comandi "Hayes"-like
Quasi completo (stiamo facendo prove per migliorare la ricezione via seriale), il codice è migliorabilissimo ;)
Ora vorremmo semplificarlo (rispetto al sorgente qui sotto) e passare alla lettura dello stream byteBybyte senza passare da un buffer (MdT like)
Albero stringhe di comando | |-P(inmode) [forse non serve, viene sempre chiamato un pinmode per ogni out] | \ | |-I-pinNumberXX [setta in input] | |-O-pinNumberXX [setta in output] | |-D(igital) | \ | |-I-pinNumberXX [ritorna valore] | |-I-A [stampa tutti i valori] | |-O-pinNumberXX-H/L | |-O-A-H/L [tutti su o giu'] | |-A(nalog) | \ | |-I-pinNumberXX [ritorna valore] | |-O-pinNumberXX-valueXXX | |-I-A [stampa tutti i valori] | |-X(eXtended) | \ | |-A-pinNumberXX-pinNumberXX-valueXXX [setta DUE pin contemporaneamente] | |-D-pinNumberXX-pinNumberXX-H/L [setta DUE pin contemporaneamente] | |-V(ersion) [ritorna valore] | |-NP(umber of pins) [ritorna valore] | |-T(est) [alza e abbassa tutti i pin]
/** * (ordine alfabetico) * Copyright 2012 Luca "Palmino" Palmulli <luca.palmulli@gmail.com> * Copyright 2012 Matteo Pessina <matteo.pessina3@studenti.unimi.it> * Copyright 2012 Andrea "Piso" Pisoni <andreapiso@gmail.com> * Copyright 2012 Simone "Pizzy" Pizzimenti <pizzy90@gmail.com> * Copyright 2012 Andrea "atrent" Trentini <andrea.trentini@unimi.it> * * This file is (the lib) part of ArduSlave. * * ArduSlave is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Arduslave is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see <http://www.gnu.org/licenses/>. * * @author tutti MASTER REF per il "linguaggetto" !!! Attenzione ad adattare MAXCOMMANDLENGTH se si aggiungono comandi lunghi Albero stringhe di comando | |-P(inmode) [forse non serve, viene sempre chiamato un pinmode per ogni out] | \ | |-I-pinNumberXX [setta in input] | |-O-pinNumberXX [setta in output] | |-D(igital) | \ | |-I-pinNumberXX [ritorna valore] | |-I-A [stampa tutti i valori] | |-O-pinNumberXX-H/L | |-O-A-H/L [tutti su o giu'] | |-A(nalog) | \ | |-I-pinNumberXX [ritorna valore] | |-O-pinNumberXX-valueXXX | |-I-A [stampa tutti i valori] | |-X(eXtended) | \ | |-A-pinNumberXX-pinNumberXX-valueXXX [setta DUE pin contemporaneamente] | |-D-pinNumberXX-pinNumberXX-H/L [setta DUE pin contemporaneamente] | |-V(ersion) [ritorna valore] | |-NP(umber of pins) [ritorna valore] | |-T(est) [alza e abbassa tutti i pin] | * * TODO aggiungere "sensori" di trigger degli input digitali in modo da rendere * arduslave non piu' totalmente passivo ma dotato di iniziativa autonoma? * * esiste modo di attivare qualche interrupt certo? (verificare su arduino.cc) * altrimenti memorizzare una stringa di bit e verificare differenze in fondo allo swiccione * * TODO ripulire man mano il codice * */ ///////////////////////////////////////////////////////////////// #define SERIALFREQ 115200 ///////////////////////////////////////////////////////////////// #define ENDCHR '#' ///////////////////////////////////////////////////////////////// #define MAXCOMMANDLENGTH 12 #define LOOPDELAY 0 #define SERIALDELAY 10 #define TESTDELAY 50 ///////////////////////////////////////////////////////////////// // valori alti per test con interazione umana, bassi in produzione #define MAXWAIT 1000 /////////////////////////////////////////////// /* per ArduinoUNO */ #define MINPIN 0 //min pin #define MAXPIN 13 //max pin /////////////////////////////////////////////// char command[MAXCOMMANDLENGTH] = ""; int pin_value; int pin_value_more; int level_value; /*********************************************************************** * setup ufficiale dell'Arduino */ void slave_setup() { // init seriale Serial.begin(SERIALFREQ); Serial.println("End of slave lib setup..."); } /***********************************************************************/ void slave_loop() { // legge da seriale readLine2(); //switchone switch(command[0]) // brancha sul primo carattere del comando (prefisso) { case 'P': //PINMODE goP(); break; case 'D': //DIGITAL goD(); break; case 'A': //ANALOG goA(); break; case 'X': //EXTENDED OUTPUT (doppio pin) goX(); break; /* case 'V': // V(ersion)? //TODO break; */ case 'T': // test goT(); break; case 'N': goN(); break; default: Serial.println("NO MATCH FOUND");//return errore break; } // pulisce stringa memset(command, 0, MAXCOMMANDLENGTH); delay(LOOPDELAY); // TODO verificare un giusto delay } /********************************** * digital */ void digital_output_all_h() { for(int i=MINPIN; i<=MAXPIN; i++) { digital_output_h(i); } } void digital_output_all_l() { for(int i=MINPIN; i<=MAXPIN; i++) { digital_output_l(i); } } void digital_output_h(int pin) { pinMode(pin, OUTPUT); digitalWrite(pin, HIGH); } void digital_output_l(int pin) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); } void digital_input(int pin) { pinMode(pin, INPUT); Serial.println(digitalRead(pin)); } void digital_input_all() { for(int i=MINPIN; i<=MAXPIN; i++) { digital_input(i); //Serial.println(); } } /********************************** * analog */ void analog_output(int pin, int value) { pinMode(pin, OUTPUT); analogWrite(pin, value); } void analog_input(int pin) { pinMode(pin, INPUT); Serial.print(pin); Serial.print(":"); Serial.println(analogRead(pin)); } void analog_input_all() { for(int i=MINPIN; i<=MAXPIN; i++) { analog_input(i); //Serial.println(); } } /** * crea l'int da una stringa di 3 caratteri */ int chars2i(char centinaia, char decina, char unita) { return (centinaia-'0')*100 + (decina-'0')*10 + (unita - '0'); } void n_pins() { Serial.print("MINPIN:"); Serial.print(MINPIN); Serial.print("\nMAXPIN:"); Serial.println(MAXPIN); } /** legge da seriale e scrive in command (andava cambiata perche' cosi' si perdevano caratteri nel senso che se uno scriveva comandi con calma la stringa ne usciva incompleta) ora semi-bloccante, con timeout void readLine() { // loop "infinito" (con timeout) int esce=MAXWAIT; for(int i=0; i<MAXCOMMANDLENGTH;) { if(Serial.available()>0) { command[i]=Serial.read(); //Serial.print("I received: "); Serial.print(command[i]); if(command[i]=='\n') break; //TODO platform dependent? i++; } delay(SERIALDELAY); // TODO verificare un giusto delay esce=esce-SERIALDELAY; if(esce==0) break; } // svuotare buffer se stringa troppo lunga? } */ void readLine2() { char c; int i=0; while((c = Serial.read())!=ENDCHR) { if (c!=-1) { command[i]=c; i++; } } } // eventualmente pensare carattere NOP, es. # void resetLine() { for(int i=0; i<MAXCOMMANDLENGTH; i++) { command[i]=0; } } /********************************** * gestione comandi */ void goP() { switch(command[1]) { case 'O': //output pin_value = chars2i('0', command[2],command[3]); // TODO: e se la stringa e' piu' corta? if((pin_value>=MINPIN) && (pin_value<=MAXPIN)) { pinMode(pin_value,OUTPUT); Serial.println("'PO' OK");//return OK } break; case 'I': //input pin_value = chars2i('0', command[2],command[3]); // TODO: e se la stringa e' piu' corta? if((pin_value>=MINPIN) && (pin_value<=MAXPIN)) { pinMode(pin_value,INPUT); Serial.println("'PI' OK");//return OK } break; default: Serial.println("'P' incomplete");//return errore break; } } void goD() { switch(command[1]) { case 'O': //output if(command[2]=='A') { if(command[3]=='H') digital_output_all_h(); if(command[3]=='L') digital_output_all_l(); } else { pin_value = chars2i('0', command[2],command[3]); // TODO: e se la stringa e' piu' corta? if((pin_value>=MINPIN) && (pin_value<=MAXPIN)) { if(command[4]=='H') digital_output_h(pin_value);//esegui il comando DOpinH if(command[4]=='L') digital_output_l(pin_value);//esegui il comando DOpinL } } Serial.println("'DO' ~OK (parziale)");//return ~OK break; case 'I': //input if(command[2]=='A') { // stampa stringa con tutti, es. 011001001 digital_input_all(); } else { pin_value = chars2i('0', command[2],command[3]); // TODO: e se la stringa e' piu' corta? if((pin_value>=MINPIN) && (pin_value<=MAXPIN)) { digital_input(pin_value);// esegui il comando DIpin } } Serial.println("'DI' ~OK (parziale)");//return ~OK break; default: Serial.println("'D' incomplete");//return errore break; } } void goA() { pin_value = chars2i('0', command[2],command[3]); if((pin_value<MINPIN) || (pin_value>MAXPIN)) return; switch(command[1]) { //output case 'O': level_value = chars2i(command[4],command[5], command[6]); if((level_value>=0) && (level_value<=255)) { analog_output(pin_value, level_value);//esegui il comando AOpinvalue Serial.println("'AO' OK ");//return OK } else Serial.println("value out of range");//return errore break; //input case 'I': if(command[2]=='A') analog_input_all(); else analog_input(pin_value);//esegui il comando AOpin break; default: Serial.println("'A' incomplete");//return errore break; } } void goX() { pin_value = chars2i('0', command[2],command[3]); pin_value_more = chars2i('0', command[4],command[5]); // TODO check espressione booleana!!! if( (pin_value<MINPIN) || (pin_value>MAXPIN) || (pin_value_more<MINPIN) || (pin_value_more>MAXPIN) ) { Serial.println("'X*' pin error");//return errore return; } switch(command[1]) { //digital case 'D': if(command[6]=='H') { digital_output_h(pin_value); digital_output_h(pin_value_more); } if(command[6]=='L') { digital_output_l(pin_value); digital_output_l(pin_value_more); } break; //analog case 'A': level_value = chars2i(command[6],command[7], command[8]); if((level_value>=0) && (level_value<=255)) { analog_output(pin_value, level_value); analog_output(pin_value_more, level_value); Serial.println("'XA' OK ");//return OK } break; default: Serial.println("'XD' incomplete");//return errore break; } } void goT() { // test for(int quante=0; quante<3; quante++) { for(int i=MINPIN; i<=MAXPIN; i++) { for(int liv=0; liv<255; liv+=30) { //digital_output_h(i); analog_output(i,liv); delay(TESTDELAY); digital_output_l(i); Serial.print("quante:"); Serial.print(quante); Serial.print(", pin:"); Serial.print(i); Serial.print(", liv:"); Serial.println(liv); } } } } void goN() { if(command[1] == 'P') { n_pins(); } }