Creative Commons BY-NC-ND 2.5Questo sito e tutto il suo contenuto sono distribuiti sotto la licenza Creative Commons Attribuzione - Non Commerciale - Non opere derivate 2.5 Italia e con le condizioni d'uso definite nel disclaimer: siete pregati di leggere entrambi questi documenti prima di usufruire dei contenuti di questo sito. Per alcuni contenuti è necessaria una registrazione gratuita: non è necessario pagare e non è necessario accumulare punteggi per accedere agli articoli e scaricare i sorgenti: basta solo essere onesti. Se volete che questo sito continui a rimanere attivo, a contribuire ogni giorno alla diffusione della cultura libera, non copiate il materiale per ripubblicarlo in altri luoghi. Se volete partecipare su settorezero e rendere le vostre idee, i vostri progetti, fruibili da tutti senza limitazioni potete farlo tranquillamente.

Corso programmazione PICMicro in C – Approfondimenti – Come utilizzare un encoder in quadratura per l’immissione dei dati

Autore: Giovanni Bernardo | Data pubblicazione: 7 febbraio 2010
Categorie: PICmicro 10/12/16 PICmicro 18 Robotica e Automazione

Ho preferito inserire questo articolo nel corso di programmazione come un’appendice e non come un capitolo a sè stante in quanto non tratta strettamente dell’utilizzo di un particolare circuito integrato o di una particolare periferica del picmicro ma piuttosto dell’utilizzo alternativo di altre tecniche già apprese fin’ora (gli interrupt e l’utilizzo dei pulsanti con l’antirimbalzo nella fattispecie). Per tale motivo, per quanto mi sia possibile, ogni tanto inserirò in questo piccolo corso anche qualche “appendice” o se preferite “appunti di utilizzo” per spiegare come fare questa o quell’altra cosa sfruttando cose che già abbiamo imparato.

In quest’articolo impareremo a conoscere uno strumento semplice e molto interessante con cui abbiamo a che fare spesso nella vita di ogni giorno e lo impareremo ad utilizzare come metodo alternativo per l’inserimento o la modifica di variabili al posto dei classici pulsanti.  In più sfrutteremo in contemporanea 2 sorgenti di interrupt le quali si aiuteranno a vicenda nello svolgimento  di un compito.

Molti di voi hanno un’autoradio in macchina, alcuni autoradio (soprattutto modelli di marche famose e di fascia medio/alta) hanno, per la regolazione del volume e dei toni, una manopola che ruota. I più attenti già sanno che quella manopola non è assolutamente il classico potenziometro (altrimenti come mai gira di continuo, senza blocchi? Ok qualcuno potrebbe pure obiettare che esistono i potenziometri a rotazione continua ma dal momento che costano un a cifra non si tratta assolutamente di questo caso). Quella manopola è un congegno davvero semplice ma geniale per alcuni aspetti: si tratta di un encoder rotativo (Rotary Encoder). Una “manopola” del genere la troviamo comunque un po’ dappertutto: ce l’hanno anche alcuni forni a microonde, anche se il suo utilizzo più “in voga” è attualmente quello della regolazione del volume audio negli impianti hi-fi.

Sappiamo bene che un encoder, in senso generale, è un dispositivo che serve per codificare un tipo di segnale in  un’altra “forma”. Un encoder rotativo è appunto un dispositivo che permette di codificare la rotazione di un albero in un segnale elettrico.

Gli encoder rotativi vengono utilizzati, soprattutto in ambito industriale, per il computo delle velocità degli alberi di rotazione. Erano usati nei vecchi mouse con la “pallina” per far muovere il puntatore, sono utilizzatissimi anche in robotica per determinare le velocità delle ruote dei robottini e quindi correggerne la traiettoria, e come abbiamo appena detto vi è anche questo utilizzo più “ludico” per il controllo del volume su un impianto audio o per impostare la temperatura del forno a microonde.

Un encoder rotativo altro non è che una serie di “contatti” (azionati in vari modi: meccanicamente, tramite infrarossi o sfruttando l’effetto hall) che chiudono ciclicamente un contatto quando l’albero ad essi collegato effettua una rotazione. A seconda del numero di contatti e del modo in cui questi vengono chiusi, abbiamo vari tipi di encoder. In questo articolo ci occuperemo unicamente dei cosiddetti encoder in quadratura.

Per capire come è fatto un encoder in quadratura possiamo anche aprire un vecchio mouse di quelli con la pallina: per ogni asse (X e Y) la pallina mette in rotazione una ruota con tante fessure, da un lato di ciascuna ruota ci sono due diodi infrarossi e dall’altro due ricevitori (in genere accorpati in un unico blocco):

MouseEncoder
Immagine prelevata da www.eehomepage.com/report.php?report=20080225

Quando di fronte ad un diodo viene a trovarsi la finestra aperta, il raggio passa mandando in conduzione il ricevitore che gli sta di fronte il quale “chiude” un contatto, quando invece tra la coppia trasmettitore/ricevitore si trova la parte di ruota “piena”, il contatto rimane aperto: all’uscita del sensore avremo quindi un segnale ad onda quadra che è indicativo del movimento che sta effettuando la ruota.

Questo particolare tipo di encoder viene definito “encoder in quadratura” perchè possiede 2 contatti che forniscono due segnali sfalsati di 90°. Ma cosa significa? Cerco di farvelo capire con delle immagini, perchè il concetto è apparentemente complicato ma nella pratica è davvero semplice. Guardiamo questa immagine stilizzata:

encoder_in_quadratura

Abbiamo la ruota sulla quale sono disegnati dei settori: i settori neri fanno rimanere il contatto aperto, i settori bianchi fanno chiudere il contatto, i due quadratini grigi sono i due contatti dell’encoder. Come vedete i due contatti si trovano sulla ruota posizionati su due rette, passanti per il centro dell’asse di rotazione, inclinate tra loro di 90°. Quando la ruota gira, ogni contatto produrrà un’onda quadra (transizioni tra contatto chiuso e contatto aperto). Avendo i due contatti posizionati come in figura, le due onde quadre prodotte saranno anch’esse sfalsate di 90° in questo modo:

encoder_in_quadratura_segnale_sfalsato_90_gradi

Ok, ma a cosa serve mettere due contatti quando per calcolare unicamente la velocità di rotazione di un albero basterebbe un unico contatto? Avete ragione: con un unico contatto sappiamo ogni quanti gradi di rotazione il contatto viene chiuso, e quindi quante volte viene chiuso per un giro di completo di 360°: calcolando il tempo impiegato per effettuare il giro completo, possiamo trovare la velocità di rotazione dell’albero. Se ci serve unicamente sapere la velocità di rotazione un unico contatto potrebbe anche bastare.

