DC Motor and LCD Screen Menu

Hi All,

I am new to Ardunio and trying to develop a small scale feeding system.

I am trying to power a 3V Geared DC motor with a 12V battery.
In addition, I am wanting to use the Arduino as a timer on/off system similar to irrigation controller.
I have developed this drawing and am wanting advice on if this would work?

Lastly, I am also trying to create an LCD screen menu.

  1. Date and Time
  2. Days
  3. Occurrence per day
  4. Length admin
  5. Set date and time
    Do anyone know how to write the code. I am terrible at it and have resorted to Visunio which is mildly easier.

Any advice is appreciated.

Not for long. 2 AA batteries will go empty rather quickly.
For a watering project using time You need an RTC, Real Time Clock.

Are you really using pins 0 and 1 for switches. Your #1 debugging tool is the hardware serial port which uses pins 0 (RX) and 1 (TX). Can you afford to do without your best debugging tool? If so, you are a better programmer than I.

Please post a schematic. That cartoon is missing so much information. Like component part numbers, pin names/numbers. A hand drawn,photographed and posted schematic is fine and preferred over the fritzing bb view.

What is powering the Uno?

Thanks for the advice.
I have changed this.

Apologies for not adding the correct battery.
It will be a 12V battery charged with an independent solar system.
I have not considered how to power the arduino - thanks for pointing this out.

I am trying to merge two pieces of code together.
Wanting to display RTC date and time under heading "Date and time".

I have an attempt which is broken.

/*
 * This code create a MENU structure on a 16x2 LCD screen.
 * Six (6) different screens are implemented, and you can travel
 * thru them by pressing a button on Arduino PIN 4. Each press
 * of the button advances one (1) screen.
 *
 * Made by Clovis Fritzen in 05/06/2017
 * http://www.FritzenMaker.com
 * http://www.FritzenLab.com.br
*/
//Based on YWROBOT's LiquidCrystal_I2C library, Library version:1.1
//Also based on the Debounce.ino sketch that comes with Arduino IDE
 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h> 

 uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
 
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
 
int WhichScreen =1;   // This variable stores the current Screen number
boolean hasChanged = true;
const int buttonPin = 4;    // the number of the pushbutton pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
 
void setup()
{
  lcd.init();// initialize the lcd
  lcd.backlight();
  pinMode(buttonPin, INPUT);
   lcd.createChar(2, clock);
  Wire.begin();
   RTC.begin();
   RTC.adjust(DateTime(22,4,28,11,14,9));
}
void loop()
{
 
  if (hasChanged == true) {
   
  switch(WhichScreen) {
    case 1:
    {
      firstScreen();
    }
      break;
   
    case 2:
      {
        secondScreen();
      }
      break;
   
    case 3:
      {
        thirdScreen();
      }
      break;
   
    case 4:
      {
        fourthScreen();
      }
      break;
   
    case 5:
      {
        fifthScreen();
      }
      break;
   
   
    case 0:
      {
       
      }
      break;
    }
}
 
    //-------------------------------
    // BEGIN of the switch debouncing code
    int reading = digitalRead(buttonPin);
  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 == HIGH) {
        hasChanged = true;
        WhichScreen++;
       
       
      }
    } else {
      hasChanged = false;
    }
  }
  lastButtonState = reading;
  // END of the switch Debouncing code
  // --------------------------------------
  if (WhichScreen > 5){
    WhichScreen = 1;
  }
}
 
void firstScreen()
  {
   lcd.clear();
   lcd.setCursor(0,0); // Column, line
   lcd.print("Date and Time");
   lcd.setCursor(0,1);
   lcd.print(" 
   lcd.clear ();
   DateTime now = RTC.now();
   lcd.printByte(2);
   lcd.print(" ");
  lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    lcd.print(now.second(), DEC);
   lcd.setCursor(0, 1);
   lcd.print(now.day(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.year(), DEC);
    lcd.print(' ');
  delay(1000); ");
  }
void secondScreen()
  {
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print("M T W T F S S");
    lcd.setCursor(0,1);
    lcd.print(" ");
  }
void thirdScreen()
  {
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print("Frequency");
    lcd.setCursor(0,1);
    lcd.print(" ");
  }
void fourthScreen()
  {
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print("Duration");
    lcd.setCursor(0,1);
    lcd.print("7 min");
  }
void fifthScreen()
  {
    lcd.clear();
    lcd.setCursor(0,0); // Column, line
    lcd.print("Set Date & Time");
    lcd.setCursor(0,1);
    lcd.print("");
  }

What does that mean? What is the problem? Does the LCD work? Does the RTC work?

Making reference to my attempt of combining the code.

Everything is working fine.

For example I can complete each tutorial successfully. However when attempting to combine it fails due to being unable to verify the newly inserted code correctly.

I have also added the additional libraries and placed additional text within void setup ().

The problem code is located under void firstScreen() and lcd.Print (" ").

I am attempting to make the LCD display
Line 0: Date and Time
Line 1: hh:mm DD:MM:YY
and be part of a 'Menu'.

Thanks for your response.

That is missing "); Is that what you mean?

Thats the area of code that seems to be the problem.
") is there after .... delay (1000); "); }

