Incubatrice

Salve a tutti, finalmente ho finito la mia incubatrice, però prima di procedere al vero e proprio test volevo delle info se possibile.

la mia configurazione è la seguente:

  1. Arduino Mega 256
  2. Sensore di umidita e temperatura HYT271
  3. Sensore di temperatura DS18B20
  4. Dispaly Blue Serial IIC/I2C/TWI 2004 204 20X4
  5. Arduino Data Logger shield RTC SD card
  6. min joystick resistivo
  7. modulo relè 4 canali optoisolati
  8. pompa acqua
  9. umidificatore

insomma non ho badato a spese :confused:

in ogni caso sembra funzionare tutto correttamente, quello che non riesco a regolare al 100% è l'oscillazione di temperatura e umidità quando tutto il sistema sta a regime.

ad esempio, per i pulcini la temperatura dovrebbe essere compresa fra 37.5 a 38.5, la mia oscillazione scende sia al di sotto e va nche al di sopra, idem per l'umidità.

Come posso fare gestire meglio questa cosa ?

Al posto di una regolazione on off con isteresi usa un regolatore PID. Pilota la resistenza con un sold state relais e con treno d' impulsi in modo da regolare la potenza di riscaldamento.
Ciao Uwe

Devi controllare anche l'umidità. Troppo bassa la cuticola si secca e il pulcino non riesce a bucare il guscio, troppo alta il pulcino muore soffocato. Se hai sbalzi di umidità nascono pulcini malformati specialmente alle zampe e devi sopprimerli.
Non incubare le uova finchè non hai raggiunto valori stabili.
Le giri a mano? Non ho visto motori o altro nella lista

Rieccomi, dopo la bacchettata che mi hanno fatto su un tred simile posto degli aggiornamenti in modo poter portare a termine la cosa visto che finalmente sono riuscito ad andare avanti...

Il materiale hardware è abbastanza simile, ho aggiunto solo dei sensori più idonei per il livello dell'acqua e adesso l'umidificatore va alla grande, grazie al sensore Di umidità e temperatura HYT 221 ho una lettura della umidità più stabile e reale, per quanto riguarda la lettura di temperatura integrato su questo device non posso dire la stessa cosa, infatti mi sono dovuto affidare ad un'altro sensore più stabile sul rilievo DS18B20.

Nell'altro Trend mi avevano chiesto dove ho collegato l'alimetazione, Arduino Mega ADK è alimentato direttamente e tutti i device extra come : Dispaly , Joistik, Sensore di temperatura, Sensore di umidità, relè shield sono collegati all'alimentatore esterno, solo la shield rtc datalogger alloggia su arduino mega e preleva l'alimentazionee dalla scheda principale.

Non ho collegato servo motori per girare le uova ma appena risolverò questi problemi di stabilità sicuramente lo farò visto che il contenitore già possiede delle coppette girevoli ma manualmente.

ALtro particolare, usando il relè sulla resistenza on-off ho un'oscillazione di circa 0.20C° che non penso siano esagerati ma in ogni caso se la cosa si rileva un problema mi è stato nominato un Relè allo stato solido, nel caso non posso fare a meno, dove posso procurarmi un buon relè di questo tipo ?

per quanto rigurda lo skatch lo incollo in modo da cominciare ad analizzare nel concreto il lavoro fatto

Questa è la parte dove ho definito costanti e librerie