Ma… La manopola del volume dello stereo? Non serve certo a calcolare la velocità con la quale la stiamo ruotando! Ha difatti ben altra funzione: se la giriamo in un senso il volume aumenta, se la giriamo nell’altro il volume diminuisce, quindi c’è qualcosa in quella manopola che capisce in quale senso la stiamo ruotando.

E difatti è proprio così. Quella manopola mette in rotazione un albero sul quale è appunto montato un encoder in quadratura come quello che abbiamo visto nell’immagine. La produzione di due segnali sfalsati di 90° permette appunto, oltre che di calcolare la velocità di rotazione (che ovviamente nel caso del volume dello stereo non viene affatto calcolata perchè non serve a nulla), di stabilire anche il verso in cui l’albero sta ruotando. Come?

Innanzitutto diamo un nome ai segnali che escono dai due contatti dell’encoder:  come il buon Guido Ottaviani mi ha insegnato, chiamerò un segnale PULSE e l’altro DIR, il perchè della scelta di questi due nomi, al posto dei classici A e B che in genere si trovano in giro, sarà presto chiaro.

Supponiamo di collegare questi due segnali a due ingressi di un picmicro.  Collegherò un segnale ad un ingresso che mi genera un interrupt (ad esempio al pin RB0 oppure ad uno dei pin da RB4 a RB7) e questo segnale sarà quello che chiamo PULSE, e colleghiamo l’altro segnale, DIR, ad un ingresso che non genera interrupt, quindi ad un ingresso qualunque.

Ruotiamo l’albero. Ad un certo punto scatterà un interrupt perchè il contatto che fornisce il segnale PULSE passa da  aperto a chiuso (o viceversa, insomma: cambia stato logico). A questo punto intercettiamo l’interrupt e confrontiamo il livello logico attuale del segnale PULSE con il livello logico attuale del segnale DIR: sta qui la “magia”!

Se entrambi i livelli logici sono uguali (entrambi alti o entrambi bassi), possiamo dire che l’albero sta ruotando in un senso (possiamo dire che l’albero sta ruotando in senso orario oppure che il nostro robottino si sta muovendo in avanti), se invece i due livelli logici sono differenti, allora l’encoder sta ruotando in senso antiorario (o il nostro robottino sta camminando all’indietro).

Un’immagine dovrebbe far capire cosa accade nella pratica:

encoder_in_quadratura_segnali_avanti_e_indietro

Ho evidenziato in viola l’istante in cui scatta l’interrupt, ovvero l’istante in cui il segnale PULSE effettua il cambio di livello logico. Notiamo inoltre come i due segnali DIR e PULSE siano sfalsati tra loro di 90° come detto in precedenza. Ruotando in avanti, al verificarsi dell’interrupt, i due segnali hanno sempre il livello logico uguale tra loro, ruotando all’indietro, invece, i livelli logici sono sempre opposti. Chiamo appunto PULSE il segnale che mi genera una “pulsazione”, ovvero l’interrupt, e DIR l’altro che mi serve per poterlo confrontare e stabilire quindi la DIRezione di rotazione.

Bene, passiamo ora ad un’applicazione pratica: sfruttiamo un encoder per incrementare/decrementare una variabile.  Questo sistema lo potete utilizzare per qualsiasi applicazione che richieda due pulsanti up/down: l’utilizzo di un encoder è sicuramente molto più professionale: un controllo di volume, la regolazione di un livello, di una temperatura, di un tempo, il posizionamento di un servocomando…

Per questo “esperimento” ho utilizzato un encoder rotativo meccanico di fascia economica ma che fa in maniera eccellente il suo lavoro. Tale encoder esternamente si presenta come un comune potenziometro ed in più ha anche un contatto che si chiude quando l’alberino viene premuto verso il basso:

encoder_rotativo_in_quadratura

Questo tipo di encoder nell’immagine è davvero economico (l’ho trovato su Ebay in Inghilterra per meno di 3 euro, ma se lo acquistate in Cina, e soprattutto se avete la pazienza di aspettare un mese, ne potete portare a casa ben 10, completi di manopole, per circa 10/12 euro). Come potete vedere è davvero molto piccolo, per tale motivo l’ho messo a confronto con la moneta da 2 euro, difatti quando mi è arrivato a casa sono rimasto un po’ smarrito perchè mi aspettavo qualcosa di un po’ più grande, almeno quanto un potenziometro.

encoder_rotativo_in_quadratura_2

Vi sono due ganci laterali per l’ancoraggio allo stampato, i tre pin vicini sono quelli dell’encoder (il centrale è il comune e i laterali sono i due contatti), gli altri due pin di fronte a quelli dell’encoder sono quelli del pulsante normalmente aperto, che si chiude premendo l’alberino. Ho visto che la nota marca PIHER (che produce potenziometri, trimmer, switch ecc) ha in catalogo un encoder molto simile a questo, lo potete vedere in questa pagina. Quello della Piher ha la stessa, identica, piedinatura e forma (non ho verificato le dimensioni).

Dovremo trattare i segnali dei due contatti dell’encoder come se fossero un normale pulsante. Trattandosi di un’encoder meccanico, la chiusura dei contatti non è pulita per cui dovremo tener conto di dover attuare anche qualche meccanismo di antirimbalzo. Utilizzando invece encoder ottici o magnetici la chiusura del contatto è pulita e quindi non dovremo preoccuparci dei rimbalzi.

Faremo arrivare il segnale di massa al comune  e i due segnali forniti dai contatti saranno applicati a due ingressi del picmicro tramite le solite resistenze di pull-up. Ovviamente dobbiamo ricordarci di collegare un segnale ad un pin che produce interrupt (lo collegheremo ad RB0) e l’altro ad un pin qualsiasi: questo concetto è essenziale. Ho montato da subito l’encoder su un pezzetto di millefori collegandovi sopra tutto l’occorrente: uno strip di contatti a 90° per la connessione con una breadboard o con il circuito di utilizzo, le resistenze di pullup (anche per il pulsante, che però in questa prova non userò) e un piccolo condensatore sull’alimentazione:

encoder_montato

Sul datasheet della Piher è consigliato l’utilizzo di due piccoli condensatori da 10nF sui due terminali dei contatti, verso massa. Per questa prova personalmente non li ho montati, anche perchè l’encoder della piher l’ho scoperto solo dopo aver fatto le prove, se fate questo circuito, montateli.

Lo schemino del circuito in foto è molto semplice:

schema_circuito_encoder

Anche se penso di essere stato abbastanza chiaro, vi espongo comunque il layout dell’encoder (prelevato dal datasheet della Piher e uguale a quello comprato su Ebay) per maggior completezza:

layout_encoder

