Diverse routine void()

buongiorno a tutti. chiedo scusa in anticipo se ho sbagliato qualcosa all'interno del forum.
Ho scritto di me nella presentazione, perciò non mi dilungo oltremodo e sparo il mio quesito(che magari vi farà pietosamente sorridere) :
come diavolo faccio ad assegnare il risultato di un calcolo matematico eseguito ed acquisito correttamente in un void calcolo() ad un altro void scrivi() in cui scrivo il dato su SD ?
Grazie mille.

ciao Clo

:warning:
Ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato. Grazie.

... studiandoti come sono fatte le funzioni del 'C', come ritornano un valore e come si passa un valore? :grin:

Se una funzione la dichiari di TIPO void vuol dire che NON ritorna nulla, se deve ritornare un valore devi dichiararla del tipo di valore che ritorna. Esempio, se faccio una funzione che torna un intero la dovrò dichiarare int e NON void:

int miaFunzione ( void ) {
   int valoreCheRitorno;
   ...
   ... // istruzioni che calcolano il mio valore
   ...
   return valoreCheRitorno;
}

... così come, se voglio ricevere un valore NON dovrò dire che la funzione non si aspetta nulla (void nella parte parametri ) ma dire cosa si aspetta ... esempio:

int miaMoltiplicazione ( byte a, byte b ) {
   int c;
   c = a * b;
   return c;
}

... che si potrebbe anche scrivere senza usare la variabile di appoggio 'c', ma ... un passo alla volta.

Tutto chiaro ?

Guglielmo

Guglielmo gli aggiungo come usare i tuoi esempi (anche se non perfetto):

...
int ris1,ris2;
ris1=miaFunzione();
ris2=miaMoltiplicazione(ris1,2);

grazie.
sto metabolizzando il concetto e darò un occhio alle funzioni del c .

a presto.
grazie ancora

Può essere utile la lettura di un breve PDF di una professoressa "Programmare arduino Tiziana Marsella":

ottimo. allora mi sa che non ci sentiremo poi così presto (80 pagine😊).
però forse ho capito, il fatto è che avevo associato alle routine la sola dicitura void , non sapevo che potevo fare diversamente. infatti tutto il mio codice è nel loop ; perchè provando a snellirlo e farlo divenire più leggibile avevo creato varie routine ma sempre come void. e non "funzionava" più.
grazie davvero tanto.

ciao

rettifico.
Sto leggendo il pdf che mi hai allegato...mi sa che quello che al momento mi angoscia è spiegato in una pagina.:woman_facepalming:
...mi sa che stanotte non dormirò...

Puoi anche "spezzare" il codice in maniera semplice, in più funzioni void, senza passare i parametri o usare return. Non è il massimo ma semplifica.
L'unica cosa è che le variabili siano globali (dichiarate ad inizio) se devono condividere dati.
Cioè:

int var=0;  // variabile globale, vista in tutto il codice, anche le funzioni
...
void loop()
{ 
  Funz1();
  Serial.println(var);       // stampa 10
  Funz2();
  Serial.println(var);      // stampa 20
}
void Funz1()
{ var=10;
}
void Funz2()
{ int varloc=1;  // var. locale, solo Funz2 la vede
  var=20;
}

Giusto una precisazione semantica: in C/C++ NON esistono le routine ma soltanto le funzioni.

Per questo motivo è necessario usare il void anche se la funzione non restituisce nulla dopo l'elaborazione.
In altre parole void nomeFunzione() è una funzione che nel comportamento equivale ad una routine (detta anche procedura a volte).

ah, io le ho chiamate routine perché scopiazzando qua e là nel web sto "seguendo" il modus-operandi di un codice che nelle descrizioni le chiamava così.

nid69ita, il tuo esempio è come ho provato a fare. ho definito le variabili a livello globale , ho "spezzettato" il codice in diversi void , ma poi non mi restituisce più i valori ottenuti.
Se non abuso troppo della vostra gentilezza e disponibilità , tra oggi e domani estrapolerò un esempio di quello che ho fatto e lo posterò.

