Go Down

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

KKMeph

Ciao a tutti, mi chiamo Marco e sono nuovo del Forum.
Ho cominciato da poco a lavorare con Arduino e lo trovo fantastico! Tuttavia il C mi fa impazzire :)!

Vi espongo il (magari banale) problema.

Devo azionare un relè: nessun problema di collegamento, funzia tutto!

Il problema risulta essere nel comando!


Ho un ingresso di riferimento (una tensione esterna, variabile da 0 a 5V). Quando la mia tensione supera i 3V, ho bisogno che il rele intervenga (stato del pin, diciamo tredici, alto). Dopo ciò, ho bisogno che il mio relè intervenga ancora dopo che si superano i 4V (stato del pin, basso)...ma che se la tensione scende sotto i 4V, lo stato del pin rimanga basso!

Il problema è che in "salita" di tensione ho bisogno di 2 azioni, ed in "discesa" di tensione di una sola!
Come posso fare?
 
Grazie!




fabpolli

Ciao, non ho tanto capito la seconda parte del problema, ovvero supero i 3V quindi il relè si attiva, supero i 4 il relè si disattiva e resta disattivato anche se torno sotto i 4V ma fino s che tensione deve restare disattivato? Se scendo sotto i 3V poi si deve riattivare se li supera nuovamente o la tensione deve andare a zero? Posta il codice che hai scritto finora e se puoi argomenta meglio il funzionamento così si evita di scrivere codice che poi non si adatta al tuo problema.
In ogni caso ti serve una macchina a stati finiti ovvero con una variabile ti memorizzi lo stato attuale e poi in base a quello valuti se attivare o disattivare il relè, questo come spunto generale poi se metti il codice entriamo in dettaglio al tuo problema.

KKMeph

Ti ringrazio per la tempestiva risposta!

Si ho bisogno di:

U > 3V ----> Pin 1 (alto)
U > 4V ----> Pin 0 (basso)
U > 4,3V --->Pin 0 (basso) <- questo è per esempio
U < 4V ----> Pin 0 (basso)

e via così...

Cioè, in discesa di tensione i comandi dovrebbero dovrebbero variare. Ho pensato di mettere un secondo controllo in // al segnale A0. Quindi fare A0 e A1 (medesimo segnale, splittare le variabili e inserire controlli diversi sulle variabili).

Ecco il codice (molto rudimentale)




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

int var;
int sub;



void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  pinMode (13, OUTPUT);
 
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  double u = sensorValue * (5.0 / 1023.0);
  double sub = sensorValue * (5.0 /1023.0);
  // print out the value you read:


//ciclo if comando iniziale

if (u < 3.0) {

                    digitalWrite (13, HIGH);
}

else if (u > 4.5) {

                    digitalWrite (13, HIGH);
}


else {
                    digitalWrite (13, LOW);
}

Serial.println(u);


// ritardo in millisecondi

nid69ita

#3
Sep 29, 2015, 11:42 am Last Edit: Sep 29, 2015, 11:42 am by nid69ita
Ciao a tutti, mi chiamo Marco e sono nuovo del Forum.
Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento se non lo hai già fatto: Regolamento
Qui una serie di link utili, non inerenti al tuo problema:
- qui una serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections
- qui le pinout delle varie schede by xxxPighi: Pinout
- qui una serie di link generali utili: Link Utili

Il codice devi racchiuderlo nei tag code, vedi sezione 7 del regolamento, spiega bene come fare  ( pulsante </> ).
Altrimenti parte del codice può essere visualizzata male o mancare perchè interpretato come attributo del testo stesso.
my name is IGOR, not AIGOR

KKMeph

Pardon, avevo già visto i link utili...mi era scappato il regolamento ed il codice!

Ecco qui, ho fatto un paio di modifiche seguendo il suggerimento datomi



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);
}

int var;
int sub;
int k = 0;


void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  int valore2 = analogRead(A1);
  pinMode (13, OUTPUT);
 
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  double u = sensorValue * (5.0 / 1023.0);
  double sub = valore2 * (5.0 /1023.0);
  // print out the value you read:


if (k==0){

             if (u>3){
                          digitalWrite (13,HIGH);}
             else {digitalWrite (13, LOW);}
                     

k=k+1;

}


if (k==1) {

            if (u>4.5){
                         digitalWrite (13, LOW);}
            else {digitalWrite (13, HIGH);}
                       
   
k=k+1;

}

if (k==2) {
            if (u <=4.5 && u > 3) {
                          digitalWrite (13,LOW);}

            else {digitalWrite (13, HIGH);}
             
k=0;
}




 





Serial.println(u);


// ritardo in millisecondi

delay (1000);

}

SukkoPera

Quel che non si capisce è cosa deve succedere quando la tensione scende. Deve rimanere spento per sempre? Oppure c'è una soglia X una volta scesi sotto la quale, se si riprende a salire, si deve riaccendere il relé?
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

KKMeph

Scusami, cerco di spiegarmi meglio, andando per step