Quindi ricapitolando: i due segnali che dovranno arrivare al pic sono quelli uscenti dai pin contrassegnati come A e B sullo schema dell’encoder, quello che collegate al pin RB0 (è indifferente: potete collegare o l’A o il B) lo chiameremo PULSE e l’altro lo collegheremo al pin RB1, quest’ultimo non scatena interrupt e ci serve per poterlo confrontare con l’altro segnale e poter quindi capire la direzione di rotazione, per cui lo chiameremo DIR. Il pulsante che si aziona premendo l’alberino, presente sui contatti E e D, non verrà usato in questa prova. Se voi lo volete usare, sapete come fare.

Il software che ho scritto esegue la funzione di base di un encoder in quadratura: la rotazione in senso orario incrementerà una variabile, la rotazione in senso antiorario invece la decrementerà, per dimostrarne il funzionamento  il valore della variabile sarà mostrato su un display LCD compatibile Hitachi HD44780. Il circuito che ho utilizzato è lo stesso della lezione 7, al quale ho ovviamente tolto i 4 led e i 3 pulsanti (insomma tutta la parte destra del circuito), rimangono quindi di quello schema solo il display e il cicalino.

Dal momento che ho utilizzato la demoboard Freedom 2, nel codice troverete un define diverso per il cicalino e la presenza di un define per abilitare la retroilluminazione dell’LCD: se usate la Freedom 2 non dovete fare modifiche al codice, altrimenti basta cambiare un paio di define del file settings.h

Lato software, dal momento che abbiamo capito come funziona un encoder in quadratura, non dovremo far altro che intercettare l’interrupt su RBO e fare le opportune considerazioni: confrontare il segnale che ha scatenato l’interrupt con l’altro: se i due segnali hanno lo stesso livello logico, mi setterò una variabile che nel main mi produrrà un incremento e viceversa:

