Come scrivere riga

Buonasera non sono un esperto in C volevo chiedere se nella funzione void loop()
dove il ciclo si ripete di continuo come posso ad esempio se ho al mikrocontroller
una resistenza di pulup al 12 della morsettiera di arduino ,tramite un pulsante cambio stato logico e lo porto a stato logico basso fin qua tutto ok
ora vorrei che ogni volta che premo il pulsante ad esempio se ho impostato come uscite ad il pin 2 ,pin 3 , pin 4 della morsettiera di arduino lui mi deve dare se con if ho avuto la prima condizione di true mi deve dare uscita pin2
e fermarsi,ripremo di nuovo il pulsante avviene la seconda condizione di true e mi deve dare uscita pin 3
e fermarsi,poi ripremo per l ultima volta il pulsante avviene la terza condizione di true mi deve dare uscita
pin 4 dopo di che il puo ripartire il codice nel void loop() andare di nuovo accapo.

non so se sono stato chiaro nel spiegare il mio problema
l
la prima condizione di true ad esempio se tramite un fotoaccoppiatore ho avuto un stato logico alto ho basso al pin 7 della morsettiera di arduino.

a seconda condizione di true ad esempio se tramite un fotoaccoppiatore ho avuto un stato logico alto ho basso al pin 8 della morsettiera di arduino.

a terza condizione di true ad esempio se tramite un fotoaccoppiatore ho avuto un stato logico alto ho basso al pin 9 della morsettiera di arduino

forse dalla funzione void loop () devo chiamare ad esempio tre funzione

void loop()
{
funzione1();

funzione2();

funzione3();

}

pero queste funzioni devono partire ad esempio funzione1() eseguita ok
passa alla funzione 2 eseguita ok passa alla funzione3() pero se esempio la funzione 1 non
esegue listruzzione da me data deve bloccarsi affinche viene esegita per passare alla funzione2 e
cosi via .

ho provato col ciclo for ma non ci sono riuscito
forse con interup non so sono confuso
grazie attendo vostra risposta

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:

Salvo1969:
non so se sono stato chiaro nel spiegare il mio problema

Per me no. Non capisco cosa vuol dire "...mi deve dare uscita pin2 e fermarsi"
Fermarsi di che ?

sintetizzo, vediamo se ho capito. Normalmente con un pulsante accendi/spegni un led.
Tu invece vorresti farlo su 4 led in successione.
Partiamo con 4 led spenti...
premo una volta... accendo led su pin 2...
premo ancora... spengo led 2 e accendo led 3
e cosi fino al led 4 per poi ricominciare dal led 2 ???

Salvo1969 così non si capisce e il motivo è che neanche tu hai le idee chiare o almeno tanto chiare
da esporle in modo comprensibile.

Tutto insieme non è possibile descriverlo e allora una cosa per volta, dividi il problema in tanti sotto problemi.
Intanto vediamo cosa devi connettere alla morsettiera di arduino, completa il seguente codice:

// es. #define PIN_PULSANTE0    3
#define PIN_PULSANTE0

// es. #define PIN_LED0    4
#define PIN_LED0 
#define PIN_LED1
#define PIN_LED2

I due esempi descrivono che al pin 3 c'è collegato il pulsante, al 4 c'è collegato un led.

Quando devi descrivere i comportamenti del programma, puoi usare lo pseudo codice, es:

IF PULSANTE0 == premuto {
Fai questo
Fai quest'altro
ecc.
}

Non esagerare con la descrizione totale di cosa deve fare il programma, limitati a descrivere la prima
cosa che deve fare, poi la seconda, ecc.

Ciao.

:slight_smile:

IF PULSANTE0 == premuto {
Fai questo prima istruzione

// grazie pero se tengo premuto PULSANTE0
// lui mi deve fare solo la prima istruzione poi lascio il //pulsante ripremo lui mi deve fare la //seconda istruzione solo la seconda
// lo rilascio per ripremerlo di nuovo lui mi deve eseguire la terza istruzione solo la terza

Fai quest'altro seconda istruzione
Fai quest'altro seconda istruzione
}

