"IF" tra segnale analogico e digitale

Ciao a tutti,
come dicevo nel topic di presentazione, sono Claudio e vivo in provincia di Cuneo. Sono approdato qui perchè ormai sono allo stremo delle forze.

Devo comandare un’uscita digitale, leggendo un segnale analogico.
Quando il segnale analogico torna sotto la soglia stabilita, deve spegnere l’uscita con un breve delay.
Per complicare tutto, su questo pc non riesco a far girare il “Monitor seriale”…sembrerebbe che ci sia un bug nella versione 1.0.1 con java che bho… insomma se apro il monito seriale, si pianta tutto.

Comunque, le due strade intraprese senza successo sono:

 if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); }  //se il valore analogico è > di 50, metto a 1 l'output cmd_tx 
 if (rx_val < 50) {                                            // se il valore analogico è < di 50
              if (cmd_tx == HIGH) {                        // e se cmd_tx è a 1
                  delay(3000);                                // attendo 3 secondi
                  digitalWrite(cmd_tx, LOW);           // e scrivo a zero cmd_tx
                  }
  }

l’altra strada provata è:

     if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); } //se il valore analogico è > di 50, metto a 1 l'output cmd_tx
     if ((rx_val < 50) && digitalRead(cmd_tx) == HIGH) {  //se il valore analogico è < di 50, e cmd_tx è a 1 
        delay(3000);                                                     //attendo 3 secondi
        digitalWrite(cmd_tx, LOW);                                //scrivo a zero cmd_tx
}

in entrambi i casi, quando rx_val supera 50, l’out cmd_tx va a 1, senza tornare però mai a zero quando rx_val scende sotto 50.
Dove stò sbagliando?

Grazie
Claudio

Fai una prova con le due righe semplici, che ti serve controllare che sia HIGH?

if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); }
if (rx_val < 50) { digitalWrite(cmd_tx, LOW); }

e vedi che succede

Ciao

Apparentemente le righe dovrebbero fare quello che ti aspetti, le info che fornisci sono insufficienti per un aiuto mirato.
Mi sorge il dubbio che non ci vai mai sotto il 50, ed è difficile arrivarci (ad esempio) con un sensore tipo fotoresistore quando i valori analogici vanno da 0-1023.

Comunque se sostieni che la 1.0.1 ha un bug, mi aspetto che lo hai provato sulla 1.0 o versione inferiore con successo.
Non dici il sistema operativo che usi
sensore che usi
lo sketch copiato è un po' poco
lo schema che usi ? sicuro sia corretto?
Hai provato ad alzare le soglie?

Non hai modo di saperlo senza una visualizzazione a video. Devi far funzionare il serial monitor per osservare i valori restituiti dalla porta analog almeno come debug poi agisci di conseguenza

ciao

prova questo tipo di codice, e occhio cosa applichi, massimo 5 volt e massimo 40mA, e cmq hai un errore di quantizzazione non indifferente la precisione e di 10 bit... cosa stai facendo di bello li in zona 1?

funziona perfettamente…

ho quindi aggiunto il delay:

if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); }
if (rx_val < 50) { 
    delay(3000); 
    digitalWrite(cmd_tx, LOW); 
     }

e funziona anche così, tuttavia se immediatamente dopo che cmd_tx è passato in low, porto nuovamente rx_val > 50, cmd_tx per tornare high ci mette un pò…diciamo 3000ms

pablos:
Ciao

Apparentemente le righe dovrebbero fare quello che ti aspetti, le info che fornisci sono insufficienti per un aiuto mirato.
Mi sorge il dubbio che non ci vai mai sotto il 50, ed è difficile arrivarci (ad esempio) con un sensore tipo fotoresistore quando i valori analogici vanno da 0-1023.

Comunque se sostieni che la 1.0.1 ha un bug, mi aspetto che lo hai provato sulla 1.0 o versione inferiore con successo.
Non dici il sistema operativo che usi
sensore che usi
lo sketch copiato è un po' poco
lo schema che usi ? sicuro sia corretto?
Hai provato ad alzare le soglie?

