[RISOLTO] Trasformare un pezzo di codice in funzione.

Avrei bisogno di un aiuto.

Ho realizzato un sistema di controllo per due pompe sommerse per pozzetti di raccolta acque.
Sia la parte HW che SW. funziona tutto. Ma implementando il sistema GMS per gli allarmi (credo che il grosso lo abbiano fatto le Library), mi trovo con la memoria delle variabili globali satura al 110% (ho saturato pure tutte le porte tranne due digital).

Passo ad arduino mega o provo ad ottimizzare il programma?

In ogni caso, intanto vorrei ottimizzare il codice laddove ho inserito la misura della corrente. In pratica ho utilizzato i sensori hall di corrente da 20A per misurare l'assorbimento delle pompe. Poichè sono in corrente alternata ho dovuto calcolare pero il valore quadratico medio (RMS) attraverso una routine sw di campionamento che ho trovato qui nel forum, e che funziona egregiamente. Ho evitato cosi ulteriore circuiteria elettronica.
La misura viene effettuata dopo 1s dall'accensione della pompa per evitare la misura delle correnti di spunto.

Solo che la routine l'ho scritta due volte, una volta per la pompa A, e poi per la pompa B. Ecco vorrei un aiuto per ridurla a funzione, eliminando diverse righe di codice (anche a prescindere dalla liberazione di memoria per le variabili). Non ho ancora sufficiente dimestichezza con la definizione di funzioni... cosi sarebbe occasione per imparare. Non credo sia complicato, ma una mano fa sempre piacere.

di seguito sono rappresentate solo le due routine di conversione AC->DC, sono identiche tranne che per la variabile in uscita IA e IB relativa alla corrente dei due motori.

Eventualmente le due variabili corr e adc_zero andrebbero definite prima di richiamare la funzione o in occasione di essa, perchè potrebbero variare per ogni motore.

// all'inizio dichiarazione delle variabili
// CONVERSIONE DC-AC corrente
const unsigned long sampleTime = 100000UL;      // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 250UL;         // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
const unsigned long sampleInterval = sampleTime / numSamples; // the sampling interval, must be longer than then ADC conversion time
int adc_zero = 512;                       // relative digital zero of the arudino input from ACS712 (could make this a variable and auto-adjust it)
float corr = 0.06;


// dentro void loop()
...

 // conversione IA
    adc_zero = 510;
    corr = 0.02;
    unsigned long currentAcc = 0;
    unsigned int counter = 0;
    unsigned long prevMicros = micros() - sampleInterval ;
    while (counter < numSamples)
    {
      if (micros() - prevMicros >= sampleInterval)
      {
        int adc_raw = analogRead(pin_IA) - adc_zero;
        currentAcc += (unsigned long)(adc_raw * adc_raw);
        ++counter;
        prevMicros += sampleInterval;
      }
    }

    IA = sqrt((float)currentAcc / (float)numSamples) * (50.00 / 1024.0) ;
    if ( IA < corr ) {
      IA = 0;
    }
    // fine conversione
    
...
 
 // conversione IB
    adc_zero = 510;
    corr = 0.02;
    unsigned long currentAcc = 0;
    unsigned int counter = 0;
    unsigned long prevMicros = micros() - sampleInterval ;
    while (counter < numSamples)
    {
      if (micros() - prevMicros >= sampleInterval)
      {
        int adc_raw = analogRead(pin_IB) - adc_zero;
        currentAcc += (unsigned long)(adc_raw * adc_raw);
        ++counter;
        prevMicros += sampleInterval;
      }
    }

    IB = sqrt((float)currentAcc / (float)numSamples) * (50.00 / 1024.0) ;
    if ( IB < corr ) {
      IB = 0;
    }
    // fine conversione

grazie

Potresti optare per una rapida lettura ad una guida alle funzioni nel C++, c'è ben poca differenza con il wiring del Arduino IDE.
In ogni caso individua le variabili nella tuo algoritmo, dopo di che lo racchiudi in una funzione con quelle variabili come argomenti in ingresso e che restituisca il valore di assorbimento.
Un consiglio, noto che usi delle variabili come costanti (esempio adc_zero) potresti definirle come costanti del preprocessore, in questo modo risparimieresti della ram preziosa, fulcro del tuo problema. Guarda qua.

si la difficoltà sta piu che altro nel passaggio delle variabili, faro' qualche tentativo. Non riesco a capire se le variabili che passo sono individuate solo dalla posizione in cui sono state passate..

es... IA = Misura (adc_zero, corr) ?

...

