19 dicembre 2012

Come costruire episodio 1: l'encoder ottico

Dopo più di 6 mesi finalmente siamo di nuovo pronti per un altro articolo: nel post precedente avevamo promesso di parlare del circuito elettronico, ma siamo ancora lontani da una versione completa e funzionante del circuito, per cui parleremo prima dei vari componenti singolarmente e, successivamente, dello schema nella sua interezza. In questo primo articolo della serie proveremo a farvi conoscere e capire in modo semplice e il più dettagliato possibile i segreti (mica tanto segreti) del componente più richiesto: l'encoder ottico.

Per chi non avesse voglia di leggere tutta sta pappardella ecco un indice col quale potrete passare direttamente alla parte che vi interessa:

 - Che cos'è
 - Come funziona (sensore infrarosso generico)
 - Come funziona (encoder ottico)
 - Pin interrupt (cos'è e perché usarlo)
Innanzitutto, che cos'è un encoder?
La tanta amata Wikipedia da questa definizione: "Il trasduttore di posizione angolare, comunemente noto in ingegneria elettronica come encoder, è un dispositivo elettromeccanico che converte la posizione angolare del suo asso rotante in segnali elettrici numerici digitali", nel caso di Explò servirà a dare indicazioni sulla rotazione delle ruote, in modo da poter fare una stima della distanza percorsa dal robot.

L'encoder che vogliamo utilizzare è molto semplice (e soprattutto molto poco costoso), ma richiede qualche piccola accortezza per funzionare al meglio, per cui cominciamo col parlare di come è fatto e del funzionamento vero e proprio.

L'encoder ottico che useremo, come già accennato in un precedente post, è sostanzialmente costituito da soli due componenti, due led infrarossi (più tardi vedremo come mai proprio infrarossi): uno detto emettitore e l'altro detto ricevitore.
L’emettitore svolge la tipica funzione di un qualsiasi LED (Light Emitting Diode, diodo ad emissione luminosa): emettere luce se ai due poli è applicata una differenza di potenziale.
Al contrario il ricevitore sfrutta una proprietà poco conosciuta dei led; infatti non solo possono emettere luce, ma sono anche in grado di fare l'esatto opposto: generare corrente elettrica se colpiti da una radiazione luminosa, proprio come fanno le celle fotovoltaiche quando colpite dai raggi solari.

Ma in che modo funziona? Con le premesse appena fatte il funzionamento è molto semplice e intuitivo.
Questi due led, posti l'uno di fronte l'altro, agiscono esattamente come le fotocellule dei cancelli o dei portoni. Il led emettitore produce costantemente una radiazione luminosa: se vi è un ostacolo tra i due diodi il led ricevitore non viene investito dalla luce e non succederà nulla; al contrario, in assenza di ostacoli, la radiazione arriverà a colpire il ricevitore, che quindi, come detto sopra, produrrà una corrente.
Proprio per evitare che il ricevitore reagisca a qualsiasi radiazione luminosa estranea (ad esempio la luce del sole), per queste applicazioni vengono utilizzati dei led IR (infrarossi): infatti ogni led reagisce solo alle radiazioni di lunghezza d’onda che sono in grado di produrre. Nel nostro caso il ricevitore reagirà soltanto ad una luce nel campo dell’infrarosso, e l’unica fonte di questo tipo di radiazione sarà l'emettitore, quindi il sensore non subirà sostanziali disturbi dalle altre radiazioni presenti nell'ambiente (nel nostro caso useremo led con lunghezza d’onda di 840 nm, ma qualsiasi tipo di led IR dovrebbe andare bene).
Se ve lo foste mai chiesto questo è praticamente lo stesso metodo utilizzato per la comunicazione tra telecomando e televisore, che infatti hanno rispettivamente un emettitore ed un ricevitore infrarosso.

Fin qua dovrebbe essere tutto chiaro (o almeno spero), però abbiamo parlato solo di raggi solari e tetti, cancelli e portoni, televisori e telecomandi: tutto questo cosa c'entra con l'encoder ottico?

Intanto grazie per la domanda azzeccatissima, cade giusto a fagiolo per introdurre il prossimo capitolo: come usare il sensore appena descritto per realizzare un encoder ottico.

Posizioniamo i due led sul telaio, o comunque fissi alla struttura portante, in modo tale che si trovino ai lati della ruota del nostro robot, il più vicino possibile alla circonferenza esterna e rivolti l’uno verso l’altro. Ora facciamo sulla ruota stessa un piccolo foro (diametro almeno 2-3mm per garantire un buon passaggio di luce), sempre vicino al bordo esterno, in linea con i led: in questo modo, con il robot è in movimento, il ricevitore produrrà un segnale elettrico quando la fessura si troverà all'altezza del sensore, e solo in quel istante. Il microcontrollore sarà allora in grado di capire quando il foro passa di fronte ai led e quindi, ad ogni impulso elettrico in arrivo dal ricevitore, saprà che la ruota avrà compiuto un giro completo sul proprio asse.

E’ un inizio, ma non ci basta; a noi serve una precisione maggiore: ora come ora abbiamo una precisione di un giro o, esprimendola in gradi, di 360°. Quindi, se prendiamo come istante iniziale la prima volta che il foro passa di fronte ai led, possiamo sapere quando la ruota ha ruotato di 360° o 720° o 1080° eccetera rispetto allo zero che abbiamo imposto, però non sappiamo niente negli istanti intermedi. Forse non sembra un gran problema, ma se pensiamo che la ruota avrà un diametro di circa 6 cm, vuol dire che conosceremo la posizione di Explò solo una volta ogni poco meno di 19 cm (lunghezza  della circonferenza), rendendo il robot praticamente inutile.

La soluzione c’è ed è anche molto semplice: usando termini tecnici, basta fare più buchi.
Tracciamo quindi una circonferenza sulla ruota, con centro nell'asse della ruota e passante per il foro già fatto: lungo questa curva facciamo gli altri fori ad egual distanza l’uno dall'altro, con l’aiuto di un goniometro. Avendo fatto il primo vicino al bordo esterno dovrebbe esserci spazio per almeno 20 fori, facendo salire la precisione a 18°, quindi, nel nostro caso, avremo informazioni praticamente ad ogni centimetro percorso da Explò. Ovviamente aumentando i fori aumenta la precisione del sensore, però se facciamo i fori troppo piccoli per risparmiare spazio, c’è il rischio, come già detto prima, che non facciano passare abbastanza luce: fate qualche prova, magari con ruote di cartone per trovare il giusto equilibrio tra quantità e larghezza dei fori.

A questo punto abbiamo pronto il nostro encoder, manca soltanto renderlo operativo attaccandolo ad un microcontrollore, nel nostro caso un Arduino UNO (le stesse considerazioni possono essere applicate a qualunque altro microcontrollore). Come abbiamo detto il sensore è formato solo da due led IR: vediamo come vanno collegati, cominciando con il led emettitore.

Per chi fosse proprio alle primissime armi nel mondo dell’elettronica ecco come riconoscere in un led quale dei due poli è il negativo (catodo) e quale il positivo (anodo).

Negativo: gamba corta e circonferenza tagliata (come si vede nella foto il bordo del led sul “lato negativo”                       non è tondo ma smussato)
Positivo: gamba lunga



Ricordiamo che il led emettitore deve solo emettere (scusate, ma proprio non mi veniva in mente nessun altro verbo) costantemente un raggio di luce, non ha bisogno di alcun controllo o non deve fornire alcun dato: ha semplicemente bisogno di essere alimentato nel modo adatto (se sapete già come alimentare un led cliccate qua per andare al collegamento del ricevitore).

Per farlo basta collegare il polo negativo alla massa (ground  in inglese e GND su Arduino) e quello positivo ad una resistenza che a sua volta è collegata all'alimentazione (Vcc sui microcontrollori e 5V su Arduino).
Il valore della resistenza (espresso in ohm, simbolo Ω) viene calcolata in base alla tensione di alimentazione, alla tensione di lavoro del led e alla corrente assorbita dallo stesso tramite questa formula: R = (Val – Vled) / Iled. Nel nostro caso abbiamo una tensione di alimentazione di 5 V (volt), una tensione di lavoro del led di circa 1,5 V e il led assorbe circa 16 mA (milliampere): la resistenza adatta è quindi di 218.75 ohm. Le resistenze che si trovano in commercio vengono prodotte solo in alcuni valori standard, quindi, per rimanere nella sicurezza, bisogna sempre arrotondare per eccesso e usare una resistenza con un valore maggiore, il più vicino possibile a quella richiesta. Noi useremo delle resistenze da 220 ohm. Il valore di ogni resistenza viene identificato dalle bande colorate impresse sulla superficie: ci sono un sacco di siti o di tabelle o di app per identificare il valore dal colore delle bande e/o viceversa, google vi sarà di aiuto.

Il collegamento del ricevitore può sembrare ancora più semplice: il polo negativo di nuovo attaccato alla massa (sempre GND su Arduino),  mentre il polo positivo collegato direttamente ad uno dei pin digitali del microcontrollore in modo da ricevere il potenziale prodotto dal ricevitore quando non vi sono ostacoli tra i due led.
Questo è stato il nostro primo tentativo, risultato: all'Arduino non arrivava assolutamente nulla.
Dopo qualche attimo di disperazione abbiamo preso il fidato multimetro e trovato la magagna. Per capire cosa non andava serve prima un po’ di teoria (se non vi interessa e volete andare subito alla soluzione pigiate qui).

I pin di un microcontrollore (nel caso di Arduino quelli digitali) sono in grado di identificare e produrre solo due tipi di segnale: HIGH (alto, attivo, vero, 1 in codice binario) e LOW (basso, non attivo, falso, 0 in codice binario).
Lo stato LOW si ha quando non vi è passaggio di corrente, o meglio quando la tensione sul pin è di circa 0 volt. Per attivare lo stato HIGH deve essere invece presente sul pin una certa tensione specifica per ogni tipo di microcontrollore. Se andiamo a controllare il datasheet del micro di Arduino (ATmega328), esattamente a pagina 313 troviamo questo:


Vcc è la tensione di funzionamento del microcontrollore, nel caso di Arduino 5V: lo stato HIGH viene quindi raggiunto oltre la tensione di circa 3 volt.

Dopo questa piccola premessa, torniamo alla pratica. Proviamo a misurare la tensione presente sul pin, in assenza di ostacoli tra i led: ricordiamo che in questa situazione il microcontrollore dovrebbe essere in grado di ricevere una “impulso” elettrico e, quindi, di leggere uno stato HIGH sul pin; però, con la nostra misurazione, abbiamo ottenuto una tensione di 900 mV (millivolt): confrontandola con i dati nella tabella qua sopra, vediamo che si trova ancora nel range dello stato LOW, ecco il problema!

Dobbiamo quindi amplificare il segnale in arrivo dal ricevitore, e per farlo basta un semplice componente: un transistor, per la precisione un transistor NPN; ma come funziona un transistor?

Per farla veloce il transistor NPN ha 3 poli, base, collettore ed emettitore: la corrente che va dal collettore all'emettitore è proporzionale alla corrente che arriva sulla base, e quindi se non c’è corrente sulla base, non passa corrente tra il collettore e l’emettitore. L’ho fatta un po’ semplice, ma è sostanzialmente quello che ci serve sapere. Se volete saperne di più in rete ci sono un mare di informazioni a riguardo, per ora torniamo al nostro problema pratico.

La prima cosa da fare è collegare la base al polo positivo del led ricevitore: in questo modo, ogni volta che arriva corrente dal led, viene consentito il passaggio di segnali elettrici tra gli altri due pin del transistor, mentre, se non arriva corrente, i due poli sono isolati l’uno dall'altro. Abbiamo quindi creato una sorta di interruttore, adesso vediamo come sfruttarlo al nostro scopo.
Colleghiamo il polo negativo del led e l’emettitore del transistor al ground, il collettore alla tensione di alimentazione (+5V di Arduino) tramite una resistenza da 10Kohm (10'000 ohm) e infine il pin digitale di Arduino al collettore (N.B. MOLTO IMPORTANTE: è da scegliere un pin così detto interrupt, nel caso di Arduino UNO il 2 o il 3; più tardi vi spiego cos'è e perché è da preferire agli altri pin). Se le parole non vi bastano ecco una piccola illustrazione e la foto del risultato finale.

Vediamo come si comporta nei due casi di funzionamento:

Ostacolo tra i led NO
La corrente in arrivo dall'emettitore va a finire sulla base, consentendo il passaggio di corrente tra collettore e emettitore. In questo caso è come se il collettore fosse direttamente collegato al ground: sappiamo che al ground (se facciamo tutto giusto) c’è una tensione di 0V, di conseguenza sia sul collettore che sul pin di Arduino la tensione sarà di 0V.
Riassumendo se non ci sono ostacoli tra i led lo stato del pin digitale sarà LOW (o 0 o basso).

Ostacolo tra i led SI
Sulla base non vi è corrente, quindi è come se il transistor non ci fosse: in pratica il pin dell’Arduino risulta essere collegato direttamente all'alimentazione tramite la resistenza, quindi ci sarà una tensione di circa 5V (un po’ meno a causa di una piccola dissipazione dovuta alla resistenza).
Quindi se ci sono ostacoli tra i led lo stato del pin digitale sarà HIGH (o 1 o alto).

Perfetto, l'encoder è pronto! Ecco lo schema elettronico definitivo e una foto del nostro encoder ottico! (Nella foto il cavo rosso porta il segnale all'Arduino)



