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

Counter con timer 1 di Arduino

Discussione in 'LAB sperimentazioni' iniziata da mincio, 21 Nov 2016.

  1. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    buogiorno
    sono un perito elettronico alle prime armi con arduino devo trasferire su questo una routine che ho scritto diverso tempo fa' in assembler per il pic16f876.

    devo utilizzare il timer 1 caricando nei registri un determinato valore poi utilizzando il pin 5 devo contare gli impulsi presenti in modo che il timer vada in overflow e attivi la chiamata alla routine di servizio dell'interrupt relativo.
    ho provato a smanettare ma senza riuscire ad avere risultati sarei grato a quasiasi riesca a fornirmi qualche pezzetto di codice.
    grazie

    allego codice

    /*
    * contatore impulsi con overflow
    *
    * ingresso di conteggio pin 5
    * per prova vengono utilizzzati impulsi a frequenza molto bassa
    */
    #include <TimerOne.h>

    const int hardwareCounterPin =5; //ingresso impulsi per conteggio con timer 1
    const int input9 = 9; //ingresso per monitor impulsi in ingresso
    const int ledPin10 =10; // led per monitor avvenuto overflow ed esecuzione routinr interrupt
    const int ledPin13 =13; //led monitor impulsi ingresso 9

    int input9State = 0;
    int byteLedPinState = 0;

    int ledOn;
    int ledState10 = LOW;
    const int cycleLedOn=100; //costante per numero cicli in cui il ledPin10 rimane
    //acceso dopo accensione da interrupt overflow timer 1
    unsigned int costSincro=65526; //costante da caricare nei registri del timer 1 per contare 10 impulsi

    void setup(){


    pinMode(ledPin10,OUTPUT);
    pinMode(ledPin13,OUTPUT);
    pinMode(input9,INPUT_PULLUP);
    pinMode(hardwareCounterPin,INPUT_PULLUP);

    ledOn=cycleLedOn;
    TCCR1A=0; //azzera valore timer 1

    bitSet (TCCR1B,ICNC1); //abilita filtro ingresso durata 4 cicli di clock interni
    bitSet (TCCR1B,ICES1); //abilita fronte di salita per conteggio
    bitSet (TCCR1B,CS12); //abilita modalita ingresso clock esterno
    bitSet (TCCR1B,CS11); //abilita modalita ingresso clock esterno
    bitSet (TCCR1B,CS10); //abilita modalita ingresso clock esterno
    bitSet (TIMSK1,ICIE1); //abilita interrupt timer 1
    bitSet (TIMSK1,TOIE1); //abilita interrupt timer 1
    bitSet (TIFR1,TOV1); //abilita interrupt overflow timer 1

    TCNT1==costSincro;

    Timer1.attachInterrupt( TIMER1_OVF_vect ); // abilita l'interrupt di overflow di timer 1
    }

    void loop(){
    led1();
    led2();

    }


    void led1(){
    if (ledState10 == 1){
    ledOn-=1;

    }
    }
    void led2(){
    if (ledOn == 0){
    ledOn=cycleLedOn;
    digitalWrite(ledPin10, LOW);
    }
    input9State = digitalRead(input9);
    if (input9State == HIGH) {
    digitalWrite(13, HIGH);
    }
    if (input9State == LOW){
    digitalWrite(13, LOW);
    }


    }
    //}
    /// ----------------------------------------
    /// Routine di servizio interrupt di timer 1
    /// ----------------------------------------

    void TIMER1_OVF_vect()
    {
    Timer1.detachInterrupt(); // disabilita interrupt overflow timer 1
    TCNT1 == costSincro;
    digitalWrite(ledPin10, HIGH);
    ledState10 = HIGH;
    Timer1.attachInterrupt( TIMER1_OVF_vect ); // riabilita interrupt overflow timer 1
    }
     
    #1
  2. RyujiAndy

    RyujiAndy Staff ᗧ͇̿ · · ᗣ͇̿ᗣ͇̿ᗣ͇̿ᗣ͇̿ Staff

    Iscritto:
    15 Dic 2014
    Messaggi:
    559
    Like ricevuti:
    390
    Ammetto che il "C" non necessita di bellagrafia ma un minimo di ordine aiuta a capire meglio il funzionamento e poi é gradito anche uno schema per capire meglio il rapporto di funzionamento, ma se ho capito bene emetti un impulso per poi contarli?
     
    #2
  3. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    buonasera
    concordo che non e' molto elegante il c che ho scritto ma sono alle prime armi
    cerco di spiegare meglio quanto intendevo fare
    lo scopo e' di contare un certo numero di impulsi provenienti da un encoder che mi portino il timer 1 in overflow permettendo cosi di esegure la relativa ruotine di interrupt la quale deve settare un uscita e ricaricare in timer 1 la variabile constSincro e riattivare l' interrupt .
    l'uscita settata verra' poi resettata dopo un numero di cicli impostati nella variabile cycleLedOn. (il numero di impulsi dell'encoder da contare e' sufficientemente alto da permettere al processore di eseguire un numero di cicli molto piu' grande della variabile cycleLedOn)
    spero di essere stato un po' piu' chiaro.
    allego listato ripulito


    Codice:
    /*
    * contatore impulsi con overflow
    *
    * ingresso di conteggio pin 5
    * per prova vengono utilizzzati impulsi a frequenza molto bassa
    */
    #include <TimerOne.h>
    
    const int hardwareCounterPin =5; //ingresso impulsi per conteggio con timer 1
    const int input9 = 9; //ingresso per monitor impulsi in ingresso
    const int ledPin10 =10; // led per monitor avvenuto overflow ed esecuzione routinr interrupt
    const int ledPin13 =13; //led monitor impulsi ingresso 9
    
    int input9State = 0;
    int byteLedPinState = 0;
    
    int ledOn;
    int ledState10 = LOW;
    const int cycleLedOn=100; //costante per numero cicli in cui il ledPin10 rimane
    //acceso dopo accensione da interrupt overflow timer 1
    unsigned int costSincro=65526; //costante da caricare nei registri del timer 1 per contare 10 impulsi
    
    void setup(){
    
    
       pinMode(ledPin10,OUTPUT);
       pinMode(ledPin13,OUTPUT);
       pinMode(input9,INPUT_PULLUP);
       pinMode(hardwareCounterPin,INPUT_PULLUP);
    
       ledOn=cycleLedOn;
       TCCR1A=0; //azzera valore timer 1
    
       bitSet (TCCR1B,ICNC1); //abilita filtro ingresso durata 4 cicli di clock interni
       bitSet (TCCR1B,ICES1); //abilita fronte di salita per conteggio
       bitSet (TCCR1B,CS12); //abilita modalita ingresso clock esterno
       bitSet (TCCR1B,CS11); //abilita modalita ingresso clock esterno
       bitSet (TCCR1B,CS10); //abilita modalita ingresso clock esterno
       bitSet (TIMSK1,ICIE1); //abilita interrupt timer 1
       bitSet (TIMSK1,TOIE1); //abilita interrupt timer 1
       bitSet (TIFR1,TOV1); //abilita interrupt overflow timer 1
    
       TCNT1==costSincro;
    
       Timer1.attachInterrupt( TIMER1_OVF_vect ); // abilita l'interrupt di overflow di timer 1
    }
    
    void loop(){
       led1();
       led2();
    }
    
    
    void led1(){
       if (ledState10 == 1){
         ledOn-=1;
       }
    }
    
    void led2(){
       if (ledOn == 0){
         ledOn=cycleLedOn;
         digitalWrite(ledPin10, LOW);
       }
       input9State = digitalRead(input9);
       if (input9State == HIGH) {
         digitalWrite(13, HIGH);
       }
       if (input9State == LOW){
         digitalWrite(13, LOW);
       }
    }
    //}
    /// ----------------------------------------
    /// Routine di servizio interrupt di timer 1
    /// ----------------------------------------
    
    void TIMER1_OVF_vect(){
       Timer1.detachInterrupt(); // disabilita interrupt overflow timer 1
       TCNT1 == costSincro;
       digitalWrite(ledPin10, HIGH);
       ledState10 = HIGH;
       Timer1.attachInterrupt( TIMER1_OVF_vect ); // riabilita interrupt overflow timer 1
    }
    
     
    #3
    Ultima modifica di un moderatore: 24 Nov 2016
  4. zoomx

    zoomx Livello 19

    Iscritto:
    12 Set 2015
    Messaggi:
    892
    Like ricevuti:
    339
    Vediamo se ho capito bene.

    Tu fai fare al Timer1 il conteggio degli impulsi per cui abiliti il clock esterno sul Timer1 sul pin5, cosa che deve essere fra i vari bitSet (non sono ferrato sui registri di Arduino).

    Poi però scrivi
    unsigned int costSincro=65526; //costante da caricare nei registri del timer 1 per contare 10 impulsi
    ma il Timer1 conterà 65526 impulsi e non 10, se non ho capito male.

    Quando scatta l'overflow Accendi il LED sul pin 10 e setti un flag LedState10.

    Nel loop esegui 2 funzioni.

    La prima conrolla lo stato del flag e decrementa un contatore che originariamente è indefinito ma non sembra essere un problema perché l'overflow all'inizio non è stato raggiunto e questa funzione non verrà eseguita.
    Io, per chiarezza, avrei messo
    int ledOn = 10;
    Inoltre cambierei if (ledState10 == 1) in if (ledState10 == HIGH)

    Nella seconda funzione fai
    if (ledOn == 0){
    quindi un confronto su una variabile che è stata dichiarata ma non settata ad alcun valore. Quindi mi sa che
    int ledOn = 10;
    ci vuole e non è un opzione.
    Dopodiché rimetti il contatore a 10 e spegni il LED.

    Io non vedo alcun punto dove ledState10 viene rimesso a LOW, credo che debba essere fatto dentro a led1().

    Non ho capito se il led in 10 deve rimanere acceso fino al decimo ciclo di conteggio e poi spento o accendersi brevemente ad ogni conteggio di ciclo. Attualmente sembra la prima.
     
    #4
  5. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    buongiorno
    scrivo unsigned int costSincro=65526; perche' il timer 1 deve incrementare per arrivare all'overflow e attivare l'interrupt..
    nella prima funzione accendo il led sul pin 10 e decremento la variabile ledOn-=1; che rappresenta quanti cicli di programma il led rimane acceso.
    nella seconda funzione si spegne il led se ledOn e' uguale a 0 e ricaricata con cycleLedOn=10.
    la variabile ledOn viene posta = cycleLedOn=10 la prima volta nel setup
    spero di essere stato chiaro.
    grazie
    saluti
     
    #5
  6. zoomx

    zoomx Livello 19

    Iscritto:
    12 Set 2015
    Messaggi:
    892
    Like ricevuti:
    339
    La prima funzione, led1 non accende nessun LED, cambia il valore di una sola variabile.Il LED viene acceso nel funzione eseguita all'interrupt con digitalWrite(ledPin10, HIGH);
    Per come è scritto lo sketch verrà spento solo dopo il completamento dei 10 cicli.

    ledOn=cycleLedOn; nel setup mi era sfuggita. scusa!

    Purtroppo non sono ferrato in interrupt e non so se all'interno di una funzione interrupt si possa mettere l'istruzione attachInterrupt.

    Mi sono accorto di una dimenticanza mia: tutte le variabili usate all'interno di un ciclo di interrupt devono essere dichiarate volatile quindi
    volatile int ledState10 = LOW;
    anche se invece di un int (2 byte) avrei usato un boolean o un byte (un solo byte).

    Ma attualmente cosa succede, come si comporta lo sketch?
     
    #6
  7. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    sembra non eseguire l'interrupt e quindi non accende il led
    la prima funzione infatti non accende il led il led deve essere acceso nella routine di interrupt ma deve contare i cicli in qui il led rimane acceso e' nella seconda funzione che viene spento se il numero dei cicli e' stato superato.
    ciao
     
    #7
  8. zoomx

    zoomx Livello 19

    Iscritto:
    12 Set 2015
    Messaggi:
    892
    Like ricevuti:
    339
    Ora ci siamo.
    Poiché ne so poco mi sono andato ad informare qui
    https://www.gammon.com.au/timers
    Nel primo sketch si fa proprio un conteggio ma tira fuori la frequenza utilizzando il Timer2.

    Quello che noto però è questo
    // start Timer 1
    // External clock source on T1 pin (D5). Clock on rising edge.
    TCCR1B = bit (CS10) | bit (CS11) | bit (CS12);

    Che invece tu scrivi
    bitSet (TCCR1B,CS12); //abilita modalita ingresso clock esterno
    bitSet (TCCR1B,CS11); //abilita modalita ingresso clock esterno
    bitSet (TCCR1B,CS10); //abilita modalita ingresso clock esterno


    Gammon scrive che quelle istruzioni di fatto fanno partire il Timer1 ma tu poi vai a scrivere in altri registri. Prova quindi a spostarle in basso ed eseguirle per ultime.
    Nota che le variabili usate all'interno dell'interrupt sono dichiarate volatile, come avevo scritto prima.

    Edit:
    Anche questo potrebbe essere utile
    https://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
     
    #8
  9. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    appena ho tempo provo e poi ti faccio sapere
    grazie ciao
     
    #9
  10. zoomx

    zoomx Livello 19

    Iscritto:
    12 Set 2015
    Messaggi:
    892
    Like ricevuti:
    339
    Be' ti devo ringraziare anche io perché grazie alla tua richiesta ho appreso dell'esistenza di una funzione del counter che in effetti mi son accorto che mi ero dimenticato esistesse.
     
    #10
  11. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    ciao
    sono andato sui siti che mi avevi segnalato e ho trovato qualche cosa che poteva fare al caso ne ho modificato un esempio lo testato e sembrava funzionare appena ho tempo lo ripulisco poi lo metto nella discussione magari puo' servire anche ad altri .
     
    #11
  12. zoomx

    zoomx Livello 19

    Iscritto:
    12 Set 2015
    Messaggi:
    892
    Like ricevuti:
    339
    Certo, i link sono in lingua inglese, in italiano c'è poco o nulla.
     
    #12
  13. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    ma traducendo la pagina con google e salvando si capisce abbastanza
     
    #13
  14. zoomx

    zoomx Livello 19

    Iscritto:
    12 Set 2015
    Messaggi:
    892
    Like ricevuti:
    339
  15. mincio

    mincio Livello 1

    Iscritto:
    21 Nov 2016
    Messaggi:
    8
    Like ricevuti:
    0
    gia visto ma quui conta inpulsi riferiti a una base tempi.
    mentre quello che usero diciamo che e' un contatore asincrono oforse e' assimilabile a un totalizzatore con preset.
    comunque grazie.
    saluti

    ciao allego sotto il codice testato di quanto volevo fare. grazie per la collaborazione

    //
    //Si utilizza l'overflow del timer 1 per generare un segnale funzione di un numero di impulsi provenienti
    //da un encoder e di durata uguale a un numero di cicli di programma

    const int input9 = 9; //ingresso per monitor impulsi in ingresso
    const int ledPin13 = 13; // the number of the LED pin
    const int ledPin10 = 10; // led per monitor avvenuto overflow ed esecuzione routinr interrupt
    volatile int costSincro = 0; //costante da caricare nei registri del timer 1 per contare impulsi usata in interrupt
    int newcostSincro = 100; //variabile di sincronizzazione da utilizzare per il prossimo impulso
    const int cycleLedOn = 5 ; //costante per numero cicli in cui il ledPin10 rimane
    int ledOn = cycleLedOn;
    int ledState10 = LOW; // ledState used to set the LED
    int input9State = LOW;

    //pin
    const byte inputPin = A0; //pin analogico di ingresso
    const byte outputPin = 7; //pin di output

    //variabili globali
    byte statoLed = 0; //contiene il valore sul pin 9

    void setup ()
    {
    pinMode (ledPin13, OUTPUT);
    pinMode (ledPin10,OUTPUT);
    pinMode(input9,INPUT_PULLUP);

    costSincro = (0xffff-newcostSincro);


    // Inizializza Timer1
    cli (); // Disabilitare gli interrupt globali
    TCCR1A = 0; // Imposta l'intero registro TCCR1A a 0
    TCCR1B = 0; // Imposta l'intero registro TCCR1A a 0

    // Abilitare Timer1 di overflow interrupt:
    TIMSK1 = (1 << TOIE1);
    TCNT1 = costSincro;
    // Set CS10 CS11 E CS12 così timer funziona con clock esterno pin 5
    TCCR1B = bit (CS10) | bit (CS11) | bit (CS12);

    // Abilitare gli interrupt globali:
    sei ();
    }

    ISR (TIMER1_OVF_vect)
    {
    TCNT1 = costSincro; // Ricaricare il precarico del timer

    ledState10 = HIGH;
    digitalWrite(ledPin10, HIGH);

    }

    void loop () {

    costSincro = (0xffff-newcostSincro);
    led1();
    led2();

    }

    void led1(){ //conta i cicli di programma
    if (ledState10 == 1){
    ledOn -= 1;
    }
    }
    void led2(){ //se superati i cicli di programma spegne il led riinizizlizza la variabile ledOn
    if (ledOn == 0){
    ledOn=cycleLedOn;
    ledState10 = LOW;
    digitalWrite(ledPin10, LOW);
    }
    }
     
    #15

Condividi questa Pagina