void interrupt ISR (void)
	{
	if (INTF) // L'interrupt è stato causato da un cambio di stato di RB0/INT ?
		{
		if (ENCODER_PULSE==ENCODER_DIR) // rotazione oraria
			{
			INTE=0; // disattivo l'interrupt su RB0/INT
			mode=INCR; // modalità incremento
			ABcounter=0; // resetto contatore
			}
		else // rotazione antioraria
			{
			INTE=0; // disattivo l'interrupt su RB0/INT
			mode=DECR; // modalità decremento
			ABcounter=0; // resetto contatore
			}
		INTF=0; // Resetto il flag interrupt su RB0/INT
		} // fine che interrupt verificatosi su RB0/INT

In realtà avrei potuto gestire l’incremento e il decremento della variabile anche nella stessa routine di interrupt, ma come vedete non l’ho fatto per vari motivi:

  1. Le routine di interrupt, come ripetuto tantissime volte, devono essere le più snelle possibile.
  2. Stiamo gestendo un encoder meccanico, per cui dobbiamo inventarci un sistema per effettuare un antirimbalzo via software. Dal momento che l’antirimbalzo via software prevede un ritardo, non possiamo assolutamente gestirlo nella routine di interrupt.

Per tale motivo ho previsto un counter (ABcounter) che viene incrementato dall’interrupt sul Timer0 e che mi serve a creare un ritardo nel main. Appena scatta l’interrupt sul pin RB0/INT, disattivo subito l’interrupt (INTE=0) per non intercettarne due successivi (come detto prima: l’encoder usato è molto economico!), mi setto una variabile (mode) che nel main mi attiverà una routine per incrementare o decrementare il valore della variabile, e azzero il contatore (ABcounter) che mi blocca il controllo del successivo interrupt per un tempo stabilito nel main. Spulciatevi il codice per vedere cosa accade. Suppongo che questa non sia la migliore gestione dell’antibounce, ma mi è venuta  al volo funzionando in maniera abbastanza soddisfacente: senza essa, difatti, l’encoder produceva degli incrementi/decrementi a volte esagerati. Penso anche che l’utilizzo dei due condensatori sui terminali di uscita dell’encoder migliori ulteriormente la situazione.

Gli iscritti possono scaricare il codice di esempio:

Corso Programmazione PICMicro in C - Approfondimenti - Utilizzo di un encoder rotativo per l'immissione dei dati (653)

Consigli e suggerimenti

Nel caso in cui si voglia collegare più di un encoder (ad esempio: un robottino per il quale dobbiamo verificare la velocità e il verso di rotazione delle due ruote), dovremo fare affidamento al cambio di interrupt sulle porte RB4/RB7, abilitando il flag RBIF. Possiamo collegare un segnale pulse ad RB0 e quello dell’altra ruota ad uno dei pin RB4-RB7 o entrambi a due pin di RB4-RB7. In quest’ultimo caso dovremo predisporre altre variabili per memorizzare lo stato precedente dei segnali per poter capire quale dei due encoder ha scatenato l’interrupt dal momento che uno qualsiasi dei pin RB4-RB7 scatena l’interrupt.

Se volete realizzare un encoder per le ruote del vostro robottino potete anche utilizzare il sensore P5587 prodotto dalla Hammamatsu, che è molto piccolo ed adatto appunto a fare questo lavoro, ovviamente sulla ruota dovrete predisporre un disco con settori bianchi e neri in quanto tale sensore lavora per riflessione. Per realizzare un encoder in quadratura avrete bisogno di due sensori per ruota.

Se volete approfondire il discorso sugli encoder, la rete è piena di esempi appunto perchè in robotica gli encoder sono uno strumento davvero necessario. Posso consigliarvi di cominciare da questa voce su wikipedia in inglese (la versione in italiano è piuttosto scarna).

L'articolo ti è piaciuto o ti è stato utile per risolvere un problema? SettoreZero è realizzato soltanto con contenuti originali: tutti gli articoli sono curati con passione dagli autori e nulla viene copiato da altri siti. Supporta e mantieni in vita SettoreZero con una donazione: basta soltanto un caffè o una birra. Puoi supportare SettoreZero anche con uno dei progetti elencati nella sezione servizi o partecipare anche tu con un tuo articolo/progetto personale.

Se desiderate che SettoreZero continui a rimanere gratuito e fruibile da tutti, non copiate il nostro materiale e segnalateci se qualcuno lo fa.

Puoi andare alla fine dell'articolo e lasciare un commento. I trackback e i ping non sono attualmente consentiti.

  1. #1 da piero il 28 giugno 2010

    Giovanni,

    ho trovato per caso questo tuo Blog googlando.
    Partendo da questo approfondimento sugli encoder ho scoperto le altre cose interessantissime e non ho esitato ad iscrivermi.
    Complimenti per l’impegno e i risultati. Approfitto di questo spazio per salutare tutti, dato che non vedo nessun posto dove fare le presentazioni.

    Cerchero’ di farmi vivo ogni tanto.

    In gamba,

    Piero

  2. #2 da vittorio il 25 luglio 2010

    sono a livello 0 in programmazione di pic e bestioline simili,ai miei tempi non esistevano,pero’ devo dire che sei riuscito a risvegliarmi un po’ di interesse per gli encoder.
    grazie e buon proseguimento
    vittorio

    • #3 da Giovanni Bernardo il 25 luglio 2010

      Salve, è un piacere avere un commento da un grande come lei. Ho visitato il suo sito e l’ho trovato molto interessante. Complimenti vivissimi per la vasta collezione di radio, che ritengo sia davvero invidiabile. Anche io adoro le radio antiche (ma purtroppo non ne capisco molto), soprattutto quelle valvolari. Ho avuto l’enorme piacere di ripararne una, con non poca fatica, appartenente ad un mio zio che oramai non c’è più, e che ora tengo bella esposta nel soggiorno, perfettamente funzionante. Sono pezzi di storia, che rievocano bei tempi andati, tempi in cui la semplicità ancora destava meraviglia e stupore.

  3. #4 da odessos il 13 febbraio 2011

    ho un encoder che fornisce un inpulso ogni 10gradi di rotazione, quindi sono 36 impulsi a giro.
    Ho la necessità di creare una funzione per calcolare la velocità di rotazione del motore. premetto che il programma utilizza già l’interrupt per altri scopi, e non posso rallentare l’esecuzione del programma utilizzando routine con Delaytime troppo lunghi. come posso fare? devo utilizzare un’altro PIC?
    salutissimi e grazie di tutto.

    • #5 da Giovanni Bernardo il 14 febbraio 2011

      Il programma usa già gli interrupt sul portb change? Se no, quale sarebbe il problema di usare l’interrupt pure per l’encoder? Se si: hai già tutte e 4 le porte B occupate?

  4. #6 da odessos il 14 febbraio 2011

    perchè uso il Timer0 per generare un segnale che pilota un motore passo passo, se leggo un,altro interrupt mi interrompe quello del Timer0, oppure si possono gestire in maniera indipendente?
    forse con un PIC serie 18F?

    • #7 da Giovanni Bernardo il 14 febbraio 2011

      Se il problema fosse questo i picmicro sarebbero andati nel dimenticatoio da un pezzo… I PIC16 gestiscono gli interrupt in sequenza, se mentre gestisci il TMR0IF si verifica un altro interrupt, non accade nulla: la ISR continua a servire il TMR0IF e quando ha finito serve l’altro. Sui PIC18 puoi impostare la priorità alta o bassa: se mentre servi un interrupt a bassa priorità si verifica uno ad alta priorità, quello a bassa viene messo in pausa e lo si torna a servire quando si è finito di servire quello ad alta. Altrimenti di default i pic18 hanno la gestione degli interrupt in modalità pic16-compatibile. Il problema per la tua applicazione non sussiste e tutto dipende da quanto rendi veloci le ISR. Se ti serve un calcolo davvero preciso della velocità, senza possibilità di errore, allora dovresti usare un pic18 con la priorità alta sull’encoder e bassa sul timer. Metti che sul pic16 ti scatta prima un interrupt sull’encoder mentre servi TMR0, e poi ne scatta un altro quando ancora non hai finito con TMR0: ovviamente ti perdi il secondo perchè il flag è già stato settato dal primo. Ma questo può accadere solo se “perdi tempo” in TMR0 e se la velocità di esecuzione è bassa.. Insomma dovresti farti due conti di quanto è la velocità massima del motore per capire ogni quanto ti scatta un interrupt sull’encoder e capire se ce la fai a gestire tutto. Io direi fai una prova, ma non preoccuparti perchè di interrupt ne puoi gestire quanti ne vuoi, cerca solo di lavorare alla massima frequenza possibile col quarzo e di rendere le ISR più snelle possibile.

    • #8 da Giovanni Bernardo il 14 febbraio 2011

      Se poi vuoi fare le cose piu complicate ma meglio, ci sono alcuni pic, anche della serie 18 che hanno la periferica QEI (Quadrature Encoder Interface) che come potrai capire gestisce tutto lei, indipendentemente dal resto. Ma non ci ho mai messo mano quindi non so dirti di più.

  5. #9 da Haru il 13 giugno 2011

    esistono anche degli encoder che invece di essere in quadratura mandano il bit sull’uscita in base al senso di rotazione? (tipo danno un impulso ogni 10 gradi di rotazione su una delle due uscite in base alla rotazione)

    perchè fino a 5 minuti fa pensavo funzionassero così :D

  6. #12 da Aigor il 4 agosto 2011

    In odore di sperimentazione ho cercato qualcosa sugli encoder e ho trovato, googolando, un sistema per usare i motori dei dischi rigidi come encoder, sperando di non violare qualche regola, ecco il link
    http://www.instructables.com/id/HDDJ-Turning-an-old-hard-disk-drive-into-a-rotary/step4/Amplifying-the-output/

  7. #13 da Haru il 21 agosto 2011

    è possibile collegare ad un pic gli encoder senza utilizzare l’interrupt? il mio problema è che ho tipo una ventina di encoder usati come manopole da controllare, ed è evidente che RB0 non mi basta… qualche consiglio?

    • #14 da Giovanni Bernardo il 21 agosto 2011

      Beh si… Te li controlli in Polling ma se non hai un Tcy abbastanza elevato non so se ce la fai a controllarti tutto.

      • #15 da Haru il 22 agosto 2011

        Tecnicamente avrei il pic che fa solo quel lavoro, l’unica altra funzione che ha è quella di inviare i dati ricavati dagli encoder tramite uart o spi (devo ancora vedere per quello).
        Per la serie nessun rallentamento dovuto a display o led, nel ciclo metto solo il controllo di ogni porta e in base allo stato precedente verifico se è stato spostato o meno, giusto?

        Un’altra cosa: dici sia meglio cloccarlo a 20MHz o gli 8 dell’oscillatore interno possono bastare?

  8. #16 da Faustino il 10 dicembre 2011

    Ciao Giovanni e a tutti
    dovrei fare qualcosa del genere, ti citerò nei commenti della sorgente :).
    Ho un encoder assoluto ottico e su due uscite ci sono le onde in quadrature citate, più un’altra uscita che mi da un impulso ogni giro. Ci sono 1000 impulsi per giro ma ce ne possono essere anche 24000 impulsi per giro (dipende dal modello).
    Per giocare ho preso quello da 1000. il data sheet mi dice che ha una banda massima di 200kHz, ovvero un impulso non può durare meno di 2.5 us. Guardando con l’oscilloscopio effettivamente, siamo lì. Al momento pensavo a far gestire la velocità a livello hardware con un convertitore frequenza-tensione e dare in pasto l’uscita al ADC del PIC, questo perchè ho il timore che non ci stia dietro. La mia idea è di interrogare da pc con comunicazion USB o RS488 per interrogare il pic su velocità, angolo e giri compiuti.
    un interrupt ad alto livello per “intercettare” l’impulso dell’angolo un secondo interrupt a basso livello per la comunicazione seriale. il mio timore è uno, domanda: se tramite hyperterminal chiedo la velocita’, con un comando ad esempio “speed”, il pic riconosce un interupt a basso livello e mentre trasmette se allo stesso tempo riceve un interupt ad alto livello, cosa succede? il pic sicuramente da’ la precedenza all’interupt ad alto livello, ma a livello di comunicazione, si interrompe? c’è il rischio che l’utente non riesca a comunicare a meno che l’encoder vada a una velocità sufficientemente bassa? o tutto avviene in “parallelo”?
    Grazie Fausto

  9. #18 da danielone il 19 dicembre 2011

    Buondì Giovanni!
    Ringraziare per i tuoi articoli è poco.

    Ho usato questo componente:
    http://www.knitter-switch.com/pdf_en_prod11/encoder_seriesMER12.pdf (vedi quello a pagina 8)
    per implementare il tuo progetto, facendo un porting su PIC18F45K22. Pulse è collegato ad RB7 e dir ad RB6. L’interrupt è scansito solo su RB7.

    In uscita visualizzo la variabile su un display 7seg a 4 digit comandato via SPI da un max7219.

    Ho sperimentato questi 2 problemini:
    1) L’encoder funziona solo in decremento…in incremento non va. Che sia colpa del componente?
    2) Circa ABcounter ho sperimentato il passaggio da Fosc a 20Mhz come il tuo progetto ad 8Mhz nel mio. Tramite il tuo programma PIC timer ho quindi impostato il prescaler ad 1:8 (anziché 1:32) e TMR0L a 6 (anziché a 100) per ottenere l’overflow ogni 1ms. Di fatto capita che il sistema risponda con una lentezza allucinante all’input dell’encoder e ruotando velocemente proprio non funzioni. Sospetto a questo punto che 8Mhz sia una frequenza troppo bassa per gestire correttamente il tutto.

    Ne approfitto anche per segnalarti che cliccando al link che indichi per l’encoder Piher (i cui dati ho cercato di consultare per verificare se effettivamente butta fuori un segnale diverso dal mio encoder…anche se non mi pare) si viene mandati su una pagina non più esistente.

    Cari saluti!

    Daniele

  10. #19 da danielone il 19 dicembre 2011

    Dimenticavo di aggiungere quella che potrebbe essere una soluzione hardware al problema di debounce. Non l’ho provato ma lo proverò. Utile magari se si vuole usare l’encoder in polling senza inserire ritardi.

    http://www.onsemi.com/pub_link/Collateral/MC14490-D.PDF

  11. #20 da Andrea Barbon il 21 dicembre 2011

    Ciao, smontando un vecchio processore audiomi son capitati tra le mani un display 240×128 con un controller strano, ed un encoder rotativo.

    Per il display mi arrangio, ma per l’encoder m’è capitato in mano un pezzo particolare. L’encoder in questione non ha i soliti “tick” che senti con un encoder normalissimo, ed è predisposto a 4 fili. La manopola che c’era sopra era un bel manopolone di ferro, e girandolo con l’inerzia tende a continuare a girare e non a bloccarsi come con i normali encoder (non avendo i famosi “tick”… Solo che non saprei come collegarlo!

    Ho il dubbio che abbia qualche sorta di bobina o comunque qualcosa di elettromagnetico all’interno, eppure sul vecchio processore il connettore era saldato al pcb con solo 3 pin, o meglio dei 4 pin che c’erano saldati solo 3 avevano la pista che andava da una uqalche parte.

    sai darmi qualche info?

  12. #21 da nikets il 29 febbraio 2012

    Ciao a tutti. Volevo sapere se quello scritto nell’approfondimento sugli encoder a quadratura funzione anche con il pic della famiglia dei 18. Perchè io avrei bisogno di usarli per far andare avanti e indietro un robottino e memorizzare il passaggio eseguito.

  13. #23 da iv3ynb il 8 aprile 2013

    Ciao a tutti. Primo mio commento su questo bellissimo sito.
    Ho realizzato tempo fa una routine in basic per encoder incrementali con il metodo del polling di due PIN.
    All’accensione il programma polla l’encoder per capire che codice quale coppia di bit del codice gray è presente sull’encoder. Se percepisce uno spostamento, con il polling, confronta la nuova coppia di bit sui due PIN con il valore vecchio e si capisce da che parte si muove.
    Pensavo di migliorare il tutto utilizzando il C e l’interrupt, in maniera simile all’esempio sopra.
    Non capisco come il codice sopra possa identificare lo spostamento dell’encoder (qualsiasi sia il verso) con il cambio di stato un solo PIN e quindi l’utilizzo dell’interrupt su RB0.
    Il codice Gray generato dall’encoder è come sotto:

    00
    01
    11
    10

    non è forse necessario tenere in considerazione entrambi i bit per determinare il movimento dell’encoder? (il verso ok con RB1).

    Dove sbaglio?

    Grazie per l’attenzione e per un’eventuale risposta.
    Matteo iv3ynb

    • #24 da iv3ynb il 9 aprile 2013

      Penso di aver trovato la soluzione:
      A e B sono i bit dell’encoder:

      A su RB0 attiva l’interrupt. B su RB1
      se A passa da 0 a 1 con B=1 o A passa da 1 a 0 con B=0 INCREMENTA
      se A passa da 0 a 1 con B=0 o A passa da 1 a 0 con B=1 DECREMENTA

      cmq grazie per gli articoli e tutto il resto
      Matteo

  14. #25 da Francesco il 9 aprile 2013

    Ciao,

    il principio di funzionamento dell’encoder che stai usando tu è diverso da quello a quadratura cui fa riferimento l’articolo, per cui il codice non può essere utilizzato così com’è, ma richiede qualche modifica.

    Per rivelare la rotazione, è necessario, come hai già intuito, monitorare lo stato di entrambi i pin e pertanto bisogna associare a ciascuno di essi un interrupt e tale interrupt deve essere del tipo “on change”, cioè l’interruzione deve aversi in presenza sia di un fronte di salita che di discesa.
    Per stabilire il verso della rotazione, a fronte dell’interruzione, confronti il bit pattern attuale dell’encoder con quello precedentemente memorizzato per stabilire se si tratta di una sequenza ascendente o discendente.

    In sostanza la logica che hai usato nel codice basic è ancora valida, ma invece di monitorare lo stato dei pin dell’encoder con il polling, usi gli interrupt.

    • #26 da iv3ynb il 10 aprile 2013

      Grazie per la risposta ! Francamente cado dalle nuvole !!! Pensavo tutti i miei encoders fossero a quadratura. Di sicuro danno segnali sfasati di 90°… adesso mi hai messo il dubbio, ovviamente !!! che i miei encoder non siano proprio a quadratura ? sono ottici, effettivamente non in tutti i datasheet c’è la parola QUADRATURA: tuttavia fuori dai miei encoders il segnale in output è proprio quello a 90° e lo schema della schedina millefori è lo stesso che utilizzo io. Anche l’encoder in foto: potrebbe essere il mio senza problemi, sono quelli low cost che si trovano anche su eBay. Controllo e mi informo meglio. Come minimo.

      Ma veniamo al C: inizialmente intendevo mantenere la mia logica del confronto ma inserirla in interrupt. Ho analizzato il la mia procedura e quella proposta: secondo il mio parere potrei anche utilizzare l’RB0 come interrupt, ma il problema è che ad ogni CLICK dell’encoder, esso genera non 1 ma 4 impulsi, ovvero 4 sequenze del codice Gray ad impulso.
      Mettendo in interrupt -ad esempio- il bit a sinistra, quando abbiamo sequenze simili:
      00 11
      01 10
      11 00
      10 01
      abbiamo un solo cambio di stato del bit a sinistra e quindi la funzione interrupt + confronto con l’altro bit può andar bene, ma con le sequenze:
      10 01
      00 11
      01 10
      11 00
      che sono probabili pure loro, abbiamo 2 cambi di stato in un solo click… in teoria abbiamo 2 eventi che stimolano l’interrupt in un solo click. Come si comportai il micro in questo caso?
      Sentito il 1° interrupt, il micro perde il 2° interrupt o lo “memorizza” per processarlo subito dopo il 1° ?
      Se lo perde: fa nulla, comunque ho identificato un avanzamento/decremento associato ad un “click” dell’encoder; altrimenti mi pare di capire che possa esserci un problema.

      Grazie per l’attenzione
      Matteo

  15. #27 da Francesco il 11 aprile 2013

    Nel primo commento hai scritto:

    iv3ynb :
    Il codice Gray generato dall’encoder è come sotto:
    00
    01
    11
    10

    ciò esclude che possa trattarsi di un encoder a quadratura, perché in tal caso, fissato il verso di rotazione, lo sfasamento tra il pin Pulse e il pin Dir dovrebbe mantenersi costante. Ora se supponiamo che il bit sulla sinistra sia associato a Pulse e quello sulla destra sia associato a Dir, nel passaggio dal terzo (11) al quarto (10) codice lo sfasamento non si mantiene costante (nel terzo codice Pulse è in anticipo rispetto a Dir, nel quarto, invece, è in ritardo rispetto a Dir).

    Comunque se il tuo encoder è a quadratura, basta che usi il codice dell’articolo e hai risolto il problema. Supponiamo, quindi, che tu abbia un encoder gray.
    Per sgombrare il campo da equivoci e rispondere alle tue domande, è necessaria una precisazione.
    In matematica si definisce genericamente codice Gray qualsiasi codice in cui ogni parola differisce dalla successiva soltanto per un carattere (ciò perché il codice Gray standard è stato storicamente il primo esempio di codice che gode di tale proprietà).
    Storicamente il codice Gray standard è stato concepito per prevenire gli output spuri degli interruttori elettromeccanici. Ad esempio, per fissare le idee, supponiamo di avere un encoder rotativo che codifica la posizione dell’albero con tre interruttori elettromeccanici. Usando il codice binario naturale, ad ogni rotazione dell’albero si ottiene la seguente sequenza di codici

    000
    001
    010
    011
    100
    101
    110
    111

    Come si vede, nel passaggio da 011 a 100 tutti e tre gli interruttori devono variare il loro stato. Per gli inevitabili difetti di costruzione, è altamente improbabile che ciò accada in modo sincrono, per cui nel transitorio si avranno codice spuri, ad esempio 010, 110, che sono causa di errore.
    Usando il codice Gray, ad ogni rotazione dell’albero si ottiene la seguente sequenza di codici

    000
    001
    011
    010
    110
    111
    101
    100

    che ad ogni transizione richiede la variazione di stato di un solo interruttore e pertanto è estremamente affidabile.
    Per inciso il codice Gray è ciclico, cioè anche la transizione dall’ultimo al primo codice richiede la modifica di un solo bit.
    Il codice Gray, quindi, è perfetto per gli encoder (e non solo per loro).

    Da quanto detto possiamo concludere che le transizioni che tu hai elencato

    00 11
    01 10
    11 00
    10 01

    10 01
    00 11
    01 10
    11 00

    sono incompatibili con la codifica Gray, in quanto richiedono la variazione di due bit.
    Anche lo scenario che hai ipotizzato in cui 2 eventi stimolano l’interrupt in un solo click, non è compatibile con gli encoder Gray in cui in ogni transizione soltanto uno switch cambia il suo stato e quindi genera un interrupt.

    In linea di massima puoi seguire questo approccio
    1) a ciascuno dei due pin dell’encoder associ un interrupt on change
    2) all’inizio del programma memorizzi il bit pattern dell’encoder
    3) nella funzione di interrupt, se l’interrupt è stato causato da uno dei due pin dell’encoder, confronti il bit pattern dell’encoder con quello precedentemente memorizzato per stabilire il verso di rotazione e infine memorizzi il bit pattern dell’encoder.

    Nell’implementazione pratica devi fare in modo che la funzione di interrupt sia il più possibile snella, in modo tale che restituisca quanto prima il controllo al sistema, per cui potresti essere costretto ad impostare semplicemente dei flag nella funzione di interrupt e a spostare tutta la logica nel main o in un’altra funzione.

    • #28 da iv3ynb il 18 aprile 2013

      Grazie per la precisazione sulla quadratura.

      Solo una precisazione: so quanto scritto sotto non è di certo un codice Gray a 4 bit ma era mia intenzione scrivere due sequenze di codice Gray a 2 bit scritte vicine… forse le ho scritte troppo vicine.
      Queste indicavano un dato verso, la prima sequenza a sinistra parte da 00 e la seconda, a destra parte da 11
      00 11
      01 10
      11 00
      10 01
      certo si poteva scrivere meglio:
      00 11
      01 10
      11 00
      10 01
      stessa cosa dicasi dei numeri che seguono nel mio esempio, indicanti l’altro verso di rotazione.
      L’approccio dell’interrupt su due linee di RB è quello che pensavo di utilizzare al posto del polling anche quando “ragionavo in basic”.

      saluti
      Matteo

  16. #29 da manfranc il 4 novembre 2014

    Un ciao a tutti
    Rinnovo i complimenti per il sito
    Ho realizzato il circuito ovviamente con PIC16F877A non avendo a disposizione un encoder simile a quello usato da Gianni ho usato due forcelle ottiche TCST 2103, OK tutto funziona perfettamente fin tanto la velocità di rotazione è molto bassa ma appena si alza un po’ il sistema va in tilt e da dei numeri casuali, ora chiedo la causa sia esclusivamente per il fatto che uso due forcelle ottiche al posto del encoder meccanico?
    Antonio

  17. #30 da EdoFede il 18 gennaio 2016

    Ciao a tutti,
    intanto un ringraziamento all’autore del sito ed a chi ha contribuito a questo progetto.
    Veramente una risorsa preziosa. Farò una piccola donazione a breve.

    Ho effettuato una piccola modifica al codice suggerito, che condivido.

    Nel mio caso, la logica è questa:
    – Nel main ho una condizione sulla variabile “mode” e su un flag “chg_go” che ho aggiunto per iniziare l’elaborazione, senza dover controllare la variabile del timer0
    – L’interrupt sul timer0 è inizialmente disattivato
    – All’arrivo del INTF, lo disattivo INTE, controllo la condizione dei due ingressi dell’encoder e setto la modalità di INCR/DECR. Infine, imposto il timer0 ed attivo il relativo interrupt
    – Nelle if della function di interrupt, ho aggiunto il controllo dei flag di enable.
    – Nel main loop, al termine delle elaborazioni, resetto INTF e riattivo INTE

    In questo modo, evito che eventuali “rimbalzi” dell’encoder durante il conteggio di timer0, possano far cambiare la modalità di intervento (INCR/DECR) successivamente elaborata nel main.

    Specifico che non ho ancora fatto test esaustivo in debug. Conto di farlo nei prossimi giorni e se trovo qualche bug, posterò le correzioni.

    Segue il codice parziale da me usato.

    Ciao,
    Edo

    #define ENC_CLK PORTAbits.RA2 // Encoder clock pin
    #define ENC_PHS PORTCbits.RC0 // Encoder phase pin

    #define MIN_VAL 0 // Min var value
    #define MAX_VAL 4095 // Max var value
    #define INCR 1 // Val increment mode
    #define DECR 2 // Val decrement mode

    ….

    void main(void) {

    ….

    val = 0;
    val_last = 1;
    mode = 0;
    chg_go = 0;

    while(1){
    if (chg_go == 1 && mode != 0) {
    if (mode == INCR) {
    val = val + 1;
    if (val val_last)
    val = MIN_VAL;
    }
    mode = 0;
    chg_go = 0;

    if (val != val_last) {
    val_last = val;

    …..

    }
    INTCONbits.INTF = 0;
    INTCONbits.INTE = 1;
    }
    }
    }

    void interrupt ISR (void) {
    if (INTCONbits.INTF && INTCONbits.INTE) { // External INT interrupt
    INTCONbits.INTE = 0;
    if (ENC_PHS == ENC_CLK)
    mode = INCR;
    else
    mode = DECR;

    TMR0 = 71; // 5ms delay for antibounce
    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;
    }

    if (INTCONbits.TMR0IF && INTCONbits.TMR0IE) { // Timer0 interrupt
    INTCONbits.TMR0IE = 0;
    chg_go = 1; // start elaboration in main loop
    }
    }

  18. #31 da EdoFede il 18 gennaio 2016

    P.S. il portale ha troncato i TAB di indentazione del codice incollato..
    Se è possibile lo edito sostituendo con spazi.
    altrimenti, potreste eliminarlo che lo ri-posto corretto?

    Grazie,
    Edo

    • #32 da Giovanni Bernardo il 19 gennaio 2016

      Ciao Edoardo.
      Innanzitutto grazie :)
      Io non ho tempo di verificare. Tu prova e vedi come si comporta il tuo codice, se funziona bene ripubblico la tua versione con estremo piacere.

  19. #33 da EdoFede il 26 gennaio 2016

    Rieccomi.
    Ho testato con successo il mio codice, e ho riscritto con indentazione a spazi invece che tab.

    Sto testando anche una parte aggiuntiva, che aumenta il fattore di incremento della variabile, se si gira velocemente l’encoder.
    Per attuarla, sfrutto il Timer1
    La logica è questa:
    – Ad ogni cambio di posizione encoder (quindi nel main loop, dentro al “if (chg_go == 1 && mode != 0)” ) controllo se il Timer1 ha sollevato il suo interrupt flag (N.B. l’interrupt per Timer1 rimane sempre disattivato)
    – Se lo ha sollevato, l’incremento o il decremento viene effettuato di 1 unità (uso una variabile d’appoggio)
    – Se non lo ha sollevato, viene effettuato un incremento o decremento maggiore (200 nel mio caso).
    – Dopo il controllo, setto il Timer1 al valore per ottenere circa 100ms dal set all’overflow
    – Resetto il flag di interrupt di Timer1
    – A seguire, l’incremento o decremento viene eseguito con il valore della variabile d’appoggio

    In pratica, se tra un cambio di posizione del encoder ed il successivo passano meno di 100ms, la variabile viene incrementata o decrementata di un valore superiore.
    Non ho incluso il codice di questa ultima funzione, perché necessita ancora aggiustamenti ed il tempo sta un po’ scarseggiando, purtroppo.
    Lascio comunque questo commento con le indicazioni per poterla realizzare facilmente.

    Ciao,
    Edo

    #define ENC_CLK PORTAbits.RA2
    #define ENC_PHS PORTCbits.RC0

    #define MIN_VAL 0 // Min value (12bits)
    #define MAX_VAL 4095 // Max value (12bits)
    #define INCR 1 // Value increment mode
    #define DECR 2 // Value decrement mode

    unsigned char mode = 0; // 0 = Do Nothing 1 = Increment 2 = Decrement
    unsigned char chg_go = 0;

    unsigned int value_last;
    unsigned int value;

    void main(void) {

    …..

    value = 0;
    value_last = 0;
    mode = 0;
    chg_go = 0;
    TMR0 = 255;

    while(1){

    if (chg_go == 1 && mode != 0) {

    // “finecorsa” min/max per la variabile
    if (mode == INCR) {
    value = value + 1;
    if (value > MAX_VAL)
    value = MAX_VAL;
    } else {
    value = value – 1;
    if (value > value_last)
    value = MIN_VAL;
    }
    mode = 0;
    chg_go = 0;

    if (value != value_last) {
    value_last = value;

    ….. // elaboration on value change

    }
    INTCONbits.INTF = 0;
    INTCONbits.INTE = 1;
    }
    }
    }

    void interrupt ISR (void) {

    if (INTCONbits.INTF && INTCONbits.INTE) {
    INTCONbits.INTE = 0;
    if (ENC_PHS == ENC_CLK)
    mode = INCR;
    else
    mode = DECR;

    TMR0 = 39; // 7ms delay for antibounce
    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;
    }

    if (INTCONbits.TMR0IF && INTCONbits.TMR0IE) {
    INTCONbits.TMR0IE = 0;
    chg_go = 1; // start elaboration in main loop
    }

    }

    • #34 da EdoFede il 26 gennaio 2016

      P.S. il modulo nel sito tronca anche gli spazi consecutivi di indentazione, non solo i tab… :(
      Se vuoi aggiungere il mio codice all’articolo, posso mandartelo via e-mail..che è certamente più leggibile.

      • #35 da Giovanni Bernardo il 26 gennaio 2016

        Si… purtroppo il modulo dei commenti è pensato per il testo semplice.
        Magari scriviamo un articolo a parte come aggiornamento di questo.
        Hai utilizzato MPLAB X?

        • #36 da EdoFede il 30 gennaio 2016

          Si, MPLAB X con XC6.

          Ciao,
          Edo

          • #37 da Giovanni Bernardo il 13 dicembre 2016

            Ciao, puoi mandarmi il codice via email (il progetto intero mplab x) ? Cosi pubblico un aggiornamento.
            Se hai pure qualche foto del circuito che hai realizzato sarebbe meglio.
            Chiaramente pubblico a nome tuo.
            settorezero chiocciola gmail punto com

  20. #38 da linor il 25 dicembre 2016

    Salve, questo è il mio primo intervento e innanzitutto ringrazio e faccio i complimenti agli autori del sito.
    Quei pochi programmi che ho fatto sono stati per pc e scritti in qbasic.
    Ho fatto qualcosina di veramente semplice riguardo la programmazione dei pic, tipo antifurto, roulette ecc.
    Uso solo il pic basic.
    Ora mi sto cimentando nella simulazione di un encoder in quadratura, ecco come dovrebbe funzionare:
    Il pic legge in ingresso analogico una tensione variabile da 0 a 5 volt, ed in uscita mi da 2 treni sfasati di 90° da 0 a 5000 hz
    proporzionali alla tensione d’ingresso, inoltre in base allo stato logico di un interruttore devo ottenere il cambio dello stato
    logico dei segnali in uscita in modo da capire che l’interruttore (fisico) ha generato un cambio di direzione.
    Con la risoluzione a 10 bit posso campionare ogni 5 mV e quindi 5 hz.
    Credete sia facilmente fattibile? Grazie

    • #39 da Giovanni Bernardo il 29 dicembre 2016

      Cioè fammi capire, girando il potenziometro vuoi variare la frequenza? O il Duty cycle? Tipo potenziometro tutto girato da un lato hai un’onda quadra a tot Hz (ammettendo un PWM del 50% come dovrebbe essere su un encoder) e girando tutto dall’altro lato hai un’altra frequenza. Certo che è fattibile. Vuoi creare in pratica un generatore PWM controllato da un potenziometro.

  21. #40 da linor il 29 dicembre 2016

    Il duty cycle deve essere 50 % per ogni onda, le onde devono essere sfasate di 90° tra di loro, la frequenza deve essere proporzionale alla
    tensione e deve andare da 0 hz a 5000. Inoltre tramite un pulsante o interruttore le due onde devono cambiare fase, quella che era in ritardo
    deve passare in anticipo, in modo da simulare il cambio di direzione, anche durante la marcia.
    Non voglio creare un pwm, ma voglio simulare un trasmettitore di impulsi tipo quelli calettati sugli assali dei treni, che di fatto ha due canali magnetoresitivi che generano due segnali sfasati di 90°, e quindi lo voglio pilotare con un potenziometro.
    Come dicevo sono veramente “indietro”, non so ancora applicare gli interrupt, lavoro solo in polling, per ora mi viene in mente sono l’idea di creare un’ array con 1024 valori preimpostati, i modo che il pic legge il valore di v, lo trasforma in un valore decimale e va a prendere il valore corrispondente
    e lo metta nel routine di calcolo dei delay. Non mi viene in mente altro, aspetto qualche consiglio.
    Grazie

  22. #41 da linor il 30 dicembre 2016

    Vorrei aggiungere:
    Con una risoluzione del convertitore AD di 10 bit vengono letti 1024 valori, quindi 0,05 volt per step.
    Quindi ogni 5 mV vorrei in uscita 5 hz, esempio 1,125 volt uguale 1125 hz e cosi via.
    Adesso che sono stato piu chiaro pensi sempre che sia fattibile?

    Grazie ancora e buon 2017.

  23. #43 da linor il 6 gennaio 2017

    Giovanni Bernardo :
    SIcuramente si. Le frequenze in gioco sono molto basse.. 0 – 5KHz hai voglia

    Si, l’ho fatto come dicevo io, con un’array e step di 20 hz per volta, va molto bene per quello che ci devo
    fare, poi posterò il video. L’ avrei voluto fare senza una matrice e usando un calcolo matematico e gli
    interrupt, ma ancora non ci arrivo.
    Sarei curioso di sapere qualcuno più esperto come l’avrebbe impostato, ciao.

Devi essere collegato per lasciare un commento.

  1. Ancora nessun trackback
settorezero.com e il logo Zroid™ ©2007÷2015 Giovanni Bernardo - E' vietata la copia e la distribuzione anche parziale dei contenuti di questo sito web senza l'esplicito consenso dell'autore.
I contenuti di settorezero.com sono distribuiti sotto una licenza Creative Commons Attribuzione-Non Commerciale-Non Opere derivate 2.5 Italia a cui vanno aggiunte le condizioni d'uso definite nel disclaimer.
settorezero.com e tutti i suoi contenuti sono tutelati dalla legge sul diritto d'autore per cui i trasgressori sono perseguibili a norma di legge. Settorezero fa uso dei cookie leggi l'informativa estesa.
Creative Commons BY-NC-ND 2.5
Il tema di questo sito è basato sul tema Fusion per wordpress, realizzato originariamente da digitalnature e fa uso del plugin Wassup per il computo delle statistiche. Per contattare l'autore siete pregati di utilizzare la sezione contatti.
Per essere aggiornato con tutte le novità di settorezero.com seguici anche anche su Facebook Twitter Tumblr Blogspot Youtube.