Problemi sul software per un progetto!

Ricontrolla tutto, ci sono molti altri errori.... parentesi che mancano, parentesi in piu, assegnazioni errate....

Ciao a tutti...dopo una mattinata a studiare e dopo le partite del campionato, ho trovato un paio di orette per dedicarmi al programma.
Lo posto nettamente modificato rispetto a quello di ieri. Spero che ci siano meno errori!!! XD

#include <LiquidCrystal.h>
#include <Servo.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Servo mioservo;
float tempC;
int sensore = A1;
int val = 0;
int vecchio_val = 0;
int stato = 0;
int valore;
int fascia;
int angolo = 0;




void setup() {
  lcd.begin(16, 2);
  pinMode(13, INPUT);
  mioservo.attach(6);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
}

void loop() {
  val = digitalRead(13);
  
  if ((val == HIGH) && (vecchio_val == LOW)) {
    stato = 1 - stato;
    delay(15);
  }
  vecchio_val = val;
  
  if (stato == 1) {
    lcdLM35(), HIGH;
    segnalatoriLM35(), HIGH;
  }
  else {
    lcdLM35(), LOW;
    segnalatoriLM35; LOW;
  }
}

void lcdLM35() {
  lcd.print( "Temperatura...");
  tempC = analogRead(sensore);
  tempC = (50. * tempC * 100.0)/1024.0;
  lcd.setCursor(0, 1);
  lcd.print(tempC);
  lcd.print(" Celsius ");
  delay(750);
  lcd.clear();
}

void segnalatoriLM35() {
  valore = analogRead(sensore);
  fascia=map(valore, 0, 1024.0, 0, 3);
  if(fascia == 0) fascia = 1;
  spegni();
  digitalWrite(11-fascia, HIGH);
}

void spegni() {
  digitalWrite(10, LOW);
  ledyellow(), LOW;
  allarme(), LOW;
}

void ledyellow() {
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(1000);
}

void allarme() {
  ledred(), HIGH;
  servo(), HIGH;
  buzzer(), HIGH;
}

void ledred() {
  digitalWrite(8, HIGH);
  delay(500);
  digitalWrite(8, LOW);
  delay(500);
}

void servo() 
{
  for(angolo = 0; angolo < 180; angolo +=1)
{
mioservo.write(angolo);
delay(20);
}
 for(angolo = 180; angolo >= 1; angolo -=1)
{
 mioservo.write(angolo);
delay(20);
}
}

void buzzer() {
  buzz(7, 1000, 500);
  delay(400);
  buzz(7, 2000, 500);
  delay(400);
}

void buzz(int targetPin, long frequency, long length) {
  long delayValue = 1000000/frequency/7;
  long numCycles = frequency * length/ 1000;
  
  for (long p=0; p < numCycles; p++) {
    digitalWrite(targetPin, HIGH);
    delayMicroseconds(delayValue);
    digitalWrite(targetPin, LOW);
    delayMicroseconds(delayValue);
  }
}

Aspetto consigli, suggerimenti o correzioni!!!
Grazie in anticipo!!!

scusami io non l'ho letto il programma... è molto più difficile correggere un programma staticamente senza ausilio di debug o di punti di controllo... normalmente quando si fa un programma si divide in sottoproblemi e nel caso di arduino dove al software devi unire la componente hardware che hai fatto tu diventa ancora più fondamentale.
Quello che io faccio di solito è (...esempio) attacco l'lcd e faccio un lcd.print per vedere se va... poi attacco il sensore di temperatura e lo provo con un analog write ed un serial print.. e poi avanti così e poi quando attacco tutto su un'unico programma ci metto di tanto in tanto dei serial.print ("sono qua") per "debug".... ripeto così staticamente diventa un po' difficile... magari se ci dici cosa "non fa" diventa più facile.

Scusa, mi spieghi queste righe di codice?

  ledyellow(), LOW;
  allarme(), LOW;

leo72:
Scusa, mi spieghi queste righe di codice?

  ledyellow(), LOW;

allarme(), LOW;

...io pensavo che non si compilassero nemmeno... :blush: ... invece il programma si compila :astonished:
Comunque consiglio acca di cominciare a scrivere sul display la sola temperatura, quando ci siamo riusciti poi andiamo avanti... una cosa semplice tipo

temperatura = analogRead(PinLM);
lcd.print (temperatura);
... e un bel delay(1000);