Non hai modo di saperlo senza una visualizzazione a video. Devi far funzionare il serial monitor per osservare i valori restituiti dalla porta analog almeno come debug poi agisci di conseguenza

ciao

che sia un bug, l'ho letto sul forum...ma ora non ho il link sottomano, sembrerebbe l'interazione del serial monitor con java(?), e l'errore era lo stesso che appariva a me, tuttavia la soluzione era disponibile solo per linux. Purtroppo io uso xp.
Di certo, ho un gabinetto di netbook con a bordo la stessa versione 1.0.1, e li funziona senza problemi.

iz2rpn:
else - Arduino Reference

prova questo tipo di codice, e occhio cosa applichi, massimo 5 volt e massimo 40mA, e cmq hai un errore di quantizzazione non indifferente la precisione e di 10 bit... cosa stai facendo di bello li in zona 1?

ciao Pietro,
l'ingresso analogico lavora tra zero (circa) e 800mV, quindi in digitale con 50 sono assolutamente sia sopra che sotto la soglia.

comunque trattasi del core di un repeater che devo andare a rimettere su mercoledì, e devo ancora sistemare la coda e il secondo identificativo in cw.
Solo che le cose te le dicono come al solito a pezzi, ed ora sono un pò stretto con i tempi :blush:

ne riparliamo con calma la prossima volta, pensavo di implementare una libreria già esistente sul cw in modo che quello che scrivi lo ritrasmetta direttamente in cw senza smazzarsi km di codice, cmq poi ne parliamo mi trovi qui, oppure in radio fai un fischio e io alzo le mie antenne :wink:

notte

per il cw ho già tutto il codice pronto e funzionante se ti serve. Non lo inserisco qui per non creare confusione con il topic.
Ciao, a presto.

astru_bale:

 if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); }  //se il valore analogico è > di 50, metto a 1 l'output cmd_tx 

if (rx_val < 50) {                                            // se il valore analogico è < di 50
              if (cmd_tx == HIGH) {                        // e se cmd_tx è a 1
                  delay(3000);                                // attendo 3 secondi
                  digitalWrite(cmd_tx, LOW);           // e scrivo a zero cmd_tx
                  }
  }

“if (cmd_tx == HIGH)” qua confronti il numero del PIN con il livello HIGH e non se quel pin é HIGH o LOW.

astru_bale:

     if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); } //se il valore analogico è > di 50, metto a 1 l'output cmd_tx

if ((rx_val < 50) && digitalRead(cmd_tx) == HIGH) {  //se il valore analogico è < di 50, e cmd_tx è a 1
        delay(3000);                                                     //attendo 3 secondi
        digitalWrite(cmd_tx, LOW);                                //scrivo a zero cmd_tx
}

Questo dovrebbe funzionare.
Comunqe metterei una minima isteresi tra acceso e spento:
if (rx_val > 55) …
if ((rx_val < 45)…

Ciao Uwe

grazie per l’intervento Uwefed, purtroppo il risultato non cambia…

anche così se porto l’ingresso analogico a +4,9V (circa 1003 in digitale) cmd_tx va regolarmente HIGH perchè supero 50.
Quando porto il segnale analogico al livello basso di 32mV (circa 8 in digitale) cmd_tx rimane in HIGH, sia con il delay che senza.

Ovviamente ho provato a cambiare l’ingresso analogico, nel dubbio che fosse brasato…

Se invece scrivo:

     if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); } //se il valore analogico è > di 50, metto a 1 l'output cmd_tx
     if (rx_val < 50) {  //se il valore analogico è < di 50, e cmd_tx è a 1 
        digitalWrite(cmd_tx, LOW);                                //scrivo a zero cmd_tx
}

funziona perfettamente, quando alzo Ax cmd_tx va in HIGH, quando abbasso Ax, cmd_tx va LOW.
Se però aggiungo un delay:

     if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); } //se il valore analogico è > di 50, metto a 1 l'output cmd_tx
     if (rx_val < 50) {  //se il valore analogico è < di 50, e cmd_tx è a 1 
        delay(3000);                               //attendo 3 secondi
        digitalWrite(cmd_tx, LOW);                                //scrivo a zero cmd_tx
}

