Go Down

Topic: Problema magari banale...ma non ci dormo la notte! (Read 1 time) previous topic - next topic

KKMeph

Ti ringrazio per la risposta e per i consigli dati (soprattutto sul tipo di variabile). Purtroppo del tuo codice ci ho capito veramente gran poco, essendo il mio C arrugginito da anni ormai.

Provo a rispiegare il tutto.

Abbiate presente una forma d'onda triangolare;

Nella fase di salita, ci sarà un punto che sarà a meta fra il punto zero e il punto MAX. Chiamiamolo punto A.
Nella fase di discesa, ci sarà analogamente un punto fra il punto MAX ed il punto zero (ovviamente traslato nel tempo). Chiamiamolo punto B.

Se sulle ascisse abbiamo il tempo, X(A) sarà ovviamente diverso da X(B). Se sulle ordinate abbiamo un valore di tensione, sarà Y(A)=Y(B).



La situazione che descrivo è la seguente, facendo un passo in più. Eliminiamo mezzo triangolo, teniamo solo la  prima parte.

Punto zero : comando
Punto fra zero e mediano: comando 1
Punto Max: comando 2.

Ora se ipotizziamo che il mio valore in ordinata cali (da MAX a zero) si troverà prima o poi sul punto relativo al comando 1. E lo eseguirà.

Ecco, io non voglio che lo esegua. Lo deve eseguire solo in salita, in discesa non deve variare il suo stato (dallo stato raggiunto con il max).


Meglio ora?


Grazie!

Maurotec

Quote
Ecco, io non voglio che lo esegua. Lo deve eseguire solo in salita, in discesa non deve variare il suo stato (dallo stato raggiunto con il max).


Meglio ora?
Per stabilire se U sale o scende si devono prendere due campioni, U(t) e U(t+1), usando gli interi con segno
puoi stabilire se sta salendo o scendendo, perché:

Salendo sta:
u(t) = 0
u(t+1) = 1
1 - 0 = 1 (positivo)

Scendendo sta:
u(t) = 1
u(t+1) = 0
0 - 1 = -1 (negativo)

Serve proprio monitorare se sta salendo o scendendo?

Quote
Purtroppo del tuo codice ci ho capito veramente gran poco, essendo il mio C arrugginito da anni ormai.
Rinfresca allora i puntatori a funzione, typedef, per tutta curiosità se al mio codice sostituisci i commenti con il codice che accende il led e che legge A0, cosa esce fuori?

ops, a proposito ti serve leggere solo A0, A1 lo hai usato nel tentativo di venirne a capo, giusto?

Ciao.


 

KKMeph

Si, A1 avevo pensato di utilizzarlo per "splittare" il segnale e quindi dare un doppio controllo...

nid69ita

1 ) non usare float o double con le if > o <, e peggio ancora se ==
     Puoi sempre usare i valori in virgola mobile per comodità, con tal fine puoi creare una macro ftoadc(v).
cos'e' questa ftoadc()  ?? 
my name is IGOR, not AIGOR

KKMeph

Mi da errore al primo led in on


Code: [Select]
typedef void (*std_fnc_ptr)(void);
std_fnc_ptr mutexRun;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode (13, OUTPUT);


  mutexRun = ledIsOff; // prenota l'esecuzione di ledIsOff()
  void ledIsOn() {
    if (u > 4.5) {
      digitalWrite (13, LOW); // spegni led
      mutexRun = ledIsOff;  // // prenota l'esecuzione di ledIsOff()
    }
  }

  void ledIsOff() {
    if ((u > 3) && (u < 4.5)) {
      ; // accendi led
      mutexRun = ledIsOn; // prenota l'esecuzione di ledIsOn()
    }
  }

  void loop() {

    int sensorValue = analogRead(A0);

    // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    float u = sensorValue * (5.0 / 1023.0);
    mutexRun();  // esegue ledIsOff o ledIsOn

    Serial.println (u);


  }