Sono riuscito ad ottenere già molto in questa mia esperienza "Arduiniana" e ne sono soddisfatto...ma siccome mi pare non ci siano limiti alle possibilità offerte , mi ritrovo ad aggiungere funzioni e richieste alla mio buon microcontrollore :wink:

Se le variabili sono globali non c'è bisogno di restituire nulla. Ogni modifica della variabile è subito visibile al di fuori della funzione.

Avrò fatto qualche altro errore , di tentativi ne ho fatti parecchi. Mi accorgo che è veramente tosto studiare senza interlocutore , senza poter mai porre domande restano dubbi ed "accettazioni per partito preso" , che certo non aiutano a migliorare.

Ci tengo ancora una volta a ringraziare tutti.

librerie

float ampere =O; //variabile globale

void ampere() //routine di calcolo
[non posto le stringhe di calcolo,ma ci sono e funzionano] [le chiamo stringhe di calcolo,
ma sono funzioni, giusto?]
Se sono funzioni la domanda cruciale è : le funzioni devono sempre essere nel loop?]
void scrivi() //routine di scrittura su sd
[come sopra]
void lcd() //routine del display
[come sopra]
void rtc() //routine relativa al modulo rtc
[come sopra]
void setup ()
[come sopra]
void loop()
{
ampere();
scrivi();
lcd();
rtc();
}
/ecco, in sintesi stavo cercando di fare una cosa del genere, ma non funziona. Provo ad essere più chiaro: (perdonate se userò termini inadeguati)
se elimino tutte le routine e le scrivo direttamente nel loop funziona tutto correttamente. Però mi ritrovo con un loop molto complesso,
visto che le routine di calcolo sono più d'una. L'unica istruzione che non smette mai di funzionare correttamente è il monitor seriale ; credo sia perchè la stringa di comando è nella routine.
Penso di aver provato un pò di tutto : ho invertito/spostato la successione delle routine, del loop, del setup.
Avevo già "sbirciato" e provato qualche comando di funzione (return, soprattutto) ma mai sono riuscito a rimandare il valore corretto ottenuto nella routine.
Ora dopo tanti fallimenti sono sinceramente un po spaesato, ormai non so nemmeno più bene cosa, come e quando ho fatto una data modifica./

scusate se sto deragliando dall'argomento e se dimostro tanta ignoranza.

grazie
ciao Claudio

Ferma...

Tira un bel respiro e riparti da capo con calma...

Hai una versione funzionante complicata, disordinata, confusa?

Se si postala

Da li passo a passo si vede di rimetterla in squadra...

Fai una cosa per volta
Per adesso vedi di avere un programma funzionante