Ipotesi di ciclo 1

U < 3, Led OFF
U > 3, Led ON
3 < U < 4.5, LED ON
U>4.5, LED OFF

e solo dopo il superamento di questa soglia

3 < U < 4.5, LED OFF -- Comando che cozza con il comando di prima.

Dopo quando la tensione scende sotto i tre, ritorna tutto normale.


nid69ita

#8
Sep 29, 2015, 12:18 pm Last Edit: Sep 29, 2015, 12:20 pm by nid69ita
Domanda un pò stupida se vogliamo, ma  @KKMeph     a che ca...spita servono quelle montagne di righe vuote ??
Ci vuole un mese per leggere il codice !!   Suggerisco di toglierle e piuttosto metti delle righe di commento per separare le varie "zone" del programma    :)
E nell'editor Arduino prova ad usare CTRL+T che rimette un pò a posto il codice come indentazione
my name is IGOR, not AIGOR

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);
}
//dichiarazione delle variabili
int sub;
int k = 0;
//parte di programma già predefinito in cui leggo l'ingresso, in 2 canali (al momento ne uso solo uno) E' sempre lo
//stesso segnale ma splittato su due ingressi
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  int valore2 = analogRead(A1);
  pinMode (13, OUTPUT);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  double u = sensorValue * (5.0 / 1023.0);
  double sub = valore2 * (5.0 / 1023.0);
  //ecco la parte di programma
  if (k == 0) {
    if (u < 3) {
      digitalWrite (13, LOW);
    }
    else {
      digitalWrite (13, HIGH);
    }

    k = k + 1;
  }
  if (k == 1) {
    if (u > 4.5) {
      digitalWrite (13, LOW);
    }
    k = k + 1;
  }
  if (k == 2) {
    if (u <= 4.5 && u > 3.0) {
      digitalWrite (13, LOW);
    }
    k = 0;
  }
  Serial.println(u);
  // ritardo in millisecondi
  delay (2);

}

fabpolli

#10
Sep 29, 2015, 01:04 pm Last Edit: Sep 29, 2015, 01:05 pm by fabpolli
Allora più o meno dovrebbe diventare una cosa del genere (non posso provarlo però):
Code: [Select]

bool bSogliaMinimaRaggiunta = false;
bool bSogliaMassimaRaggiunta = false;
if(!bSogliaMinimaRaggiunta ){
  bSogliaMinimaRaggiunta = valore>3;
  if(bSogliaMinimaRaggiunta ){
    digitalWrite (13, HIGH);
    bSogliaMassimaRaggiunta  = false;
  }
}
else{
  bSogliaMassimaRaggiunta = bSogliaMassimaRaggiunta || valore > 4.5;
  if(bSogliaMassimaRaggiunta){
     digitalWrite (13, LOW);
  }
  bSogliaMinimaRaggiunta = valore>3;
}

KKMeph

Ho appena provato...si accende (ho anche un led che prende alimentazione dal pin 13, in modo da far prima e non basandomi solo sul clic del relè) ai 3V e poi sta sempre acceso :(

fabpolli

prima di ricontrollare il codice, ti faccio una domanda, ma non è che questo controllo ti serve per gestire l'isteresi di una temperatura per evitare il continuo accendersi / spegnersi della caldaia o simile?

KKMeph

No, serve a gestire dei valori in tensione (opportunamente serviti ad Arduino mediante apposito partitore). Tali valori di tensioni sono dovuti (per dover di cronaca) ad una variazione di resistività di un materiale, dovuta (finalmente ci arrivo) ad una variazione di temperatura.

Perchè? Non riesco a darne fuori comunque :(

Maurotec

Quote
Perchè? Non riesco a darne fuori comunque :(
Io ho la febbre, quindi ...do un po i numeri.

Io mica l'ho capito, intanto noto incongruenze tra codice tuo e descrizione, cioè nel codice accendi quando nella descrizione dici di spegnere.

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).
2 ) La macchina a stati la puoi fare con switch case, in fondo il led può essere acceso o spento e quando
     è spento non serve ricontrollare se è spento e viceversa. In sostanza i due stati sono mutualmente esclusivi.
3 ) Non ti voglio male, ma capisci che ho la febbre, la bronchite e il naso chiuso e ciò mi rende capriccioso. 8)

Tiè una bella macchina a stati per cerebrolesi.

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);
  mutexRun = ledIsOff; // prenota l'esecuzione di ledIsOff()
 
}

void ledIsOn() {
    if (analogValue > 4.5) {
        ; // spegni led
        mutexRun = ledIsOff;  // // prenota l'esecuzione di ledIsOff()
    }
}

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

void loop() {
  mutexRun();  // esegue ledIsOff o ledIsOn
}



Per evitare di usare i float come in if (analogValue > 4.5) { dovresti creare la macro con define, ma ora sono
a corto di pazienza. Il codice si trasformerebbe in

 if ( analogValue > ftoadc(4.5) ) {

Ciao.

 

Go Up