istruzione che viene eseguita una sola volta

Salve gente

esiste una funzione che non contenga if, variabili o altre condizioni e che in un ciclo loop o in uno switch case esegue delle istruzioni una sola volta all'avvio?

Grazie
Giuseppe

peppe123:
Salve gente

esiste una funzione che non contenga if, variabili o altre condizioni e che in un ciclo loop o in uno switch case esegue delle istruzioni una sola volta all'avvio?

Grazie
Giuseppe

e perchè dovrebbe esistere? c'è già la funzione setup che è fatta per quello e se no si usa un flag che segnali il "già fatto".

qsecofr:

peppe123:
Salve gente

esiste una funzione che non contenga if, variabili o altre condizioni e che in un ciclo loop o in uno switch case esegue delle istruzioni una sola volta all'avvio?

Grazie
Giuseppe

e perchè dovrebbe esistere? c'è già la funzione setup che è fatta per quello e se no si usa un flag che segnali il "già fatto".

per farti un esempio, entro in un case voglio che il buzzer mi suoni due volte e basta.
il setup esegue si una sola volta le istruzioni ma all'avvio di arduino, invece io voglio eseguire quella istruzione una sola volta quando accedo ad uno specifico case.

grazie

Si.
Puoi dichiarare una variabile globale, ad esempio:

bool onetime = true;

poi nel case metti:

case X:
 if (onetime) {
 // codice che vuoi eseguire
 onetime = false;
 }
 break;

in questo modo onetime è vera all'avvio di Arduino.
Appena viene richiamato il caso X viene eseguito l'if e quindi le tue istruzioni. infine viene posto onetime = false.
Al successivo richiamo del caso X, onetime è falso e quindi l'if non viene eseguito.

Ciao, accodo un altro metodo a quelli proposti da PaoloP
Nel tuo case, dopo l'operazione specifica, puoi aggiungere questa istruzione:

while(true);

che di fatto è un loop infinito.

Appena posso sperimento tutto.

Vi ringrazio.. sempre gentili e disponibili.

Saluti
Giuseppe

peppe123:
Appena posso sperimento tutto.

Vi ringrazio.. sempre gentili e disponibili.

Saluti
Giuseppe

si però il mettere il while true blocca di fatto l'arduino in un ciclo infinito ed il ciclo loop di fatto non viene più eseguito... mentre il case postato prima va contro la richiesta di peppe:

esiste una funzione che non contenga if, variabili o altre condizioni...

@qsecofr (questo nick mi ricorda troppo il mondo AS400 :P)
il

while(true);

di fatto blocca l'esecuzione del codice, in quanto si tratta di loop infinito - e questo l'ho detto nel mio post.

A questo punto, la domanda è:
l'esecuzione del codice deve essere bloccata (ovvero, dopo il case non eseguire più nulla), o la domanda di peppe123 era di fatto mooolto più semplice?

Ovvero: ad una determinata condizione, suona il buzzer N volte, poi smetti. MA se risuccede l'evento, suona nuovamente il buzzer N volte etc etc etc?
Perchè in questo ultimo caso nessuna delle ipotesi di cui si è discusso fin'ora è idonea...

/**
  * Esegue il codice contenuto nel blocco una sola volta
  * example: new_one_shot(only_one) {
  *             your code here...
  *             ....
  *          }
  * Questa macro è utile se usata all'interno di un loop.
  * Nota che only_one è il nome di una variabile e quindi
  * si dovrà usare un nome diverso in ogni uso di
  * new_one_shot(var_name)

  *
  */
#define new_one_shot(shot_name) static uint8_t shot_name = 1;\
                for ( ; shot_name > 0; shot_name-- )

Esegue solo una volta il codice contenuto nel blocco delimitato dalle graffe, ma se shot_name vale 2 lo esegue 2 volte.

Dopo la prima esecuzione puoi stabilire quante volte vuoi che il codice venga eseuito.

while (true) {
    uint8_t alarm_count = 0;
    new_one_shot(cica_alarm) {
        alarm_bip();
        alarm_led();
        alarm_count++;
       // ecc.
    }

    if (alarm_count > 3)
       cica_alarm = 3; // new_one_shot girerà 3 volte
}

Se si vuole si può parametrizzare, al fine di decidere subito quante volte dovrà essere esguito il ciclo, es n_repeat(my_loop, 5)
In questo modo verrà eseguito solo 5 volte e mai più a meno che non si reimposti la variabile my_loop = 5 o altro valore.

Ciao.

esempio:

switch (x)
{
case 0:
{suona il buzzer 2 volte} // questa istruzione voglio che venga eseguita in concomitanza con l'accesso al case
// per una sola volta,anche se effettuo altri accessi allo stesso case non voglio che si ripeta
// chiedevo appunto se ci fosse un codice che non utilizza variabili

istruzioni... // queste istruzioni devono essere eseguite fino a che non si esce dal case
istruzioni...
istruzioni...

break;
}