... e sul delay poi avremo da lavorare perchè tu intendi far lampeggiare tutto con il delay ma il delay ti blocca tutto il programma quindi... casino... bisogna cambiare approccio.

qsecofr:

leo72:
Scusa, mi spieghi queste righe di codice?

  ledyellow(), LOW;

allarme(), LOW;

...io pensavo che non si compilassero nemmeno... :blush: ... invece il programma si compila :astonished:

Perché la virgola fra 2 operandi indica al compilatore l'uso dell'operatore "," che istruisce appunto il compilatore a verificare le condizioni ma a restituire quella più a destra. Qui LOW non viene assegnato a nulla. Se avessi fatto:
byte temp = ledyellow(), LOW;
dopo l'esecuzione della riga di codice temp avrebbe assunto il valore LOW (cioè "0").
Nell'esempio che ho mostrato, non ha senso. Cos'è che si voleva fare?

Guardando il codice mi pare di capire che scrivendo

 ledyellow(), LOW;
  allarme(), LOW;

lui volesse/credesse in qualche modo di pilotare le void esterne al loop con il LOW e HIGH......dico questo perchè lo ripete più volte nel loop e lo utilizza sempre con le void esterne pensando magari che con LOW non entra nella void e che con HIGH invece si. Se così fosse non si scrive "ledyellow(),HIGH;" se si vuole entrare nella void ma semplicemente "ledyellow();".
In buona sostanza tutte le void esterne non vengono mai eseguite fino a quando non vengono chiamate dal loop principale e,una volta letta ed eseguito il codice scritto,si ritorna in automatico al loop principale continuando da dove aveva lasciato.

tonid:
lui volesse/credesse in qualche modo di pilotare le void esterne al loop con il LOW e HIGH......dico questo perchè lo ripete più volte nel loop e lo utilizza sempre con le void esterne pensando magari che con LOW non entra nella void e che con HIGH invece si.

Probabile. Difatti chiedevo appunto cosa volesse fare, perché qualunque cosa fosse, in quel modo era sbagliato :sweat_smile:

Ciao scusate il ritardo, ma sono appena tornato dall'università.
il mio intendo era quello di bloccare i 2 sottoprogrammi qualora non ci siano state le condizioni per attivarli,
cioè raggiungere una determinata temperatura.
Per quanto riguarda la lettura della temperatura sull' lcd ci sono riuscito senza problemi, per il resto, da come avete notato un po' tutti, ho fatto un grandissimo casino. Sinceramente avevo pensato che quei 2 sottoprogrammi li avrei potuti attivare semplicemente come attivare un pin (es: accendere un led normale). Quindi....
1)come posso integrare i sottoprogrammi con il programma principale in modo corretto?
2)in molti avete scritto che uso troppi delay(), come potrei sostituirli?
Grazie in anticipo!!!! :blush:

acca90:
Ciao scusate il ritardo, ma sono appena tornato dall'università.

1)come posso integrare i sottoprogrammi con il programma principale in modo corretto?
2)in molti avete scritto che uso troppi delay(), come potrei sostituirli?
Grazie in anticipo!!!! :blush:

...io partirei da uno schema generale un po' diverso... ti accontenti di un piccolo programmino assolutamente non testato?
Manca da muovere il servo... vedrai dopo... intanto vendiamo se funzionano i led... non ho l'arduino collegato ne il sensore ne il display quindi te lo scrivo di istinto... bene sarebbe mettere un bel serial.print di tanto in tanto per capire dove sta andando il programma...

#include <LiquidCrystal.h>
#include <Servo.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Servo mioservo;
float tempC;
int sensore = A1;
int val = 0;
int vecchio_val = 0;
int stato = 0;
int valore;
int fascia;
int angolo = 0;

// ***************occhio qua.... ho messo delle costanti a caso tu metti quelle giuste ****************
const byte tempOttimaMin = 10;
const byte tempOttimaMax = 20;
const byte tempCritica = 30;
const byte ledVerde = 7;
const byte ledGiallo = 8;
const byte ledRosso = 9;

// ***************qui ci sono tre flag che mi indicano in ogni momento lo stato ****************
bool Verde=false;
bool Giallo=false;
bool Rosso=false;




//****************** questa è farina del tuo sacco... aggiungimi anche l'output dei 3 led... *****************
void setup() {
  lcd.begin(16, 2);
  pinMode(13, INPUT);
  mioservo.attach(6);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
}

