Arduino cambia frequenza se viene usato un display

Ciao a tutti, ho costruito un semplice oscillatore. Purtroppo non riesco a capire perchè se non uso un display viene generata una frequenza da 0 a 250hz(frequenza che mi serve), mentre se abilito il display la frequenza arriva a 99hz e successivamente passa a 83hz e rimane tale. Dove sto sbagliando? Allego la parte dello Sketch che da problemi.Grazie a tutti.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27


int imp_giu = 4; // Pin Incremento impulsi
int imp_su =7;   // Pin Decremento impulsi



long previousMillis1 = 0;        // imposta momentaneamente il timer a 0
long interval1 = 0;  // imposta il valore dei microsecondi a 0
long SceltaImpulsi = 1; // imposta il contatore degli impulsi a 1
long Uscita2 = 13; // imposta come Uscita2 il PIN 13 (Frequenza Impulsi)

int StatoUscita2 = LOW; // imposta lo stato dell'uscita a Low


void setup() {

    
  pinMode(imp_su, INPUT_PULLUP); //imposta il pulsante "Su" sfruttando la resistenza interna di Pullup
  pinMode(imp_giu, INPUT_PULLUP); //imposta il pulsante "Giu" sfruttando la resistenza interna di Pullup
  pinMode(Uscita2, OUTPUT); // imposta il pin 13 in uscita
   
lcd.init();// inizializza il display LCD
lcd.backlight(); // accende la luce dell'Lcd
  
}


void impulsi()
{
long (currentMillis1) = micros (); 

if (currentMillis1 - previousMillis1 >= interval1 && SceltaImpulsi >=1) {

    previousMillis1 = currentMillis1;

    interval1 = (5000000/SceltaImpulsi);
    if (StatoUscita2 == LOW) {
      StatoUscita2 = HIGH;
    } else {
      StatoUscita2 = LOW;
    }
      
   
lcd.setCursor(0, 1);
    lcd.print(SceltaImpulsi/10);
 digitalWrite(Uscita2, StatoUscita2);
   
    }
  }


void loop() {


 
 
 //**********LETTURA DEI PULSANTI IMPULSI*************
 int valoreimp_su = digitalRead(imp_su);
  int  valoreimp_giu = digitalRead(imp_giu);
   
  if (valoreimp_su == LOW) {
    SceltaImpulsi ++;
    delay(10);
    if(SceltaImpulsi>2500){SceltaImpulsi=1;
    
       }
     }
  else if (valoreimp_giu == LOW) {
    SceltaImpulsi --;
    delay(10);
   if(SceltaImpulsi <1){SceltaImpulsi =2500;
   
   }
   
  }

   
  
  impulsi();
  
  
 
  }

allora cominciamo :slight_smile:

prima di tutto tutte le variabili che contengono dei tempi (millis o micro) vanno dichiarate unsigned long altrimenti sono troppo piccole e ti danno problemi

secondo
tu non stai misurando una frequenza, stai misurando il tempo di esecuzione del tuo programma, ovviamente siccome le operazioni di scrittura sull'lcd sono lente incidono pesantemente sulla rapidità di esecuzione del tuo codice

terzo
non hai usato nessuna tecnica di debounce sui pulsanti per cui quando li premi con sai esattamente quale valore assumerà la variabile SceltaImpulsi, potrebbe incrementare o decrementare anche di un paio di decine di unità alla volta

quarto
a che ti serve l'incremento o decremento di tale variabile?

dividi un valore per questa variabile che corrisponde al numero di volte che hai premuto il pulsante per aggiornare la variabile interval1 che poi usi come intervallo per eseguire nuovamente il ricalcolo e ti stampi su lcd il numero di volte che hai premuto il pulsante/10

praticamente all'accensione tu hai il led che comincia a lampeggiare al ritmo di 5 secondi (5.000.000 /1 microsecondi= 5 secondi)
se dopo un po premi il pulsante su
se ti è andata bene hai incrementato di una unità quindi la prossima volta che entra nel ciclo di impulsi cambia la frequenza di lampeggio a 2,5 secondi (5.000.000 / 2 = 2.500.000 micro)
ad una nuova pressione diventano 5.000.000 / 3 =1.666.666 micro .... e così via
e avrai come stampa su lcd
1/10= 0,1
2/10=0,2
3/10=0,3
e così via

