Errore di codice

Salve!
Ho preparato un piccolo programma di cui allego il codice:

#include <EEPROM.h>;
int dir;
int inv;

void setup(){
  pinMode(5, INPUT);

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}

void loop(){
  inv = digitalRead(5);
  
  if(inv == LOW){                 //marcia
            
      dir = EEPROM.read(0);       
      if(dir == 0){               //marcia a
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);           
      digitalWrite(4, LOW);
      digitalWrite(8, HIGH);
      digitalWrite(9, LOW);}
      else{                       //marcia b
      digitalWrite(2, HIGH);    
      digitalWrite(3, LOW);            
      digitalWrite(4, HIGH);
      digitalWrite(8, LOW);
      digitalWrite(9, HIGH);}
        }

  else{
       digitalWrite(2, LOW);       //fermo motore
       digitalWrite(3, LOW);       //fermo motore
       digitalWrite(4, LOW);       //fermo motore
       digitalWrite(8, LOW);       //spente luci
       digitalWrite(9, LOW);       //spente luci         
       
       if(dir == 0){          //cambio direzione
       dir = dir+1;
       EEPROM.write(0, dir);  
       delay(3000);           //aspetto
       }
       else{
       dir = dir-1;
       EEPROM.write(0, dir);             
       delay(3000);}
      }}

Dovrebbe permettere l’inversione di marcia di un motore DC controllato da un Ponte ad H e sincronizzare l’accensione delle luci con il senso di marcia.

La variabile “dir”, memorizzata nell’EEPROM per conservarla anche in caso di mancanza di corrente, stabilisce la direzione e la variabile “inv”, prodotta da un impulso di sovracorrente ridotto da un diodo zener alla tensione di 5V e stabilizzato da un condensatore, ne effettua il cambiamento.

Quando “inv” è “LOW” avviene la marcia, quando è “HIGH” avviene l’inversione.

Durante l’operazione di inversione della polarità il motore e le luci sono disattivate.

L’impulso di inversione è un impulso pulito, della durata di circa un secondo ed il delay di 3000 ms serve per stabilizzarlo e separarlo dal resto.

In questa versione funziona tutto ma non avviene l’inversione, cioè “dir” rimane sempre = 0 o non viene memorizzata.

Con l’emulatore Autodesk funziona perfettamente invece su di un Arduino Pro Micro no.

Mi è stata suggerita l’ipotesi di cambiare il tipo di variabile da “int” a “byte” ma la situazione è peggiorata in quanto non funziona più nulla.
Qualcuno mi può auitare?
Claudio Dionisi

... dato che hai aperto un nuovo thread, che mi sembra meglio dettagliato, ho provveduto ad eliminare il vecchio ed a lasciare solo questo più pulito.

Guglielmo

Da una veloce scorsa vedo che hai dichiarato delle variabili di tipo "int" (quindi a 16 bit), ma poi le vai ad utilizzare le due chiamate EEPROM.read() ed EEPROM.write() che invece lavorano con un SINGOLO byte. Ovviamente questo NON da alcun problema se i valori che tratti sono tra 0 e 255 (-128 .. +127), ma se i valori vanno fuori di questo intervallo avrai un troncamento.

Quindi, o ti bastano i valori di un byte e allora perché sprechi spazio dichiarando le variabili che salvi in EEPROM come int, o ti servono effettivamente valori più grandi ed allora è errato il metodo per salvarli/recuperarli.

Guglielmo

P.S.: Se nel IDE usi Tools -> Auto format ... il codice verrà sistemato in un modo più ordinato e sarà più facile seguire le varie indentature :wink:

... aggiungo, se bastano valoro tra -128 e +127 allora si può usare il tipo "char" che è appunto un byte con segno.

Guglielmo

Grazie DOCSAVAGE per l'interesse al mio problema!

Hai indovinato, si tratta di effettuare l'inversione di marcia di una locomotiva del sistema Marklin, che funziona appunto con un impulso di sovratensione; vorrei emulare il classico doppio relais passo passo con un Arduino Pro Micro, scelgo questa versione per le dimensioni che mi permettono di inserire la scheda all'interno della loco.

Ho segnato "dir" come variabile booleana ed impostando manualmente dir = 0 o dir = 1 tutto funziona, ma quando vado a scrivere in memoria dir non me la scrive.

dir = EEPROM.read la devo lasciare nel loop altrimenti non viene cambiata se l'inversione avviene in marcia.

Con la tua versione mantenendo delay = 3000 non funziona invece togliendo delay si provoca un curioso effetto albero di Natale: oscilla in continuazione tra marcia a e marcia b.

Cordiali saluti
Claudio Dionisi

Salve Docsavage!
Ho modificato il tuo programma in questo modo:

#include <EEPROM.h>;
boolean dir;

void setup() {
  pinMode(5, INPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}

void loop() {
  dir = EEPROM.read(0);
  
  if (!digitalRead(5)) {               //marcia


        if (dir) {             //marcia a
        digitalWrite(2, HIGH);
        digitalWrite(3, HIGH);
        digitalWrite(4, LOW);
        digitalWrite(8, HIGH);
        digitalWrite(9, LOW);
        }
        else {                      //marcia b
        digitalWrite(2, HIGH);
        digitalWrite(3, LOW);
        digitalWrite(4, HIGH);
        digitalWrite(8, LOW);
        digitalWrite(9, HIGH);
        }
  }

  else {
    digitalWrite(2, LOW);       //fermo motore
    digitalWrite(3, LOW);       //fermo motore
    digitalWrite(4, LOW);       //fermo motore
    digitalWrite(8, LOW);       //spente luci
    digitalWrite(9, LOW);       //spente luci

    EEPROM.write(0, dir = !dir);

  }
}

ed ora funziona abbastanza bene.
L’ultimo problema consiste nel fatto che l’impulso deve essere brevissimo, se invece inserisco un delay dopo EEPREM.write, per allungare il tempo dell’impulso, il programma non funziona e tutte le uscite rimangono sempre LOW.

Anzi mi correggo:
l'inversione funziona ma non viene memorizzata e quando termina l'alimentazione "dir" torna a zero.

Quindi ci sono due problemi:

  1. Come evitare il rimbalzo senza fermare l'esecuzione;
  2. Come memorizzare dir nella EEPROM in maniera che rimanga il valore anche senza alimentazione.

Cordiali saluti
Claudio Dionisi

Salve DOCSAVAGE!

Tutto risolto!

Ho semplicemente diminuito la resistenza polarizzatrice sul pin di input; in letteratura viene indicato un valore di 2 / 5 M Ohm; ora con una di 460 Ohm, al limite per corrente e potenza, il pin si carica a 4,65 V e si scarica molto rapidamente e tutto funziona a perfezione.

Cordiali saluti

Claudio Dionisi