Questa è la procedura passo-passo per installare e programmare arduino in modo che possa ricevere comandi da Raspberry per l’apertura del garage o cancello automatico.
Vedendo i singoli passi puoi personalizzarli a tuo piacere.
Se hai fretta ti conviene invece seguire questa procedura che utilizza l’immagine del raspberry già configurata e ti permette di saltare alcuni passi: Aprire il garage da una pagina web.
Prerequisiti
- Avere Arduino Nano
- Avere la scheda relè
- Avere Raspberry con gli accessori
- Aver configurato il Raspberry come descritto in Installare il software per Raspberry
Installare il software Arduino su Raspberry
- Accendere il Raspberry collegandolo ad una TV o alla rete Lan
- Accedere al Raspberry (se via lan attraverso vnc)
- aprire lx-terminal
- per installare il software Arduino, digitare
sudo apt-get install arduino
- aggiungere l’utente corrente (pi) al gruppo tty in modo da poter controllare via seriale (via usb)
sudo usermod -aG tty pi
- collegare arduino ad una porta USB
Creare lo sketch per Arduino
- Installare la libreria per Arduino EgoMiniTimer
- Scompattarla nella cartella libraries di Arduino.
- Aprire il software Arduino
- Nella schermata copiare ed incollare il seguente contenuto:
#include "Timer.h" #define LUCE_PIN 11 #define ACCENDI_LUCE 0 #define SPEGNI_LUCE 1 //solo promemoria, non utilizzati #define APRI_BOX_PIN 13 #define CHIUDI_BOX_PIN 12 #define BASE_PIN 2 //digital pin 2 #define N_INPUT 4 #define N_OUTPUT 4 #define BASE_PIN_OUT 10 //da d2 a d5 sono input //da d10 a d13 sono output //#########azioni #define DO_NOTHING 0 Timer timer; typedef void (*DoActionFunction) (const byte pin); DoActionFunction doActionFunction; typedef void (*SimpleFunction) (); const char* inputDescr0[]={"Box chiuso1", "chiuso2", "chiuso3", "chiuso4"}; const char* inputDescr1[]={"Box aperto1", "aperto2", "aperto3", "aperto4"}; void doNothing(const byte pin){ } void doPrint0(const byte pin){ Serial.print("status: "); Serial.println(inputDescr0[pin]); } void doPrint1(const byte pin){ Serial.print("status: "); Serial.println(inputDescr1[pin]); } void doSpegniLuce(const byte pin){ digitalWrite(LUCE_PIN,SPEGNI_LUCE); doPrint0(pin); } void doAccendiLuce(const byte pin){ digitalWrite(LUCE_PIN,ACCENDI_LUCE); doPrint1(pin); } byte simulateInputs=0; //setta a 1 i bit degli input da forzare byte simulateValues=0; //valore per i bit da simulare; //int simulateDurations[]={-1,-1,-1,-1}; //Timer simulateTimers[4]; int simulateTimerId[N_INPUT]; void noSimulateInput(int inp){ Serial.println("no simulate "+String(inp)); bitClear(simulateInputs,inp); timer.stop(simulateTimerId[inp]); } void outputHigh(int out){ Serial.println("output high to "+String(out)); digitalWrite(BASE_PIN_OUT+out,HIGH); printOutStatus(out); } void outputLow(int out){ Serial.println("output low to "+String(out)); digitalWrite(BASE_PIN_OUT+out,LOW); printOutStatus(out); } DoActionFunction doAction0[]={ doSpegniLuce, doPrint0, doPrint0, doPrint0 }; DoActionFunction doAction1[]={ doAccendiLuce, doPrint1, doPrint1, doPrint1 }; byte prevInputs; String inputString = ""; void setup() { //start serial connection Serial.begin(9600); //configure pin2 as an input and enable the internal pull-up resistor byte base=BASE_PIN; for (byte pin = 0; pin < N_INPUT; pin++) { pinMode(base+pin, INPUT_PULLUP); } base=BASE_PIN_OUT; for (byte pin = 0; pin < N_OUTPUT; pin++) { pinMode(base+pin, OUTPUT); digitalWrite(base+pin,HIGH); //condizione di riposo per i relè } // reserve 100 bytes for the inputString: inputString.reserve(300); } void loop() { byte inputs=0; byte base=BASE_PIN; for (byte pin = 0; pin < N_INPUT; pin++) { byte sensorVal = digitalRead(base+pin); if(bitRead(simulateInputs,pin)==HIGH){ sensorVal=bitRead(simulateValues,pin); }; if (sensorVal == HIGH) { bitSet(inputs,pin); } else { bitClear(inputs,pin); } } if(prevInputs!=inputs){ Serial.println(inputs,BIN); checkInputs(inputs,prevInputs); prevInputs=inputs; } timer.update(); } void checkInputs(byte in,byte prevIn){ for (byte pin = 0; pin < N_INPUT; pin++) { if (bitRead(in,pin) == bitRead(prevIn,pin)) {//si attiva sul fronte alto o basso dell'impulso } else { if (bitRead(in,pin) == LOW ){ doAction0[pin](pin); } else{ doAction1[pin](pin); } } } } void printInputs(){ byte in=prevInputs; for (byte pin = 0; pin < N_INPUT; pin++) { Serial.print("status: "); if (bitRead(in,pin) == LOW ){ Serial.println(inputDescr0[pin]); } else{ Serial.println(inputDescr1[pin]); } } } void printOutStatus(byte pin){ Serial.print("status: out"); Serial.print(pin); if (digitalRead(pin+BASE_PIN_OUT) == LOW ){ Serial.println(" low"); } else{ Serial.println(" high"); } } void printOutputs(){ byte in=prevInputs; for (byte pin = 0; pin < N_OUTPUT; pin++) { printOutStatus(pin); } } void serialEvent() { while (Serial.available()) { // get the new byte: char inChar = (char)Serial.read(); // add it to the inputString: inputString += inChar; // if the incoming character is a newline, set a flag // so the main loop can do something about it: if (inChar == '\n') { Serial.println(inputString); if (inputString.startsWith("status")) { Serial.println("status: reply to "+ inputString.substring(7)); printInputs(); printOutputs(); Serial.println("status: end"); } //set output :3=1 5 imposta l'uscita 3 a 1 per 5 secondi if (inputString.startsWith("set output")) { String resto=tail(inputString,':'); String outs=head(resto,'='); String vals=tail(resto,'='); String durs=tail(vals,' '); durs.trim(); if(durs.length()>0){ vals=head(vals,' '); } int out=outs.toInt(); String risposta="Set output "+outs; int val=vals.toInt(); if(val>0){ outputHigh(out); risposta+="=1"; if(durs.length()>0){ int dur=durs.toInt(); timer.after(dur*1000,outputLow,out); risposta+=" for "+String(dur)+" sec"; }; }else{ outputLow(out); risposta+="=0"; if(durs.length()>0){ int dur=durs.toInt(); timer.after(dur*1000,outputHigh,out); risposta+=" for "+String(dur)+" sec"; }; }; Serial.println(risposta); } inputString=""; } } } String head(String s,char separator){ int sepIndex = s.indexOf(separator); if(sepIndex<0){ return s; } String firstValue = s.substring(0, sepIndex); return firstValue; } String tail(String s,char separator){ int sepIndex = s.indexOf(separator); if(sepIndex<0){ return ""; } String value = s.substring(sepIndex+1); return value; }
- Ecco il risultato
- Salvare con nome egodomo_garage
- Scegliere Strumenti/Scheda
- Scegliere Arduino Nano w/ATmega328
- Scegliere la seriale (USB)
- Scegliere il tipo di programmatore Arduino as ISP
- Scegliere Sketch/Carica.
- Se il carimento è avvenuto senza errori, provare a vedere se si comunica con Arduino.
- Scegliere monitor seriale
- Digitare Status nel monitor seriale, controllando che sia aggiunto un NL a fine riga
Se arduino risponde con lo stato del garage allora il tutto funziona.
A questo punto siamo pronti per collegarci la scheda relè e da questa la luce del garage e i pulsanti di apertura e chiusura.
Comandi utili per fissare il nome della seriale arduino
Provare uno dei seguenti comandi, quello che restituisce delle risposte che non siano
device node not found
Questi i comandi:
udevadm info --name=/dev/ttyACM0 --attribute-walk|less udevadm info --name=/dev/ttyACM1 --attribute-walk|less udevadm info --name=/dev/ttyUSB0 --attribute-walk|less udevadm info --name=/dev/ttyUSB1 --attribute-walk|less
Scorrere il risultato e cercare la stringa “ATTRS{idVendor}” che può valere
ATTRS{idVendor}=="2a03"
oppure
ATTRS{idVendor}=="1a86"
premere q per uscire dalla modalità di scorrimento del risultato (less).
Creare il file di regole per udev per assegnare sempre lo stesso nome di device ad arduino, digitando:
sudo nano /etc/udev/rules.d/99-usb-serial.rules
Usare una o l’altra riga a seconda del risultato sopra riscontrato:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{serial}=="8543833303635150A0C1", SYMLINK+="arduino"
oppure (per Arduino Nano compatibile)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="arduino"
Premere CTRL+X e premere Y per uscire e salvare.