#include <OneWire.h>
  #include <Wire.h>
  #include <RTClib.h>
  #include <LiquidCrystal_I2C.h>
  //Sensor DS18B20 Temperature
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;
  OneWire  ds(3); //Pin Termometro
  //End Temp Var
  //Sensor HYT 221-I2C Humidity and temperature
  #define HYT_ADDR 0x28
  double humidity;
  double temperature;
  int b1,b2,b3,b4,rawHumidity,rawTemperature;
  //RELE
  /*
      R2 //POMPA
      R3 //UMIDIFICATORE
      R4 //RESISTENZA
      V1 //VENTOLA UMIDIFICATORE
   */
  #define R1 24
  #define R2 27
  #define R3 26
  #define R4 25
  #define V1 41
  //JoyStick
  // x
  // y
  // z
  #define JoyStick_X A0
  #define JoyStick_Y A1
  #define JoyStick_Z 4 
  //Livello acqua
  #define PIN_S_ACQ 40
  #define cleanstring "                    "
  //RTC SD CARD
  RTC_DS1307 RTC;
  int OLD_TIME;
  int OLD_R1 = 9;//0
  int OLD_R2 = 9;//0
  int OLD_R3 = 9;//1
  int OLD_R4 = 9;//1
  int OLD_V1 = 9;//0
  int OLD_S_ACQ = 9;//0
  unsigned long prewTimer1 = 0;
  unsigned long prewTimer2 = 0;
  //DISPLAY
  LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
  float T,H,T2;
  int x,y,z;
  int S_ACQ = 0;
  //RESSSS
  byte cfg;
  int16_t raw;

onestamente per ora non sono molto contento di come ho scritto il codice, appena comincerò a prendere familiarità con Arduino, sicuramente lo sistemerò alla grande

Setup

void setup(void) {
 
  //OUTPUT DEFINITION
  pinMode(R1,OUTPUT);
  digitalWrite(R1,HIGH); //VENTOLA Grande
 
  pinMode(R2,OUTPUT);
  digitalWrite(R2,HIGH); //POMPA
 
  pinMode(R3,OUTPUT); //UMIDIFICATO
  digitalWrite(R3,HIGH);
 
  pinMode(R4,OUTPUT); //RESISTENZA
  digitalWrite(R4,HIGH);

  pinMode(V1,OUTPUT);
  digitalWrite(V1,LOW);
  //JOYSTIK
  pinMode (JoyStick_X, INPUT);
  pinMode (JoyStick_Y, INPUT);
  pinMode (JoyStick_Z, INPUT);
  //Sensonre livello Acqua
  pinMode (PIN_S_ACQ, INPUT);
  S_ACQ = digitalRead(PIN_S_ACQ);
  Wire.begin();
  RTC.begin();
  OLD_TIME = 0;
  Serial.begin(9600);
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    //RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  //DISPLAY
  lcd.begin(20,4);
  clean_display();
  //lcd.noBacklight();
  lcd.backlight(); 
}

LOOP

void loop(void) {
  //  read_joistick();
  DateTime now = RTC.now();
  if (OLD_TIME != now.second()) {   
    OLD_TIME = now.second();
    T = getTemp();
    delay(1500);
    H = getHYT(1);
    Serial.print("T: ");
    Serial.print(T);
    Serial.print("C H: ");
    Serial.print(H);
    Serial.println("%");
    setRes();
    setHum();
    getAcq();
    clean_display();
    lcd.setCursor(0,0); 
    lcd.print("T:" + String(T));
    lcd.setCursor(8,0);
    lcd.print("C H:" + String(H) + " %");
  } 
}

Funzioni

float clean_display() {
  lcd.setCursor(0,0);
  lcd.print(cleanstring);
  lcd.setCursor(0,1);
  lcd.print(cleanstring);
  lcd.setCursor(0,2);
  lcd.print(cleanstring);
  lcd.setCursor(0,3);
  lcd.print(cleanstring);
}
float getHYT(char Type){
    Wire.beginTransmission(HYT_ADDR);   // Begin transmission with given device on I2C bus
    Wire.requestFrom(HYT_ADDR, 4);      // Request 4 bytes
    if(Wire.available() == 4) {                   
      b1 = Wire.read();
      b2 = Wire.read();
      b3 = Wire.read();
      b4 = Wire.read();
      Wire.endTransmission();           // End transmission and release I2C bus
      rawHumidity = b1 << 8 | b2;
      rawHumidity =  (rawHumidity &= 0x3FFF);
      humidity = 100.0 / pow(2,14) * rawHumidity;
      b4 = (b4 >> 2); // Mask away 2 least significant bits see HYT 221 doc
      rawTemperature = b3 << 6 | b4;
      temperature = 165.0 / pow(2,14) * rawTemperature - 40;
      switch (Type) {
        case (1):
          return humidity;
        break;
        case (0):
          return temperature;
        break;
        default :
          return humidity;
      }
    }
  }

