Digital Read molto lento nel rilevare il cambio di stato

Buona sera a tutti.
Utilizzo un Arduino mega R3.

questo è il codice in questione

// testing motors
// 
 int motor1Pin;    // H-bridge leg 1 (pin 2, 1A)
 int motor2Pin;    // H-bridge leg 2 (pin 7, 2A)
 int enablePin;    // H-bridge enable pin
 int fineCorsa;    // Fine Corsa 
 
void setup() {
  Serial.begin(9600); // open serial port to receive data
}

//Nome: attivaPin
//ToDo: Attiva i pin relativi al cassetto selezionato
void attivaPin(){
      digitalWrite(enablePin, HIGH);  // accende il motore
      digitalWrite(motor1Pin, HIGH);   // set leg 1 of the H-bridge low
      delay(4000);
      digitalWrite(enablePin, LOW);
      digitalWrite(motor1Pin, LOW);     
         
}

void setPin (int pin){
if (pin == 1){
  motor1Pin = pin;
  motor2Pin = pin + 1;
  enablePin = pin + 2;
  fineCorsa = pin + 3;
  pinMode(motor1Pin, OUTPUT);
  pinMode(motor2Pin, OUTPUT);
  pinMode(enablePin, OUTPUT);
  pinMode(fineCorsa, INPUT);
}
else{
   motor1Pin = (pin * 4) - 3;
   motor2Pin = (pin * 4) - 2;
   enablePin = (pin * 4) - 1;
   fineCorsa = (pin * 4);
   pinMode(motor1Pin, OUTPUT);
   pinMode(motor2Pin, OUTPUT);
   pinMode(enablePin, OUTPUT);
   pinMode(fineCorsa, INPUT);
 }
}

int verificaFineCorsa(int inputPin){
    delay(1300);
    int val;
    val = digitalRead(inputPin);
    if (val == HIGH){
      Serial.println("Tutti i fine corsa sono chiusi");
      return 0;
    }
    else{
      Serial.println("FineCorsa Aperto");
      return 1;
    }
} 
 
 
void gestioneElettropermanente(int incomingByte){
  setPin(incomingByte);
  if (verificaFineCorsa(fineCorsa) == 0)
      attivaPin();
    
}

 
void loop() {
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    int incomingByte = Serial.read() - '0';
    gestioneElettropermanente(incomingByte);
    // if it's a capital H (ASCII 72), turn on the LED:
  }
}

Il problema è che il digitalRead(pin) è veramente lento, impiega anche più di 8 secondi a rilevare il cambio di stato, come mai??? come posso risolvere?
avete suggerimenti?

Grazie a tutti in anticipo

Non ho analizzato il codice, ci sono persone molto più preparate di me che lo faranno meglio.
Voglio solo dirti che il modo migliore, a mio modesto parere, per intercettare in tempo reale il cambio di stato di un pin sia quello di usare un interrupt.

Oddio mi apri un mondo nuovo...
Un interrupt fisico (quindi un interruttore, ipotesi da scartare) o un interrupt software?
Arduino permette di utilizzare la logica degli interrupt?? :open_mouth:

Il comando digitalRead di suo è velocissimo (es. quasi 100KHz), nel codice hai dei delay() che fermano il micro per molto tempo..
usa gli interrupt (software) o rivedi il codice

Ciao

nienteposta:
Oddio mi apri un mondo nuovo...
Un interrupt fisico (quindi un interruttore, ipotesi da scartare) o un interrupt software?
Arduino permette di utilizzare la logica degli interrupt?? :open_mouth:

Certamente, esistono alcuni pin preposti direttamente dal micro; la libreria pinChangeInt ti permette di scegliere qualsiasi altro pin ed assegnargli questa funzione. Poi puoi intercettare eventi come il change, il falling ed il rising

flz47655:
nel codice hai dei delay() che fermano il micro per molto tempo..

E' questo il problema, se metti un delay equivale a mettere uno stop. ll micro si ferma completamente e non esegue altro. Quindi la tua funzione sta ferma 1,3 secondi e poi legge lo stato dei pin.

In sostituzione del delay usa invece millis(), trovi l'esempio di uso nell'ide di Arduino, la logica si complica un poco ma non c'è altra soluzione.
Ciao.

allora la prima lettura scommetto che avviene dopo 1.3 secondi e la seconda dopo 5.3 secondi :stuck_out_tongue:

arduino non è multitasking, una funzione non è un task.

ci sono 2 modi per creare un "multitask" (anche se non sarebbe corretto) su arduino:

  • l'uso della funzione millis()
  • l'uso di un timer che allo scadere scatena un interrupt che va a chiamare una funzione bloccando il processo in atto.

se pensi che la seconda sia più complicata io direi di no in quanto esiste il "leOS":
http://arduino.cc/forum/index.php/topic,111732.0.html
però non credo sia il tuo caso in quanto tu vai a richiamare determinate funzioni nel codice (insomma non vanno a eseguirsi ognuna per conto suo e poi leggi magari una variabile globale apposita ma proprio tu le chiami interrogando il risultato della funzione).

il primo metodo è il più usato, in pratica il comando millis() restituisce i millisecondi da quando il programma è partito.
è preciso in quanto si appoggia al timer0 del microcontrollore e quindi ha risoluzione di 16MHz, con dei controlli if su variabili unsigned long memorizzate puoi arrivare a oltre 50 anni di utilizzo senza che millis() vada in overflow :wink:

Ciao superlol, il timer ha risoluzione di 16MHZ??? :astonished:

Allora a questa ora sono più fresco di te (ma fra poco crollo), rettifico io. :stuck_out_tongue:

Il timer0 ha un contatore ad 8 bit e quindi ha risoluzione di 8 bit.

il timer di millis() io ricordo che va in overflow molto prima di 50 anni e potrebbe essere un problema se non si prende precauzione, ma comunque si tratta di mesi prima che vada in owerflow.

Ciao.

MauroTec:
Ciao superlol, il timer ha risoluzione di 16MHZ??? :astonished:

Allora a questa ora sono più fresco di te (ma fra poco crollo), rettifico io. :stuck_out_tongue:

Il timer0 ha un contatore ad 8 bit e quindi ha risoluzione di 8 bit.

il timer di millis() io ricordo che va in overflow molto prima di 50 anni e potrebbe essere un problema se non si prende precauzione, ma comunque si tratta di mesi prima che vada in owerflow.

Ciao.

Ah, annamo bbene ...
Se un timer a 8 bit ci mette qualche mese ad andare in overflow stiamo freschi!
L'overflow viene generato durante il passaggio del contatore del timer stesso da 255(8 bit) a 0 e questo avviene esattamente (prescaler a parte) con un clock a 16mhz 15625 volte al secondo.
Facciamo che è la funzione millis che restituendo un u long si azzera ogni 4,294,967,295 millisecondi equivalenti a circa 49 giorni 16 ore e spicci, ma ciò non toglie che poi riparte correttamente da zero ed è pertanto cmq utilizzabile anche in seguito.

Non bisogna scrivere dopo le 24:00 :stuck_out_tongue_closed_eyes:

a parte il dealy, ma nessun ha notato che nel loop()

if (Serial.available() > 0) {
balbla
}

ovvero, esegue i controllo SE E SOLO SE ci sono dati nella seriale?

Non ho guardato il codice. Hai fatto bene a farlo notare.