Grazie!!! Non ho usato il debounce, ne alcun condensatore in parallelo perchè a me conveniva il fatto che lasciando premuto su o giù, l’incremento della frequenza con duty cycle 50% vista all’oscilloscopio risultava lineare, però, la sorpresa è stata quando ho superato i 99hz. Quindi, che ne pensate se per ottenere frequenze fino a 250hz ed oltre di usare “Tone”, mentre per quelle inferiori a 30 Hz… lasciare così? :wink: voglio premettere che l’uscita l’ho applicata ad un TIP120 collegato ad una bobina tra collettore e + 12 Vcc., per irradiare il campo elettromagnetico indicato.

Ho usato unsigned long, come consigliato; come vedi, ho disabilitato il display (lcd.init) e, guardando l’oscilloscopio ed il frequenzimetro, riscontro che la frequenza scorre regolarmente fino a 250hz (ho provato fino a 1000 e va bene) e la forma d’onda è sufficientemente quadra. A questo punto non mi resta che usare un piccolo frequenzimetro esterno… che ne pensi? Grazie tantissimo per la pazienza e per i suggerimenti, vista la mia scarsa esperienza con questi microcontrollori, magari, mi potrai suggerire una soluzione diversa…

[code]
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27


int imp_giu = 4; // Pin Incremento impulsi
int imp_su =7;   // Pin Decremento impulsi



unsigned long previousMillis1 = 0;        // imposta momentaneamente il timer a 0
unsigned long interval1 = 0;  // imposta il valore dei microsecondi a 0
unsigned long SceltaImpulsi = 1; // imposta il contatore degli impulsi a 1
unsigned long Uscita2 = 13; // imposta come Uscita2 il PIN 13 (Frequenza Impulsi)

int StatoUscita2 = LOW; // imposta lo stato dell'uscita a Low




void setup() {

  
  
  pinMode(imp_su, INPUT_PULLUP); //imposta il pulsante "Su" sfruttando la resistenza interna di Pullup
  pinMode(imp_giu, INPUT_PULLUP); //imposta il pulsante "Giu" sfruttando la resistenza interna di Pullup
  pinMode(Uscita2, OUTPUT); // imposta il pin 13 in uscita
   
//lcd.init();// inizializza il display LCD
//lcd.backlight(); // accende la luce dell'Lcd
  
}


void impulsi()
{
long (currentMillis1) = micros (); 

if (currentMillis1 - previousMillis1 >= interval1 && SceltaImpulsi >=1) {

    previousMillis1 = currentMillis1;

    interval1 = (5000000/SceltaImpulsi);
    if (StatoUscita2 == LOW) {
      StatoUscita2 = HIGH;
    } else {
      StatoUscita2 = LOW;
    }
      
   
lcd.setCursor(0, 1);
    lcd.print(SceltaImpulsi/10);
 digitalWrite(Uscita2, StatoUscita2);
   
    }
  }


void loop() {


 
 
 //*********************LETTURA DEI PULSANTI IMPULSI********************************
 int valoreimp_su = digitalRead(imp_su);
  int  valoreimp_giu = digitalRead(imp_giu);
   
  if (valoreimp_su == LOW) {
    SceltaImpulsi ++;
    delay(10);
    if(SceltaImpulsi>2500){SceltaImpulsi=1;
    
       }
     }
  else if (valoreimp_giu == LOW) {
    SceltaImpulsi --;
    delay(10);
   if(SceltaImpulsi <1){SceltaImpulsi =2500;
   
   }
   
  }

   
  
  impulsi();
  
  
 
  }

[/code]

se scrivi su lcd solo se la frequenza cambia, il ciclo non perde tempo a fare cose inutili
verifica come va questo…

