Conta metri up/down

Salve,
sto sviluppando un contametri che deve controllare il numero di giri che compie una puleggia.
Il problema è che devo contare sia incrementi che decrementi.
Quindi uso due sensori induttivi per verificare il senso di rotazione.
Il problema è che via software non riesco a trovare un modo che mi legga il senso.
Questo è come avevo pensato di impostare il codice ma non va.
Qualche anima pia che ha suggerimenti?

void contaUP()
{
 UP =true;
 a = 1;
 b=0;
}
void contaDOWN()
{
 DOWN = true;
 a = 0;
 b=1;
}

void loop() {

if (UP == true && DOWN == true){
 if (b == 1){
   count--;
 }
 if (a == 1){
   count++;
 }
UP = false; 
DOWN = false;  
a = 0;    
b=0;
Serial.println(count);
}

 if(digitalRead(_up)==HIGH){contaUP();  
 //Serial.println("UP");  
 }  
 if(digitalRead(_down)==HIGH){contaDOWN();  
 //Serial.println("DOWN");
 }
 

delay (10);
}

Dopo che avrai incluso il codice tra i giusti tag
Cerca encoder a quadratura

>skizz0to: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More → Modify che si trova in basso a destra del tuo post) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati. Grazie.

Guglielmo

Se devi contare solo il numero dei giri che fa (e quindi la precisione non e' critica), puoi usare un paio di reed o di sensori hall messi uno di fianco all'altro a pochi mm di distanza, ed uno o piu magnetini (piu di uno, migliore precisione, a condizione che siano posizionati in modo che un magnete possa far chiudere entrambi i reed, ma non faccia mai chiudere un reed quando l'altro e' tenuto chiuso da UN'ALTRO magnete) posizionati sulla puleggia (in che modo, dipende dalla puleggia) ... poi pero' dipende dalla velocita' a cui deve girare ... se e' bassa, ti basta usare due ingressi e delle digitalRead, se la velocita' e' maggiore, e' meglio usare un'interrupt per l'ingresso che conta ...

Il principio e' semplice ... se usi gli ingressi o l'interrupt, poco cambia ... perche' se i due reed sono uno di fianco all'altro, la puleggia girando chiudera' sempre uno prima dell'altro, se gira in un senso chiudera' sempre il primo prima del secondo, e viceversa ... per cui, quando leggi il secondo, o l'interrupt collegato al secondo scatta, controlli il primo, se e' chiuso stai girando in un senso e sommi, se e' aperto stai girando nell'altro e sottrai ... :wink:

la soluzione dei due sensori vicini l’avevo scartata perchè può portare a dei falsi positivi.
Mi spiego la puleggia può anche essere in una condizione di oscillazione, in questo caso potrebbe esserci il rischio che un reed resta sempre attivo e l’altro chiude/apre facendo sballare il conteggio.
La velocità di rotazione è comunque sempre bassa e per questo al momento non avevo usato interrupt.
Per l’encoder a quadratura non è una soluzione percorribile poichè la puleggia non può montare sistemi troppo complessi di lettura, il massimo possibile è montarci magneti/pezzi metallici per sensori esterni
Chiedo scusa mi ero dimenticato i tag per il codice, ho provveduto.

Ok, così hai scartato l'unica soluzione possibile. mi spiego, due micro che si sovrappongono fanno un encoder a quadratura
Quindi non abbiamo più soluzioni da proporti.
Non è vero, se non vai talmente veloce da rendere necessario l'uso di interrupt vedo una soluzione
Aspetti un HIGH su un micro qualsiasi,
Allo HIGH NON fai un conteggio, ma passi ad aspettare un HIGH sull'altro micro
Solo li conti, e ricominci ad aspettare da tutti e due
Tieni i micro belli distanti. Garantito non in sovrapposizione
Però potrebbe sbagliare il conto al Primo giro dopo una inversione
Che precisione ti serve?
Edit
Visto adesso mia collega Bionda, non inganniere, che fa avvolgimenti, la sua bobinatrice quando la ferma per fare le prese intermedie ha la puleggia che oscilla. Anche tu stessa cosa?

La velocità è bassa si parla di un giro/sec.
e la risoluzione è un metro/giro
Così stavo facendo aspetto le due letture HIGH e poi incremento.

Il problema è che usando digitalread nel loop mi fa casino.

void contaUP()
{
  UP =true;
  a = 1;
  b=0;
}
void contaDOWN()
{
  DOWN = true;
  a = 0;
  b=1;
}

void loop() {

if (UP == true && DOWN == true){
  if (b == 1){
    count--;
  }
  if (a == 1){
    count++;
  }
UP = false; 
DOWN = false;  
a = 0;    
b=0;
Serial.println(count);
}
if(digitalRead(_up)==HIGH){
contaUP();  
  //Serial.println("UP");  
  }  
  if(digitalRead(_down)==HIGH){
contaDOWN();  
  //Serial.println("DOWN");
  }

Forse sono io che sbaglio qualcosa?

Da Android mica riesco a scrivere codice
Porta pazienza

Aspetta, cosa non chiara:
Quando oscilla, più o meno con che frequenza oscilla?
Dico questo perché se fa un giro al secondo significa 36 gradi ogni decimo
36 gradi sono un sacco, oscillera' magari anche meno, ma oscillare di una 30ina di gradi sono 5 oscillazioni al secondo, basta fare un debounce da 300ms e siamo a posto, sbaglio?

L'oscillazione può essere assolutamente casuale, il debounce potrebbe essere funzionale ma non garantirebbe il 100% di sicurezza anche se 300 ms potrebbero essere un buon compromesso. Al massimo potrei perdere un conteggio se la puleggia torna indietro appena passato il sensore

Cmq grazie

Tre sensori, e si esclude ogni errore

Chiamiamoli p per più, m per meno e c per centrale
Io monti in sequenza pcm, senza alcuna sovrapposizione

Aspetti c
Dopo c aspetti quale dei due arriva prima
Arrivato uno ricomincia ad aspettare c

Butta giù un programma che vediamo

Standardoil mi ha preceduto, ma si, se hai problemi di oscillazione, tre sensori sono una delle poche opzioni (l'altra, la migliore, era montare un disco encoder con tanti passi per giro, ma se non puoi montare encoder sulla puleggia, siamo gia a posto da questo lato)

Potrebbero benissimo essere anche tre reed attaccati uno all'altro (in modo che con il magnete al centro della posizione dei reed siano chiusi tutti) e chiusi in rapida sequenza dal magnete ... perche' per contare il giro, sempre la stessa sequenza "completa" servirebbe (chiuso 1, chiuso 2, chiuso 3, aperto 1, aperto 2, aperto 3, o viceversa se srotoli), quindi anche se oscilla con il magnete che chiude uno o piu reed non in sequenza corretta, non verrebbero conteggiati ... niente sequenza completa e corretta, niente conteggio ...

Mmh interessante,
ho fatto qualche prova di codice con tre sensori però avevo valutato la cosa singolarmente. (In questo modo non risolvevo il problema delle oscillazioni).
Controllando la sequenza di chiusura invece mi sembra meglio.
Faccio qualche prova e nel caso vi disturbo di nuovo.
Grazie per adesso :slight_smile:

Rieccomi, ragionando un poco credo che la cosa si possa anche fare usando solo due reed.
Di seguito il codice che ho buttato giù per fare qualche prova.
Avevo pensato di usare gli interrupts sfruttando il mode RISING però ho il richiamo alla funzione sia nel momento della chiusura del reed che all’apertura.

int count=0;
volatile boolean UP = false; 
volatile boolean DOWN = false;

volatile int a =0;
volatile int b = 0;

/* sensor part */

// TIME VARIABLES

// TIME VARIABLES

void setup() {
attachInterrupt(digitalPinToInterrupt(2), contaUP, RISING);
attachInterrupt(digitalPinToInterrupt(3), contaDOWN, RISING);

pinMode(_up, INPUT);
pinMode(_down, INPUT);
pinMode(_up, INPUT_PULLUP);
pinMode(_down, INPUT_PULLUP);
pinMode(_conto,INPUT);
pinMode(_conto,INPUT_PULLUP);

digitalWrite(_up,LOW);
digitalWrite(_down,LOW);
Serial.begin(115200);


Serial.println("start");
delay(100); 
}


void contaUP()
{
 UP =true;
 a = millis();
Serial.println("contaUP");
}
void contaDOWN()
{
 DOWN = true;
 b = millis();
Serial.println("contaDOWN");
}

void loop() {
 noInterrupts();
if(UP==HIGH && DOWN == HIGH) {
  if (a - b > 0) {
    count++;
    //Serial.println(a);
  } else if (a - b < 0){
    count--;
      //Serial.println(b);
  }
  Serial.println(count);
  UP=false;
  DOWN=false;
  //delay(500);
}

delay (10);
interrupts();
}

Sarò cotto ma non capisco dove sbaglio.Ciao

Mi sembra che ti sia un po' confuso, in particolare selle pinmode, decidi se usi il sensore diretto o negato, fai la connessione alle pullup esterne se serve e via andare

prova una cosa del genere

int count;
bool prenotato;
const byte a = 2;
const byte b = 3;
const byte c = 4;
// mettere i numeri giusti dei sensori

#define A (digitalRead(a))
// casomai mettere ! davanti per sensori negati
#define B (digitalRead(b))
// casomai mettere ! davanti per sensori negati
#define C (digitalRead(c))
// casomai mettere ! davanti per sensori negati


void setup()
{
    pinMode(a, INPUT);
    pinMode(b, INPUT);
    pinMode(c, INPUT);
    // mettere casomai INPUT_PULLUP
    // apri le seriali, e tutte le altre cose che devi fare
}
void loop()
{
    if (prenotato)
    {
        if (A)
        {
            count++;
            prenotato = 0;
        }

        if (B)
        {
            count--;
            prenotato = 0;
        }
    }
    else
    {
        if (C)
        {
            prenotato = 1;
        }
    }
}

Naturalmente non ci devono essere sovrapposizioni tra i sensori, nemmeno nello lo spazio di indecisione a causa della puleggia che pendola

Grazie per il contributo ma come hai impostato i loop, il contatore non incrementa una sola volta a causa del tempo che ci può mettere a passare sopra i magneti. Nel caso poi si dovesse fermare proprio sul magnete sarebbe anche peggio.
Credo che sia migliore la strada dell'interrupt con uso del mode RISING.
Grazie lo stesso

Hai provato?

Si nel momento in cui i contatti sono chiusi la variabile count varia in continuo

Vabbe' Buon viaggio

Allora giusto per chiudere, ho provato con gli interrupt in RISING mode ma mi facevano casino con la gestione del debounce.
Allora ho sfruttato il suggerimento di Etemenanki e credo di avere risolto così usando solo due sensori e sembra a posto:

volatile unsigned int count = 0;
volatile int debounceTime = 50;

void loop()
{
  test();
  test1();
}
void setup()
{
  Serial.begin(115200);
 pinMode(2, INPUT);
 pinMode(3, INPUT);
 pinMode(2, INPUT_PULLUP);
 pinMode(3, INPUT_PULLUP);
}

void test () { // 
  static unsigned long previousStateChangeMillis = 0;
  static bool previousPinState = HIGH;

  bool pinState = digitalRead(2);
  if (pinState != previousPinState) {    
  bool pinState1 = digitalRead(3);
  if (pinState == HIGH && pinState1 ==HIGH) { 
      if ((millis() - previousStateChangeMillis) > debounceTime) { // debounce
        count++;
        Serial.println(count);
      }
    }
    previousPinState = pinState;
    previousStateChangeMillis = millis();
  }
}
void test1 () {
  static unsigned long previousStateChangeMillis = 0;
  static bool previousPinState = HIGH;

  bool pinState = digitalRead(3);
  if (pinState != previousPinState) { 
    bool pinState1 = digitalRead(2);
    if (pinState == HIGH && pinState1 ==HIGH) { 
      if ((millis() - previousStateChangeMillis) > debounceTime) { // debounce
        count--;
        Serial.println(count);
      }
    }
    previousPinState = pinState;
    previousStateChangeMillis = millis();
  }
}

Grazie