//****************** questa è farina del tuo sacco*****************
void lcdLM35() {
  lcd.print( "Temperatura...");
  tempC = analogRead(sensore);
  tempC = (50. * tempC * 100.0)/1024.0;
  lcd.setCursor(0, 1);
  lcd.print(tempC);
  lcd.print(" Celsius ");
  //delay(750);
  lcd.clear();
}


//****************** qui guardo lo stato e accendo e spengo i led *****************
void AggiornaColori(){
  
  if (Verde == true) {
          digitalWrite(ledVerde,HIGH);  
    } else
    {    digitalWrite(ledVerde,LOW);  
  };
    
  if (Giallo == true) {
//** qui devi testare se funziona... l'idea è che interroghi la funzione millis e fai il modulo a 1000 se il resto dell'operazione
// è maggiore di 500 accende il led altrimenti lo spegne... quindi mi aspetto un lampeggio acceso+spento al secondo.
        if ((millis() % 1000) > 500) 
        {
             digitalWrite(ledGiallo,HIGH);  }
         else {
            digitalWrite(ledGiallo,LOW);  }
            
    } else
    {    digitalWrite(ledGiallo,LOW);  };
    
  if (Rosso == true) {
        if ((millis() % 1000) > 500){
             digitalWrite(ledRosso,HIGH);  }
         else {
            digitalWrite(ledRosso,LOW);  }
            
    } else
    {    digitalWrite(ledRosso,LOW);  };
  
  
  
  }




void loop() {
   lcdLM35();    //legge la temperatura

   if ((tempC >= tempOttimaMin) && (tempC <= tempOttimaMax))
       { Verde = true;
    } else {
      Verde = false;
    }; 
  
    if ((tempC > tempOttimaMax) && (tempC <= tempCritica))
       { Giallo = true;
    } else {
      Giallo = false;
    }; 
    
    if (tempC > tempCritica)
       { Rosso = true;
    } else {
      Rosso = false;
    };  
 
   AggiornaColori();   
      
}

Ciao a tutti....nel mio programma in pratica, non funziona niente...o per meglio dire viene tutto avviato ma senza che io abbia dato l'imput con il pulsante, e per il resto lasciamo perdere.... p.s.
Ogni singolo programma funziona perfettamente.
Rimane il problema di unirli e far attivare il ciclo con il button!!!
Ho fatto alcuni tentativi...ma non riesco a risolvere!!! :frowning:

acca90:
Ciao a tutti....nel mio programma in pratica, non funziona niente...o per meglio dire viene tutto avviato ma senza che io abbia dato l'imput con il pulsante, e per il resto lasciamo perdere....

be... ma facci capire... ora che cosa stai usando? hai ripensato alla mia struttura di programma?
io il bottone non l'ho proprio considerato ma se hai difficoltà a far partire un programma dopo la pressione di un tasto questo programma ti risulta palesemente complesso.
Mi pare di capire che ti manca il concetto di "top-down" della risoluzione dei problemi.... tu devi sempre puntare a risolvere un problema per volta: prima fai il programma che quando premi un bottone accende il led verde, poi aggiungi che quando accende il led verde fa il display della temperatura, poi fai che disquisisce sulla temperatura il led verde e giallo... e quando fra 2 settimane avrai fatto tutto l'aggeggio con il led ci aggiungi il servo.

Probabilmente è così.
Dal bottone deve partire l' lcd e lm35;
poi a seconda delle temperature vengono attivati sottoprogrammi diversi.
Il fatto è che non ho capito come posso integrarli.
Ho controllato il tuo programma, ma non va!!!
Un mio amico mi ha consigliato di usare i comandi switch/case; oppure if/else.
Tranquillamente riesco a far partire con il button singoli led, ma non riesco per sottoprogrammi!!!

acca90:
Probabilmente è così.
Dal bottone deve partire l' lcd e lm35;
poi a seconda delle temperature vengono attivati sottoprogrammi diversi.
Il fatto è che non ho capito come posso integrarli.
Ho controllato il tuo programma, ma non va!!!
Un mio amico mi ha consigliato di usare i comandi switch/case; oppure if/else.
Tranquillamente riesco a far partire con il button singoli led, ma non riesco per sottoprogrammi!!!

