Problemi sul software per un progetto!

Ciao a tutti, essendo un principiante ed avendo tempi ristretti, mi trovo nella situazione di chiedere un vostro aiuto...
Devo fare un progetto utile ad un esame per l'università, ma mi sono bloccato poichè non riesco a capire l'errore nel programma :~.
I componenti che devo usare sono:
Arduino uno;
sensore termico LM35;
un microservo;
un LCD 16x2;
un pulsantino (per l'accensione e spegnimento);
un buzzer;
3 led(rosso, giallo e verde).
Il mio scopo è quello di avere un termostato in cui la temperatura viene visualizzata sull' LCD;
a determinate temperature vengono attivati differenti sottoprogrammi:
temperatura ottimale: led verde;
temperatura critica: led giallo ad intermittenza;
superata la temperatura critica: led rosso ad intermittenza, servo e buzzer.
Ecco il programma.

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

#define BUTTON 1                    
#define LM35 2
#define D4 3
#define D5 4
#define D6 5
#define D7 6
#define RS 7
#define EN 8
#define SERVO 9
#define BUZZER 10
#define LEDRED 11
#define LEDYELLOW 12
#define LEDGREEN 13


float vref = 1.1;
LiquidCrystal lcd( D4, D5, D6, D7, RS, EN );
Servo myservo;

int val = 0;                        
int vecchio_val = 0;                
int stato = 0;                      
int pos = 0;
int fascia;
int valore;

void setup() {
  pinMode( BUTTON, INPUT);
  pinMode( LM35, INPUT );
  pinMode( LEDGREEN, OUTPUT);
  analogReference( INTERNAL );
  analogRead( LM35 );
  lcd.begin( 2, 16 );
  pinMode( LEDYELLOW, OUTPUT );
  pinMode( LEDRED, OUTPUT );
  pinMode( BUZZER, OUTPUT );
  myservo.attach ( 9 );
  }
  
void loop(void) {
  val = digitalRead(BUTTON);
  
  if ((val = HIGH) && (vecchio_val == LOW)) {
    stato = 1 - stato;
    delay(35);
  }
  vecchio_val = val;
  
  if (stato == 1) {
    lcdLM35(), HIGH;
    segnalatoriLM35(), HIGH;
  }
  else {
    lcdLM35(), LOW;
    segnalatoriLM35(), LOW;
  }
  
  
  void lcdLM35()
  {
    float temp = readTemp());  
    sendTempToLCD( temp );    
  }


float readTemp()
{
  float temp = 0.0;       
  int val = 0;            
  int nread = 5;          
  float somma = 0.0;      
  for (int i=0; i<nread; i++)
  {
    val = analogRead( LM35 );               
    temp = ( 100.0 *  vref * val ) / 1024.0;   
    somma += temp;                                
  }   
  return ( somma / nread );                     
}


void sendTempToLCD( float temp )
{
  lcd.clear();                
  lcd.setCursor( 0, 0 );     
  lcd.print( "Temperatura di: ");
  lcd.setCursor( 0, 1 );     
  lcd.print( temp );         
  lcd.print( ' ' );          
  lcd.print( (char) 223 );   
  lcd.print( 'C' );
  delay( 250 );
}


void segnalatoriLM35()
{
valore=analogRead(LM35);     
fascia=map(valore, 0, 1023, 0, 3);
if (fascia==0) fascia=1;       
spegni(); 
digitalWrite(14-fascia, HIGH);  
delay(500);                     
}

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

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

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

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

void servo() { 
  for(pos = 0; pos < 180; pos +=1)
  {
    myservo.write(pos);
    delay(15);
  }
  for(pos = 180 ;pos >= 1; pos -=1)
  {
  myservo.write(pos);
  delay(15);
  }  
}

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

P.S.
nelle temperature deve essere presente un range,
il led verde deve essere acceso tra 0 e 20°C;
il led giallo invece tra 21°C e 30°C;
il led rosso, buzzer e microservo, infine, dai 31°C in poi.

Grazie in anticipo per l'aiuto :open_mouth:

Ma qual'è il problema di fondo?
Dov'è che ti sei bloccato,cosa non capisci?
Se tu esponessi più informazioni sarebbe più semplice poterti aiutare :slight_smile:

Quando vado a fare la verifica mi da degli errori nei sottoprogrammi...e non riesco a capire il motivo.
Visto che non riesco a finire il programma, non posso nemmeno provare se funziona come io voglio.
precisamente questo:

progetto.ino: In function 'void loop()':
progetto:63: error: a function-definition is not allowed here before '{' token
progetto:70: error: a function-definition is not allowed here before '{' token
progetto:165: error: expected `}' at end of input

Ti manca semplicemente una parentesi graffa di chiusura del loop

void loop(void) {
  val = digitalRead(BUTTON);
  
  if ((val = HIGH) && (vecchio_val == LOW)) {
    stato = 1 - stato;
    delay(35);
  }
  vecchio_val = val;
  
  if (stato == 1) {
    lcdLM35(), HIGH;
    segnalatoriLM35(), HIGH;
  }
  else {
    lcdLM35(), LOW;
    segnalatoriLM35(), LOW;
  }
} LA DEVI INSERIRE QUI

e comunque ci sono un sacco di errori

l'assegnazione dei pin LCd e' errata
LiquidCrystal lcd( D4, D5, D6, D7, RS, EN );
quella corretta e' LiquidCrystal lcd( RS, EN, D4, D5, D6, D7 );

l'LM35 lo hai collegato a un input digitale ( Pin 2 )
dato che devi leggere un valore analogico, va' usato su una porta da A0 a A5

in lcd.begin( 2, 16 );
prima si mette il numero dei caratteri e poi le righe. lcd.begin( 16 , 2 );

e poi chissa' cosa hai combinato

Grazie...infatti ho notato che qualcosa non quadrava...
Altri errori di che genere?

io mi sono fermato alle prime righe

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!!!