Problem with automatic petfeeder with real-time clock

beste,

ik ben bezig met het maken van een automatische petfeeder.
ik heb al grotendeels een code maar zit nu een beetje in de problemen.
na 5 seconden toont de lcd de tijd en datum maar niet zo heel duidelijk. petfeeder toont hij de eerste 5 seconden wel duidelijk.
Na die 5 seconden begint de servo ook direct te draaien.
Ik weet niet waar mijn probleem ligt maar heb na lang zoeken nog steeds niets gevonden.
ik heb geen foutmeldingen.

//REAL TIME CLOCK MODULE
  // CONNECTIONS:
  // DS1302 CLK/SCLK --> 5
  // DS1302 DAT/IO --> 4
  // DS1302 RST/CE --> 2
  // DS1302 VCC --> 3.3v - 5v
  // DS1302 GND --> GND

  #include <ThreeWire.h>  
  #include <RtcDS1302.h>

  ThreeWire myWire(4,5,2); // IO, SCLK, CE
  RtcDS1302<ThreeWire> Rtc(myWire);

  int uur;
  int minuten;
  int seconden;

//SERVO
  #include <Servo.h>
  Servo myservo;


//LCD SCHERM
  #include <LiquidCrystal_I2C.h>
  #include <Wire.h> 

  LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

//POTENTIOMETER
  const int pinPotentiometer = A0;

  int resultaatUUR = 0;
  int resultaatMINUUT = 0;

//KNOP  
  const byte button    = 7;

  byte buttonState     = 0;
  byte lastButtonState = HIGH;
  byte buttonCounter   = 0;


// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;  // will store last time LED was updated

// constants won't change:
const long interval = 1000;  // interval at which to blink (milliseconds)


//******************************************** 
  void setup () 
{
//REAL TIME CLOCK MODULE
  Serial.begin(57600);

  Serial.print("compiled: ");
  Serial.print(__DATE__);
  Serial.println(__TIME__);

  Rtc.Begin();

  RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
  printDateTime(compiled);
  Serial.println();

  if (!Rtc.IsDateTimeValid()) 
  {
      // Common Causes:
      //    1) first time you ran and the device wasn't running yet
      //    2) the battery on the device is low or even missing

      Serial.println("RTC lost confidence in the DateTime!");
      Rtc.SetDateTime(compiled);
  }

  if (Rtc.GetIsWriteProtected())
  {
      Serial.println("RTC was write protected, enabling writing now");
      Rtc.SetIsWriteProtected(false);
  }

  if (!Rtc.GetIsRunning())
  {
      Serial.println("RTC was not actively running, starting now");
      Rtc.SetIsRunning(true);
  }

  RtcDateTime now = Rtc.GetDateTime();
  if (now < compiled) 
  {
      Serial.println("RTC is older than compile time!  (Updating DateTime)");
      Rtc.SetDateTime(compiled);
  }
  else if (now > compiled) 
  {
      Serial.println("RTC is newer than compile time. (this is expected)");
  }
  else if (now == compiled) 
  {
      Serial.println("RTC is the same as compile time! (not expected but all is fine)");
  }
  
//LCD SCHERM
  lcd.init();
  lcd.backlight();
  lcd.setCursor(1,0);
  lcd.print("Petfeeder");
  delay(5000);

//SERVO
  myservo.attach(13);
  myservo.write(55); 

//POTENTIOMETER
  pinMode(pinPotentiometer, INPUT);

//KNOP
  pinMode(button, INPUT_PULLUP);
  
} //END of      s e t u p ( )

//********************************************

bool modeInstellen = false;

 void loop () 
{
//REAL TIME CLOCK MODULE
  RtcDateTime now = Rtc.GetDateTime();

  printDateTime(now);
  Serial.println();
  
  int reading = digitalRead(button);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == LOW) {
        modeInstellen = !modeInstellen;
      }
    }
  }

  /*Serial.print("MI:");
  Serial.println(modeInstellen);*/
  
//KNOP + POTENTIOMETER
  if(modeInstellen == true)
  {
    checkButton();

    if (buttonCounter == 1)
    {
      lcd.clear();
      lcd.setCursor(1,0);
      lcd.print("ingesteld feed uur");
      lcd.setCursor(1,1);
      lcd.print("00:00");
    }
    
    if (buttonCounter == 2)
    {
      int valueUUR = analogRead(pinPotentiometer); //0 1023
      Serial.println(valueUUR);
      resultaatUUR = valueUUR / 42.625 ;
      lcd.setCursor(1,0);
      lcd.print("ingesteld feed uur");
      lcd.setCursor(1,1);
      if(resultaatUUR < 10)
      {
        lcd.print("0");
      }
      lcd.print(resultaatUUR);
      Serial.println(resultaatUUR);
      lcd.print(":00");
    }
    if (buttonCounter == 3)
    {
      int valueMINUUT = analogRead(pinPotentiometer); //0 1023
      Serial.println(valueMINUUT);
      resultaatMINUUT = valueMINUUT / 17.05 ;
      lcd.setCursor(3,1);
      lcd.print(":");
      lcd.setCursor(4,1);
      if(resultaatMINUUT < 10)
      {
        lcd.print("0");
      }
      lcd.print(resultaatMINUUT);
      Serial.println(resultaatMINUUT);
    }
    if (buttonCounter == 4)
    {
      modeInstellen = false;
      buttonCounter = 0;
    }
  }
  else
  {
    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;
  
      //REAL TIME CLOCK MODULE
    
      if (!now.IsValid())
      {
          // Common Causes:
          //    1) the battery on the device is low or even missing and the power line was disconnected
          Serial.println("RTC lost confidence in the DateTime!");
      }      
//SERVO
      else
      {
        Serial.println(resultaatUUR);
        Serial.println(resultaatMINUUT);
        Serial.println(uur);
        Serial.println(minuten);
        Serial.println(seconden);    
        if(uur == resultaatUUR && minuten == resultaatMINUUT && seconden == 00) 
        {
          myservo.write(100);
          delay(1000);
          myservo.write(55);
        }
        
      }
    }
  }

  lastButtonState = reading;
}

  #define countof(a) (sizeof(a) / sizeof(a[0]))