Per ultima cosa diamo un’occhiata a come far interagire il microcontrollore con il sensore.
Come vi abbiamo detto poco sopra, è meglio, se non addirittura necessario, scegliere un pin interrupt per collegare l’encoder all'Arduino, ma perché?

A noi non serve semplicemente leggere lo stato in cui si trova il pin (alto o basso) in un determinato momento, ma ci interessa sapere quando avviene il cambiamento dello stato da alto a basso e viceversa, cioè, quando lo spazio tra i due led passa dall'essere libero all'essere ostruito da un ostacolo e viceversa; quindi il programma deve verificare che ci sia il cambiamento di stato e dunque lanciare una funzione specifica. Vediamo allora cosa cambia utilizzando i pin normali e gli interrupt.

Pin digitali (normali)
Prima di tutto bisogna scrivere, in un punto preciso del programma, una funzione di lettura dello stato del pin; poi bisogna controllare la lettura precedente e verificare che effettivamente è avvenuto il cambiamento di stato, ed infine, se c’è stato cambiamento di stato, lanciare la funzione: insomma molte righe per lanciare una singola funzione.
Tutto ciò, inoltre, è inserito in mezzo ad altre decine se non centinaia di righe di programma, sorge quindi un altro problema: e se il cambiamento di stato avviene mentre il microprocessore sta facendo qualcos'altro? Beh, se il programma è particolarmente complesso è possibile che uno o più cambiamenti di stato vengano saltati, quindi tutto il sistema perde notevolmente in precisione ed affidabilità. Insomma, non è un gran che, non resta che sperare nell'interrupt.