grazie

La descrizione nel linguaggio umano sarebbe quindi la seguente.
Devo fare eseguire 3 funzioni da richiesta utente.
L'ultente ha un solo pulsante a disposizione.
Alla prima pressione e rilascio deve eseguire la funzione0
Alla seconda pressione e rilascio deve eseguire la funzione1
Alla terza pressione e rilascio deve eseguire la funzione2

Per fare si che il programma si comporti così ci sono tanti modi, ma entrambe devono prima risolvere il problema che
affligge i pulsanti meccanici, in breve alla pressione del pulsante anziché avere un solo cambio di stato in un tempo infinitesimale, abbiamo più di un cambio di stato (rimbalzo), ciò avviene molto rapidamente e se il micro fosse lento, il rimbalzo non influirebbe negativamente. Purtroppo il micro è rapido ed è in gradi di leggere il ribalzo e lo interpreta con precisione, riproponendo tutti i cambi di stato dovuti al ribalzo del contatto.

Quindi prima devi risolvere il problema del rimbalzo, ci sono vari modo uno di questo è stato usato in un esempio presente nell'ide.

Risolto il problema debuonce e sufficente contare quante volte il pulsante è stato premuto. Serve una variabile contatore

byte counterP0 = 0;

counterP0 può contenere i seguenti valori:
0 (nessuna funzione eseguita),
1 (esegui funzione0)
2 (esegui funzione1)
3 (esegui funzione2)

IF PULSANTE0 == premuto {
    couterP0++;  // incrementa di uno 
    if (counterP0 > 3)
          counterP0 = 0; 
}

switch (counterP0) {
    case 0:
            // non fannulla
            break;
    case 1:
            funzione0();   // chiama funzione0
            break;
    case 2:
           funzione1();   // chiama funzione1
            break;
    case 3:
           funzione2();   // chiama funzione2
            break;
}

Questo codice però ha un comportamento non richiesto, descritto a seguire:
Se counterP0 vale 1 verrà chiamata la funzione0 e ciò avverrà ad ogni ciclo di loop.
Tu invece vorresti che se la funzione0 è già stata eseguita non deve essere eseguita una seconda e terza volta.

Si può ovviare in tanti modi, mantenendo questo codice, si deve introdurre nella funzione0, un guardian, la funzione si presenterà simile alla seguente:

void funzione0() {
     if (alredyRun0 == true)
         return;
    
     // altro codice funzionale

     // prima di terminare configurare il guardian
     // alredyRun0 = true;
}

Quindi nel loop funzione0 viene chiamata fintanto che counterP0 vale "1", ma la prima volta alredyRun0 vale "false"
e quindi tutta la funzione viene eseguita e terminata. La seconda chiamata alredyRun0 vale "true" e cioè fa terminare la funzione prematuramente, infatti "return" impone l'uscita dalla funzione.

Si può sicuramente scrivere in modo meno macchinoso e meno dispendioso di memoria, ma per fini didattici tutto o permesso.

Forse è il caso che metti tutto assieme in un sketch e lo posto. Occhio che è meglio che introduci meno codice possibile,
ad esempio scriverai solo il case 1 chiamando la funzione0.
Usa Serial.println("entro in funzione0), Serial.println(esco da funzione0), stampi anche il valore di counterP0.

Ciao.

:slight_smile: Grazie Mauro qualcosa pero non faccio ancora esatto sono
troppo incapace nella materia
ti posto lo sketch mi dice errore --- expected initializer before IF---

#define led1 2
#define led2 3
#define led3 4
#define PULSANTE0 7

void setup() {

pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(PULSANTE0,INPUT);

}

void loop()
IF PULSANTE0== premuto {
counterP0++;
if(counterP0 >3)
counterP0 = 0;
}
switcht(counterP0)
{
Case 0 :
break;
Case 1 : funzione0();
break;
Case 2 : funzione1();
break;
Case 3 : funzione2();
break;
}
void funzione0()
{
if(alredyRun0==true)
return;
Serial.println("entro in funzione 0");
if (digitalRead(input1)==LOW)
digitalWrite(led1)==HIGH)
return;
}
void funzione1()
{
if(alredyRun0==true)
return;
Serial.println("entro in funzione 0");
if (digitalRead(input1)==LOW)
digitalWrite(led2)==HIGH)
return;
}
void funzione2()
{
if(alredyRun0==true)
return;
Serial.println("entro in funzione 0");
if (digitalRead(input1)==LOW)
digitalWrite(led3)==HIGH)
return;
}
}

