Arduino nano reset, quando attivo una delle 6 pompe

Buongiorno ragazzi, devo creare una prova speciale per un torneo di softair.
Il funzionamento è semplice l'arduino è alimentato con un trasformatore a 12V che sotto chiave viene attivato e alimenta direttamente una scheda con 8 relè a 12V e un arduino NANO tramite uno stepdown a 5V.
Tramite tastierino e display vengono chiesti, uno per volta, 6 quantitativi numerici (ml) e al click su "#" viene attivato il relè dall'1 al 6 per il tempo ottenuto moltiplicando il quantitativo inserito per una costante. Il relè quando si attiva alimenta una delle 6 pompe a 12vdc e assorbono 0.5-0.7A (ogni relè ha una pompa), se la pompa lavora senza acqua nessun problema, se metto l'acqua capita in modo casuale che si riavii arduino. Le pompe sono alimentate dallo stesso traformatore.
Cosa può essere? Chiedetemi e proverò a rispondervi e grazie per l'aiuto.
Qui sotto foto della parte elettronica e codice.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <I2CKeyPad.h>
#include "pitches.h"

#define I2CADDR 0x21

int tempo=108;
int melody[] = {  NOTE_D4,8, NOTE_E4,8, NOTE_F4,8, NOTE_E4,8, NOTE_D4,8,};
int notes=sizeof(melody)/sizeof(melody[0])/2; 
int wholenote = (60000 * 4) / tempo;
int divider = 0, noteDuration = 0;

char phone_layout[19] = "123A456B789C*0#DNF";  // N = NoKey, F = Fail

I2CKeyPad keyPad(I2CADDR);
LiquidCrystal_I2C lcd(0x27,16,2);

int liquido[6];
int liquidoESATTO[6]={44,51,60,43,53,46};

char inputCode[7];// CODICE INSERIMENTO
int rele1 = 5;// USCITA PER ATTIVARE IL RELE'
int rele2 = 6;// USCITA PER ATTIVARE IL RELE'
int rele3 = 7;// USCITA PER ATTIVARE IL RELE'
int rele4 = 8;// USCITA PER ATTIVARE IL RELE'
int rele5 = 9;// USCITA PER ATTIVARE IL RELE'
int rele6 = 10;// USCITA PER ATTIVARE IL RELE'
int rele7 = 11;// USCITA PER ATTIVARE IL RELE led'
int buzz = 4;
int inputCode_idx;//CONTATORE PER DODICE INSERITO
int menu=0;
#define unml 35  // moltiplicatore per associare ml a ms di funzionamento di una pompa
boolean entryComplete;
unsigned int total = 0;
char key;
byte keyAsANumber;
byte digitCount = 0;
bool esito = false;

//These 5 arrays paint the bars that go across the screen.  
uint8_t  zero[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t  one[8] = {B10000,B10000,B10000,B10000,B10000,B10000,B10000,B10000};
uint8_t  two[8] = {B11000,B11000,B11000,B11000,B11000,B11000,B11000,B11000};
uint8_t  three[8] = {B11100,B11100,B11100,B11100,B11100,B11100,B11100,B11100};
uint8_t  four[8] = {B11110,B11110,B11110,B11110,B11110,B11110,B11110,B11110};
uint8_t  five[8] = {B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111};

void setup(){
  
    for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
    divider = melody[thisNote + 1];
    if (divider > 0) {
      // regular note, just proceed
      noteDuration = (wholenote) / divider;
    } else if (divider < 0) {
      noteDuration = (wholenote) / abs(divider);
      noteDuration *= 1.5; // increases the duration in half for dotted notes
    }
    tone(buzz, melody[thisNote], noteDuration*0.9);
    delay(noteDuration);
    noTone(buzz);
  }
  
  lcd.init();
  lcd.backlight();
  lcd.createChar(0, zero);
  lcd.createChar(1, one);
  lcd.createChar(2, two);
  lcd.createChar(3, three);
  lcd.createChar(4, four);
  lcd.createChar(5, five);

  Serial.begin(115200);
  Wire.begin();
  keyPad.setKeyPadMode(I2C_KEYPAD_4x4);

    keyPad.loadKeyMap(phone_layout);
     
  lcd.clear();
    
    pinMode(rele1,OUTPUT);
    pinMode(rele2,OUTPUT);
    pinMode(rele3,OUTPUT);
    pinMode(rele4,OUTPUT);
    pinMode(rele5,OUTPUT);
    pinMode(rele6,OUTPUT);
    pinMode(rele7,OUTPUT);
    pinMode(buzz,OUTPUT);
    inputCode_idx = 0;// RESETTA IL CONTATORE DEL CODICE
     digitalWrite(rele1,LOW);
     digitalWrite(rele2,LOW);
     digitalWrite(rele3,LOW);
     digitalWrite(rele4,LOW);
     digitalWrite(rele5,LOW);
     digitalWrite(rele6,LOW);
     digitalWrite(rele7,LOW);
}