Pin interrupt
Spendiamo prima due parole per spiegare di cosa si tratta.
L’interrupt è una funzione che permette letteralmente di interrompere il programma in qualsiasi momento per avviare un funzione specifica; una volta terminata la funzione, il programma riprende da dove è stato fermato. Questo interrupt deve essere lanciato da un qualche tipo di comando: il pin interrupt ha proprio questo scopo, ed esegue il suo compito in modo completamente diverso da ogni altro pin. In pratica il microcontrollore lancia un interrupt quando un particolare evento, deciso dall'utente, accade sul pin interrupt; non c’è più bisogno di specificare un punto del programma in cui effettuare la lettura dello stato del pin: non appena l’evento specifico avviene, il microcontrollore lancia l’interrupt e la funzione collegata può essere svolta.
Tra gli eventi che si possono specificare c’è CHANGE che fa proprio al caso nostro: ogni volta che lo stato del pin cambia da alto a basso o viceversa, l’interrupt viene lanciato.

Come si può vedere i vantaggi nell'usare questo tipo di pin sono multipli e risolvono tutti i problemi dell’usarne uno qualsiasi. L’intero funzionamento dell’interrupt è racchiuso in una sola riga di programma: infatti con un singolo comando si specifica il pin interrupt che si vuol usare, la funzione da lanciare e l’evento scatenante l’interrupt (qua trovate come dichiarare e far funzionare un interrupt con Arduino). Altro vantaggio nell'uso dell'interrupt, è che, come abbiamo già detto più volte, può essere lanciato in qualsiasi momento, sia con il microcontrollore inattivo, sia durante altre operazioni: diventa quindi praticamente impossibile perdere il passaggio da presenza di ostacolo ad assenza (e viceversa) tra i led dell’encoder. Inoltre, utilizzando l'evento change, con un solo foro potremo lanciare l'interrupt due volte: infatti verrà lanciato al passaggio da ruota a foro e di nuovo al passaggio da foro a ruota. In questo modo avremo raddoppiato la precisione del sensore senza modificare la ruota o il sensore stesso, e senza aggiungere alcuna riga di programma.