:o non ci sto capendo piu niente fumo ora mi dice Case was not declared in this al case1

#define led1 2
#define led2 3
#define led3 4
#define PULSANTE 7
int counterP0;
boolean premuto=true;

void setup() {

pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(PULSANTE,INPUT);

}

void loop() {
if (PULSANTE == premuto )
counterP0++;
if(counterP0 >3)
counterP0 = 0;

{
switch (counterP0)
Case 0 :

break;
Case 1 : funzione0()

if(alredyRun0==true)
return;
Serial.println("entro in funzione 0");
if (digitalRead(input1)==LOW)
digitalWrite(led1)==HIGH)
return;

break;
Case 2 : funzione1()

if(alredyRun0==true)
return;
Serial.println("entro in funzione 1");
if (digitalRead(input1)==LOW)
digitalWrite(led1)==HIGH)
return;

break;
Case 3 : funzione2()

if(alredyRun0==true)
return;
Serial.println("entro in funzione 2");
if (digitalRead(input1)==LOW)
digitalWrite(led1)==HIGH)
return;

}

}

:slight_smile: Grazie Mauro qualcosa pero non faccio ancora esatto sono
troppo incapace nella materia
ti posto lo sketch mi dice errore --- expected initializer before IF---

Si vede, comunque si tratta di un malinteso. La IF non è una keyword C (C Language Keywords).

Il malinteso nasce dalla parola psedo codice che ho usato prima, qui trovi maggiori info in merito:Pseudocodice - Wikipedia

Scrivendo direttamente in form si possono commettere errori di sintassi, ciò capita anche a chi programma tutti i giorni, cio posso sbagliare PULSANTE0 e scrivere pulsante0, l'utente che legge si accorge dell'errore e scrive
la cosa corretta nell'editor dell'ide. Ecco il vantaggio di usare lo pseudocodice e che non esiste l'errore di sintassi, perché l'obbiettivo è descrivere l'algoritmo in modo facilmente interpretabile anche da chi non conosce il linguaccio C.

Descrivere l'algoritmo con il linguaggio correntemente usato dagli umani è proprio impossibile perché
introduce ambiguità e se c'è ambiguità non può essere un algoritmo. Per cui si è cercato (e ancora si cerca)
un modo per descrivere l'algoritmo, che non lasci spazio all'ambiguità, che sia comprensibile anche da chi non conosce il linguaggio di programmazione che si intende usare, e che abbia tante altre caratteristiche da renderlo un linguaggio universale e usabile in qualunque ambito della programmazione.

Il primo pulsante nel form del forum serve a pubblicare codice sorgente, grazie a questo tag, il codice sorgente
viene inserito in una minipage e formattato in modo più leggibile. Quindi modifica il tuo post, selezioni il codice sorgente e poi premi il primo pulsante </>

La prima if corretta:

