Datalogger in een pompgroep met problemen. (DANGER: lang postje)

Hoi!

Sommige mensen hebben me misschien al eens gezien op dit arduino forum maar zo niet: Ik werk met een groep aan een schoolproject waarbij we een natuurreservaat moeten onderhouden met een pompgroep.

Het doel van ons programma:

Als de hoofdschakelaar bediend is mag het programma beginnen werken.
Anders staat de pomp uit en brand er geen enkel lichtje. Als de hoofdschakelaar bediend is start het
eigenlijke programma. Er zal een lichtje branden als indicatie. Als de sensor laag water detecteert zal, na een hysteresis, de pomp beginnen werken als dit gebeurt dan zal de datum en tijd ook worden weggeschreven. Als de sensor hoog water detecteert dan valt de pomp af en wordt er opnieuw datum en tijd weggeschreven.

We hebben ook een LCD nodig die weergeeft of de pomp aan het draaien is of niet.
Als de hoofdschakelaar aan is en niemand drukt op een knopje, dan zal de achtergrondverlichting van het LCD uitschakelen. Als er iemand op een knopje duwt dan gaat die licht voor een poosje branden en scrolt het volgende op het scherm:

  1. Is er een error? 2.De status van de pomp.

Ik heb wel ondervonden dat er een groot probleem is, mijn collega gebruikt de millis functies, maar die kunnen maar tot ongeveer 50dagen tellen waarna deze resetten. (Source) maar omdat ze liever hun eigen zin doordrijven en mij erbuiten laten, kan ik hier niet veel aan doen.

Zoals je ziet (in het totale programma) zal er veel gedocumenteerd staan, dat is de manier waarop ik werk.. Maar mijn collega's niet echt. Dit zorgt voor het probleem dat telkens als zij het beter weten (en dat is heel veel) dat ik dit weer moet controleren en documenteren..

Dus deze keer niet anders, en dan vind ik dit:

#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); 
#endif
  rtc.begin();

  rtc.adjust(DateTime(2015,3,26,9,44,0));  // Het juist zetten van de datum en de tijd in het real time shield.
                                           // (DateTime(jaar,maand,dag,uur,minuten,seconden))

Mijn vraag:
Gebruikt men dit om de RTC te initialiseren? ik heb het opgezocht op de arduino website maar het enigste wat ik ervan versta is dat dit wordt gebruikt voor I2C communicatie?

Kan iemand me dit uitleggen?

We monteren het Datalogger shieldje op onze arduino mega zodat de 5v, gnd etc.. op elkaar zit. (Dus shieldje helemaal langs links)


Onze setup:

