Project tutorial
Doggo Water Bowl Refill Monitor/Indicator - Part 2

Doggo Water Bowl Refill Monitor/Indicator - Part 2 © GPL3+

The sequel to Part 1 of the same video title.

  • 1,720 views
  • 0 comments
  • 3 respects

Components and supplies

Necessary tools and machines

Electric Drill
Step Drill Bit
Rotary Tool
I used a Dremel.
Ruler
For marking stuff.
Digital Caliper
For measuring the components.
Project Box
For the housing/case.
Glue Gun and Hot Glue

Apps and online services

About this project

Ok, so, yeah. This is the part 2 of this project: https://create.arduino.cc/projecthub/Heathen_Hacks-v2/doggo-water-bowl-refill-monitor-indicator-part-1-e59b80?ref=user&ref_id=550502&offset=0

I think a short story would suffice, since I have already told it on Part 1.

This is just the continuation.

Here, I talked about the assembly (not the PCB assembly of course. PCBWay handled that) and talked about the code a little bit.

I know I said on Part 1 that I will elaborate or explain the code on the 2nd part, but idk. I think the code is pretty easy to understand. I also showed the sources of the codes which you can see here, so you could do some reading there.

Yeah, I'm not good at explaining things, but I'm trying.

CHECK OUT PCBWay's Program for Engineering Students and get Sponsored on your project!

LINK: https://www.pcbway.com/sponsor.html

Don't worry, I wouldn't get anything if you decide to try their services. I just wanted to help.

Sources Used For Inspiration and Code:

http://www.gammon.com.au/switches

https://create.arduino.cc/projecthub/SURYATEJA/use-a-buzzer-module-piezo-speaker-using-arduino-uno-89df45

http://forum.arduino.cc/index.php?topic=273932.0

https://www.instructables.com/id/How-to-use-a-Buzzer-Arduino-Tutorial/

******************************************************************************

Social Media Links To Follow (I mean, if you want to):

Facebook - https://fb.me/HeathenHacks

Instagram - https://instagr.am/HeathenHacks

******************************************************************************

Code

Doggie Water Bowl Refill Indicator/Monitor Project FileArduino
#include "Arduino.h"
#include "LiquidCrystal_PCF8574.h"
#define LCD_ADDRESS 0x27
#define LCD_ROWS 2
#define LCD_COLUMNS 16
#define SCROLL_DELAY 150
#define BACKLIGHT 255
int LED1 = 2;
int LED2 = 3;
int BUZZ = 4;
int RST = RST;
int switchPinCounter = 0;
int switchPinState = 0;
int lastSwitchPinState = 0;

LiquidCrystal_PCF8574 LCDi2C;

const byte switchPin = 8;

void setup ()
{
  Serial.begin (115200);
  pinMode (switchPin, INPUT);
  pinMode (RST, INPUT_PULLUP);
  pinMode (LED1, OUTPUT);
  pinMode (LED2, OUTPUT);
  pinMode (BUZZ, OUTPUT);
  LCDi2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
}

void loop () {

  switchPinState = digitalRead(switchPin);
  LCDi2C.setCursor(0, 0);
  LCDi2C.print("Refill Count: ");
  LCDi2C.print(switchPinCounter);

  if (switchPinState != lastSwitchPinState) {
    if (digitalRead (switchPin) == LOW) {

      switchPinCounter++;
      digitalWrite (LED1, HIGH);
      digitalWrite (LED2, LOW);
      LCDi2C.selectLine(2);
      LCDi2C.print("Water Lvl = SAFE");
      noTone (BUZZ);
    }
    lastSwitchPinState = switchPinState;

    if (digitalRead (switchPin) == HIGH)
    {

      digitalWrite (LED2, HIGH);
      digitalWrite (LED1, LOW);
      LCDi2C.selectLine(2);
      LCDi2C.print("Time To REFILL!!");
      tone (BUZZ, 1000);
    }
  }
}
LiquidCrystal_PCF8574C/C++
///
/// \file LiquidCrystal_PCF8574.cpp
/// \brief LiquidCrystal (LCD) library with PCF8574 I2C adapter.
///
/// \author Matthias Hertel, http://www.mathertel.de
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n
/// This work is licensed under a BSD style license.\n
/// See http://www.mathertel.de/License.aspx
/// 
/// \details
/// This is a library for driving LiquidCrystal displays (LCD) by using the I2C bus and an PCF8574 I2C adapter.
/// This library is derived from the original Arduino LiquidCrystal library and uses the original Wire library for communication.
///
/// More documentation and source code is available at http://www.mathertel.de/Arduino
///
/// ChangeLog see: LiquidCrystal_PCF8574.h