void loop(){
 
switch (menu) {
case 0:   
  lcd.setCursor(0, 0);
  lcd.print("Avvio produzione");
  lcd.setCursor(5, 1);
  lcd.print("URANIO");
  delay(3000);
  lcd.clear();
  menu=1;
break;

case 1:
lcd.setCursor(0, 0);
lcd.print("CISTERNA " +String(menu)+ "  (ml)");
entryComplete = false;  //will be checked after reading a key
  readKeypad();
   if (entryComplete)  //number entry is complete
  {
    liquido[0]=atoi(inputCode); 
    succhia(atoi(inputCode), menu);
    lcd.clear();
    menu=2;
  }     
 break;
 
case 2:
lcd.setCursor(0, 0);
lcd.print("CISTERNA " +String(menu)+ "  (ml)");
entryComplete = false;  //will be checked after reading a key
  readKeypad();
   if (entryComplete)  //number entry is complete
  {
    liquido[1]=atoi(inputCode);
    succhia(atoi(inputCode), menu);
    lcd.clear();
    menu=3;
  }     
 break;

case 3:
lcd.setCursor(0, 0);
lcd.print("CISTERNA " +String(menu)+ "  (ml)");
entryComplete = false;  //will be checked after reading a key
  readKeypad();
   if (entryComplete)  //number entry is complete
  {
    liquido[2]=atoi(inputCode);
    succhia(atoi(inputCode), menu);
    lcd.clear();
    menu=4;
  }     
 break;

case 4:
lcd.setCursor(0, 0);
lcd.print("CISTERNA " +String(menu)+ "  (ml)");
entryComplete = false;  //will be checked after reading a key
  readKeypad();
   if (entryComplete)  //number entry is complete
  {
    liquido[3]=atoi(inputCode);
    succhia(atoi(inputCode), menu);
    lcd.clear();
    menu=5;
  }     
 break;

case 5:
lcd.setCursor(0, 0);
lcd.print("CISTERNA " +String(menu)+ "  (ml)");
entryComplete = false;  //will be checked after reading a key
  readKeypad();
   if (entryComplete)  //number entry is complete
  {
    liquido[4]=atoi(inputCode);
    succhia(atoi(inputCode), menu);
    lcd.clear();
    menu=6;
  }     
 break;

 case 6:

lcd.setCursor(0, 0);
lcd.print("CISTERNA " +String(menu)+ "  (ml)");
entryComplete = false;  //will be checked after reading a key
  readKeypad();
   if (entryComplete)  //number entry is complete
  {
    liquido[5]=atoi(inputCode);
    succhia(atoi(inputCode), menu);
    lcd.clear();
    menu=7;
  }     
 break;

 case 7:

 char inserito;
 inserito=liquido[0]+','+ liquido[1]+','+ liquido[2]+','+ liquido[3]+','+ liquido[4]+','+ liquido[5];
 Serial.write(inserito);
 for (int i = 0;  i < 6; i++)
{
   Serial.print(liquido[i] );
  
  if( liquido[i] != liquidoESATTO[i] ) 
  {
    Serial.println("not equal");   
      esito=false;
  }else{
      esito=true;
  }
}
  if(!esito){
     lcd.setCursor(3, 0);
      lcd.print("Operazione");
      lcd.setCursor(4, 1);
      lcd.print("FALLITA");
  }else{
    lcd.setCursor(3, 0);
      lcd.print("Operazione");
      lcd.setCursor(4, 1);
      lcd.print("RIUSCITA");
  }
  
delay(6000);
menu=8;
 break;

 case 8:
  lcd.clear();
  lcd.setCursor(0, 0);
  for (int i = 0;  i < 6; i++)
  {
lcd.print(liquido[i]);
lcd.setCursor(i*3, 0);
  }
  lcd.setCursor(0, 1);
  for (int i = 0;  i < 6; i++)
  {
lcd.print(liquidoESATTO[i]);
lcd.setCursor(i*3, 1);
  }
delay(30000);
 break;

}
  
  
}

void succhia(int quanto,int cosa)
{
  lcd.clear();
  digitalWrite(cosa+4, HIGH);
 // digitalWrite(rele7,HIGH);
  lcd.setCursor(0, 0);
  lcd.print("Aspirazione "+ String(cosa));
  int quantoT=quanto * unml;
  updateProgressBar(quantoT, 1);
  digitalWrite(cosa+4,LOW);
 // digitalWrite(rele7,LOW);
  delay(1000);
}