Arduino Mega 2560
Adafruit datalogger shield (Documentatie
HD44780 LCD display
Ik gebruik liever geen I2C voor de simpele reden: Ik ken er niet veel van, buiten dat het een middel is om met de arduino te communiceren.

sorry het programma is te lang voor in 1post!

#include <LiquidCrystal.h> // Library voor LCD aan te sturen.
LiquidCrystal lcd(40, 50, 49, 48, 47, 46);

#include <SPI.h>
#include <SD.h>
File myFile;

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;

/*Ingangen benoemen*/

const int EH = 23;                      //Sensor: Endress & Hauser trilvork                   
const int MainSwitch = 39;              //Hoofdschakelaar                                     

/*Uitgangen benoemen*/
const int PumpHigh = 27;                //Geel lampje als pomp werkt                          
const int PumpLow = 29;                 //Rood lampje als de pomp niet werkt                  
const int LSHigh = 31;                  //Geel lampje als niveau goed is                      
const int Pump = 33;                    //Relais van de pomp                                 
const int MainSwitchHigh = 35;          //Rood lampje Hoofdschakelaar
const int ledPin =  36;                 // De pin nummer van het lcd scherm
const int ledPin2 =  37;                // De pin nummer van het lcd scherm
const int PumpPin = 30;                 // De pin waar het signaal van "de motor draait" op aangesloten wordt.
const int buttonPin2 = 31;              // Knop voor het lcd scherm aan te zetten
const int SDaanwezig = 2;               // Hardware aansluiting dat SD aanwezig is of niet.
const long interval = 10000;            // tijd dat het lcd scherm aan blijft in miliseconden
const long interval2 = 10000;           // Hysteresis van de pomp!!

int SensorState = 0;                    //In rust is de status van de sensor laag
int MainSwitchState =0;                 //In rust is de status van de hoofdschakelaar laag
int buttonState = 0;                    // De initiële stand van de knop ("motor draait ingang")
int lastButtonState = 0;                // Vorige staat van de knop (zorgt voor flankdetectie)
int buttonState2 = 0;                   // De initiële stand van de knop lcd scherm
int ledState = LOW;                     // De initiële stand van de pin van het scherm
int ledState2 = LOW;                    // De initiële stand van de background pin van het scherm

/*In- en uitgangen instellen*/
void setup ()
{
Serial.begin(9600);                     //Serieel inlezen van data met een snelheid van 9600 baud
  pinMode(EH,INPUT);              
  pinMode(PumpHigh,OUTPUT);      
  pinMode(PumpLow,OUTPUT);
  pinMode(LSHigh,OUTPUT);
  pinMode(Pump,OUTPUT);
  pinMode(MainSwitch,INPUT_PULLUP);     //PULLUP weerstand om stoorsignaal te ellimineren
  pinMode(MainSwitchHigh,OUTPUT);
  pinMode(PumpPin, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(SDaanwezig,INPUT_PULLUP);     //pullup omdat deze rehtstreeks aan de ground hangt
 
  lcd.begin(16,2);
  lcd.noDisplay();
  SD.begin(10, 11, 12, 13);               // De pinnen die gebruikt worden om op de SD-kaart weg te schrijven
  
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); 
#endif
  rtc.begin();

  rtc.adjust(DateTime(2015,3,26,9,44,0));  // Het juist zetten van de datum en de tijd in het real time shield.
                                           // (DateTime(jaar,maand,dag,uur,minuten,seconden))

}

/*Het programma*/
void loop()
{

    DateTime now = rtc.now();
    buttonState2 = digitalRead(buttonPin2);                       // Hier word de status van de buttonpin weggeschreven in de buttonState2
    unsigned long currentMillis = millis();                       // Hier word de tijd dat het systeem draait weggeschreven naar currentMillis
    unsigned long currentMillis2 = millis();

MainSwitchState = digitalRead (MainSwitch);    //Status van de hoofdschakelaar inlezen
if (MainSwitchState == LOW)                    //Als de status v.d. hoofdschakelaar laag is
{
  digitalWrite(MainSwitchHigh,HIGH);           //Led hoofdschakelaar hoog
  SensorState = digitalRead (EH);              //Status van de sensor inlezen op ingang EH
      if (SensorState == HIGH)                 //Als status sensor = hoog
        {
          previousMillis2 = currentMillis;
          digitalWrite (Pump,LOW);             //Pomp => laag
          digitalWrite (PumpHigh,LOW);         //Led dat zegt dat pomp aan staat => laag
          digitalWrite (PumpLow,HIGH);         //Led dat zegt dat pomp uit staat => hoog
          digitalWrite(LSHigh,HIGH);           //Led dat zegt dat sensor bediend wordt => hoog
          Serial.println("pomp = LOW");        //Status van de pomp doorsturen naar seriële monitor
          digitalWrite (buttonState, LOW);
        }
      else {                                     //Sensor niet bediend
          if (currentMillis - previousMillis2 >=interval2) {
            
           digitalWrite (Pump,HIGH);           //Pomp => aan
           digitalWrite (PumpHigh,HIGH);       //Led pomp aan => hoog
           digitalWrite (PumpLow,LOW);         //Led pomp uit => laag
           digitalWrite(LSHigh,LOW);           //LevelSwitchHoog Led => laag
           Serial.println("pomp = HIGH");      //Status van de pomp doorsturen naar seriële monitor
           digitalWrite (buttonState, HIGH);
          }
       };
 }
 else                                          //Als de hoofdschakelaar af staat werkt de pomp niet nog branden de ledjes
 {
   digitalWrite(Pump,LOW);                     
   digitalWrite(PumpLow,LOW);
   digitalWrite(PumpHigh,LOW);
   digitalWrite(LSHigh,LOW);
   digitalWrite(MainSwitchHigh,LOW);
   digitalWrite (buttonState, LOW);
   Serial.println("alles = LOW");
 };
 if (buttonState != lastButtonState) {                         // Edge detection of the pump
                                                                  // Het geïnverteerde van lastButtonState wordt dan weggeschreven in buttonState
    
      if (buttonState == HIGH) {                                  // Als buttonState hoog is wil dit zeggen dat de pomp begint met draaien
      
    
      myFile = SD.open("werkuren.txt", FILE_WRITE);               // Voor men in een bestand kan schrijven moet men dit eerst openen
      
      myFile.print("Start pompen");                               //
      myFile.println();  
      myFile.print(now.year(), DEC);
      myFile.print('/');
      myFile.print(now.month(), DEC);
      myFile.print('/');
      myFile.print(now.day(), DEC);
      myFile.print(' ');
      myFile.print(now.hour(), DEC);
      myFile.print(':');
      myFile.print(now.minute(), DEC);
      myFile.print(':');
      myFile.print(now.second(), DEC);
      myFile.println();
      myFile.close();  
      }
    
      else {
           
      myFile = SD.open("werkuren.txt", FILE_WRITE);
      myFile.print(now.year(), DEC);
      myFile.print('/');
      myFile.print(now.month(), DEC);
      myFile.print('/');
      myFile.print(now.day(), DEC);
      myFile.print(' ');
      myFile.print(now.hour(), DEC);
      myFile.print(':');
      myFile.print(now.minute(), DEC);
      myFile.print(':');
      myFile.print(now.second(), DEC);
      myFile.println();
      myFile.print("Einde pompen");
      myFile.println();
      myFile.println();
      myFile.close();
      }
    }
    if (buttonState2 == HIGH) {                                   // Als de knop van lcd scherm aan hoog wordt dan gebeurt het volgende (zier hieronder)
      previousMillis = currentMillis;                             // PreviousMillis wordt gelijk aan currentMillis, previousMillis houd de tijd bij van de laatste keer dat er op de knop lcd aan werd gedrukt
      digitalWrite(ledPin , HIGH);                                // De pin van het scherm en van de background worden hier hoog gezet, het scherm gaat dus aan
      lcd.display();
    }
      
    if(currentMillis - previousMillis >= interval) {              // Als currentMillis (momentele systeem tijd) min de previousMillis (laatste keer dat op knop is gedrukt)
                                                                  // groter of gelijk wordt aan het interval (tijd dat lcd aan mag blijven) dan gebeurt het volgende
      digitalWrite(ledPin , LOW);                                 // De schermpin en backgroundpin worden hier weer laag gezet wanneer de tijd verlopen is.
      lcd.noDisplay();
    }
    
    if (digitalRead (SDaanwezig) == HIGH)          // origineel SD.begin(10, 11, 12, 13), werkt niet , high = geen detectie
  {
                                              //Als niemand op het knopje voor de error te skippen duwt
    while(digitalRead (buttonState) == LOW)                 //Dan blijf je de error op het LCD schrijven. (while loop gaat oneindig keer door. -- aangepast
    {
      while(digitalRead (SDaanwezig) == HIGH);
   lcd.clear(); 
   lcd.setCursor(0,0); 
   lcd.println("SD card error");         // Error if SD doesnt load
    }
                                   
    { delay(2000);
    }
    
     if (buttonState == HIGH) {
      lcd.clear();
      lcd.setCursor(0,0);  
      lcd.print("pomp aan");
    }
    else {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("pomp uit");
    }
    
    lastButtonState = buttonState;
    delay (1000);
};

Met wire kan ik je niet veel helpen.
Ik ben zelf nog te veel aan het studeren.

Voor een timertje dat 30x age of universe meegaat heeft Rob Tillaart mij ooit eens geholpen.
Ik kan je garanderen dat het timertje echt echt echt werkt.

Het doet geen schrikkeljaren en zelfs geen 31ste dag,
maar voor dataloggen moet het toch bruikbaar zijn.

link naar het timertje van Rob Tillaart.

je hebt eigenlijk al heel wat voor elkaar.
je hoeft je collega niet te controleren als je elk een deel doet.
zijn oplossing is prima, zelfs bij een overflow gaat het goed.

rtc er zit en klein batterijtje in de rtc die hoef je dus alleen maar gelijk te zetten als je de batterij vrqisselt (nooit dus) dus die regel eruit.

sdfile eerst de datum (een functie van maken) en dan de actie erachter, dan staat het mooi onder elkaar.
gebruik delimiters dan kun je berekeningen gaan maken, zoals looptijd,stoptijd.

ja documentatie is belangrijk, echter wel functioneel.
wat veel belangrijker is zijn diagrammen, tekeningen, flowsheet, etc.
oja planning

Vriendelijk bedankt voor de reacties!