void loop() { // non dimenticare la parentesi apertura "blocco di codice", e quella di chiusura qui non visibile

    // == HIGH o == LOW in base allo stato corrente che ha il pin quando il pulsante risulta premuto
    if ( digitalRead(PULSANTE0) == HIGH )  { 

        counterP0++;
        if ( counterP0 > 3 )
            counterP0 = 0;

    } // endif  digitalRead(PULSANTE0) == HIGH


    // il resto del codice qui

Basta provare questo codice soltanto, aggiungendo una riga che stampa il valore di counterP0, tuttavia
counterP0 non è stato dichiarato in nessun posto e il compilatore non sa come usarlo, quindi sotto il gruppo
delle #define, inserisce un commento e poi dichiari la variabile, più o meno così:

byte counterP0 = 0;

Per stampare con Serial.print, ti devi un po arrangiare perché non mi ricordo bene, prova
con << Serial.print(counterP0); >> (i simboli >><< servono solo a evidenziare il codice e non devi inserirli).

Tuttavia stamperà sul serial monitor a tutta velocità, la cosa più adatta invece sarebbe di stampare solo
quando counterP0 ha cambiato valore, si può fare nel seguente modo:

// le #define sono macro per differneziarle dalle variabili si scrivono in maiuscolo, puoi anche usare
// il simbolo _ come separatore , es LED_0. 
// PS: i programmatori contano sempre a partire da zero, per questo LED0, c'è un motivo per ciò ma ancora è  
// presto
 
// define constant
#define LED0     2
#define LED1     3
#define LED2     4
#define PULSANTE0 7

// declare global variable
byte counterP0 = 0;
byte oldCounterP0 = 255;

void setup() {
 
    pinMode( LED0, OUTPUT );
    pinMode( LED1, OUTPUT );
    pinMode( LED2, OUTPUT );

    pinMode( PULSANTE0, INPUT );

}

void loop() {

     if ( digitalRead(PULSANTE0) == HIGH )  { 

        counterP0++;
        if ( counterP0 > 3 )
            counterP0 = 0;

    } // endif  digitalRead(PULSANTE0) == HIGH

    if (counterP0 != oldCounterP0) {
        Serial.print( counterP0 );
    }

}

Questo pezzo di codice ti mostra il problema del rimbalzo di cui è afflitto.

non ci sto capendo piu niente fumo ora mi dice Case was not declared in this al case1

Sei cosciente che senza un libro sul C, il tuo cervello si può sciogliere come burro, senza raggiungere il risultato.

Ciao.

:slight_smile: grazie Mauro per il consiglio oggi mi sona andato a comprare il libro in C
oggi ho progammato con la scheda di arduino il codice mi funziona cioe premo
PULSANTE_O mi apre il canale tra INPUT1 e LED1 ripremo PULSANTE_O e
mi apre il canale tra INPUT2 e LED2 e cosi via pero avvolte mi salta se
sono alla posizione INPUT1 e LED1 premo PULSANTE_O mi va INPUT3 e LED3
forse a che fare con rinbalzo essere sincero no sono riuscito ad piazzare nel codice
ecco lo sketc

#define LED1 2
#define LED2 3
#define LED3 4
#define PULSANTE_0 7
#define INPUT_1 11
#define INPUT_2 12
#define INPUT_3 13
int counterPO=0;
int ouldCounterPO=255;

void setup() {
pinMode (LED1,OUTPUT);
pinMode (LED2,OUTPUT);
pinMode (LED3,OUTPUT);
pinMode (PULSANTE_0,INPUT);
pinMode (INPUT_1,INPUT);
pinMode (INPUT_2,INPUT);
pinMode (INPUT_3,INPUT);
Serial.begin(9600);
}

void loop() {
if (digitalRead(PULSANTE_0)==LOW)
counterPO++;
if( counterPO>3)
counterPO = 0;
{
switch (counterPO) {
case 0: // non fannulla
break;

case 1:
void funzione0(); // chiama funzione0
if (digitalRead(INPUT_1)==LOW)
{
digitalWrite(LED1, HIGH);
Serial.print("sono la funzione 1");
}
else if (digitalRead(INPUT_1)==HIGH)
{
digitalWrite(LED1, LOW);
}
break;

case 2:
void funzione1(); // chiama funzione1
if (digitalRead(INPUT_2)==LOW)
{
digitalWrite(LED2, HIGH);
Serial.print("sono la funzione 2 ");
}
else if (digitalRead(INPUT_2)==HIGH)
{
digitalWrite(LED2, LOW);
}
break;

scusa ne ho dimenticato un pezzo

#define LED1 2
#define LED2 3
#define LED3 4
#define PULSANTE_0 7
#define INPUT_1 11
#define INPUT_2 12
#define INPUT_3 13
int counterPO=0;
int ouldCounterPO=255;

void setup() {
pinMode (LED1,OUTPUT);
pinMode (LED2,OUTPUT);
pinMode (LED3,OUTPUT);
pinMode (PULSANTE_0,INPUT);
pinMode (INPUT_1,INPUT);
pinMode (INPUT_2,INPUT);
pinMode (INPUT_3,INPUT);
Serial.begin(9600);
}

void loop() {
if (digitalRead(PULSANTE_0)==LOW)
counterPO++;
if( counterPO>3)
counterPO = 0;
{
switch (counterPO) {
case 0: // non fannulla
break;

case 1:
void funzione0(); // chiama funzione0
if (digitalRead(INPUT_1)==LOW)
{
digitalWrite(LED1, HIGH);
Serial.print("sono la funzione 1");
}
else if (digitalRead(INPUT_1)==HIGH)
{
digitalWrite(LED1, LOW);
}
break;

case 2:
void funzione1(); // chiama funzione1
if (digitalRead(INPUT_2)==LOW)
{
digitalWrite(LED2, HIGH);
Serial.print("sono la funzione 2 ");
}
else if (digitalRead(INPUT_2)==HIGH)
{
digitalWrite(LED2, LOW);
}
break;

case 3:
void funzione2(); // chiama funzione2
if (digitalRead(INPUT_3)==LOW)
{
digitalWrite(LED3, HIGH);
Serial.print("sono la funzione 3 ");
}
else if (digitalRead(INPUT_3)==HIGH)
{
digitalWrite(LED3, LOW);
}

break;

}
}

}

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.

Ti consiglio anche di usare CTRL+T dentro all'IDE, sistema un pò l'indentazione del codice

:slight_smile: Grazie nid69ita

:o buonasera a tutti , MauroTec
volevo chiedere alla variabile counterPO o assegnato il valore di 0
quando il mio pulsante lo premo porto attraverso la resistenza di
pullup allo stato di Low, con lo la condizione di if incremeto la
varibile counter di 1 (counterPO++) e dico alloperatore =
finche ( counterPO>3) e piu piccolo di 3 incrementa
dopo ritorna a zero ora attraverso il monitor seriale di arduino
quando tengo il pulsante sempre premuto mi da Serial.print(counterPO)
123 - lo porto a 0 ----premo una volta e va ad 1 ed e giusto ----ripremo va a 2 e pure giusto---
ripremo di nuovo anziche andare a 3 ritorna ad 1-----
sembra che avvolte nel pulsante il contatto sbalza

grazie non vorrei che vi sto stressando troppo

}

void loop() {
if (digitalRead(PULSANTE)==LOW) 
counterPO++;
if( counterPO>3)
counterPO = 0;
Serial.print(counterPO);

 
{

:slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile:
Buona sera --- MauroTec il problema del sbalzo pulsante lo risolto
mi manca solo il guardian per fare eseguire solo una volta lo switch

ti posto lo sketch

#define LED1 2
 #define LED2 3
 #define LED3 4
 #define PULSANTE_0 7
 #define INPUT_1 11
 #define INPUT_2 12
 #define INPUT_3 13
 int counterPO=0;
 //int ouldCounterPO=255;
 
int statopulsante = LOW;         
int pulsantepremuto = 0;        
           
          
int tempoSbalzo = 200;         
unsigned long pulsanteTempo = 0;   
    



void setup() {
 pinMode (LED1,OUTPUT);
pinMode (LED2,OUTPUT);
pinMode (LED3,OUTPUT);
pinMode (PULSANTE_0,INPUT);
pinMode (INPUT_1,INPUT);
pinMode (INPUT_2,INPUT);
pinMode (INPUT_3,INPUT);


Serial.begin(9600);
}

void loop() {

 statopulsante=digitalRead (PULSANTE_0);
if (statopulsante ==LOW)
pulsanteTempo  = millis();    
  pulsantepremuto = 1;      
  if ((millis() - pulsanteTempo > tempoSbalzo) && pulsantepremuto == 1)
  {
  
    pulsantepremuto = 0;    
  }
counterPO++;
if( counterPO>3)
counterPO = 0;
{
switch (counterPO) {
case 0:   // non fannulla
break;            

case 1:   
void funzione0();  // chiama funzione0
if (digitalRead(INPUT_1)==LOW)
{
digitalWrite(LED1, HIGH);
Serial.print("sono la funzione 1");
}
else if (digitalRead(INPUT_1)==HIGH)
{     
digitalWrite(LED1, LOW);
}     
 break;


case 2:
void funzione1();   // chiama funzione1
if (digitalRead(INPUT_2)==LOW)
{
digitalWrite(LED2, HIGH);
Serial.print("sono la funzione 2 ");      
}
else if (digitalRead(INPUT_2)==HIGH)
{     
digitalWrite(LED2, LOW);
}  
break;
           





case 3:
void funzione2();   // chiama funzione2
if (digitalRead(INPUT_3)==LOW)
{
digitalWrite(LED3, HIGH);
Serial.print("sono la funzione 3 "); 
}
else if (digitalRead(INPUT_3)==HIGH)
{     
digitalWrite(LED3, LOW);
} 


break;


}
}

}

Buona sera --- MauroTec il problema del sbalzo pulsante lo risolto
mi manca solo il guardian per fare eseguire solo una volta lo switch

ti posto lo sketch

Vedo che stai usando millis e mi sembra anche in modo non consueto e ciò lascia intendere sia farina del tuo sacco, cioè ha capito come mettere a frutto millis().

Il libro che hai comprato di sicuro ha un merito riguardo ai progressi fatti. Sono sicuro che ci arriverai da solo, rileggendo la parte iniziale, dove si parla dei tipi di dato, io aggiungo che in questo ambito usare il tipo 'int' per una variabile che lungo il programma non supererà mai il valore di 255 è considerato uno spreco.

Usare il tipo giusto, chiedendosi se serve usare tipi con segno o meno.

Il guardian viene dalla descrizione delle macchine a stati finiti, ed è interpretabile in tanti modi, qui prende forma di un variabile di tipo 'bool', una per ogni funzione. La puoi applicare nel modo che ti ho mostrato prima oppure nello "switch case".

Devi porre la chiamata a funzione sotto una condizione if, es in pseudocodice:
Il nome della variabile di tipo 'bool' (il guardian) può essere scelto in modo che suoni come una domanda.
è già stata chiamata la funzione 0? oppure; ho già chiamato la funzione 0?

Sintetizzando: è la prima chiamata; isFirstCalled

if (isFirstCalledFunction0) {
    function0(); // chiama la funzione function0
    isFirstCalledFunction0 = true;
}

C'è un corto circuito nella condizione, che in base alla domanda deve valere true se la funzione è già stata chiamata e false se non è stata chiamata ancora.

Si risolve negando la condizione if

if (!isFirstCalledFunction0) {  // nota il punto esclamativo
    function0(); // chiama la funzione function0
    isFirstCalledFunction0 = true;
}

che equivale alla versione lunga seguente:

if ( isFirstCalledFunction0 == false ) {  
    function0(); // chiama la funzione function0
    isFirstCalledFunction0 = true;
}

Nel case 0 se vuoi puoi spegnere il guardian così: isFirstCalledFunction0 = false;

Nota che ci sono tantissimi modi per avviare le funzioni una sola volta, anche se dentro un loop, fai riferimento al libro in merito alle funzioni che prendono e restituiscono valori (argomenti).

PS: Occhio che bool è un tipo di dato presente solo in C++.

Ciao.