float setRes(){
  if(T < 37.5){
    if(OLD_R4 != 0){
      OLD_R4 = 0;
      digitalWrite(R4,LOW); 
    }
  } else {
    if(OLD_R4 != 1){
      OLD_R4 = 1;
      digitalWrite(R4,HIGH); 
    }
  }
  if(T == 00.00) {
    digitalWrite(R4,HIGH); 
  }
}

float setHum() {
  if(getHYT(1) < 60) {
    if(OLD_R3 != 0){
      OLD_R3 = 0;
      digitalWrite(R3,LOW);
    }
    if(OLD_V1 != 1) {
      OLD_V1 = 1;
      delay(1500);
      digitalWrite(V1,HIGH);
    }
  }else {
    if(OLD_R3 != 1){
      OLD_R3 = 1;
      digitalWrite(R3,HIGH);
    }   
    if(OLD_V1 != 0){
      OLD_V1 = 0;
      delay(1500);
      digitalWrite(V1,LOW);
    } 
  } 
}

float getTemp(){
  //error
  if ( !ds.search(addr)) {
    ds.reset_search();
  }
  //error
  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
  }
  switch (addr[0]) {
    case 0x10:
      //Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      //Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      //Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    //default:
    //Serial.println("Device is not a DS18x20 family device."); 
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44);
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);       
  for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
  OneWire::crc8(data, 8);
  raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw & ~7;
    else if (cfg == 0x20) raw = raw & ~3;
    else if (cfg == 0x40) raw = raw & ~1;
  }
  celsius = (float)raw / 16.0;
  return celsius;
}
int getAcq(){
  //Accendere pompa
  S_ACQ = digitalRead(PIN_S_ACQ); 
  if(S_ACQ == 1) {
    if(OLD_S_ACQ != 0){
      Serial.println("Pompa accesa"); 
      digitalWrite(R2,LOW);
      OLD_S_ACQ = 0;
    }
  }else {
    if(OLD_S_ACQ != 1){
      digitalWrite(R2,HIGH);
      Serial.println("Pompa spenta");       
      OLD_S_ACQ = 1;
    }
  } 
}

int read_joistick(){
  x = analogRead (JoyStick_X);
  y = analogRead (JoyStick_Y);
  z = digitalRead (JoyStick_Z);
}

Avevo raggiunto il limite massimo di caratteri :-P, in più aggiungo quanto segue:

Mi è stato ribadito chè è un problema di alimentazione, e proprio per questo ho controllato le oscillazioni che ci sono sul circuito, ma sono veramente minime, nonscendono al di sotto dei 5.5v solo quando si attivano i relè.

Per chi sta leggendo questa mia risposta vi aggiorno sulla problematica fondamentale, adesso tutto il processo funziona bene, la temperatura è molto stabilè e l'umidificatore fa il suo lavoro, ho veramente quasi raggiunto la perfezione nel mantenere umidità e temperatura stabili il problema risiede nel fatto che circa dopo 10 minuti il display rimane acceso solo con la luce e non visualizza nessun aggiornamento mentre sulla seriale continuano ad arrivare info e dopo circa 4 ore il sistema va in blocco, non mi arrivano info nemmeno dalla seriale e i relè sembrano morti.

Da dove posso cominciare a risolvere problemi ?