Ci siamo, ogni problema dovrebbe essere risolto e le nostre prove lo dimostrano: questo encoder ottico funziona davvero!

Se volete testare il vostro encoder, o comunque volete farvi un’idea di come richiamare un interrupt con Arduino, qua sotto vi alleghiamo un piccolo programma di controllo: come potrete notare una volta caricato il file sulla scheda, anche mettendo il microcontrollore in pausa (con la funzione delay), l’interrupt è comunque in grado di interagire con il processore, facendogli lanciare la funzione di nostra scelta (nel nostro caso un semplice contatore).


volatile long contatore = 0;           // dichiarando la variabile come volatile, il suo valore viene salvato anche quando il loop ricomincia

void setup(){
  Serial.begin(9600);
  attachInterrupt(0, conta, CHANGE);   // dichiaro il pin interrupt, la funzione da lanciare e l'evento scatenante
}                                      // nella dichiarazione 0 corrisponde al pin 2 su Arduino, 1 al pin 3

void loop(){                           // il programma continua a girare per conto suo
  delay(1000);                         // il microcontrollore viene messo in pausa per un secondo (1000 millisecondi)
  Serial.print("passato un secondo");  // questo comando serve per verificare che effettivamente il loop continua a funzionare
}

void conta(){                          // non appena l'evento dichiarato in setup avviene sul pin scelto, parte questa funzione
  contatore++;
  Serial.println(contatore);
}