#include "LiquidCrystal_PCF8574.h"

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"
#include <Wire.h>

/// Definitions on how the PCF8574 is connected to the LCD

/// These are Bit-Masks for the special signals and background light
#define PCF_RS  0x01
#define PCF_RW  0x02
#define PCF_EN  0x04
#define PCF_BACKLIGHT 0x08

// Definitions on how the PCF8574 is connected to the LCD
// These are Bit-Masks for the special signals and Background
#define RSMODE_CMD  0
#define RSMODE_DATA 1


// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set: 
//    DL = 1; 8-bit interface data 
//    N = 0; 1-line display 
//    F = 0; 5x8 dot character font 
// 3. Display on/off control: 
//    D = 0; Display off 
//    C = 0; Cursor off 
//    B = 0; Blinking off 
// 4. Entry mode set: 
//    I/D = 1; Increment by 1 
//    S = 0; No shift 
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).

// modification:
// don't use ports from Arduino, but use ports from Wire

// a nibble is a half Byte

// NEW: http://playground.arduino.cc//Code/LCDAPI
// NEW: setBacklight

LiquidCrystal_PCF8574::LiquidCrystal_PCF8574()
{
  //_backlight = 255;
} // LiquidCrystal_PCF8574

LiquidCrystal_PCF8574::LiquidCrystal_PCF8574(uint8_t addr)
{
  _Addr = addr;
  _backlight = 0;
} // LiquidCrystal_PCF8574

void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, uint8_t addr, uint8_t backlight)
{
  _backlight = backlight;
  _Addr = addr;
  begin(cols, lines);
}

void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
  // cols ignored !
  _numlines = lines;

  _displayfunction = 0;

  if (lines > 1) {
    _displayfunction |= LCD_2LINE;
  }

  // for some 1 line displays you can select a 10 pixel high font
  if ((dotsize != 0) && (lines == 1)) {
    _displayfunction |= LCD_5x10DOTS;
  }

  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
  // according to datasheet, we need at least 40ms after power rises above 2.7V
  // before sending commands. Arduino can turn on way befor 4.5V so we'll wait 50
  Wire.begin();

  // initializing th display
  _write2Wire(0x00, LOW, false);
  delayMicroseconds(50000); 

  // put the LCD into 4 bit mode according to the hitachi HD44780 datasheet figure 26, pg 47
  _sendNibble(0x03, RSMODE_CMD);
  delayMicroseconds(4500); 
  _sendNibble(0x03, RSMODE_CMD);
  delayMicroseconds(4500); 
  _sendNibble(0x03, RSMODE_CMD);
  delayMicroseconds(150);
  // finally, set to 4-bit interface
  _sendNibble(0x02, RSMODE_CMD);

  // finally, set # lines, font size, etc.
  _command(LCD_FUNCTIONSET | _displayfunction);  

  // turn the display on with no cursor or blinking default
  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;  
  display();

  // clear it off
  clear();

  // Initialize to default text direction (for romance languages)
  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
  // set the entry mode
  _command(LCD_ENTRYMODESET | _displaymode);

  setBacklight(_backlight);
  checkI2CConnection();
}

/********** high level commands, for the user! */
void LiquidCrystal_PCF8574::clear()
{
  _command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
  delayMicroseconds(2000);  // this command takes a long time!
}

void LiquidCrystal_PCF8574::home()
{
  _command(LCD_RETURNHOME);  // set cursor position to zero
  delayMicroseconds(2000);  // this command takes a long time!
}


/// Set the cursor to a new position. 
void LiquidCrystal_PCF8574::setCursor(uint8_t col, uint8_t row)
{
  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54   };
  if ( row >= _numlines ) {
    row = _numlines-1;    // we count rows starting w/0
  }

  _command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

/** select begining of line
 *  line - 1 for first row, 2 for second row
 *  
 */
void LiquidCrystal_PCF8574::selectLine(uint8_t line)
{
  setCursor(0, line - 1);
}