Le funzioni le chiami dove servono. Di solito le chiami da dentro la loop() ma possono anche essere chiamate da dentro un'altra funzione.
Arduino si programma in C/C++
Di base un programma in C ha una funzione principale main() e il programma parte da li.
Il core di Arduino nasconde questo (all'incirca):

void main()
{ setup();
  while(1)       // ciclo infinito
  { loop();
  }
}

Un programma arduino è un main classico del C che obbliga ad avere una funzione setup() eseguita solo 1 volta e poi una funzione loop() eseguita all'infinito.

si , ho una versione funzionante complicata, disordinata, confusa.
ok, la posto molto volentieri. grazie!
Tenete presente che nelle mie intenzioni non è affatto finita!:blush:

in breve si tratta di gestire due circuiti di batterie caricate da un modulo fotovoltaico.
poi , se vorrete vi dirò cosa manca da implementare.

20_02_IN_USO_.ino (12,6 KB)

Grazie a tutti, beninteso.

Prima cosa:

    unsigned int v2 = 0;                      //definisco variabile solo positiva tensione c.to2
    for (int v2 = 0; v2 < 1000; v2++) {      //ricavo 1000 valori

Inutile la dichiarazione di v2 prima del for. Se nel for metti int v2 la stai dichiarando li

  1. Secondo me ti conviene per prima cosa dichiarare tutte le variabili che hai nella loop() all'inizio della loop() e non in mezzo al codice. Così magari vedi anche che alcune sono inutili.

  2. non ha molto senso come metti le graffe

    float watt1 = 0;                          //definisco watt1
    watt1 = 0;                       
    {
      watt1 = (ampere1 * volt1);              //formula risultato finale legge di omh
      delay(1);
    }

Quelle graffe non hanno nessun senso pratico. Poi hai già detto che vale 0

  1. togli un bel pò di quelle righe vuote. Allunga il codice per nulla. Non stai scrivendo il temino per la maestra, più è lungo meglio è.
    Piuttosto se vuoi separare pezzi di codice, metti una bella riga di commento
    come hai fatto qui ad esempio:
// aspetta un secondo prima di andare ad esporre
// nuovi dati, al fine di consentire al display una visualizzazione
  1. inutile, troppe tonde
    digits = (second());
    E' come scrivere Acslettura1 = ( analogRead(A0) ) ;
    Basta digits = second();

  2. Importante. Variabili globali e variabili locali. Prendiamo la variabile volt1
    Tu la dichiari ad inizio programma, fuori dalle funzioni. Quindi è globale.
    Poi la dichiari in loop() quindi ne dichiari UN'ALTRA che ha lo stesso nome ma è locale.

Dentro la tua funzione loop() quando usi volt1 stai usando la variabile locale.
Questa NON viene vista al di fuori della loop()
Esempio

int x=10;
void setup() 
{ Serial.begin(9600);
  Serial.println(x);      // stampa 10
}
void loop()
{ int x=20;            // dichiara una x che nasconde la x globale
  Serial.println(x);      // stampa 20
}

Le funzioni dovrebbero essere utili per spezzare un codice lungo, ad esempio questo:

lcd.clear();                  //PULISCO IL DISPLAY
    lcd.begin(16, 2);             //INIZIALIZZO IL DISPLAY LCD
    delay(50);                    //PAUSA
    lcd.setCursor(0, 0);          //STABILISCO LA POSIZIONE DEL CURSORE
    lcd.print("A1");              //SCRIVO corrente c.to1
    lcd.setCursor(8, 0 );         //STABILISCO LA POSIZIONE DEL CURSORE
    lcd.print("V1");              //SCRIVO tensione c.to1
    lcd.setCursor(0, 1);          //STABILISCO LA POSIZIONE DEL CURSORE
    lcd.print("A2");              //SCRIVO corrente c.to2
    lcd.setCursor(8, 1);          //STABILISCO LA POSIZIONE DEL CURSORE
    lcd.print("V2");              //SCRIVO tensione c.to2
    lcd.setCursor(3, 0);
    lcd.print(ampere1);
    lcd.print(" ");               //ASSEGNO VALORI OTTENUTI
    lcd.setCursor(11, 0);
    lcd.print(volt1);
    lcd.print(" ");               //ASSEGNO VALORI OTTENUTI
    lcd.setCursor(3, 1);
    lcd.print(ampere2);
    lcd.print(" ");               //ASSEGNO VALORI OTTENUTI
    lcd.setCursor(11, 1);
    lcd.print(volt2);
    lcd.print(" ");               //ASSEGNO VALORI OTTENUTI
    delay(5000);

Puoi creare una funzione StampaLcdXXX() in modo da rendere il loop() più leggibile. XXX dovrebbe essere una parola che fa capire cosa sta stampando
Le variabili che stampa però DEVONO essere globali. (oppure le passi come parametri, per ora segui la strada più semplice)
20_02_IN_USO_.ino (11,4 KB)
Non ho le tue librerie, non posso provarlo