void readKeypad()
{
 
  if(keyPad.isPressed()){ 
  key = keyPad.getChar();
  tone(buzz, 400, 70);
  if (key >= '0' && key <= '9') //only act on numeric keys
  {lcd.setCursor(digitCount, 1);
    inputCode[digitCount++]=key;    
    lcd.print(key);
    delay(600);
  }
  if (key == '#') //user has entered 3 digits
  {
    delay(400);
    entryComplete = true; //flag completion
    digitCount = 0;
    //Serial.println();
    //Serial.println("entry is complete");
    return; //exit the function
  }
}}


 void updateProgressBar(unsigned long tempo, int lineToPrintOn) {
    double factor = tempo/80.0;
   // Serial.println(factor);
   // Serial.println(tempo);
      for(int i=0; i <= 80; i++){
        int remainder = i % 5;
        int number = i / 5;      
       lcd.setCursor(number,lineToPrintOn);
       lcd.write(byte(remainder+1));

    delay(factor);  }
    return;
 }


Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Fatto, non sono pratico dei forum :smiley:

Purtroppo con i relé ed i disturbi EMC che ne conseguono, capita spesso ... puoi provare a:

  • allontanare i fili
  • separare TOTALMENTE le alimentazione tra Arduino ed il modulo relé
  • mettere un qualche fîltro sui carichi per eliminare i disturbi.

La cosa più importante, normalmente, è separare le alimentazioni ed usare DUE alimentatori separati (senza neanche i GND in comune) ... uno per il solo Arduino a 5V ed uno per il resto a12V. Il collegamento è il seguente:

In questo modo avrai un funzionamento a logica inversa: pin HIGH -> relé OFF, pin LOW -> relé ON.

Comincia con l'allontanre i fili e questa separazione, poi, se ancora hai disturbi, c'è da verificare i vari carichi.

Guglielmo

Per prima cosa complimenti allo OP
ha ben descritto il problema ed ha un programma ben scritto e ben indentato, e anche la parte HW è ben fatta
noi crediamo che il problema sia dovuto al differente carico tra assenza e presenza acqua nelle pompe

separeremmo l'alimentazione 12 e 5 V
comunque alla fine differente causa stessa soluzione di Guglielmo

a voler proprio fare un appunto allo OP ci sarebbe l'uso di oggetti stringa, ma è male comune agli inizi

gli oggetti stringa sono il male, il lato oscuro, i sith di arduino
sono gli oscuri emissari della seconda fondazione (chi ha letto Asimov ha capito)

invece di fare

lcd.print("CISTERNA " +String(menu)+ " (ml)");

così:

lcd.print("CISTERNA ");
lcd.print(menu);
lcd.print( "  (ml)");

lo sappiamo che è una menata rispetto all'uso di String
ma è di molto più sicuro, se non si vuole finire dimenticati su Vesta (che ha letto Asimov ha capito)

Ragazzi grazie per i consigli e i complimenti. Avevamo capito che era un problema di carichi e stavamo pensando di separare l'alimentazione arduino+ relè da quella delle pompe xchè non associo il problema acqua o non acqua al relè ma alla pompa. Se anche così non va allora faremo come dite e modificherò anche il codice.
Poi dopo il torneo vi farò vedere il funzionamento completo prima non lo posso svelare :wink:

I 12V sono stabili all'avvio delle pompe, oppure scendono per un attimo a un valore tale da non garantire più i 5V all'uscita del convertitore?

Fai anche attenzione al giro delle masse: il filo di massa che va alle pompe non deve passare prima da Arduino, ma deve essere indipendente, altrimenti sui picchi di assorbimento delle pompe gli 0V si alzano e tra i 5V e massa non ci sono più 5V!

Grazie per l'aiuto, le pompe sono su un secondo alimentatore.
Oggi ho tolto corrente alle pompe e alimentando arduino con un powerbanck ha funzionato tutto.
L'arduino si riavvia appena la pompa smette di funzionare!
Se alimento i relè dal secondo alimentatore si accendono tutti i relè.
Non sò più che altro inventarmi.

Ciao Guglielmo,
io ho questa scheda relè non ho ben capito tu dove fai quella connessione che fai in basso a destra.
La posso fare su un jumper qualsiasi?

No. Questa scheda è diversa. La separazione delle alimentazioni non è possibile in modo totale, anche alimentando la scheda con un secondo alimentatore a 5V il GND è in comune, ma ritengo sia comunque meglio che lasciare in comune anche i 5V di logica e bobine. Quello che manca sicuramente sono gli snubber sui contatti, per cui ad ogni apertura scintillano e disturbano la logica (e dureranno anche poco). In parallelo ad ogni motore (parliamo di corrente continua vero?) va aggiunto un diodo con il catodo (punta) verso il positivo.

Grazie per l'aiuto, ma prima di leggere la tua risposta stamattina ho trovato su altri forum un problema simile al mio che avevano risolto mettendo un diodo su ogni motore. Così ho provato pure io e ad ora non mi sta dando più problemi, ma devo testalo più volte xchè non voglio sorprese. Comunque avevo ordinato anche una seconda scheda relè simile a quella dello schema di Guglielmo. Appena lo completo vi posto una foto.
Qui è ancora work in progress

Ciao