// Turn the display on/off (quickly)
void LiquidCrystal_PCF8574::noDisplay() {
  _displaycontrol &= ~LCD_DISPLAYON;
  _command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_PCF8574::display() {
  _displaycontrol |= LCD_DISPLAYON;
  _command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// Turns the underline cursor on/off
void LiquidCrystal_PCF8574::noCursor() {
  _displaycontrol &= ~LCD_CURSORON;
  _command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_PCF8574::cursor() {
  _displaycontrol |= LCD_CURSORON;
  _command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// Turn on and off the blinking cursor
void LiquidCrystal_PCF8574::noBlink() {
  _displaycontrol &= ~LCD_BLINKON;
  _command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_PCF8574::blink() {
  _displaycontrol |= LCD_BLINKON;
  _command(LCD_DISPLAYCONTROL | _displaycontrol);
}

/** These commands scroll the display without changing the RAM
 *  charsToScroll - how many chars to scroll left
 *  scrollSpeed - define scrolling speed, im milliseconds.
 */

void LiquidCrystal_PCF8574::scrollDisplayLeft(int charsToScroll, int scrollSpeed) {
  for (int i=0 ; i < charsToScroll ; i++)
    {
     _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
    delay(scrollSpeed);
    }
}

/** These commands scroll the display without changing the RAM
 *  charsToScroll - how many chars to scroll right
 *  scrollSpeed - define scrolling speed, im milliseconds.
 */

void LiquidCrystal_PCF8574::scrollDisplayRight(int charsToScroll, int scrollSpeed) {
  for (int i=0 ; i < charsToScroll ; i++)
    {
    _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
    delay(scrollSpeed);
    }
}

// This is for text that flows Left to Right
void LiquidCrystal_PCF8574::leftToRight(void) {
  _displaymode |= LCD_ENTRYLEFT;
  _command(LCD_ENTRYMODESET | _displaymode);
}

// This is for text that flows Right to Left
void LiquidCrystal_PCF8574::rightToLeft(void) {
  _displaymode &= ~LCD_ENTRYLEFT;
  _command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'right justify' text from the cursor
void LiquidCrystal_PCF8574::autoscroll(void) {
  _displaymode |= LCD_ENTRYSHIFTINCREMENT;
  _command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'left justify' text from the cursor
void LiquidCrystal_PCF8574::noAutoscroll(void) {
  _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
  _command(LCD_ENTRYMODESET | _displaymode);
}


/// Setting the brightness of the background display light.
/// The backlight can be switched on and off.
/// The current brightness is stored in the private _backlight variable to have it available for further data transfers.
void LiquidCrystal_PCF8574::setBacklight(uint8_t brightness) {
  _backlight = brightness;
  // send no data but set the background-pin right;
  _write2Wire(0x00, RSMODE_DATA, false);
} // setBacklight


// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_PCF8574::createChar(uint8_t location, uint8_t charmap[]) {
  location &= 0x7; // we only have 8 locations 0-7
  _command(LCD_SETCGRAMADDR | (location << 3));
  for (int i=0; i<8; i++) {
    write(charmap[i]);
  }
}

/* The write function is needed for derivation from the Print class. */
inline size_t LiquidCrystal_PCF8574::write(uint8_t value) {
  _send(value, RSMODE_DATA);
  return 1; // assume sucess
}

/* ----- low level functions ----- */

inline void LiquidCrystal_PCF8574::_command(uint8_t value) {
  _send(value, RSMODE_CMD);
} // _command()


// write either command or data
void LiquidCrystal_PCF8574::_send(uint8_t value, uint8_t mode) {
  // separate the 4 value-nibbles
  uint8_t valueLo = value    & 0x0F;
  uint8_t valueHi = value>>4 & 0x0F;

  _sendNibble(valueHi, mode);
  _sendNibble(valueLo, mode);
} // _send()


// write a nibble / halfByte with handshake
void LiquidCrystal_PCF8574::_sendNibble(uint8_t halfByte, uint8_t mode) {
  _write2Wire(halfByte, mode, true);
  delayMicroseconds(1);    // enable pulse must be >450ns
  _write2Wire(halfByte, mode, false);
  delayMicroseconds(37);   // commands need > 37us to settle
} // _sendNibble


// private function to change the PCF8674 pins to the given value
void LiquidCrystal_PCF8574::_write2Wire(uint8_t halfByte, uint8_t mode, uint8_t enable) {
  // map the given values to the hardware of the I2C schema
  uint8_t i2cData = halfByte << 4;
  if (mode > 0) i2cData |= PCF_RS;
  // PCF_RW is never used.
  if (enable > 0) i2cData |= PCF_EN;
  if (_backlight > 0) i2cData |= PCF_BACKLIGHT;

  Wire.beginTransmission(_Addr);
  Wire.write(i2cData);
  Wire.endTransmission();   
} // write2Wire

bool LiquidCrystal_PCF8574::checkI2CConnection()
{
  int error;
  // See http://playground.arduino.cc/Main/I2cScanner
  Wire.begin();
  Wire.beginTransmission(_Addr);
  error = Wire.endTransmission();
  
  if (error) 
  {
    Serial.println("LCD not found.");
  }
  return error;
  
}

// The End.
LiquidCrystal_PCF8574C Header File
///
/// \file LiquidCrystal_PCF8574.h
/// \brief LiquidCrystal library with PCF8574 I2C adapter.
///
/// \author Matthias Hertel, http://www.mathertel.de
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n
/// This work is licensed under a BSD style license.\n
/// See http://www.mathertel.de/License.aspx
/// 
/// Copyright (c) 2005-2012 by Matthias Hertel, http://www.mathertel.de/
/// All rights reserved.
///
/// * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
/// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
/// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the 
///   documentation and/or other materials provided with the distribution. Neither the name of the copyright owners nor the names of its 
///   contributors may be used to endorse or promote products derived from this software without specific prior written permission.
///
/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
/// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
/// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
/// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
/// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
/// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


/// \details
/// This is a library for driving LiquidCrystal displays (LCD) by using the I2C bus and an PCF8574 I2C adapter.
/// This library is derived from the original Arduino LiquidCrystal library and uses the original Wire library for communication.
///
/// ChangeLog:
/// --------
/// * 19.10.2013 created.
/// * 24.05.2015 Arduino Library Manager compatible.
/// * 20.12.2016 circuito.io:
///                 * Added scrolling multiple chars to scrolling functions
///                 * Added selectLine function, same as setCursor(0, line - 1)
///                 * Added checkI2CConnection - prints to the serial monitor if connection faild. it is called inside begin.



#ifndef LiquidCrystal_PCF8574_h
#define LiquidCrystal_PCF8574_h

#include <inttypes.h>
#include "Print.h"

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

class LiquidCrystal_PCF8574 : public Print {
public:

  LiquidCrystal_PCF8574();
  LiquidCrystal_PCF8574(uint8_t addr);

  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
  void begin(uint8_t cols, uint8_t lines, uint8_t addr, uint8_t backlight);
  bool checkI2CConnection();

  void clear();
  void home();
  
  void noDisplay();
  void display();
  void noBlink();
  void blink();
  void noCursor();
  void cursor();
  void scrollDisplayLeft(int charsToScroll, int scrollSpeed);
  void scrollDisplayRight(int charsToScroll, int scrollSpeed);
  void leftToRight();
  void rightToLeft();
  void autoscroll();
  void noAutoscroll();

  void setBacklight(uint8_t brightness);
  
  void createChar(uint8_t, uint8_t[]);
  void setCursor(uint8_t col, uint8_t row);
  void selectLine(uint8_t line);

  virtual size_t write(uint8_t);
  using Print::write;

private:
  // low level functions
  void _command(uint8_t);
  void _send(uint8_t value, uint8_t mode);
  void _sendNibble(uint8_t halfByte, uint8_t mode);
  void _write2Wire(uint8_t halfByte, uint8_t mode, uint8_t enable);

// NEW:
  uint8_t _Addr;        ///< Wire Address of the LCD
  uint8_t _backlight;   ///< the backlight intensity 

  uint8_t _displayfunction; ///< lines and dots mode
  uint8_t _displaycontrol;  ///< cursor, display, blink flags
  uint8_t _displaymode;     ///< left2right, autoscroll

  uint8_t _numlines;        ///< The number of rows the display supports.
};

#endif

Custom parts and enclosures

This is the layout of the PCB.
Without the grayed out parts and the connections to ground of the SWITCH and LCD.
Desktop screenshot 2018 kpret5ceyo
Used TinkerCad For 3D Mock-up
Sizzling bruticus 1eb3yoxqyq iilptiqo3p

Schematics

Water Bowl Refill Schematic.
Just match the dots and names/labels and I'm sure you'd understand how it's connected.
Doggiebowlschematic jalirgwspb

Comments

Author

Heathen hacks v2
HeathenHacks
  • 9 projects
  • 10 followers

Additional contributors

Published on

November 4, 2018

Members who respect this project

Avatar fofgrbxpczProfilepicErospeter
See similar projects
you might like

Similar projects you might like

Doggo Water Bowl Refill Monitor/Indicator - Part 1

Project tutorial by Heathen_Hacks-v2

  • 681 views
  • 2 comments
  • 3 respects

Sound Sensor Activated LEDs with LCD for Sound Level Data!

Project tutorial by Heathen_Hacks-v2

  • 1,412 views
  • 2 comments
  • 8 respects

The Vibrating Pressure Temperature Altitude Tilt Detector

Project tutorial by Kutluhan Aktar

  • 1,009 views
  • 0 comments
  • 4 respects

Arduino-Powered Water Bottle

Project tutorial by Md. Khairul Alam

  • 7,195 views
  • 5 comments
  • 32 respects

Simple Arduino Digital Clock Without RTC

Project in progress by Annlee Fores

  • 99,273 views
  • 24 comments
  • 89 respects

Marduino Party 1

Project tutorial by Arduino “having11” Guy

  • 1,235 views
  • 0 comments
  • 1 respect
Add projectSign up / Login