sper di essere stato piu chiaro :slight_smile:

grazie

Che io sappia non è possibile mantenere un valore senza fare uso di variabili, quindi non conosco un modo per far fare al micro ciò che ti serve.

Occhio che potresti trovare una funzione o macro che fa quello che vuoi ma sotto sotto una variabile ci sarà sempre.

Ciao.

peppe123:
esiste una funzione che non contenga if, variabili o altre condizioni e che in un ciclo loop o in uno switch case esegue delle istruzioni una sola volta all'avvio?

Quindi, per i motivi su esposti, la risposta è: no.
Ma perché non vuoi usare variabili?

leo72:

peppe123:
esiste una funzione che non contenga if, variabili o altre condizioni e che in un ciclo loop o in uno switch case esegue delle istruzioni una sola volta all'avvio?

Quindi, per i motivi su esposti, la risposta è: no.
Ma perché non vuoi usare variabili?

non avrei problemi ad utilizzare variabili, pensavo ci fosse la possibilità di utilizzare un codice semplice che non utilizza variabili, tutto qui.
a questo punto direi che il modo piu snello e semplice per gestire la cosa è una variabile booleana come suggerito da PaoloP

PaoloP:
Si.
Puoi dichiarare una variabile globale, ad esempio:

bool onetime = true;

poi nel case metti:

case X:

if (onetime) {
// codice che vuoi eseguire
onetime = false;
}
break;

Grazie a tutti..

Buongiorno a tutti,

ho un problema simile......

devo fare eseguire del codice SOLAMENTE all'accensione di Arduino e mai più anche se richiamo
un soft_restart();

Ma va bene anche se venisse rieseguito con la pressione del pulsante di reset della scheda
ma NON QUANDO ESEGUO UN RESET SOFTWERE.

Grazie

C'è un registro che ti permette di risalire alla causa dell'ultimo reset. Ora non ricordo quale sia, ma dovresti poterlo leggere e comportarti di conseguenza (Sempre che sia lasciato intatto dal bootloader...). Dai un'occhiata al datasheet.

Ma per curiosità, perché devi fare ciò?

pilotinocarter:
Buongiorno a tutti,

ho un problema simile......

devo fare eseguire del codice SOLAMENTE all'accensione di Arduino e mai più anche se richiamo
un soft_restart();

Ma va bene anche se venisse rieseguito con la pressione del pulsante di reset della scheda
ma NON QUANDO ESEGUO UN RESET SOFTWERE.

Grazie

Ciao,
alcuni micro permettono di detectarlo scrivendo un valore su un registro. Non so se è il caso dell'AVR.
Un metodo per farlo (senza dover scartabellare il datasheet del micro) potrebbe essere scrivere un valore particolare in EEPROM quando fai il SW reset e poi leggerlo all'avvio per capire se devi eseguire o meno il codice

SukkoPera:
C'è un registro che ti permette di risalire alla causa dell'ultimo reset. Ora non ricordo quale sia, ma dovresti poterlo leggere e comportarti di conseguenza (Sempre che sia lasciato intatto dal bootloader...). Dai un'occhiata al datasheet.

Esatto ...
... le informazioni si trovano nel registro MCUSR (bit 0..3) documentato a pag. 54 del datasheet (10/2014).

Purtroppo NON sono sicuro che il registro non venga alterato dal "core" di Arduino (... rammento che setup() e loop() vengono chiamate DOPO tutta un'altra serie di funzioni del "core" all'avvio del programma).

Guglielmo

Purtroppo il registro è sicuramente "sporcato" già dal bootloader. Tuttavia, ho trovato qualcosa di interessante: se usi un Arduino con Optiboot (il che credo succeda nel 99% dei casi), c'è uno sketch di esempio che fa proprio quel che ti serve:

https://github.com/Optiboot/optiboot/blob/master/optiboot/examples/test_reset/test_reset.ino

@SukkoPera

Anche io ho provato una tecnica simile e ci sono esempi forniti da Atmel stessa ma ...
... c'è un problemino, almeno sino al rilascio del IDE 1.6.6 che, con il nuovo "builder", dovrebbe comportarsi correttamente. L'IDE dichiara COMUNQUE lui i "prototipi" di qualsiasi funzione (ANCHE se già li hai dichiarati) e, a seconda di come lo fa, può vanificare i vari "attribute ((section(".noinit")));" e così via ... :frowning:

Guglielmo

P.S. : Ovviamente la cosa funziona se usi Atmel Studio ed hai tu il controllo del tuo sorgente :wink:

... per inciso, il metodo suggerito da Atmel è :

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
...
...
void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));
...
...
void get_mcusr(void)
{
   mcusr_mirror = MCUSR;
   MCUSR = 0;
   wdt_disable();
}

... e ti trovi in mcusr_mirror il valore del registro MCUSR.

Guglielmo