uscita immediata da un loop o un ciclo

@Pablos
ho visto il link che mi hai mandato, sembra buono... mi da un errore il codice che ha postato il tipo però... ho anche aggiunto la libreria che mi dice di aggiungere, ma non mi riconosce GICR |= ( 1 < < INT0);
forse perchè lui usa un atmega8... bo...

Mica li devi sostituire e basta... Sennò quale sarebbe la differenza?
Vedo di buttare giù una bozza, poi la smussi te...

Ti consiglio di leggere qui: http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Scusami se il codice è diventato "largo" ma mi sta troppo sulle scatole che il programma di Arduino usi due spazi per le indentazioni, quindi ne uso uno esterno per scrivere il codice e uso i TAB, ma quando incolli il codice qui poi è un macello.... Ti consiglio di installarti Notepad++ (è gratuito) e incollare li il codice.

#include "pitches.h"

int ledRosso = 4;
int ledBlu = 5;
int pulsanteRosso = 2;
int pulsanteBlu = 3;
int sirena = 6;
int statoRosso = 0;
int statoBlu = 0;
int melody[] = {
	NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};
int noteDurations[] = {
	4, 8, 8, 4,4,4,4,4 };




void setup(){
	pinMode (ledRosso, OUTPUT);
	pinMode (ledBlu, OUTPUT);
	pinMode (pulsanteRosso, INPUT);
	pinMode (pulsanteBlu, INPUT);
	pinMode (sirena, OUTPUT);
}


unsigned long int inizioTimer;
byte stato;
bool toneImpostato;
byte contatore;
bool fineCiclo;

void loop() {
	statoRosso=digitalRead(pulsanteRosso);
	if (statoRosso==HIGH){
		if (!fineCiclo) {
			digitalWrite(ledRosso, HIGH);
			if (contatore < 5) {
				switch (stato) {
					case 0:	
						if (!toneImpostato) {
							tone(sirena, 880, 200);
							toneImpostato = true;
							inizioTimer = millis();
						};
						if (millis() - inizioTimer >= 50) {
							stato++;
							toneImpostato = false;
						};
						break;
						
					case 1;
						if (!toneImpostato) {
							tone(sirena, 1000, 200);
							toneImpostato = true;
							inizioTimer = millis();
						};
						if (millis() - inizioTimer >= 50) {
							stato++;
							toneImpostato = false;
						};
						break;
						
					case 2:
						if (!toneImpostato) {
							tone(sirena, 1400, 200);
							toneImpostato = true;
							inizioTimer = millis();
						};
						if (millis() - inizioTimer >= 50) {
							stato = 0;
							contatore++;
							toneImpostato = false;
						};
						break;
					
					default:
						stato = 0;
						contatore = 0;
						toneImpostato = false;
						break;
					
				}
			}
			else {
				if (!toneImpostato) {		//Ho riciclato una variabile che in questa parte del codice non serve
					inizioTimer = millis();	//Qui ne ho riciclata un'altra
					toneImpostato = true;
				}
				if (toneImpostato && (millis() - inizioTimer >= 1000)) {
					digitalWrite(ledRosso, LOW);
					fineCiclo = true;
				};
			};
		}
		//Se non metti questa riga lui ti esegue a diritto
		//Così invece fa un ciclo e prima di fare il successivo aspetta che tu alzi il tasto
		else (!digitalWrite(ledRosso, HIGH)) fineCiclo = false;		//Se non metti questa riga lui ti esegue a diritto
	}
	else {
		melodia();
	}
}

void melodia(){
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second 
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000/noteDurations[thisNote];
    tone(sirena, melody[thisNote],noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(sirena);
  }
}

non centra perchè lui è dentro a una funzione quando ha bisogno di leggere la pressione del bottone che impegna il suo tempo, non ha mica un delay da 10 minuti

loop()

Vai alla funzione 1()
Vai alla funzione 2()
Vai alla funzione 3()
Vai alla funzione 4()
leggi il pulsante

il pulsante lo legge solo quando ha terminato le 4 funzioni, ci vuole qualcosa che intercetti il pulsante interrompendo per un istante tutto quello che il micro sta facendo, questo lo fa solo attivando un interrupt

P.S. Per usare gli interrupt leggi qui:
http://arduino.cc/en/Reference/AttachInterrupt
http://arduino.cc/en/Reference/DetachInterrupt

@Pablos
Prima di dare suggerimenti agli altri ti consiglio di approfondire tu stesso le tue conoscenze in materia, visto che non sai la differenza fra delay() e millis() e che suggerisci improbabili esempi sulla gestione degli interrupt quando ci sono le apposite funzioni... Inoltre qui, anche usando l'interrupt, se sei bloccato in un dealy non ne esci.
P.S. Leggi per bene il mio codice e poi parla... Inoltre consiglio anche a te di leggere http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Si janos vado a studiare, intanto tu fagli usare un millis() per 50ms

