1. A breve aggiorneremo la piattaforma di Reboot per risolvere alcuni problemi con i plug-in, quindi chiediamo ancora un po' di pazienza, Lo staff di Reboot

Strumento multifunzionale - Contagiri | Contachilometri | e altro!

Discussione in 'LAB sperimentazioni' iniziata da bizz8luca, 16 Ago 2016.

  1. bizz8luca

    bizz8luca Livello 1

    Iscritto:
    4 Feb 2015
    Messaggi:
    7
    Like ricevuti:
    6
    Salve ragazzi! :sunglasses: approfitto delle vacanze per presentarvi un progetto che fino ad ora non avevo condiviso con nessuno, lo finii 3 anni fa e da allora è rimasto in una cartella su dropbox, mi sembrava brutto non condividerlo, spero possa dare qualche spunto per i vostri progetti!
    Tutto il materiale usato: codice, parti 3D, schemi e CS sono disponibli in basso tra gli allegati

    [​IMG]

    Mai nome piu generico di questo! ebbene si, vi starete domandando: "ma cos'è questo coso?".
    Nulla di complicato! un arduino, un display e un paio di pulsanti, tutto qui!

    L'idea del progetto: una breve storia


    Questo piccolo strumento nacque da una serie di eventi positivi, che mi trovai a vivere a scuola. Ultimo anno di superiori nel corso di elettronica e telecomunicazioni 2012/2013 : tutto sommato si viveva bene! Qualche professore bravo, classe affiatata, ore ed ore passate in laboratorio. Grazie ad un professore giovane e molto bravo, che avevo avuto nell'anno precedente, attivammo un corso GRATUITO extracurriculare per tutti gli studenti della scuola (e purtroppo il professore nemmeno veniva pagato) di programmazione e utilizzo di Arduino (una novità all'epoca), non tutti gli studenti di istituto tecnico o professionale avevano la possibilità di imparare con esso, se si pensa che in laboratorio utilizzavamo soltanto amplificatori operazionali, porte logiche, contatori, MUX ecc...
    Il professore riuscì a far comprare per il laboratori della scuola, una 30ina di schede arduino ed una stampante 3D, usata anche dai nostri amici meccanici.

    Ci trovammo in una decina, un pomeriggio a settimana. Eravamo ragazzi appassionati, o comunque con voglia di imparare, e il corso si svolse al meglio. Da esso nacquero un paio di progetti che alcuni di noi portarono avanti, tra questi il mio, che usai come tesina per l'esame di maturità.

    L'idea era quella di creare uno strumento da laboratorio facilmente riprogrammabile, che presentasse una serie di sensori facilmente intercambiabili, che permettessero di svolgere piu funzioni in un unico strumento.

    La progettazione di una shield per arduino


    Visto che all'epoca non esisteva la shield che volevo, ne progettai una tutta mia, costituita da un display grafico, 5 pulsanti e dei connettori per i sensori. Per lo schema e una spiegazione piu dettagliata, per chi è interessato, vi rimando a quanto è scritto nel PDF allegato, che è un ritaglio della tesina (ho tolto considerazioni superflue). Il CS è stato realizzato con KiCad, un CAD gratuito per la progettazione di circuiti stampati.

    [​IMG]

    L'involucro: dalla progettazione, alla stampa 3D


    una volta realizzato il circuito stampato, ho cominciato a prendere mano con la stampante 3D che la scuola aveva appena acquistato. Visto che avevo già una buona dimestichezza con l'uso di un CAD parametrico meccanico, non mi fu difficile realizzarne l'involucro. Sarebbe stato da riprogettare un paio di cose (per esempio un apertura per facilitare il cambio della batteria!) ma mi accontentai perchè il tempo stringeva. In allegato ci sono i file 3D STL per poter stampare la scatola, e un file PDF 3D dell'assieme che può essere aperto semplicemente con Adobe PDF! (abilitando la visualizzazione 3D)

    [​IMG]

    Un pezzo di codice interessante: 5 pulsanti ed un solo ingresso


    Una soluzione che può essere applicata in qualsiasi progetto per risparmiare un pò di porte I/O, è quella di utilizzare un unico ingresso analogico per leggere lo stato di piu pulsanti, sacrificando però, la possibilità di premere piu tasti contemporaneamente (nella maggior parte dei casi, questo non ci interessa, oltretutto non avevo abbastanza porte a disposizione) lo schema utilizzato nella mia shield è il seguente:

    [​IMG]

    come possiamo notare dallo schema, fin tanto che nessun SW è premuto, la tensione sul filo di uscita "button" rimane a 5V, visto che nessuna resistenza è collegata al potenziale di massa. Non appena premiamo un SW, apriamo una "strada" nella quale la corrente può fluire verso il potenziale di massa. Seguendo questa logica, possiamo ottenere 5 circuiti associati, di cui 4 formati da un partitore di tensione, che generano 5 valori diversi di tensione (4 perchè nel caso di SW1, l'uscita viene portata direttamente a massa) la scelta delle resistenze probabilmente la scelsi per distanziare il piu possibile i valori di tensione tra uno e l'altro, in modo da minimizzare l'errore di lettura.
    La formula del partitore di tensione, per chi non si ricordasse è:

    V_uscita = V_ingresso*(resistenza interessata/resistenza totale)
    dove la resistenza interessata è la somma delle resistenze che vanno dal terminale di uscita, a massa. Mentre la resistenza totale è la somma delle resistenze che vanno dal terminale di Vin (5 volt) fino al terminale di massa.

    Pulsante premutoLivello logico associato
    SW5Vout = Vin*(R5_6_7_8/R4_5_6_7_8) = ~ 3,28 V
    SW4Vout = Vin*(R5_6_7/R4_5_6_7) = ~ 2,39 V
    SW3Vout = Vin*(R5_6/R4_5_6) = ~ 1,57 V
    SW2Vout = Vin*(R5/R4_5) = ~ 0,65
    SW1Vout = 0
    Ora non ci rimane che creare un codice in cui legga il valore di tensione in ingresso al pin analogico scelto, e che ne confronti tale valore con la tabella precedente! se rientra con una certa tolleranza tra questi, allora possiamo rilevare quale pulsante è stato premuto. In arduino UNO, abbiamo a disposizione il metodo analogRead(Pin) che però restituisce un intero che va da 0 a 1024. Nessun problema, basta fare una proporzione:

    Proporzione (esempio con SW3) Formula girata
    5 volt : 1024 = 1,57 volt : X_valore X_valore = (1,57*1024)/5 = 321
    Da notare però, che nel caso di SW5, il valore della tensione calcolata, discosta molto da quello che ho usato nello sketch! questo probabilmente è dovuto al fatto che ogni resistenza con normale precisione commerciale, ha un valore di resistenza che si discosta di + - 5%, se siamo sfortunati, nel caso peggiore, tale errore può sommarsi per ogni resistenza. Inoltre la formula del partitore, vale nel caso in cui non vi sia assorbimento di corrente da parte dell'ingresso del microcontrollore, che nella pratica assorbe invece qualche microAmprere.
    La cosa più ovvia da fare, una volta montate le resistenze, è di misurare con un voltmetro l'effettivo valore di tensione per ogni pulsante, ed utilizzare quei valori per la proporzione.

    Qui in seguito riporto uno sketch di test dove viene provato l'utilizzo dei 5 pulsanti. viene disegnato un pixel alla volta su un display grafico. Maggiori descrizioni nei commenti sul codice e nel PDF
    Codice:
    /************sketch arduino Pulsanti_strumento************\
    *******************Luca Bizzotto, 5 TNA********************
    * in questo sketch si descrive come usare i pulsanti dello
    * strumento in modo grafico: si disegna infatti linee
    * comandate con i 4 pulsanti di direzione, e con il pulsante
    * OK si attiva o si disattiva lo strumento "gomma"
    */
    
    
    #include "glcd.h"  // includo le librerie necessarie
    #include "fonts/allFonts.h"  //  allo sketch
    #include "bitmaps/allBitmaps.h"  //
    
    int Pulsante_Up = 487;  // setto i valori di tensione espressi in binario
    int Pulsante_Down = 132;  // che serviranno poi per verificare che siano premuti
    int Pulsante_Right = 0;  // i pulsanti di selezione, questi sono i valori
    int Pulsante_Left = 321;  // standard dello strumento
    int Pulsante_Ok = 723;  //
    int X = 0;  // variabili utilizzate come coordinate per disegnare il punto
    int Y = 0;  // sullo schermo
    
    unsigned long Time = 0;  // variabile che serve per misurare il T trascorso
    boolean Gomma = false; // variabile per attivare la cancellazione dei Picsel
    int CambioXY = 0;  // usata per sapere quale era l'ultimo punto disegnato
    
    void setup() {
    
    GLCD.Init(NON_INVERTED); // inizializzo il display con
      // sfondo bianco, scritte nere
    
    }
    
    void loop(){ // ciclo che si ripete all'infinito
    
    Ctr_Pulsanti(); // controllo i pulsanti
    
    if(Gomma == false) GLCD.SetDot(X,Y,BLACK);// se la gomma è disatt. scrivo il
      // punto di coordinate X Y
    
    if((Gomma) && (CambioXY == 1)){  // se la gomma è attiva e ho incrementato X vuol
      GLCD.SetDot(X,Y,BLACK);  // dire che quello prima era X-1, scrivo attuale
      GLCD.SetDot(X-1,Y,WHITE);  // cancello precedente
    }
    
    if((Gomma) && (CambioXY == 2 )){ // se la gomma è attiva e ho decrementato X vuol
      GLCD.SetDot(X,Y,BLACK);  // dire che quello prima era X+1, scrivo attuale
      GLCD.SetDot(X+1,Y,WHITE);  // cancello precedente
    }
    
    if((Gomma) && (CambioXY == 3)){ // se la gomma è attiva e ho incrementato Y vuol
      GLCD.SetDot(X,Y,BLACK);  // dire che quello prima era Y-1, scrivo attuale
      GLCD.SetDot(X,Y-1,WHITE);  // cancello precedente
    }
    
    if((Gomma) && (CambioXY == 4)){ //se la gomma è attiva e ho decrementato Y vuol
      GLCD.SetDot(X,Y,BLACK);  // dire che quello prima era Y+1, scrivo attuale
      GLCD.SetDot(X,Y+1,WHITE);  // cancello precedente
    }
    }
    
    
    void Ctr_Pulsanti(){
    /* i pulsanti sono premuti se il valore analogico letto sul pin di arduino
      A5 corrisponde al codice di uno dei 5 pulsanti, o almeno discosta di un
      valore di piu o in meno di 5 rispetto a quello previsto... se uno dei 4
      if iniziali è vero, aspetto almeno 30 millisecondi per evitare che ci
      sia stato un disturbo o un rimbalzo del contatto meccanico del pulsante.
      controllo di nuovo e se effettivamente è premuto faccio delle determinate
      azioni in base al pulsante premuto. In tutti e 5 pulsanti verifico che
      sia passato un certo lasco di tempo dall'ultima volta che ho premuto,
      questo per evitare bruschi incrementi di variabili o altro all'interno
      del'if... questo è dovuto perchè arduino, eseguendo operazioni in modo
      velocissimo (ricordo che il clock è 16 MHZ) si ritroverebbe a "passare"
      molte volte per questo punto prima che stacchiamo il dito dal nostro
      pulsante!!!  */
    
      if ((analogRead(A5) > (Pulsante_Ok - 5)) && (analogRead(A5) < (Pulsante_Ok + 5))){
      delay(30);
      if ((analogRead(A5) > (Pulsante_Ok - 5)) && (analogRead(A5) < (Pulsante_Ok + 5))){
      if((millis()-Time) > 200){  // se è passato 200 millis dall'ultima volta...
      if(Gomma == true) Gomma = false; // se la gomma era abilitata, la disabilito
      else Gomma = true;  // se era disabilitata, la abilito
      Time = millis();  // mi tengo in memoria l'ultima volta che
      }  // ho premuto il pulsante
      }
      }
    
      if ((analogRead(A5) > (Pulsante_Right - 5)) && (analogRead(A5) < (Pulsante_Right + 5))){
      delay(30);
      if ((analogRead(A5) > (Pulsante_Right - 5)) && (analogRead(A5) < (Pulsante_Right + 5))){
      if((millis()-Time) > 40){ // se è passato 40 millis.……
      X++;  // incremento X
      if(X > 128) X = 0; // se eccede dallo schermo, la faccio ripartire da zero
      CambioXY = 1;  // indico che ho appena incrementato X
      Time = millis(); // mi tengo in memoria il tempo in cui ho premuto il pulsante
      }
      }
      }
    
      if ((analogRead(A5) > (Pulsante_Left - 5)) && (analogRead(A5) < (Pulsante_Left + 5))){
      delay(30);
      if ((analogRead(A5) > (Pulsante_Left - 5)) && (analogRead(A5) < (Pulsante_Left + 5))){
      if((millis()-Time) > 40){ //…….
      X--;  // decremento X
      if(X < 0) X = 128;// se eccede dallo schermo, la faccio ripartire da 128
      CambioXY = 2;  // indico che ho appena decrementato X
      Time = millis();// mi tengo in memoria ….
      }
      }
      }
    
      if ((analogRead(A5) > (Pulsante_Down - 5)) && (analogRead(A5) < (Pulsante_Down + 5))){
      delay(30);
      if ((analogRead(A5) > (Pulsante_Down - 5)) && (analogRead(A5) < (Pulsante_Down + 5))){
      if((millis()-Time) > 40){ // …..
      Y++;  // incremento Y
      if(Y > 64) Y = 0; // se eccede dallo schermo...
      CambioXY = 3;  // indico che ho appena incrementato Y
      Time = millis();// mi tengo in memoria.…
    
      }
      }
      }
    
      if ((analogRead(A5) > (Pulsante_Up - 5)) && (analogRead(A5) < (Pulsante_Up + 5))){
      delay(30);
      if ((analogRead(A5) > (Pulsante_Up - 5)) && (analogRead(A5) < (Pulsante_Up + 5))){
      if((millis()-Time) > 40){ // …
      Y--;  // decremento Y
      if(Y < 0) Y = 64; // se eccede dallo schermo...
      CambioXY = 4;  // indico che ho appena decrementato Y
      Time = millis();// mi tengo in memoria...
      }
      }
    }
    }
    

    I progetti finali: contagiri e contachilometri


    Come applicazione di esempio dello strumento, sviluppai un contagiri digitale a LASER, quindi senza contatto fisico, che permetteva di misurare i giri di un rotore da 0 a 30.000 giri per minuto (cioè ben 500 giri al secondo!!) applicando una semplice striscia adesiva. Per provarne la taratura, comprai uno strumento analogo (una 30ina di euro). Data l'altissima velocità di lettura tra una misura e l'altra, nello sketch viene usato una modalità che soltanto alcuni pin hanno: l'interrupt. Quando avviene una variazione veloce di stato logico ( da un valore alto di tensione ad uno basso o viceversa, a seconda dell'esigenza) in uno di questi pin, il normale flusso del codice devia su un metodo nel quale si eseguono delle routine, ad esempio, l'incremento di una variabile (in questo caso +1 sui giri e l'aggiornamento del tempo dell'ultimo passaggio). Portò via la maggior parte del tempo la fase di debug e di filtraggio del segnale proveniente dal sensore, per questo venne sviluppata soltanto una schermata con i giri/min. Nelle note finali, misi anche lo sketch che avevo sviluppato per un progetto di un contachilometri digitale, con un sensore del tipo Reed switch (sostituito poi con un sensore Hall). Maggiori info e foto nel PDF. Ecco una foto del tutto (purtroppo non ne ho una con il motore in movimento):
    [​IMG]

    direi che è tutto! spero di non avervi rubato troppo tempo e che magari qualche pezzettino di codice possa tornarvi utile per costruire qualcosa! :grin:
    però adesso avendolo tirato fuori, sarei curioso di vedere se lo tengono ancora li a scuola :tearsofjoy: magari a settembre vado a salutare qualche Prof.

    Buone vacanze a tutti!
     

    File Allegati:

    #1
    Ultima modifica: 16 Ago 2016
    A ecos piace questo elemento.

Condividi questa Pagina