Misura (adc_zero, corr, pin) {

ma non mi è chiaro come fare a passare il valore ottenuto alla variabile IA o IB...

per quanto riguarda le costanti, mi pare di capire che "const" è preferito a #define, ma entrambe sortiscono l'effetto di risparmiare memoria in quanto trasformo una varaibile globale in costante/variabile di scopo, giusto?

domanda banale: il codice della funziona dove lo scrivo? dentro il loop o fuori alla fine (o all'inizio)?

cmq sono un po demoralizzato... l'ottimizzazione è un buon esercizio per prendere dimestichezza con arduino, ma non penso di riuscire a recuperare 200 e rotti byte ... mi sembrano un po tantini. E al modulo GSM non posso rinunciare perchè è il fondamento del progetto.

leggere il manuale del C++ è sicuramente la strada maestra, pensavo di prendere una scorciatoia....

Si, i parametri sono posizionali, quindi il primo che scrivi nella chiamata è il primo che descrivi nella definizione

void miaFunz( int p1, long p2, char p3)
{ ...

miaFunz( 1, 2, '3'); // chiamata  p1=1 p2=2 p3='3'

Con void davanti la funzione non ritorna valore, con un tipo davanti, la funzione ritorna un valore di quel tipo, basta che nella funzione usi return(valore);

long miaFunz(long p1, long p2)
{ long ret=p1*p2;
  return(ret);
}
long x=miaFunz(10,20);

In C le funzioni dovrebbero essere scritte prima di dove le usi, in Arduino non è importante. Le puoi scrivere anche dopo la loop()

grazie, era l'hint che mi serviva, spiegazione semplice chiara ed elegante.

p.s. prima di chiedere qui in genere faccio prima una ricerca veloce su qualche documento. Mi sembra scontato. Debbo dire che quello che ho trovato finora è abbastanza delundente come qualità didattica/euristica.

Prova a cercare "Programmare Arduino Tiziana Marsella"
un buon pdf in italiano di una prof (è documento pubblico)

Grazie appena ho tempo me lo cerco.

intanto ho riscritto il codice insierendo la funzione come segue, il compilatore non mi ha dato errori:

// inizio fuori del loop

// CONVERSIONE DC-AC corrente
const unsigned long sampleTime = 100000UL;      // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 250UL;         // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
const unsigned long sampleInterval = sampleTime / numSamples; // the sampling interval, must be longer than then ADC conversion time

// FUNZIONE di conversione AC-DC
float misura (int adc_zero, float corr, int pinI) {
  unsigned long currentAcc = 0;
  unsigned int counter = 0;
  unsigned long prevMicros = micros() - sampleInterval ;
  float AMP = 0;
  while (counter < numSamples)
  {
    if (micros() - prevMicros >= sampleInterval)
    {
      int adc_raw = analogRead(pinI) - adc_zero;
      currentAcc += (unsigned long)(adc_raw * adc_raw);
      ++counter;
      prevMicros += sampleInterval;
    }
  }

  AMP = sqrt((float)currentAcc / (float)numSamples) * (50.00 / 1024.0) ;
  if ( AMP < corr ) {
    AMP = 0;
  }
  return (AMP);
}
// fine conversione

...

// dentro il loop {} richiamo la funzione una volta per la pompa A e un 'altra per la pompa B

 //misura POMPA A
  if (A == !HIGH) {

    int adc_zero = 510;
    float corr = 0.02;
    byte pin_I = pin_IA;

    IA = misura (adc_zero, corr, pin_I);

    if ( IA < 0 or IA > IAmax) {
      FA = 1;  // pompa in corto o interrotta
    }
    else {
      FA = 0;
    }
  }

  //misura POMPA B
  if (B == !HIGH) {

    int adc_zero = 509;
    float corr = 0.02;
    byte pin_I = pin_IB;

    IB = misura (adc_zero, corr, pin_I);

    if (IB < 0 or IB > IBmax) {
      FB = 1;
    }
    else {
      FB = 0;
    }
  }

non l'ho ancora provato, ma potrebbe andare cosi?

bye

se il manualetto è questo
http://cabestano.altervista.org/alterpages/files/TizianaMarsella-ProgrammareArduino.pdf

è uno dei primi che ho scaricato e letto. Va bene per i rudimenti, ma le funzioni sono spiegate male.

La funzione sembra correttà, non resta che testarla, per la prova del 9.
Ricordati di dichiarare FA e FB.

A parer mio i mezzi semplificati soprattutto nell'informatica sono armi a doppio taglio, io ti consiglierei se c'è interesse e tempo una rapida lettura di un buon manuale di C/C++, male non fa, e da li a capire le semplificazioni del wiring ci vuole un attimo.

Se FB è un bool, questo

if (IB < 0 or IB > IBmax) {
      FB = 1;
    }
    else {
      FB = 0;
    }

lo puoi semplificare in questo

FB = IB < 0 or IB > IBmax;

RobertoBochet:

  1. io ti consiglierei se c'è interesse e tempo una rapida lettura di un buon manuale di C/C++, male non fa,

  2. lo puoi semplificare in questo
    FB = IB < 0 or IB > IBmax;

  1. con me sfondi una porta aperta, io consiero l'uso di testi fondamentale e il ricorso al forum utile per il confronto. Le cose vanno necessariamente di pari passo.
    Il testo che mi aveva consigliato NID per esempio lo avevo già letto quasi tutto. Mi sembrava ben fatto, ancorchè elementare.. e infatti la parte sulle funzioni è un po imbarazzante... nel senso di assolutamente insufficiente.

  2. ottimo, qui si tratta di prendere un po' dimestichezza con la sintassi del linguaggio

grazie

Ho appena consigliato il testo di Kernighan linguaggio C in un altro thread. Kernighan è uno dei creatori del C, il testo non tiene conto ne del C99 ne del C11 e ovviamente non parla del C++. In ogni caso è un ottima partenza per imparare a programmare. Dopo di che sarà necessaria un infarinatura di C++ per quanto riguarda il paradigma ad oggetti, dopo di che la stesura di codice per Arduino diventa una passeggiata.

questo?

http://www.iups.org/media/meeting_minutes/C.pdf

Ehm non credo sia un libro in libera consultazione... Potrei anche sbagliarmi però...