Go Down

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

KKMeph

BUongiorno a tutti!

Ho provato il codice datomi da MauroTec: comincio a vedere la luce, nel senso che almeno ho capito il codice.


Praticamente definisco varie funzioni in base all'ingresso che ho:

ingresso A ---> fai funzione relativa all'ingresso A
ingresso B ---> fai funzione relativa all'ingresso B



E fin qui ok. Il problema che si pone è che lo stato non si conserva.


Ingresso A ---> fai funzione relativa all'ingresso A
Ingresso B ---> fai funzione relativa all'ingresso B
Ingresso A (DOPO AVER AVUTO INGRESSO B) ---> mantieni la funzione relativa all'ingresso B

tanto per capirsi eh.




KKMeph

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 funprova() {

  if (vinAdc0 < 3) {
    digitalWrite (13, LOW);
    mutexRun = funprova;
  }
  else {
    mutexRun = 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);
delay (2);
 
}

KKMeph

Per l'utente Etemenanki

Ho capito il concetto, l'avevo già provato dichiarando una variabile k esterna a tutti ed assegnando un valore di k ad ogni "stato if".


KKMeph

Code: [Select]
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);


  pinMode (13, OUTPUT);
  digitalWrite (13, LOW);
}

void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  byte flag  = 0;
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float u = sensorValue * (5.0 / 1023.0);


  if ((u <= 3) && (flag == 0))
  {
    digitalWrite(13, LOW);
    flag = 1;
  }
  if ((u >= 3) && (u <= 4.5) && (flag == 1))
  {
    digitalWrite(13, HIGH);
    flag = 2;
  }
  if ((u > 4.5) && (flag == 2))
  {
    digitalWrite(13, LOW);
    flag = 3;
  }
  if ((u < 4.5 ) && (u > 3) && (flag == 3)) {
    digitalWrite (13, LOW);
    flag = 0;
  }


  // ritardo in millisecondi

  delay (2);


  Serial.println(u);
}





ecco il codice (che non funzia)

Etemenanki

Si, scusami, non ho precisato bene (do sempre per scontato che se uno usa una variabile, la dichiari per forza nel setup, e mi dimentico di specificarlo a volte) ... un "flag" non e' un comando, e' solo una variabile che tu usi per fare in modo che lo sketch sappia cosa fare in diverse occasioni, puo avere il nome che preferisci tu (pippo, vattelapesca, mariorossi, quello che vuoi ... io ho usato flag per fare l'esempio, ma se te ne servissero 10, le puoi chiamare come preferisci) ... i flag sono utili quando hai sketch che devono eseguire diverse operazioni con stati diversi, oppure che devono eseguire una singola operazione una sola volta, e poi aspettare una diversa operazione prima di rieseguirla, o in altri casi simili ...

Ad esempio ... nel pezzo di codice che ho postato, quando flag vale 0, significa che lo stato precedente era sotto i 3V, quindi il secondo if accende l'uscita solo nel caso il valore vada fra 3V e 4V arrivando da sotto i 3V, poi mette il flag a valore 1, il che gli impedisce di accenderla di nuovo prima che flag sia stato resettato ... se in questo caso scende sotto i 3V di nuovo, il primo if lo resetta a 0, se invece sale sopra i 4V, il terzo if vede dal flag ad 1 che il rele' e' stato acceso, lo spegne, e mette il flag a 2 ... in questa condizione, il secondo if non riaccende piu il rele' quando passi da sopra a sotto i 4V, perche' il flag e' a 2, ed anche il terzo if non fa piu nulla, almeno finche' non torni sotto i 3V, quando questo succede, il primo if "vede" che il flag e' diverso da 0 e lo resetta, consentendo di riprendere il ciclo ... e dato che tutto quello che c'e' all'interno di un ciclo if viene ignorato se l'espressione di controllo non e' soddisfatta, in stati diversi e' come se nemmeno ci fossero ...
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

KKMeph

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'
byte k = 0;


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()
    k = k + 1;
  }

} // 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 inizio() { //funzione inziale

  if ((vinAdc0 > 0) && (vinAdc0 < 3)) {
    digitalWrite (13, LOW);
    mutexRun = inizio;
  }
}

void manstato () {  //prova di funzione con mantenimento dello stato
  if ((vinAdc0 > 3) && (vinAdc0 < 4.5) && (k == 1)) {
    digitalWrite (13, LOW);
    mutexRun = manstato;
    k = 0;
  }

}

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);
  delay (2);

}



Sto prendendo spunto da tutti i consigli. Ho implementato due funzioni nuove (iniziali e finali), inserendo anche il controllo "flag". Non mi funge ancora, ma sento di non essere troppo distante :)

Etemenanki