What I tried to do was copy and paste the void script into where you would typically type text.

I hope that helps.

Now I see what your problem is. Your code will not compile. You should have stated that in the beginning and included the entire error message. It is easy to do. There is a button (lower right of the IDE window) called "copy error message". Copy the error and paste into a post in code tags.

OK, I got it to compile, though I do not know if it will work right as I do not have the hardware to test.

/*
   This code create a MENU structure on a 16x2 LCD screen.
   Six (6) different screens are implemented, and you can travel
   thru them by pressing a button on Arduino PIN 4. Each press
   of the button advances one (1) screen.

   Made by Clovis Fritzen in 05/06/2017
   http://www.FritzenMaker.com
   http://www.FritzenLab.com.br
*/
//Based on YWROBOT's LiquidCrystal_I2C library, Library version:1.1
//Also based on the Debounce.ino sketch that comes with Arduino IDE

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

uint8_t clock[8] = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0};

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

int WhichScreen = 1;  // This variable stores the current Screen number
boolean hasChanged = true;
const int buttonPin = 4;    // the number of the pushbutton pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup()
{
   lcd.init();// initialize the lcd
   lcd.backlight();
   pinMode(buttonPin, INPUT);
   lcd.createChar(2, clock);
   Wire.begin();
   RTC.begin();
   RTC.adjust(DateTime(22, 4, 28, 11, 14, 9));
}
void loop()
{

   if (hasChanged == true)
   {

      switch (WhichScreen)
      {
         case 1:
            {
               firstScreen();
            }
            break;

         case 2:
            {
               secondScreen();
            }
            break;

         case 3:
            {
               thirdScreen();
            }
            break;

         case 4:
            {
               fourthScreen();
            }
            break;

         case 5:
            {
               fifthScreen();
            }
            break;


         case 0:
            {

            }
            break;
      }
   }

   //-------------------------------
   // BEGIN of the switch debouncing code
   int reading = digitalRead(buttonPin);
   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 == HIGH)
         {
            hasChanged = true;
            WhichScreen++;
         }
      }
      else
      {
         hasChanged = false;
      }
   }
   lastButtonState = reading;
   // END of the switch Debouncing code
   // --------------------------------------
   if (WhichScreen > 5)
   {
      WhichScreen = 1;
   }
}

void firstScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Date and Time");
   lcd.setCursor(0, 1);
   lcd.print(" ");
   lcd.clear ();
   DateTime now = RTC.now();
   lcd.print(byte(2));  // fixed
   lcd.print(" ");
   lcd.print(now.hour(), DEC);
   lcd.print(':');
   lcd.print(now.minute(), DEC);
   lcd.print(':');
   lcd.print(now.second(), DEC);
   lcd.setCursor(0, 1);
   lcd.print(now.day(), DEC);
   lcd.print('/');
   lcd.print(now.month(), DEC);
   lcd.print('/');
   lcd.print(now.year(), DEC);
   lcd.print(' ');
   delay(1000);
}
void secondScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("M T W T F S S");
   lcd.setCursor(0, 1);
   lcd.print(" ");
}
void thirdScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Frequency");
   lcd.setCursor(0, 1);
   lcd.print(" ");
}
void fourthScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Duration");
   lcd.setCursor(0, 1);
   lcd.print("7 min");
}
void fifthScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Set Date & Time");
   lcd.setCursor(0, 1);
   lcd.print("");
}

In this part of the code, the "Date and Time" will not show up because you write it to the display then right away clear the display. You may want to examine the code for any more mistakes like that.

void firstScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Date and Time");
   lcd.setCursor(0, 1);
   lcd.print(" ");
   lcd.clear ();
   DateTime now = RTC.now();

Thanks that has worked mostly well.

cd.clear ();
DateTime now = RTC.now();
lcd.print(byte()); // fixed
lcd.print(" ");

I removed the 2 from "(byte());" which made it "0" instead of "2" before the time.
Do you know how to remove it completely? I also trired " ", which made it say 69. Leaving it blank makes "0".

Also, I notice the time does not change when viewing. It changes if you cycle through the menu again. Would that be associated with the "clear elements"?

I have also tried to move it to the second line, I thought the code was correct whereby it stated, "setCursor(0,1);" therefore it should be on the second line. Any thoughts?

Thanks again for your help and apologies for not mentioning the complie issues earlier.