quando alzo Ax per poco circa un secondo non succede nulla, se lo tengo alto per 3 secondi cmd_tx va HIGH, per poi tornare LOW dopo 3 secondi come da istruzione quando Ax torna sotto il livello. E’ come se avessi il delay anche sulla prima istruzione.

…non so, sembra proprio che voglia fare cioè che vuole lui, e non quello che voglio io :frowning:

Dacci tutto il codice completo.
Ciao Uwe

eccolo:

int cmd_tx = 5;
int analogPin = 3; 
int rx_val = 0;


void setup()
{
  pinMode(cmd_tx, OUTPUT);

}

void loop()
{
    rx_val = analogRead(analogPin); 
    
    
    if (rx_val > 50) { digitalWrite(cmd_tx, HIGH); } //se il valore analogico è > di 50, metto a 1 l'output cmd_tx
    if ((rx_val < 50) && digitalRead(cmd_tx) == HIGH) {  //se il valore analogico è < di 50, e cmd_tx è a 1 
        delay(3000);                                                     //attendo 3 secondi
        digitalWrite(cmd_tx, LOW);                                //scrivo a zero cmd_tx
}

}

prova questo codice collegando l’il segnale analogico al pin A3 e guarda che valori da sul terminale del IDE:

int cmd_tx = 5;
int analogPin = 3; 
int rx_val = 0;


void setup()
{
  Serial.begin(9600);
  delay(3000); 
  pinMode(cmd_tx, OUTPUT);
  digitalWrite(cmd_tx, LOW);
}

void loop()
{
    rx_val = analogRead(analogPin); 
    Serial.println(rx_val,DEC);        
    if (rx_val > 50)          //se il valore analogico è > di 50, metto a 1 l'output cmd_tx
  { 
  digitalWrite(cmd_tx, HIGH); 
  Serial.println("HIGH");    
  } 
    if ((rx_val < 50) && digitalRead(cmd_tx))    //se il valore analogico è < di 50, e cmd_tx è a 1 
    {  
    Serial.println("Aspetta");  
        delay(3000);                                                     //attendo 3 secondi
        digitalWrite(cmd_tx, LOW);
    Serial.println("LOW");                                        //scrivo a zero cmd_tx
}
delay(100);
}

Ciao Uwe

5
5
3
5
4
5
4
4
4
5
3
4
4
4
4
6
4
4
4
4
5
4
4
5
4
4
4
1023     //qui ho alzato l'input analogico
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH                //qui ho portato al valore basso l'input analogico...
4
5
4
5
4
5
4
4
4
3
5
4
3
4
5
4
3
5
3
5
7
4
5
5
7
4
6
4
4
4
4
3
4
4
5
3
4
4
4
5
3
4
5
4
3
3
6
4
2
4
4
7
4
4
4
4
4
2
6
6
4
3
4
4
4
5
6
5
4
4
4
1
3
4
4
4
4
3
4
4
4
3
3
4
3
6
3
2
4
3
4
4

dopo circa una decina di secondi, non vedendo cambiamenti di stato ho interrotto premendo il tast reset

altra prova:

int cmd_tx = 5;
int analogPin = 3; 
int rx_val = 0;


void setup()
{
  Serial.begin(9600);
  delay(3000); 
  pinMode(cmd_tx, OUTPUT);
  digitalWrite(cmd_tx, LOW);
}

void loop()
{
    rx_val = analogRead(analogPin); 
    Serial.println(rx_val,DEC);        
    if (rx_val > 50)          //se il valore analogico è > di 50, metto a 1 l'output cmd_tx
  { 
  digitalWrite(cmd_tx, HIGH); 
  Serial.println("HIGH");    
  } 

    if (rx_val < 50)
   {
  Serial.println("LOW1");
  if (digitalRead(cmd_tx))    //se il valore analogico è < di 50, e cmd_tx è a 1 
    {  
    Serial.println("Aspetta");  
        delay(3000);                                                     //attendo 3 secondi
        digitalWrite(cmd_tx, LOW2);
    Serial.println("LOW");                                        //scrivo a zero cmd_tx
}}
delay(100);
}