#36
Sep 30, 2015, 10:19 am Last Edit: Sep 30, 2015, 10:20 am by Etemenanki
...
ecco il codice (che non funzia)
Secondo me manca la dichiarazione di qualche variabile, ed inoltre i cicli if sono "strani" ... ed in piu, per il poco che mi ricordo, la mappatura non funziona con i float ... pero' si puo aggirare ... giusto per curiosita', se puoi (io non ho la possibilita' di provare qui) prova a sostituirlo con una cosa tipo questa

Code: [Select]

int ingresso = A0;
int valore = 0;
byte flag = 0;

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

void loop() {
  ingresso = analogRead(A0);
  valore = map(ingresso, 0, 50, 0, 1023);

  if ((valore < 30) && (flag != 0))
  {
    digitalWrite(13, LOW);
    flag = 0;
  }
  if ((valore >= 30) && (valore < 45) && (flag == 0))
  {
    digitalWrite(13, HIGH);
    flag = 1;
  }
  if ((valore >= 45) && (flag == 1))
  {
    digitalWrite(13, LOW);
    flag = 2;
  }

  delay (2);
  Serial.println(valore);
}
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

KKMeph

OK, allora immettendo in valori giusti (visti dal serial) ci siamo quasi!

Ai 3, si accende
Ai 4.5 si spegne
Tornando giù dai 4.5 rimane spento!!!!!!! YEAH!

Ma quando si oltrepassa il 3 deve accendersi ancora!

KKMeph

Code: [Select]
int ingresso = A0;
int valore = 0;
byte flag = 0;

void setup() {
  Serial.begin(9600);
  pinMode (13, OUTPUT);

  //pinMode (8, OUTPUT);
}

void loop() {
  ingresso = analogRead(A0);
  valore = map(ingresso, 0, 1023, 0, 1023);

  if ((valore < 500) && (flag != 0))
  {
    digitalWrite(13, HIGH);
    flag = 0;
  }
  if ((valore >= 500) && (valore < 918) && (flag == 0))
  {
    digitalWrite(13, HIGH);
    flag = 1;
  }
  if ((valore >= 918) && (flag == 1))
  {
    digitalWrite(13, LOW);
    flag = 2;
  }
  if (flag == 2)
  {
    digitalWrite (13, LOW);
    flag = 3;
  }
  if ((flag == 3) && (valore == 500)) {
    digitalWrite (13, HIGH);
    flag = 4;


  }


  delay (500);
  Serial.println(valore * 5.000 / 1023);
  Serial.println(flag);
}



Ci siamo!

Etemenanki

#39
Sep 30, 2015, 11:31 am Last Edit: Sep 30, 2015, 11:33 am by Etemenanki
Intendi quando scende sotto il 3 e poi risale di nuovo, immagino ... quello dovrebbe farlo il primo if ... non lo fa ?

EDIT: Intendi il codice che ho postato io ? ... quello e' differente ... a proposito, "map(ingresso, 0, 1023, 0, 1023)" non ha senso ;)
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

KKMeph

Quello che ho postato finale, che è praticamente il tuo, funzia come voglio!

Per i valori di tensione mi trovo gli equivalenti in "numero" e poi nel monitor seriale li converto in valore di tensione. Solo che facendo il map 1023 come avevo fatto avevo il segnale giusto (3V sul generatore DC, 3V visti da arduino) mentre mettendo map (0, 255, 0, 1023) no

Etemenanki

No, intendevo dire che e' inutile mappare da 0 a 1023 un valore che e' gia di suo da 0 a 1023 ... puoi usarlo direttamente senza alcun map (il map ha senso se devi convertire una scala in un'altra diversa, nel tuo caso "valore" restituirebbe semplicemente lo stesso valore di "ingresso", quindi se usi direttamente "ingresso"  al posto di "valore" fai prima e risparmi memoria e cicli programma ;) )
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

Etemenanki

... poi non capisco questo

  if (flag == 2)
  {
    digitalWrite (13, LOW);
    flag = 3;
  }

la riga prima metti flag a 2, poi questo if te lo mette immediatamente a 3 ... non capisco il senso ...

Inoltre l'ultimo if riaccende quando va sotto il 3V, ma questo non l'avevi detto ... quindi meglio che il controllo lo fai su <=299 e non su =300, perche' se la tensione scende molto velocemente e passa da 301 a 299 fra due letture, non ti eseguira' il ciclo
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

KKMeph

BHO! :)

In realtà sono andato a naso, plottando anche lo stato della bandierina su seriale e lavorando da questo punto di vista.

Perchè funzioni correttamente, per aver lo start devo compilare e far partire da tensione 0 ma non è un problema.

Il led è solo un indicazione, forse per questo è complicato, il mio interesse è il relè, che deve fare clic/cloc :) che il clic cloc sia relativo a led acceso o led spento non importa, basta che ci sia!



GRAZIE MILLE A TUTTI COMUNQUE!

KKMeph

Ciliegina sulla torta!

Ma se mentre il loop looppa, io volessi far fare ad un altro ingresso e ad un altra uscita altre cose...devo fare un ciclo while comprendente tutto il loop?

Go Up