Bene, direi che finalmente arrivati alla conclusione: il post è davvero lungo, ma spero lo troviate utile e completo.
Come sempre per ogni domanda, dubbio, insulto, complimento o qualsiasi altra cosa scriveteci un commento qua sotto.

Alla prossima da io e ancheio.

31 commenti:

  1. Ti faccio una domanda da ignorantone...ma come fa ad arrivare corrente sulla base del transistor se questa non è collegata a Vcc?
    Scusa l'ingnoranza ma non capisco proprio...

    RispondiElimina
    Risposte
    1. Cioè mi spiego meglio...Se l'anodo del LED ricevente non è connesso a Vcc come può funzionare lo stesso LED? e poi soprattutto come fa ad arrivare corrente sulla base del transistor se non è collegata a Vcc?

      Elimina
    2. In realtà non è niente di complicato: per capire lo schema devi ricordarti che i LED, oltre ad emettere luce, hanno anche la proprietà di generare un impulso elettrico se colpiti dalla luce, proprio come fa una cella fotovoltaica (vedi paragrafo Com'è fatto). In pratica quando il LED emettitore è acceso, la luce che emana colpisce il LED ricevente, che non deve illuminarsi (quindi non deve essere collegato alla Vcc), ma deve trasformare la luce che lo colpisce in corrente elettrica. Questa corrente, generata dal LED ricevente, arriva tramite il catodo (quindi il positivo del led) alla base del transistor, che può quindi funzionare senza ricevere corrente dalla Vcc, ma solo con quella generata dal LED.
      Spero sia un po' più chiaro, comunque se c'è qualcosa che non ti torna scrivi pure. Ciao, alla prossima

      Elimina
    3. Intanto grazie mille per avermi risposto!!!
      Cioè intendevi dire, arriva all'anodo(che è il positivo del LED) vero?
      Ma il discorso che il led genera corrente vale solo per i LED riceventi? Non c'è bisogno di mettere una resistenza limitatrice? Quanta corrente genera?

      Scusa se ti assalto dalle domande ma sono alle prime armi e sono affamato di chiarimenti!!!
      Grazie ancora!

      Elimina
    4. Comunque ti faccio i miei complimenti per la chiarezza con cui spieghi...è dote di pochi!!!

      Elimina
    5. Si, intendevo l'anodo, mi confondo ogni volta... (avevo pure sbagliato sul blog, ho corretto grazie mille!)
      QUALSIASI LED ha proprietà fotovoltaiche, cioè appunto trasformare luce in impulsi elettrici, e può essere utilizzato sia come ricevitore che come emettitore, dipende solo da come lo colleghi al resto del circuito: se lo colleghi ad una tensione esterna (come può essere Vcc) sarà un emettitore di luce (che è l'utilizzo classico), se invece non lo alimenti in nessun modo genererà un tensione proporzionale all'intensità della luce che lo colpisce e sarà un led ricevente. Non è una gran risposta, ma volevo essere conciso: se non ti convince del tutto proverò a fare un mini articolo sul blog per spiegarlo meglio.
      Per quanto riguarda la corrente che genera non c'è bisogno di limitarla in alcun modo perché è davvero minuscola, meno di 10 microAmpere (10^-6 Ampere). Una corrente così bassa non può fare del male a niente o nessuno, quindi non servono ne resistenze ne circuiti di sicurezza o cose simili: attacca e via.
      Grazie a te per i complimenti! Continua pure a fare domande e soprattutto prova con mano e fai esperimenti, è il modo migliore per imparare! Prima o poi tornerò a scrivere un articolo qua sopra, quindi ogni tanto dacci un occhio e magari ritroverai qualcosa di interessante. Alla prossima, ciao

      Elimina
  2. Grazie mille di avermi chiarito le idee!!! Comunque mi farebbe molto piacere se potessi scrivere un articolo a riguardo di queste proprietà dei LED...
    Ciao alla prossima e grazie ancora!

    RispondiElimina
  3. Ciao mi potreste aiutare per un esperimento simile? avrei bisogno di un contatore di passaggio e direyione a ir. Cioè mi spiego vorrei creare un tubo nel quale passano insetti, e calcolare quanti escono e quanti entrano. Se tutto cio fosse possibile qualcuno potrebbe aiutarmi? graie mille

    RispondiElimina
    Risposte
    1. Ciao, direi che il sensore sopra si può tranquillamente adattare al tuo progetto, però ci vorrebbe qualche informazione in più. Comunque come contatore questo encoder va benissimo e per capire in che direzione vanno si potrebbe metterne due uno in fila all'altro e a seconda di quale dei due scatta prima si può capire da che parte vanno. Se comunque hai bisogno scrivi pure qua. Ciao

      Elimina
    2. Ciao, grazie mille ho studiato un sistema con dei integrati NTE74LS86 in poche parole facendo dei comandi logici e come risultato mi da 1 impulso per direzione. Grazie mille di tutto..

      Elimina
  4. Ciao scusa avrei bisogno ancora di aiuto...sto impazzendo con un modulo gsm.. qualsiasi sketch che carico mi da sempre errore char. ecco un esempio.

    /*
    http://www.plexishop.it/it/arduino-gsm-shield-con-antenna-integrata.html
    Plexishop.it (Global Engineering Network srl) investe tempo e risorse per produrre tutorial ed esempi di programmazione, vi preghiamo di supportarci acquistando i prodotti dal nostro sito. Questo sketch è rilasciato sotto licenza BSD (vedi file di licenza allegato). La licenza impone che tutto il testo qua sopra sia lasciato integro in ogni redistribuzione del file, anche se il codice viene modificato.
    */

    // ITA: Si includono le librerie GSM
    // ENG: Include the GSM library
    #include


    // ITA: Inizializzazione delle librerie
    // ENG: Initialize the library instances
    GSM gsmAccess;
    GSM_SMS sms;

    //ITA: Numero di telefono
    //ENG: Telephone number
    char telefono[14]="+3932xxxxxxxx";


    // ITA: Assegno i pin ai led

    int pulsante=10;
    int ledVerde=12;

    void setup()
    {
    // ENG: Setup pins for OUTPUT
    // ITA: Imposto i pin come OUTPUT

    pinMode(pulsante, INPUT);
    pinMode(ledVerde, OUTPUT);

    boolean connessione = true;

    // ITA: Attivo la connessione GSM
    // ENG: Start GSM connection
    while(connessione)
    {
    if(gsmAccess.begin()==GSM_READY)
    connessione = false;
    }

    // ENG: GSM initialized
    // ITA: Il GSM è pronto per ricevere messaggi
    digitalWrite(ledVerde,HIGH);
    }
    //ENG: Variable declaration
    //ITA: Dichiarazione variabili

    float valoreSensore=0;
    float tensioneLetta=0;
    float valoreAcquisito=0;

    void loop()
    {
    if(digitalRead(pulsante))
    {
    // ITA: Invia il messaggio
    // ENG: Send the message
    sms.beginSMS(telefono);
    sms.print(leggiTemp());
    sms.endSMS();
    }

    }


    //ITA: Leggi la temperatura
    //ENG: Acquire temperature
    float leggiTemp()
    {

    valoreSensore=analogRead(A0);
    tensioneLetta=(valoreSensore/1024.0)*5.0;
    return (tensioneLetta-0.5)*100;
    }

    pure anche con quelli originali di arduino mi fa sempre lo stesso scherzo..Ti ringrazio aticipatamente

    Saluti Ricky

    RispondiElimina
    Risposte
    1. Ciao, un problema sicuramente presente nel tuo codice è che non hai caricato la libreria: con la funzione #include dichiari quali libreria vuoi utilizzare, e per farlo devi dire ad arduino come si chiama questa libreria. Nel tuo caso non hai messo nessun nome e quindi non carica nulla e le funzioni successive vengono date come errori perché non le riconosce. Prova semplicemente a scrivere dopo #include, nelle prime righe: provando a compilarlo con questa piccola aggiunta sul mio pc non ha dato nessun errore.

      Elimina
    2. Ho visto che la roba tra le parentesi < non le pubblica nei commenti, quindi forse anche te hai già scritto GSM.h dopo #include. Che versione del software Arduino stai usando? Lo vedi in alto nella finestra principale

      Elimina
    3. Ciao, io uso arduino 1.0.6 per progrmmare. Scusa ma non ho capito cosa dici di scrivere dopo a #include?? cioè sapresti dirmi corretto come sarebbe lo sketch scritto sopra? grazie mile

      Elimina
    4. Hai Skype cosi possiamo sentirci e capirci meglio ok? grazi mille per gli aiuti :)

      Elimina
    5. Per skype ora non ci posso essere, comunque per lo sketch deve esserci scritto #include < GSM.h > senza spazi tra < > e GSM.h. Se il codice ti da ancora errore scrivimi esattamente cosa dice in basso

      Elimina
  5. Ciao si è incluso GSM.h.. il problema è il seguente:

    C:\Users\Ricky\Downloads\arduino-1.0.6-windows\arduino-1.0.6\libraries\GSM\GSM3ShieldV1ModemVerification.cpp: In member function 'String GSM3ShieldV1ModemVerification::getIMEI()':
    C:\Users\Ricky\Downloads\arduino-1.0.6-windows\arduino-1.0.6\libraries\GSM\GSM3ShieldV1ModemVerification.cpp:72: error: conversion from 'int' to 'String' is ambiguous
    C:\Users\Ricky\Downloads\arduino-1.0.6-windows\arduino-1.0.6\hardware\arduino\cores\arduino/WString.h:61: note: candidates are: String::String(const __FlashStringHelper*)
    C:\Users\Ricky\Downloads\arduino-1.0.6-windows\arduino-1.0.6\hardware\arduino\cores\arduino/WString.h:59: note: String::String(const char*)

    Mi spiace ma veramente non so più cosa fare.. e mi spiace aver speso soldi senza usarli. Ti ringrazio veramente tanto per il tuo aiuto.

    RispondiElimina
    Risposte
    1. Ciao, a quanto pare il problema è della versione di Arduino, ci deve essere qualche bug nella libreria GSM. In effetti come ti dicevo prima a me non dava nessun problema, ma io usavo Arduino 1.0.5: ho provato a scaricare 1.0.6 e il problema è spuntato anche a me. Una semplice soluzione è usare la libreria di un'altra versione, puoi scaricarla da qua http://downloads.arduino.cc/GSM-Arduino-1.0.7-afc368b.zip che è quella della versione 1.0.7 che dovrebbe uscire tra poco.
      Per sostituire la libreria per prima cosa estrai dal file zip del link sopra la cartella GSM e quindi copiala in ...\arduino-1.0.6\libraries\.
      Fammi sapere se il fix funziona

      Elimina
    2. Ciao grayie mille, ora funziona.. amche se non capisco perché invia 8 sms alla volta ;(.. per il resto e tutto ok.. ti ringrazio veramente tanto.. era un po' che stavo impazzendo..

      Elimina
    3. Tranquillo, anche io sto usando un modulo gsm per un altro progetto e anche a me non mancano i mal di testa. Per il fatto che mandi molti sms con un solo click di tasto prova a vedere il debouncing del bottone: in pratica non essendo perfetto i contatti del pulsante ad un singolo click i segnali inviati sono multipli. Per risolvere puoi fare per via software (Debounce Arduino) oppure via hardware, comunque su internet si trova molto.
      Ciao alla prossima

      Elimina
  6. Ciao scusa ma mi sto perdendo in un semplicissimo comando e non capisco perché.. cosa sbaglio secondo te? dovrebb essere una semplice variabile che cambia i led ma nulla.. ;(
    saluti Ricky


    const int ledVerde = 2;
    const int ledRosso = 7;
    const int pulsante = A0;


    void setup(){

    pinMode(ledVerde, OUTPUT);
    pinMode(ledRosso, OUTPUT);
    pinMode(pulsante, INPUT);
    }

    void loop (){

    if (pulsante == HIGH){
    digitalWrite(ledRosso,HIGH);
    digitalWrite(ledVerde,LOW);
    }
    else {
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledRosso,LOW);
    }
    delay(100);
    }

    RispondiElimina
    Risposte
    1. Ciao, il problema è molto semplice. All'inizio hai dichiarato che pulsante = A0, quindi quando nell'if dici pulsante == HIGH questo non si verificherà mai perché alla variabile "pulsante" hai dato il valore A0, e quel valore rimane fisso. Quello che devi fare è chiedere esplicitamente ad Arduino qual'è il valore del segnale sul pin "pulsante", cioè A0: per fare ciò ti basta la funzione digitalRead, quindi nel tuo programma al posto di if(pulsante == HIGH) devi mettere if (digitalRead(pulsante) == HIGH). Guardati questo esempio se non ti torna qualcosa. Fammi sapere se funziona, alla prossima, ciao

      Elimina
    2. Ciao si grazie... funziona ora.. sbagliavo. non davo digitalRead. grazie mille buona serata e scusa il disturbo

      Elimina
  7. Ciao scusate avrei bisogno di un aiuto, ho scaricato un codice per la scheda gsm una scheda relé, lo sketch non mi da errore ma non vanno i comandi che dovrebbero essere "accendi" e "spegni" . che poi dovro modificare per la mia scheda relé a 8. se qualcuno potrebbe darmi una mano lo ringrazio.....


    #include

    const int heaterControlPin = 12;

    // initialize the library instances
    GSM gsmAccess;
    GSM_SMS sms;

    // Array to hold the number a SMS is retreived from
    char senderNumber[20];

    // String to hold the incoming message
    String message = "";

    // String that will contain the parsed values from the message
    String commandID, deviceID;

    void setup()
    {
    // set the pin connected to the relay that control the heater as output
    pinMode(heaterControlPin, OUTPUT);

    // initialize serial communications and wait for port to open:
    Serial.begin(9600);
    while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
    }

    // connection state
    boolean notConnected = true;

    // Start GSM connection
    while(notConnected)
    {
    if(gsmAccess.begin()==GSM_READY)
    notConnected = false;
    else
    {
    Serial.println("Not connected");
    delay(1000);
    }
    }

    Serial.println("GSM initialized");

    }

    void loop()
    {
    char c;

    // If there are any SMS available
    if (sms.available())
    {
    Serial.println("Message received from:");

    // Get remote number
    sms.remoteNumber(senderNumber, 20);
    Serial.println(senderNumber);

    // An example of message disposal
    // Any messages starting with # should be discarded
    // usually anonymous messages starts with #
    if(sms.peek()=='#')
    {
    Serial.println("Discarded SMS");
    sms.flush();
    }

    // Read message bytes and print them
    while(c = sms.read())
    message += c;

    // cancella message ricevuto
    sms.flush();
    Serial.println("MESSAGE DELETED");
    }

    // if there is a new message start to parse the command and the device to control
    if(message != "") {

    // put the incoming characters that compose the message to lower case
    message.toLowerCase();

    int i=0;

    // deviceID and commandID are separated by a space
    // find it and store the position in two strings
    while(message.charAt(i) != ' ') i++;

    commandID = message.substring(0,i);
    deviceID = message.substring(i+1, message.length());

    // check the device to control
    if(deviceID == "stufetta")
    {
    //check the command to execute
    if(commandID == "accendi") {
    sendFeedbackSMS(senderNumber, deviceID, "ON"); // send the feedback to the sender
    digitalWrite(heaterControlPin, HIGH);
    }
    if(commandID == "spegni") {
    sendFeedbackSMS(senderNumber, deviceID, "OFF"); // send the feedback to the sender
    digitalWrite(heaterControlPin, LOW);
    }
    }

    // clear the message that has just been processed
    message = "";
    }

    delay(1000);
    }

    // this function, given a phone number and two strings representing the device and
    // its state send a feedback text message to the phone number
    void sendFeedbackSMS(char remoteNum[], String devString, String devState) {
    String txtMsg = devString + " " + devState;
    Serial.println(txtMsg);
    Serial.println(remoteNum);

    sms.beginSMS(remoteNum);
    sms.print(txtMsg);
    sms.endSMS();
    }


    Grazie a tutti Loris

    RispondiElimina
  8. lo sketch inizzia con , #include non solo, #Include

    ciao loris

    RispondiElimina
    Risposte
    1. Ciao, sinceramente così su due piedi non saprei, puoi essere un po' più specifico sul sistema che stai usando e sul problema che riscontri.

      Elimina
  9. ciao, io ho una scheda gsm che uso come recive sms, ed una scheda a 8 relé. vorrei che con un comando tramite sms mi apra o chiuda i relé.
    ho scaricato questo sketch ma non funziona il comando che dovrebbe essere "accendi" e "spegni", se mi potete aiutare perché io non ho trovato il problema, ringrazio a tutti ciao Loris

    RispondiElimina
  10. ciao, ho una scheda gsm che uso come recive sms, ed una scheda relé. vorrei che con un comando tramite sms possa aprire o chiudere il relé,ho scaricato questo sketch ma non mi funziona, i comandi dovrebbero essere "accendi" o "spegni", io non sono riuscito a trovare il problema....... ringrazio tantissimo saluti Loris

    RispondiElimina
  11. Ciao pure io ho quel problema... lo Sketch e copiato da arduino http://playground.arduino.cc/Italiano/TutorialWired#SMSHeather però pure a me non funziona e non riesco a capire il motivo ;( anche modificando i "dati" accendi e spegni con numeri non mi funziona...
    Mi spiace perché era una cosa molto utile per me, ore e ore per nulla..
    grazie a tutti

    RispondiElimina
  12. Ciao, vorrei provare a fare un circuito come al tuo ma a 24vcc mi puoi aiutare? Grazie

    RispondiElimina