si non va per forza... non l'ho testato,non è completo e devi mettere a posto ingressi ed uscite... ma tu di quel programma dovevi capire il concetto generale del funzionamento... come funzionava in logica per poi implementarlo TE.
il costrutto switch case lo puoi usare ma viene usato per scelte multiple e comunque è sempre sostituibile con il costrutto if then else... nel tuo caso non saprei dove piazzarlo in ogni caso non è che perchè hai una bella istruzione la devi usare per forza.
...il serial... ed il display lcd... ti possono essere utilissime per fare il debug del programma e capire cosa va e cosa non va.

i sottoprogrammi si chiamano "procedure" e sono di fatto delle funzioni che ritornano "void" cioè nulla... togliti dalla testa la chiamata che hai fatto sul tuo programma... non si fa così...e non si può bloccare/sbloccare in automatico con un HIGH o un LOW l'esecuzione ... si fa come ho scritto sul mio codice ed un esempio è la chiamata alla procedura

 lcdLM35();    //legge la temperatura

e basta... tutto al più ci metti un if se è una chiamata condizionata ad una condizione (temperatura entro un certo range per esempio).

La procedura setup è particolare e viene eseguita solo appena acceso l'arduino mentre la procedura loop viene ripetuta all'infinito.
che ruolo ha il tasto? ok lo premo e partono le lucette... e poi cosa succede? lo ripremo e si spegne tutto?
questo potrebbe essere codificato per esempio in un codice loop di questo genere:

sulle var globlali dichiari
bool modoStart=false; // ---> se true è in start mode se no è stoppato...
e nel loop

tasto = digitalRead(pinTasto);
if (tasto == HIGH) {
while (tasto ==HIGH) {tasto = digitalRead(pinTasto); }; // interrompe il ciclo loop ed attende il
//fronte di discesa del tasto
modoStart = !modoStart; //scambia da modo start a stop.
};

if (modoStart) fai_Il_Caffe()
else boo fa niente...

Ciao....ho visto cosa era sbagliato nel programma e l'ho corretto.
Il valore compreso tra i 2 (cioè il led giallo) risponde esattamente alla temperatura.
Anche la temperatura va bene.Quindi penso già di aver fatto un bel passo in avanti, adesso devo solo aggiustare i valori nel miglior modo possibile.
Adesso mi manca una cosa da capire bene:
Come faccio a disattivare il servo e buzzer quando si abbassa la temperatura visto che sono altri 2 processi diversi?
Riesco ad attivarli, ma quando si abbassa la temperatura non si spengono.

#include <Servo.h>
#include <LiquidCrystal.h> 

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 
float tempC;      
int sensore = A1; 
int val = 0;                    
int vecchio_val = 0;            
int stato = 0;
int valore;
int angolo = 0;
Servo mioservo;


const byte tempOttima = 0;
const byte tempOttimaMax = 20;
const byte tempCritica = 25;
const byte ledgreen = 10;
const byte ledyellow = 9;
const byte ledred = 8;

bool green=false;
bool yellow=false;
bool red=false;
bool buzzer=false;
bool servo=false;
  