/*
 *  non mi serve misurare il tempo che passa
 *  uso il risultato del calcolo 5.000.000/SceltaImpulsi per effettuare il
 *  ciclo HIGH e LOW del pin 13
 *  Se il valore di SceltaImpulsi cambia scrivo su LCD il nuovo valore
 *  altrimenti non aggiorno inutilmente l'LCD
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27

byte imp_giu = 4;       // Pin Incremento impulsi
byte imp_su = 7;        // Pin Decremento impulsi
byte Uscita = 13;       // imposta come Uscita il PIN 13 (Frequenza lampeggio)
bool stato = false;

long intervallo = 0;       // imposta il valore dei microsecondi a 0
long SceltaImpulsi = 1;    // imposta il contatore degli impulsi a 1
long oldImpulsi = 0;

unsigned long previousMicros = 0;


void setup() {
   pinMode(imp_su, INPUT_PULLUP);   //imposta il pulsante "Su" sfruttando la resistenza interna di Pullup
   pinMode(imp_giu, INPUT_PULLUP);  //imposta il pulsante "Giu" sfruttando la resistenza interna di Pullup
   pinMode(Uscita, OUTPUT);         // imposta il pin 13 in uscita
   lcd.init();                      // inizializza il display LCD
   lcd.backlight();                 // accende la luce dell'Lcd
}

void loop() {
   //**********LETTURA DEI PULSANTI IMPULSI*************
   checkImpulsi();                              // verifico se tasti premuti
   if (SceltaImpulsi != oldImpulsi) {           // se il valore attuale è diverso
      intervallo = (5000000 / SceltaImpulsi);   // da quello salvato, ricalcolo
      lcd.setCursor(0, 1);                      // stampo una volta su lcd
      lcd.print(1/(intervallo/1000000) );              // la frequenza in Hz F=1/T
      oldImpulsi = SceltaImpulsi;               // memorizzo nuovo valore
   }
   attivaUscita();                              //attivo uscita
}
//controllo se tasti premuti (senza debouncing)
void checkImpulsi() {
   bool valoreSu = digitalRead(imp_su);
   bool valoreGiu = digitalRead(imp_giu);

   if (valoreSu == LOW) {
      SceltaImpulsi ++;
      delay(10);
      if (SceltaImpulsi > 3000) {   // premo su se valore 3000 resta a 3000
         SceltaImpulsi = 3000;
      }
   } else if (valoreGiu == LOW) {
      SceltaImpulsi --;
      delay(10);
      if (SceltaImpulsi < 1) {      // premo giù se valore 1 resta 1
         SceltaImpulsi = 1;
      }
   }
}
//
void attivaUscita() {
   // usando la manipolazione diretta dei pin è più rapido
   // il cambio di stato tra LOW e HIGH
   if (micros() - previousMicros >= intervallo) {
      previousMicros = micros();
      stato = !stato;
      if (stato) {
         PORTB = B11100000;                           // accendo il led
      } else {
         PORTB = B11000000;                           // spengo il led
      }
   }
}

Sia frequenza che forma d’onda sono Perfette! Lo sketch lo hai totalmente riscritto. Bellissimo! Complimenti! Ho soltanto apportato una piccola variante in modo che il display segni esattamente la frequenza indicata sul frequenzimetro e sull’oscilloscopio, (lcd.print(SceltaImpulsi/10 ):wink: (Vpp5.00, Vmax2.41, Vmin2.59 Duty 50%… Testata con le bobine esterne usando uno stadio finale con TIP 120 :slight_smile: fino a 300 hz, è Perfetto e ne sono certo che potrà andare oltre senza che il display dia… “fastidio”. Grazie anche per gli ottimi consigli! Sei un Grande!!!

[code]


/*
 *  non mi serve misurare il tempo che passa
 *  uso il risultato del calcolo 5.000.000/SceltaImpulsi per effettuare il
 *  ciclo HIGH e LOW del pin 13
 *  Se il valore di SceltaImpulsi cambia scrivo su LCD il nuovo valore
 *  altrimenti non aggiorno inutilmente l'LCD
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27

byte imp_giu = 4;       // Pin Incremento impulsi
byte imp_su = 7;        // Pin Decremento impulsi
// byte Uscita = 13;       // imposta come Uscita il PIN 13 (Frequenza lampeggio)
bool stato = false;

long intervallo = 0;       // imposta il valore dei microsecondi a 0
long SceltaImpulsi = 1;    // imposta il contatore degli impulsi a 1
long oldImpulsi = 0;

unsigned long previousMicros = 0;


void setup() {
   pinMode(imp_su, INPUT_PULLUP);   //imposta il pulsante "Su" sfruttando la resistenza interna di Pullup
   pinMode(imp_giu, INPUT_PULLUP);  //imposta il pulsante "Giu" sfruttando la resistenza interna di Pullup
  // pinMode(Uscita, OUTPUT);         // imposta il pin 13 in uscita
   lcd.init();                      // inizializza il display LCD
   lcd.backlight();                 // accende la luce dell'Lcd
}

void loop() {
   //**********LETTURA DEI PULSANTI IMPULSI*************
   checkImpulsi();                              // verifico se tasti premuti
   if (SceltaImpulsi != oldImpulsi) {           // se il valore attuale è diverso
      intervallo = (5000000 / SceltaImpulsi);   // da quello salvato, ricalcolo
      lcd.setCursor(0, 1);                      // stampo una volta su lcd
     // lcd.print(1/intervallo );              // la frequenza in Hz F=1/T
     lcd.print(SceltaImpulsi/10 ); 
      oldImpulsi = SceltaImpulsi;               // memorizzo nuovo valore
   }
   attivaUscita();                              //attivo uscita
}
//controllo se tasti premuti (senza debouncing)
void checkImpulsi() {
   bool valoreSu = digitalRead(imp_su);
   bool valoreGiu = digitalRead(imp_giu);

   if (valoreSu == LOW) {
      SceltaImpulsi ++;
      delay(10);
      if (SceltaImpulsi > 3000) {   // premo su se valore 3000 resta a 3000
         SceltaImpulsi = 3000;
      }
   } else if (valoreGiu == LOW) {
      SceltaImpulsi --;
      delay(10);
      if (SceltaImpulsi < 1) {      // premo giù se valore 1 resta 1
         SceltaImpulsi = 1;
      }
   }
}
//
void attivaUscita() {
   // usando la manipolazione diretta dei pin è più rapido
   // il cambio di stato tra LOW e HIGH
   if (micros() - previousMicros >= intervallo) {
      previousMicros = micros();
      stato = !stato;
      if (stato) {
         PORTB = B11100000;                           // accendo il led
      } else {
         PORTB = B11000000;                           // spengo il led
      }
   }
}

[/code]

prego :smiley:

in effetti prima avevo fatto in un modo, poi ho reitrodotto il controllo del tempo, solo che non ho modificato il commento iniziale :slight_smile:

sicuramente può arrivare ben oltre i 300 Hz ti basta aumentare il limite nella if e portarlo a 30.000 avresti un impulso ogni 166,6 microsecondi...

Grazie! Perfetto! Tutto OK. Alle prossime :slight_smile: :slight_smile: :slight_smile:

Devo fare un appunto sulla funzione 'attivaUscita', si è andati a scrivere sulle porte per guadagnare tempo, ottima cosa, ma poi si accumula l'errore di jitter di micros (±4µs ad ogni giro più eventuali altri µs per l'esecuzione di altre istruzioni della loop).

Se ne era parlato qui.

Non ci si accorge perché le frequenze sono molto basse e l'errore probabilmente resta sotto la risoluzione del frequenzimetro (sicuramente di quella visiva dell'oscilloscopio).

L'errore aumenta con la frequenza, se a 10Hz è di circa 0.01%, a 1kHz è dell'1% e a 10kHz del 10%.

grazie Claudio... questa (discussione) mi era sfuggita :slight_smile:

quindi

   if (micros() - previousMicros >= intervallo) {
      previousMicros = micros();

deve diventare

   if (micros() - previousMicros >= intervallo) {
      previousMicros += intervallo;

se ho letto bene

Patrick_M:
deve diventare

   if (micros() - previousMicros >= intervallo) {

previousMicros += intervallo;

Esatto.

Succede solo una cosa... se nel programma avvengono dei ritardi maggiori di 'intervallo', come quando si variano i valori e si scrive su LCD, poi la condizione micros()-previousMicros>=intervallo risulta vera diverse volte di seguito, finché 'previousMicros' a forza di incrementi si "riporta al passo".

Per evitare questo (nel caso in cui dia fastidio, e qui potrebbe darlo generando alcuni periodi a frequenza ultrasonica) basta reimpostare previousMicros=micros() alla fine di ogni aggiornamento LCD.

si certo per togliere ritardi imposti dall'lcd...

se ho capito bene le esigenze dellOP la frequenza non dovrebbe essere superiore ai 200 - 300 Hz quindi non penso che sia necessario, oltretutto immagino che una volta stabilita una frequenza di lavoro questa non venga variata ulteriormente quindi l'lcd non viene più aggiornato

Patrick_M:
la frequenza non dovrebbe essere superiore ai 200 - 300 Hz quindi non penso che sia necessario

Forse no, ma visto che pilota bobine mi domandavo se brevi periodi a 20..30kHz durante i cambiamenti di frequenza non possano creare qualche problema a livello hardware.

Ho utilizzato il programma per circa un giorno intero, lasciandolo oscillare a 400 Hz e sia sull'oscilloscopio che sul frequenzimentro non si notano slittamenti di frequenza. Ma, è possibile sfruttare la stessa scheda per prelevare da un altro pin un segnale con frequenza diversa mentre l'attuale si mantiene così preciso? :slight_smile: Forse ancora non mi sto rendendo conto delle gradi potenzialità di questi microcontrollori associate ad una conoscenza approfondita degli stessi. :slight_smile: :slight_smile: :slight_smile:

si certo fai un ciclo di aggiornamento parallelo al primo su un altro pin e questi lavoreranno in modo indipendente... sempre con le precisioni e tolleranze ammesse dalla scheda

Ho fatto un duplicato di tutto, solo che ho cercato di prelevare il segnale dal PIN 8,(PORTB = B11000001) ma purtroppo non da nulla; se imposto il pin 13 anche nella seconda copia (attivaUscitaf PORTB = B11000001) il segnale viene pilotato dall’altra coppia di pulsanti in 0 e 1, ed esce soltanto dal pin 13 :confused: che succede? in ogni caso rimane perfettamente stabile.

[code]
/*
 *  non mi serve misurare il tempo che passa
 *  uso il risultato del calcolo 5.000.000/SceltaImpulsi per effettuare il
 *  ciclo HIGH e LOW del pin 13
 *  Se il valore di SceltaImpulsi cambia scrivo su LCD il nuovo valore
 *  altrimenti non aggiorno inutilmente l'LCD
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27

//****DICHIARAZIONE FREQUENZA******
byte freq_giu = 0;       // Pin Incremento frequenza
byte freq_su = 1;        // Pin Decremento frequenza
bool statof = false;

long intervallof = 0;       // imposta il valore dei microsecondi a 0
long SceltaFrequenza = 1;    // imposta il contatore della frequenza a 1
long oldFrequenza = 0;

unsigned long previousMicrosf = 0;


//****DICHIARAZIONE IMPULSI******
byte imp_giu = 4;       // Pin Incremento impulsi
byte imp_su = 7;        // Pin Decremento impulsi

bool stato = false;

long intervallo = 0;       // imposta il valore dei microsecondi a 0
long SceltaImpulsi = 1;    // imposta il contatore degli impulsi a 1
long oldImpulsi = 0;

unsigned long previousMicros = 0;


void setup() {
   pinMode(imp_su, INPUT_PULLUP);   //imposta il pulsante "Su" sfruttando la resistenza interna di Pullup
   pinMode(imp_giu, INPUT_PULLUP);  //imposta il pulsante "Giu" sfruttando la resistenza interna di Pullup
   pinMode(freq_su, INPUT_PULLUP);   //imposta il pulsante "Su" sfruttando la resistenza interna di Pullup
   pinMode(freq_giu, INPUT_PULLUP);  //imposta il pulsante "Giu" sfruttando la resistenza interna di Pullup
     lcd.init();                      // inizializza il display LCD
   lcd.backlight();                 // accende la luce dell'Lcd
}

void loop() {
   //**********LETTURA DEI PULSANTI IMPULSI*************
   checkImpulsi();                              // verifico se tasti premuti
   if (SceltaImpulsi != oldImpulsi) {           // se il valore attuale è diverso
      intervallo = (5000000 / SceltaImpulsi);   // da quello salvato, ricalcolo
      lcd.setCursor(0, 1);                      // stampo una volta su lcd
     
     lcd.print(SceltaImpulsi/10 ); 
     previousMicros=micros();
      oldImpulsi = SceltaImpulsi;               // memorizzo nuovo valore
   }
   attivaUscita();                              //attivo uscita


{
   //**********LETTURA DEI PULSANTI FREQUENZA*************
   checkFrequenza();                              // verifico se tasti premuti
   if (SceltaFrequenza != oldFrequenza) {           // se il valore attuale è diverso
      intervallof = (5000000 / SceltaFrequenza);   // da quello salvato, ricalcolo
      lcd.setCursor(0, 0);                      // stampo una volta su lcd
      lcd.print(SceltaFrequenza/10 ); 
     previousMicrosf=micros();
      oldFrequenza = SceltaFrequenza;               // memorizzo nuovo valore
   }
   attivaUscitaf();                              //attivo uscita
}
}


//controllo se tasti premuti Impulsi (senza debouncing)
void checkImpulsi() {
   bool valoreSu = digitalRead(imp_su);
   bool valoreGiu = digitalRead(imp_giu);

   if (valoreSu == LOW) {
      SceltaImpulsi ++;
      delay(10);
      if (SceltaImpulsi > 3000) {   // premo su se valore 3000 resta a 3000
         SceltaImpulsi = 3000;
      }
   } else if (valoreGiu == LOW) {
      SceltaImpulsi --;
      delay(10);
      if (SceltaImpulsi < 1) {      // premo giù se valore 1 resta 1
         SceltaImpulsi = 1;
      }
   }
}
//controllo se tasti premuti Frequenza (senza debouncing)
void checkFrequenza() {
   bool valorefSu = digitalRead(freq_su);
   bool valorefGiu = digitalRead(freq_giu);

   if (valorefSu == LOW) {
      SceltaFrequenza ++;
      delay(10);
      if (SceltaFrequenza > 3000) {   // premo su se valore 3000 resta a 3000
         SceltaFrequenza = 3000;
      }
   } else if (valorefGiu == LOW) {
      SceltaFrequenza --;
      delay(10);
      if (SceltaFrequenza < 1) {      // premo giù se valore 1 resta 1
         SceltaFrequenza = 1;
      }
   }
}


//
void attivaUscita() {
   // usando la manipolazione diretta dei pin è più rapido
   // il cambio di stato tra LOW e HIGH
   if (micros() - previousMicros >= intervallo) {
      previousMicros += intervallo;
      stato = !stato;
      if (stato) {
         PORTB = B11100000;                           // accendo il led
      } else {
         PORTB = B11000000;                           // spengo il led
      }
   }
}

void attivaUscitaf() {
   // usando la manipolazione diretta dei pin è più rapido
   // il cambio di stato tra LOW e HIGH
   if (micros() - previousMicrosf >= intervallof) {
      previousMicrosf += intervallof;
      statof = !statof;
      if (statof) {
         PORTB = B11000001;                           // accendo il led
      } else {
         PORTB = B11000000;                           // spengo il led
      }
   }
}

[/code]

immaginavo che sarebbe successo :smiley:

ovviamente non puoi più fare una assegnazione diretta come portb=b11100000 perchè così facento imposti anche il pin 8 a zero
devi fare in modo di impostare il pin (bit) che ti serve ma senza cambiare lo stato degli altri perciò devi utilizzare gli operatori and e or per eseguire le operazioni

quindi se PORTB vale ad un certo istante 11000001 e vuoi alzare il pin 13 devi variare solo il bit 6 e lo fai con

PORTB=PORTB | B00100000

11000001 (|)or    <---valore iniziale
00100000  =
--------------
11100001    con or dove c'è almeno un 1 il risultato è 1

al contrario se vuoi azzerare lo stesso bit devi fare un and

PORTB=PORTB & B11011111

11100001 (&) and         <------- valore iniziale
11011111  =
--------------
11000001   con and solo dove entrambi sono 1 resta 1

ovviamente per il pin 8 farai or e and con l’uno e lo zero nel primo bit

Bellissimo :slight_smile: :slight_smile: :slight_smile: sembrano due oscillatori completamente indipendenti!!! Complimenti!