Do you have any self-help content that you would recommend or is it simply learn by doing?

20220429_143154_GIF

I had to reduce the size of the GIF so it would upload. Apologies for if too small.
The GIF shows the movement through the menu and the time only updating when being represented.

I wired up a DS1307 and 16x2 LCD to my Uno and worked on the code some. I made some pretty significant changes. I use the hd44780 library for my I2C LCDs. It is better, faster and actively maintained, unlike the older LiquidCrystal_I2C libraries. The hd44780 library is available via the IDE library manager. Look for the hd44780 library by Bill Perry.

I also changed the switch to active low with the internal pullup resistor enabled on the switch pin. I use the state change detection method from my state change detection for active low inputs tutorial. You will need to change the switch wiring as shown in the tutorial. Debounce not required.

Modify the switch wiring and try this to see if this works for you.

/*
   This code create a MENU structure on a 16x2 LCD screen.
   Six (6) different screens are implemented, and you can travel
   thru them by pressing a button on Arduino PIN 4. Each press
   of the button advances one (1) screen.

   Made by Clovis Fritzen in 05/06/2017
   http://www.FritzenMaker.com
   http://www.FritzenLab.com.br
*/

#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

uint8_t clock[8] = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0};

//LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
RTC_DS1307 RTC;

int WhichScreen = 1;  // This variable stores the current Screen number
boolean hasChanged = true;
const byte buttonPin = 4;    // the number of the pushbutton pin
int buttonState;             // the current reading from the input pin
int lastButtonState = HIGH;   // the previous reading from the input pin

void setup()
{
   Serial.begin(115200);
   //lcd.init();// initialize the lcd
   lcd.begin(16, 2);
   lcd.backlight();
   pinMode(buttonPin, INPUT_PULLUP);
   lcd.createChar(2, clock);
   Wire.begin();
   RTC.begin();
   //RTC.adjust(DateTime(22, 4, 28, 11, 14, 9));
   //RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
void loop()
{
   checkButton();

   static unsigned long rtcTimer = 0;
   unsigned long rtcInterval = 200;
   if (millis() - rtcTimer >= rtcInterval)
   {
      rtcTimer = millis();
      switch (WhichScreen)
      {
         case 1:
            {
               firstScreen();
            }
            break;

         case 2:
            {
               secondScreen();
            }
            break;

         case 3:
            {
               thirdScreen();
            }
            break;

         case 4:
            {
               fourthScreen();
            }
            break;

         case 5:
            {
               fifthScreen();
            }
            break;


         case 0:
            {

            }
            break;
      }
   }
}

void checkButton()
{
   static unsigned long timer = 0;
   unsigned long interval = 50;
   if (millis() - timer >= interval)
   {
      timer = millis();

      buttonState = digitalRead(buttonPin);
      if (buttonState != lastButtonState)
      {
         // if the button state has changed:
         if (buttonState == LOW)
         {
            Serial.println("button");
            hasChanged = true;
            WhichScreen++;
            if (WhichScreen > 5)
            {
               WhichScreen = 1;
            }
         }
         lastButtonState = buttonState;
      }
      /*
         else
         {
         hasChanged = false;
         }
      */
   }
}

void firstScreen()
{
   lcd.clear();
   DateTime now = RTC.now();
   lcd.write(2);  // created character
   lcd.print("   ");
   lcd.print(now.hour(), DEC);
   lcd.print(':');
   lcd.print(now.minute(), DEC);
   lcd.print(':');
   lcd.print(now.second(), DEC);
   lcd.setCursor(4, 1);
   lcd.print(now.day(), DEC);
   lcd.print('/');
   lcd.print(now.month(), DEC);
   lcd.print('/');
   lcd.print(now.year(), DEC);
   lcd.print(' ');
}
void secondScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("M T W T F S S");
   lcd.setCursor(0, 1);
   lcd.print(" ");
}
void thirdScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Frequency");
   lcd.setCursor(0, 1);
   lcd.print(" ");
}
void fourthScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Duration");
   lcd.setCursor(0, 1);
   lcd.print("7 min");
}
void fifthScreen()
{
   lcd.clear();
   lcd.setCursor(0, 0); // Column, line
   lcd.print("Set Date & Time");
   lcd.setCursor(0, 1);
   lcd.print("");
}

That lcd.print(byte(2)); was an attempt to print the special created character "clock". However that is the wrong syntax. It should be lcd.write(2);.

Since you have only 2 lines to show date and time, I left the "Date and Time" heading off. I did put the clock symbol on the first line, though.

If the screen flicker is annoying you will need to change the way that you update the LCD to get rid of calls to lcd.clear().

Thanks, Ill have to do some reading about the new wirirng.
I have had an attempt this morning but it didn't work so well.

Thanks for all your time and efforts.

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