Come sei messo a "memoria libera" dopo un po' che il programma gira? Perché sembrerebbe quasi un esaurimento della SRAM con conseguente impazzimento del programma.

Per vedere quale è l'andamento della memoria, prova a leggere QUI :wink:

Guglielmo

Buongiorno, grazie per la risposta @gpb01 , stamattina ho incluso la libreria MemoryFree.sh sul mio Sketch, visto le configurazioni che ho sul MAC non volevo installare AVR-SIZE...

Comunque veniamo a noi, dovo ver incluso la libreria, in void loop()... ho incluso il seguente codice

    Serial.print("Memory Free : ");  
    Serial.println(freeMemory());

Mi restitusce sempre 7479 come valore.. è corretto o sto analizzando qualcosa di sbagliato ?

Tu sei un una Mega 2560 giusto ? Se SI, la Mega ha 8KB di SRAM quindi ... quella potrebbe essere una cifra veritiera ... anche se mi sembra che indichi un uso un po' troppo ridotto della memoria ... ::slight_smile:

Se metti il Verbose nelle preferenze dell'IDE e compili, che indicazioni di occupazione ti da ? Perché se veramente ne usi così poca, allora il problema è da ricercare altrove ...

Guglielmo

Ecco cosa mi dice l'ide dopo la compilazione

Lo sketch usa 14.654 byte (5%) dello spazio disponibile per i programmi. Il massimo è 253.952 byte.
Le variabili globali usano 680 byte (8%) di memoria dinamica, lasciando altri 7.512 byte liberi per le variabili locali. Il massimo è 8.192 byte.

Credo di aver risolto il problema che va in blocco, anche se l'alimentatore che ho usato è un vero mostro, i relè sono il vero problema, per risolvere con queste interferenze prodotte dai relè ho aggiunto dei ritardi nello skatch in prossimità delle funzioni che li attivano.

ecco il codice:

void loop(void) {
  //  read_joistick();
  DateTime now = RTC.now();
  if (OLD_TIME != now.second()) {     
    Serial.print("Memory Free : ");  
    Serial.println(freeRam());
    OLD_TIME = now.second();
    T = getTemp();
    delay(1500);
    H = getHYT(1);
    Serial.print("T: ");
    Serial.print(T);
    Serial.print("C H: ");
    Serial.print(H);
    Serial.println("%");
    setRes();
    delay(1500);
    setHum();
    delay(1500);
    getAcq();
    delay(1500);
    clean_display();
    lcd.setCursor(0,0);  
    lcd.print("T:" + String(T));
    lcd.setCursor(8,0);
    lcd.print("C H:" + String(H) + " %"); 
  }  
}

In ogni cosa, mi conviene risolvere il problema elettrico e eliminare i delay() ?

Assolutamente ti consiglierei di risolvere il problema elettrico.
Studia il modo di utilizzare delle Reti RC (Snubber).

In pratica poni in parallelo al carico una resistenza ed un condensatore.

Se mi indichi con precisione i carichi (col voltaggio) provo a consigliarti al meglio.

PS I delay andrebbero comunque evitati... in quanto bloccano il programma ... quando metterai in opera progetti più complessi non potrai permettertelo.

Ho utilizzato questa scheda : MODULO SCHEDA RELE' ARDUINO 5V DC A 4 CANALI 220V 250V 10A AC RELAY SHIELD E LED | eBay

Un modulo a 4 relè, mm ma ora mi sorge un dubbio, guardando nei dettagli tecnici di questa scheda

Specifiche tecniche:

- 4 Relè a bordo SRD-05VDC-SL-C ;
- Tensione alimentazione 5Vdc (5,3Vdc fino a 5,8Vdc tensioni suggerite);
- Tensione di pilotaggio per ogni canale (IN1-IN4) 1,5Vdc
- Corrente di assorbimento circa 100mA per ciascun per relè;
- Commutazioni in uscita 28Vdc 7A / 240Vca 7A / 125Vca 10A;
- Strip connessione 2.54mm ;
- 4 Contatti NC e 2 contatti NA ;
- 4 LED SMD di segnalazione ;
- Modulo optoisolato;