void printDateTime(const RtcDateTime& dt)
{
  char datestring[20];

  snprintf_P(datestring, 
          countof(datestring),
          PSTR("%02u/%02u/%04u "),
          dt.Month(),
          dt.Day(),
          dt.Year() );
  Serial.print(datestring);

  char datestring2[20];

    snprintf_P(datestring2, 
          countof(datestring2),
          PSTR("%02u:%02u:%02u"),
          dt.Hour(),
          dt.Minute(),
          dt.Second() ); 
  uur = dt.Hour();
  minuten = dt.Minute();
  seconden = dt.Second();
  Serial.print(datestring2);
  
//LCD SCHERM
  lcd.clear();
  lcd.setCursor(1,0);
  lcd.print(datestring);
  lcd.setCursor(1,1);
  lcd.print(datestring2);

} //END of     l  o o p ( )


//********************************************
void checkButton()
{
  buttonState = digitalRead(button);

  if (lastButtonState != buttonState)
  {
    lastButtonState = buttonState;

    //has the button been released (HIGH is not pushed)
    if (buttonState == HIGH)
    {
      buttonCounter++;
    }
  }

} //END of     c h e c k B u t t o n ( )

You are using one button in two different sections of code, to do two different things.

You are also reusing variables which makes it confusing, even if the logic is correct.

I can't figure out what your program does, or how the one button is meant to control it.

But in any case:

Your first button debouncing code simply does not work. I placed it in the wokwi and stripped it down to confirm that, and rewrote that section to conform to a common programming pattern used for debouncing a button - read and act on the button, then do not read the button again unless and until the debounce period has elapsed.

// https://wokwi.com/projects/351778896982573647
// https://forum.arduino.cc/t/problem-with-automatic-petfeeder-with-real-time-clock/1068511
 
  const byte button    = 7;

  byte buttonState     = 0;
  byte lastButtonState = HIGH;
  byte buttonCounter   = 0;

unsigned long lastDebounceTime = 0; 
unsigned long debounceDelay = 50;

unsigned long previousMillis = 0;

const long interval = 1000;

# define lamp 6

void setup () 
{
  Serial.begin(57600);
  Serial.println("Jello Whirled!\n");

  pinMode(button, INPUT_PULLUP);

  pinMode(lamp, OUTPUT);

}

bool modeInstellen = false;

void loop () 
{
if (1) {  // works - change to 0 to run original algorithm

  if ((millis() - lastDebounceTime) > debounceDelay) {
    int reading = digitalRead(button);
    if (reading != lastButtonState) {
      lastButtonState = reading;

      if (reading == LOW)
        modeInstellen = !modeInstellen;
  
      lastDebounceTime = millis();
    }
  }
}

else {  /* doesn't? */

  int reading = digitalRead(button);

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {

    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == LOW) {
        modeInstellen = !modeInstellen;
      }
    }
  }
}
  digitalWrite(lamp, modeInstellen ? 1 : 0);
}

See that small problem in the wokwi simulator.

Since this got moved to the International / Netherlands forum while I was at the beach, I will leave you with this and a wish of good luck. I know my cat very much appreciates his Arduino-controlled food dispenser, and so far he has not figured out how to change the potentiometer to increase the delivered amount.

a7

Verwijder de servo even volledig en kijk dan of je LCD nog steeds dimt na 5 seconden.

Hoe vaak schrijf je naar je display? Als dit elke loop is, krijg je iets heel wazig.

Petfeeder wordt mooi weergegeven omdat je 5 seconden wacht om nog iets te schrijven naar je display.

Zo lang je modeInstellen waar is en je buttonCounter == 1 ga je het display eerst wissen. Wat enkele µs duurt om dan weer hetzelfde te schrijven. Een fractie van een seconde later gebeurt er weer hetzelfde. Zet eens een delay(2000); achter lcd.print("00:00"); en je zal zien dat je display de tekst correct weergeeft.

Je display volledig wissen is niet altijd nodig. Dat doe je pas als je zowat alles moet vernieuwen. Je schrijft ook alleen naar je display de zaken die wijzigen. Net om geflikker tegen te gaan.

Een byte (=8 bits) om een true/false op te slaan is meer dan overkill. Een bool(ean) is meer dan voldoende.

Een int (-32767 -> 32767) om uur en minuten op te slaan is ook ruim. Neem een uint8_t of een unsigned byte. Neem je variabelen zo klein als mogelijk.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.