Per te sono un'inezia 50ms ma nella realtà dell'elettronica 50ms sono un tempo abissale. Pensa che il processore esegue un'istruzione ogni 62ns, quindi con un delay(50) fai stare fermo il processore per ben 806.000 operazioni. Inoltre quello che conta di più è imparare il metodo, quando sai come usarlo poi decidi tu se e quando usarlo...

pablos:
Si janos vado a studiare, intanto tu fagli usare un millis() per 50ms

ai fini pratici ha ragione pablos ai fini teorici ha ragione janos :grin: ora non litigate o vi mando al quizzettone :wink:

ehm i delay NON bloccano gli interrupt, altrimentio non usciresti mai dalla delay visto che è basata su un interrupt del timer1 :slight_smile:

Si janos vado a studiare, intanto tu fagli usare un millis() per 50ms

Per te sono un'inezia 50ms ma nella realtà dell'elettronica 50ms

ma un pulsante premuto (da un essere umano) per meno di 50ms è abbastanza impossibile nella realtà..

Il problema è che quei delay(50) sono in loop e seguiti anche da delay(1000), il che rende il tempo della funzione troppo alto.

Io sono d'accordo con janos di usare la millis() come per l'esempio blinkWithoutDelay;
in particolare , mio caro matt-korban, se non lo fai, finchè l'arduino suona NON legge i pulsanti.

il sistema consigliato da pablos non è errato, ma un'alternativa assai valida: l'uso della millis costringe a riscirvere buona parte del codice, con memorizzazione dello stato tra un loop e l'altro (macchina a stati), e permette di interrompere a metà l'esecuzione di una canzoncina per effettuarne un altra.
l'interrupt permette di sostituire la digitalRead con una variabile booleana settata dall'interrupt e azzerata dopo il suo uso nel loop(l'interrupt conterrà al suo interno un algoritmo anti-bounce, o un anti-bounce HardWare), ma essa non verrà usata finchè il loop corrente è finito, quindi la canzincina deve finire.

kiss

lesto:
ehm i delay NON bloccano gli interrupt, altrimentio non usciresti mai dalla delay visto che è basata su un interrupt del timer1 :slight_smile:

Sono d'accordo con te, ma se lanci un delay(1000) e avviene un interrupt tu vai a eseguire l'interrupt. Il problema è che da interrupt non puoi fare niente perché una volta uscito torni a finire quanto ti resta del delay...

Diciamo che una soluzione intelligente, vista l'applicazione, sarebbe stata di lasciare i delay(50) e sostituire il delay(1000) con millis()...

approvo su tutta la linea :grin:

cioè ma io posso scatenare un casino epocale per un quizzone di m____a?
quindi in parole povere mio caro lesto, quello che dovrei fare è???
usare gli interrupt oppure sostituire i delay con dei millis?

da quello che ho capito non basta sostituire le voci delay con millis, devo pure modificare il programma, giusto?

ma poi ragazzi il delay 1000 non mi da nessun fastidio in quanto tiene il led acceso per un secondo dopo la sirena, e questo mi sta bene... quello che blocca il programma è l'esecuzione della canzoncina prima che venga premuto il pulsante... una volta premuto il pulsante infatti, la canzoncina si ferma e parte una "sirena" che dura qualcosa come un secondo, e si accende un led...

Mi sono preso la briga di prendere il tuo codice e modificarlo, ti ho dato tutti i link per documentarti, che vuoi di più?

un lucano! hahahaha ma si, ho caricato il tuo codice, ma non esce comunque dalla canzoncina quando premo il pulsante... magari riprovo un altro po e provo a smanettarci su, vediamo che succede...

@janos
sto sistemando il tuo codice sull'ide e sembra tutto ok, però quando vado a caricare mi da questo errore:

could not convert 'digitalWrite(((uint8_t)ledRosso), 1u)' to 'bool'

su questa riga:

else (!digitalWrite(ledRosso, HIGH)) fineCiclo = false;		//Se non metti questa riga lui ti esegue a diritto

qualche idea?

digitalòWrite ritorna HIGH o LOW (int), non true/false (boolean), janos ha confuso questo particolare.

Sistema l'if di conseguenza.

No, l'errore non è li. La condizione dell'if può essere applicata anche ai numeri (in questo caso un int) e viene considerato falso lo zero e vero un qualsiasi numero diverso da zero. Il problema è che mi sono confuso, prova a sostiruire la riga con questo:

else (!statoRosso) fineCiclo = false;		//Se non metti questa riga lui ti esegue a diritto

hahahaha sembra la storia infinita... mi da un altro errore...

expected ';' before 'fineCiclo'

comunque ho provato a risolvere cambiando l'else con else if, oppure modificando la punteggiatura e carica bene... il problema però rimane sempre... mentre suona non legge il pulsante... devo tenerlo premuto per farglielo leggere alla fine della musichetta...

Allora, vediamo un attimo di fare il punto perché probabilente non ho capito bene cose deve fare... Me lo spieghi nel dettaglio?