vedo che la tensione di pilotaggio è 1.5v ma io gli passo 5V direttamente da Arduino :frowning: questo potrebbe causare problemi ?

Zamundo:
I delay andrebbero comunque evitati... in quanto bloccano il programma ... quando metterai in opera progetti più complessi non potrai permettertelo.

Evitiamo di "demonizzare" il delay() ... :smiling_imp:
... è una funzione utile che può essere tranquillamente usata dove il programma lo permetta, indipendentemente dalla sua complessità.

Ho un oggetto, gestito da un firmware fatto da oltre 2000 linee di codice e faccio ampio uso della delay() ...
... essa va tassativamente evitata nel caso in cui, durante il periodo di "attesa" occorra necessariamente fare altre cose, in tutti gli casi ... è inutile complicarsi la vita. :grin:

Guglielmo

Specifichiamo meglio.

Un delay() breve di 10mS per un debonce semplice nella maggior parte dei casi é ammissibile. Anche dei delay() per dare il tempo di inizializzare hardware o che sensori o interfaccie possano fornire dati spesso é utile.

Delay() piú lunghi bloccano il codice. Spesso questo é un problema perché un programma deve reagire a dei imput sia da sensori o da pulsanti.

Ciao Uwe

uwefed:
Un delay() breve di 10mS per un debonce semplice nella maggior parte dei casi é ammissibile. ... [omissis]

Delay() piú lunghi bloccano il codice. Spesso questo é un problema ... [omissis]

... non sono d'accordo a porre limiti temporali ... 10mSec, 100mSec, ecc ... il punto è ... durante la delay() occorre fare o meno altre cose ?

Se SI, non si può usare, se NO, si può tranquillamente usare, indipendentemente dalla sua durata. :slight_smile:

Guglielmo

P.S: Nel FW a cui accennavo i delay() sono anche di secondi ... :wink:

Mi do vinto. :wink: :wink: :wink: :wink: :wink:
Ciao Uwe

Abbiamo sempre detto a chi non è proprio agli inizi di evitare il delay e studiare molto bene il millis,
perchè non blocca il codice (anche nella semplice pressione di un pulsante!) e permette di gestire più ritardi contemporaneamente.

Adesso questo consiglio di fare uso del delay mi stupisce un pochino..... ma ubi maior minor cessat!

:wink:

Zamundo:
Abbiamo sempre detto a chi non è proprio agli inizi di evitare il delay e studiare molto bene il millis,
perché non blocca il codice

... esatto ... e ribadisco ... DOVE serve che il codice NON venga bloccato, ma, dove questo non ha importanza, perché complicarsi la vita ? :slight_smile:

Guglielmo

P.S: Il che non toglie che ... la millis() vada STUDIATA :smiley: :smiley: :smiley:

Mi è molto chiara questa problematica e infatti sicuramente in questo codice implementerò un sistema di mapping temporale stile multitimer che ho già utilizzato in altri linguaggi quindi per adesso posso considerare questo problema dei delay() risolto...

Quello che mi rimane adesso come errore hardware fa riferimento ai relè che manda in tilt il sistema, ho già scritto in una mia vecchia risposta su questo argomento, la shield utilizza dei segnali di attuazione per abilitare i relè di 1.5v ma io gli passo direttamente i 5v di arduino...

Funziona ma credo che questo sarà un problema che dovrò risolvere frapponendo una semplice resistenza tra pinout arduino e I1 I2 I3 I4, inoltre come posso fare a utilizzare un circuito rc su questa shield per risolvere le interferenze generati dall'eccitazione dei relè ? mica posso fare delle modifiche al circuito della shield ?

sjpagan,
ti ho risposto a questo il 9 gennaio!!!