Etemenanki

#20
Sep 29, 2015, 04:57 pm Last Edit: Sep 29, 2015, 05:01 pm by Etemenanki
...
Ecco, io non voglio che lo esegua....
... e fin qui si era capito ... quello che vogliono sapere e', "quando" deve tornare ad eseguire il comando 1 ?

Detto in pratica:

sotto i 3V, nulla
sale ... a 3V, accendi
sale ancora ... a 4V, spegni
(opzione 1) se invece di salire scende ... sotto i 3V deve rispegnere ?
(opzione 2) scende dai 4V ... fra 3 e 4 V, NON riaccendere
*adesso*, se scende ANCHE sotto i 3V, deve continuare a NON riaccendere (cioe', ti esegue quei comandi una sola volta in tutto), oppure se scende sotto i 3V (o una qualsiasi altra soglia minore di 3V), deve poi rieseguire l'accensione salendo di nuovo sopra i 3V ?

EDIT: perche' a me questo sembra solo una macchina a stati variabili ... ;)
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Maurotec

Quote
typedef void (*std_fnc_ptr)(void);
std_fnc_ptr mutexRun;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode (13, OUTPUT);


  mutexRun = ledIsOff; // prenota l'esecuzione di ledIsOff()

}  // end setup

void ledIsOn() {
    if (u > 4.5) {
      digitalWrite (13, LOW); // spegni led
      mutexRun = ledIsOff;  // // prenota l'esecuzione di ledIsOff()
    }
} // end ledIsOn

void ledIsOff() {
    if ((u > 3) && (u < 4.5)) {
      ; // accendi led
      mutexRun = ledIsOn; // prenota l'esecuzione di ledIsOn()
    }
} // end ledIsOff

  void loop() {

    int sensorValue = analogRead(A0);

    // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    float u = sensorValue * (5.0 / 1023.0);
    mutexRun();  // esegue ledIsOff o ledIsOn

    Serial.println (u);


  }

Prova così.

Ciao.

KKMeph

Ti ringrazio moltissimo. Dopo aver dichiarato le variabili all'interno dei vodi, succede questa cosa qui:

0-3V: stato 0, bene.
U>3V: stato 1, bene.
3 < U < 4,5: stato 1, bene.
U>4,5V: stato 0, bene.

3< U < 4,5 (dopo aver superato i 4,5): stato 1, male. Come prima.
0< U < 3V: stato 1, male. Dovrebbe ritornare allo stato 0 qui.




Code: [Select]
typedef void (*std_fnc_ptr)(void);
std_fnc_ptr mutexRun;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode (13, OUTPUT);


  mutexRun = ledIsOff; // prenota l'esecuzione di ledIsOff()

}  // end setup

void ledIsOn() {
  int sensorValue = analogRead(A0);

  float u = sensorValue * (5.0 / 1023.0);
  if (u > 4.5) {
    digitalWrite (13, LOW); // spegni led
    mutexRun = ledIsOff;  // // prenota l'esecuzione di ledIsOff()
  }
} // end ledIsOn

void ledIsOff() {
  int sensorValue = analogRead(A0);

  float u = sensorValue * (5.0 / 1023.0);
  if ((u > 3) && (u < 4.5)) {
    digitalWrite (13, HIGH); // accendi led
    mutexRun = ledIsOn; // prenota l'esecuzione di ledIsOn()
  }
} // end ledIsOff

void loop() {

  int sensorValue = analogRead(A0);

  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float u = sensorValue * (5.0 / 1023.0);
  mutexRun();  // esegue ledIsOff o ledIsOn

  Serial.println (u);


}

KKMeph

... e fin qui si era capito ... quello che vogliono sapere e', "quando" deve tornare ad eseguire il comando 1 ?

Detto in pratica:

sotto i 3V, nulla
sale ... a 3V, accendi
sale ancora ... a 4V, spegni
(opzione 1) se invece di salire scende ... sotto i 3V deve rispegnere ?
(opzione 2) scende dai 4V ... fra 3 e 4 V, NON riaccendere
*adesso*, se scende ANCHE sotto i 3V, deve continuare a NON riaccendere (cioe', ti esegue quei comandi una sola volta in tutto), oppure se scende sotto i 3V (o una qualsiasi altra soglia minore di 3V), deve poi rieseguire l'accensione salendo di nuovo sopra i 3V ?

EDIT: perche' a me questo sembra solo una macchina a stati variabili ... ;)
sotto i 3V, nulla
sale ... a 3V, accendi
sale ancora ... a 4V, spegni
(opzione 1) se invece di salire scende ... sotto i 3V deve rispegnere ? SI
(opzione 2) scende dai 4V ... fra 3 e 4 V, NON riaccendere ESATTO, MA DEVE RIACCENDERE SOTTO I 3V
*adesso*, se scende ANCHE sotto i 3V, deve continuare a NON riaccendere (cioe', ti esegue quei comandi una sola volta in tutto), oppure se scende sotto i 3V (o una qualsiasi altra soglia minore di 3V), deve poi rieseguire l'accensione salendo di nuovo sopra i 3V ? SI, ESATTO.





Etemenanki

#24
Sep 29, 2015, 05:52 pm Last Edit: Sep 29, 2015, 06:01 pm by Etemenanki
Detta cosi, mi da l'impressione che si possa fare con una macchina a stati ed un flag ... in fondo hai 3 possibili stati in ingresso, sotto i 3V, fra 3v e 4V, sopra i 4V, e solo alcune possibili condizioni da controllare ... con 5 3 if ed un flag dovresti poterle gestire tutte (in questo caso, il flag ha 3 possibili valori, cioe' 0 = era sotto i 3V ... 1 = e' passato da sotto a sopra 3V ... 2 = e' passato da sotto a sopra 4V) ... ovviamente e' da controllare, perche' sto ragionando "al volo" e non posso testarlo in pratica, ma secondo me potrebbe funzionare in questo modo ...

prima condizione, e' sopra i 3V ed il flag e' a 0 --> accendi e setta il flag ad 1 (qui il flag dice allo sketch che hai acceso al passaggio, quindi dovra' spegnere quando passera' sopra i 4V)

seconda condizione, e' sopra i 3V e sotto i 4V ed il flag e' ad 1 --> non fai nulla EDIT: questa condizione e' inutile controllarla, probabilmente, perche' sarebbe comunque una condizione in cui non devi fare nulla

terza seconda condizione, e' sotto i 3V ed il flag non e' a 0 --> spegni e resetta il flag a 0

quarta terza condizione, e' sopra i 4V ed il flag e' ad 1 --> spegni e setta il flag a 2 (qui il flag dice allo sketch che c'e' gia stata l'accensione del rele', quindi deve spegnerlo e cambiarne il valore per evitare che alla successiva risalita si riaccenda)

quarta condizione, e' fra 3V e 4V ed il flag e' a 2 --> non fai nulla (qui il flag a 2 dice allo sketch che il passaggio acceso-spento c'e' gia stato, quindi non deve essere ripetuto finche' non sara' passato di nuovo sotto i 3V e resettato il flag a 0) RIEDIT: a pensarci bene, anche questo controllo non ha senso :P

"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Maurotec

Code: [Select]


/* Declare global variable */
typedef void (*std_fnc_ptr)(void);   // definizione nuovo tipo std_fnc_ptr
std_fnc_ptr mutexRun;                  // puntatore a funzione generica

// Le variabili globali non devono avere nomi di un singolo carattere e almeno minimo 5
float vinAdc0;        // ex 'u'
uint16_t rawAdc0; // ex 'sensorValue'

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode (13, OUTPUT);

  mutexRun = ledIsOff; // prenota l'esecuzione di ledIsOff()

}  // end setup