Ciao Uwe
[/quote]

Ciao,

non sono un esperto di arduino quindi ciò che ti scrivo prendila come una mia idea rozza
Io scriverei il codice così

void setup()
{
  pinMode(cmd_tx, OUTPUT);
  int tempo;
}

void loop()
{
   if (rx_val>50) { 
     digitalWrite(cmd_tx, HIGH); 
     tempo=0;
   }

   if (rx_val<50 and cmd_tx !=0) { tempo++; }

   if(tempo>3000) {
     digitalWrite(cmd_tx, LOW);
     tempo=0;
   }
}

Tuttavia in questo modo il ‘3000’ che c’è nell’if non è preciso in quanto io sto semplicemente addizionando una unità alla variabile tempo ad ogni ciclo del programma e e quindi non si basa sul tempo trascorso. Quindi quello che si potrebbe fare è utilizzare la funzione millis per ricavare il tempo ciclo del programma e ricavarti poi l’effettivo valore da inserire per far si che siano 3000ms. Forse sono stato un pò contorto ma è da principiante è l’unica cosa che mi viene in mente :stuck_out_tongue:

PS il codice l’ho scritto al volo quindi può essere che abbia commesso qualche errore di sintassi

nel finale del codice mi dava errore, ho quindi scritto:

  if (digitalRead(cmd_tx))    //se il valore analogico è < di 50, e cmd_tx è a 1 
    {  
    Serial.println("Aspetta");  
        delay(3000);                                                     //attendo 3 secondi
        digitalWrite(cmd_tx, LOW);
    Serial.println("LOW2");                                        //scrivo a zero cmd_tx
}}
delay(100);
}

comunque:

(cut)
4
LOW1
5
LOW1
4
LOW1
4
LOW1
1023  //porto analogico 3 a livello alto
HIGH
1023
HIGH
1023
HIGH

taglio per non rubare troppo spazio

1023
HIGH
1023
HIGH
1023
HIGH
1023
HIGH
4          //porto analogico 3 a livello basso...
LOW1
2
LOW1
3
LOW1
4
LOW1
5
LOW1
4
LOW1
4
LOW1
4
LOW1
....etc etc etc... fino a reset

Grazie per il tuo intervento Nagy, e stai tranquillo che pure io sono decisamente nabbo.
Vista la mia attività lavorativa, ho approcciato Arduino a scopo di hobby pensando di fare una passeggiata, ma non mi ero accorto di essere "Scalzo sui vetri"...

L'idea può essere sicuramente buona, tuttavia mi pare di capire che il problema stà nel fatto che non vuole saperne di fare quell'IF con l'AND tra il valore analogico e quello digitale, sia scritto come (&&) che come due IF in cascata.
Risolto questo dovrò capire come contare il tempo senza piantare il programma con il DELAY, ma per quello la tua può essere già la soluzione. Tuttavia avevo già sperimentato la libreria METRO con successo.

Il delay in questo momento non é il problema. :wink: :wink: :wink:
comunque: http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Facciamo una cosa: definiamo una variabile di stato per il pin di uscita e vediamo:

int cmd_tx = 5;
int analogPin = 3;
int rx_val = 0;
int stato_tx =0;

void setup()
{
Serial.begin(9600);
delay(3000);
pinMode(cmd_tx, OUTPUT);
digitalWrite(cmd_tx, stato_tx);
}

void loop()
{
rx_val = analogRead(analogPin);
Serial.println(rx_val,DEC);
if (rx_val > 50) //se il valore analogico è > di 50, metto a 1 l’output cmd_tx
{
stato_tx = 1;
digitalWrite(cmd_tx, stato_tx);
Serial.println(“HIGH”);
}

if (rx_val < 50)
{
Serial.println(“LOW1”);
if (stato_tx) //se il valore analogico è < di 50, e cmd_tx è a 1
{
Serial.println(“Aspetta”);
delay(3000); //attendo 3 secondi
stato_tx =0;
digitalWrite(cmd_tx, stato_tx);
Serial.println(“LOW2”); //scrivo a zero cmd_tx
}}
delay(100);
}