void setup() {                  
  lcd.begin(16, 2);
  pinMode(13, INPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  mioservo.attach(6);
  pinMode(7, OUTPUT);
}
void loop() {
  lcdlm35();
  
  if ((tempC >= tempOttima) && (tempC <= tempOttimaMax))
  {green = true;}
  else { green = false;};
  
  if ((tempC >tempOttimaMax) && (tempC <= tempCritica))
  {yellow = true; }
  else { yellow = false; };
  
  if (tempC > tempCritica)
  {red = true;}
  else {red = false;}
  
  if (tempC > tempCritica)
  {buzzer = true;}
  else {buzzer = false;}
  
  if (tempC > tempCritica)
  {servo = true;}
  else {servo = false;}
  aggiornacolori();
  }

void lcdlm35() {
  lcd.clear();
  lcd.print( "Temperatura...");
  tempC = analogRead(sensore);
  tempC = (5.0 * tempC * 100.0)/1024.0;
  lcd.setCursor(0, 1);
  lcd.print(tempC);
  lcd.print( (char) 223);
  lcd.print(" Celsius ");
  delay(1500);
  lcd.clear();
}

void aggiornacolori() {
  if (green == true) {
    digitalWrite(ledgreen, HIGH);
  }
  else {
    digitalWrite(ledgreen, LOW);
  };
  if (yellow == true) {
    if(( millis() % 1000) > 500)
    {
      digitalWrite(ledyellow, HIGH);
    }
    else {
      digitalWrite(ledyellow, LOW);
    }
  }
  else {
    digitalWrite(ledyellow, LOW);
  }
  if (red == true) {
    if(( millis() % 1000) > 500) {
      digitalWrite(ledred, HIGH);
    }
    else {
     digitalWrite(ledred, LOW);
    }
  }
  else {
    digitalWrite(ledred, LOW);
  }
  if ( buzzer == true) {
    if((millis()% 1000) < 500) {
      buzzer1();}
  }
   
  if (servo == true) {
    if((millis() % 1000) >500){
    servo1();}
  }
}

void buzzer1() {
  buzz(7, 1000, 500);
  delay(400);
  buzz(7, 2000, 500);
  delay(400);
}

void buzz(int targetPin, long frequency, long length) {
  long delayValue = 100000/frequency/7;
  long numCycles = frequency * length/ 1000;
  
  for (long p=0; p < numCycles; p++) {
    digitalWrite(targetPin, HIGH);
    delayMicroseconds(delayValue);
    digitalWrite(targetPin, LOW);
    delayMicroseconds(delayValue);
  }
}
    
void servo1() 
{
  for(angolo = 0; angolo < 180; angolo +=1)
{
mioservo.write(angolo);
delay(20);
}
 for(angolo = 180; angolo >= 1; angolo -=1)
{
 mioservo.write(angolo);
delay(20);
}
}

Ecco il codice.
Come posso regolare per bene il servo e il buzzer affinchè si disattivino appena la temperatura scende sotto i 25°?
Inoltre il buzzer non funziona come vorrei:
1)Perchè "suona" ogni tot di tempo e non come se fosse un allarme?
2)Perchè produce una "nota" completa ma semplicemente un minuscolo bip, non intendo come volume, ma come durata del suono, cioè è molto breve...

Grazie e scusatemi ancora!!!!

acca90:
Come posso regolare per bene il servo e il buzzer affinchè si disattivino appena la temperatura scende sotto i 25°?

Sui servo ti aiuterà qualcun altro...

Inoltre il buzzer non funziona come vorrei:
1)Perchè "suona" ogni tot di tempo e non come se fosse un allarme?

Perché la funzione per emettere il suono la chiami ogni tot, quindi viene suonata la nota ogni tot.

2)Perchè produce una "nota" completa ma semplicemente un minuscolo bip, non intendo come volume, ma come durata del suono, cioè è molto breve...

Per il motivo di cui sopra. Per far sì che la nota sia emessa sempre, bisogna che ci sia un generatore di onda quadra collegato al buzzer, altrimenti sentirai solo "sputacchi".
Perché non usi la funzione Tone, scusa?
http://arduino.cc/en/Reference/Tone

 if (red == true) {
    if(( millis() % 1000) > 500) {
      digitalWrite(ledred, HIGH);
    }
    else {
     digitalWrite(ledred, LOW);
    }
  }
  else {
    digitalWrite(ledred, LOW);
  }
  if ( buzzer == true) {
    if((millis()% 1000) < 500) {
      buzzer1();}
  }

vedi il codice sopra? il red è il mio if... il buzzer è il tuo...se il boolean "buzzer" è falso tu devi spegnerlo...ti manca il ramo else... addirittura potresti buttar via il tuo lavoro ed integrare il buzzer nel mio if red... fare tipo una cosa così:

if (red == true) {
    tone(pin, 1000);
    if(( millis() % 1000) > 500) {
      digitalWrite(ledred, HIGH);
    }
    else {
     digitalWrite(ledred, LOW);
    }
  }
  else {
    noTone(pin);
    digitalWrite(ledred, LOW);
  }

...forse poi spostando il tone dopo il digitalWrite High e mettendone un tone ad altra frequenza dopo il digitalwrite low potresti ottenere un bitonale simpatico.

...passiamo al servo?

Mi dà lo stesso problema di prima...anche cambiando le impostazioni!!!
Dà sempre quella specie di "sputo" =(

acca90:
Mi dà lo stesso problema di prima...anche cambiando le impostazioni!!!
Dà sempre quella specie di "sputo" =(

Ma hai provato ad usare la funzione Tone? Con la Tone NON puoi avere lo sputacchìo perché la funzione genera una nota con una determinata frequenza usando un timer del microcontrollore, quindi senza i problemi che ti avevo descritto del tuo programma.