void ledIsOn() {

  if (vinAdc0 > 4.5) {
    digitalWrite (13, LOW); // spegni led
    mutexRun = ledIsOff;  // // prenota l'esecuzione di ledIsOff()
  }

} // end ledIsOn

void ledIsOff() {

  if ( (vinAdc0 > 3) && (vinAdc0 < 4.5) ) {
    digitalWrite (13, HIGH); // accendi led
    mutexRun = ledIsOn; // prenota l'esecuzione di ledIsOn()
  }

} // end ledIsOff

void loop() {

  rawAdc0 = analogRead(A0);

  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  vinAdc0 = rawAdc0 * (5.0 / 1023.0);

  mutexRun();  // esegue ledIsOff o ledIsOn

  Serial.println (vinAdc0);
}



Il programma non è cambiato ho solo dato una ripulita. Se si ha la certezza che al power on vinAdc0 può solo aumentare possiamo passare a risolvere il caso inverso, diversamente si devono campionare due valori e stabilire la tendenza. Puoi confermare che vinAdc0 (ex 'u') al power on tende a salire?

Se la tendenza a salire si inverte dopo avere superato la soglia di 4.5, basta usare una variabile di stato in cui prendere nota della inversione di tendenza.

Comunque penso che se è realmente un onda triangolare questa si ripeterà all'infinito, pertanto bisogna ricavare la tendenza (toUp o toDown).

Ciao.

 

Etemenanki

> MauroTec: ma non e' piu semplice un sistema a stati ?

Voglio dire, a lui non serve sapere se la tensione sta salendo o scendendo, ma solo in che condizione si trova il sistema ...

Dimmi se sbaglio ... supponiamo di usare una variabile di controllo per l'ingresso analogico, chiamiamola var, e mappiamola in modo che rispecchi i millivolt (solo per comodita' di lettura), e di usare un flag ...

Code: [Select]

if ((var <= 2999) && (flag != 0))
    {
    digitalWrite(out, LOW);
    flag = 0;
    }
if ((var => 3000) && (var <= 3999) && (flag == 0))
    {
    digitalWrite(out, HIGH);
    flag = 1;
    }
if ((var => 4000) && (flag == 1))
    {
    digitalWrite(out, LOW);
    flag = 2;
    }


Questi 3 if, non sarebbero sufficenti a fare quello che vuole ?
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Maurotec

Quote
Questi 3 if, non sarebbero sufficenti a fare quello che vuole ?
ni, penso, forse, ma non sono sicuro, che giorno è? :smiley-mr-green:

Comunque gli ho dato una macchina a stati superflessibile, basta aggiungere una funzione e prenotarla.
Un funzione è uno 'stato' (azzoppato di degli pseudo stati, entry state, exit state, ecc).

Code: [Select]


void newState() {
   if ...
       mutexRun = newState; sta ciclando su newState
   else if ...
       mutexRun = ledIsOn;
}


Sinceramente con la poca lucidità che mi è rimasta il tuo codice mi sembra sufficiente.

Aspettiamo che dice lui.

KKMeph

Ringrazio tutti della partecipazione e mi scuso nuovamente della mia pochezza di conoscenza di C. Purtroppo questa sera non riesco a provare nulla, domani proverò i vostri consigli!

di flag non ne avevo mai sentito parlare...pure sul mio vecchio libro di C non c'è nulla :(

Maurotec

Quote
di flag non ne avevo mai sentito parlare...pure sul mio vecchio libro di C non c'è nulla :(
Non prendere fischi per fiaschi, quello di ete è un esempio, dove si capisce che 'flag' è un nome di variabile che per sintetizzare non ha dichiarato. Comunque flag (bandierina), qui intesa come segnapunto.

Quindi se vuoi provare quel codice devi dichiarare la variabile globale flag, es:
Code: [Select]

byte flag = 0; // fuori da ogni funzione


Ciao.

Go Up