Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

Arduino-Based Automated Dosing System with Keypad, LCD, Servo, and RTC

View and Edit Project In Cirkit DesignerImage of Arduino-Based Automated Dosing System with Keypad, LCD, Servo, and RTC

Circuit Documentation

Summary

This circuit integrates a 4x4 membrane keypad, a 16x2 I2C LCD, a micro servo, a DS3231 RTC, and a buzzer with an Arduino UNO. The user inputs a dose and time using the keypad, which is displayed on the LCD. The servo motor operates for the specified time, and the buzzer sounds when the time elapses.

Component List

  1. Arduino UNO

    • Description: A microcontroller board based on the ATmega328P.
    • Pins: UNUSED, IOREF, Reset, 3.3V, 5V, GND, Vin, A0, A1, A2, A3, A4, A5, SCL, SDA, AREF, D13, D12, D11, D10, D9, D8, D7, D6, D5, D4, D3, D2, D1, D0
  2. Micro servo 9G

    • Description: A small servo motor used for precise control of angular position.
    • Pins: GND, +5V, PWM
  3. 4X4 Membrane Matrix Keypad

    • Description: A keypad with 16 buttons arranged in a 4x4 matrix.
    • Pins: R1, R2, R3, R4, C1, C2, C3, C4
  4. 16x2 I2C LCD

    • Description: A 16x2 character LCD display with I2C interface.
    • Pins: GND, VCC, SDA, SCL
  5. Buzzer

    • Description: An electronic device that emits sound.
    • Pins: PIN, GND
  6. DS3231 RTC

    • Description: A real-time clock module with I2C interface.
    • Pins: 32K, SQW, SCL, SDA, VCC, GND
  7. Pushbutton

    • Description: A simple pushbutton switch.
    • Pins: Pin 3 (out), Pin 4 (out), Pin 1 (in), Pin 2 (in)
  8. Resistor

    • Description: A 200 Ohms resistor.
    • Pins: pin1, pin2
    • Properties: Resistance: 200 Ohms

Wiring Details

Arduino UNO

Micro servo 9G

4X4 Membrane Matrix Keypad

16x2 I2C LCD

Buzzer

DS3231 RTC

Pushbutton

Resistor

Code Documentation

Arduino UNO Code

/*
 * This Arduino Sketch integrates a 4x4 membrane keypad, a 16x2 I2C LCD, a
 * micro servo, a DS3231 RTC, and a buzzer. The user inputs a dose and time
 * using the keypad, which is displayed on the LCD. The servo motor operates
 * for the specified time, and the buzzer sounds when the time elapses.
 */

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

LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 rtc;
Servo myservo;

const byte ROWS = 4; // four rows
const byte COLS = 4; // four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9}; // connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

int buzzerPin = 10;
int buttonPin = 11;
int servoPin = 9;

void setup() {
  lcd.begin();
  lcd.backlight();
  myservo.attach(servoPin);
  pinMode(buzzerPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  if (!rtc.begin()) {
    lcd.print("Couldn't find RTC");
    while (1);
  }
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  lcd.print("Enter dose (ml):");
}

void loop() {
  static String dose = "";
  static String time = "";
  static bool doseEntered = false;
  static bool timeEntered = false;
  static bool pumpStarted = false;
  static DateTime startTime;

  char key = keypad.getKey();
  if (key) {
    if (!doseEntered) {
      if (key == '#') {
        doseEntered = true;
        lcd.clear();
        lcd.print("Enter time (s):");
      } else {
        dose += key;
        lcd.setCursor(dose.length() - 1, 1);
        lcd.print(key);
      }
    } else if (!timeEntered) {
      if (key == '#') {
        timeEntered = true;
        lcd.clear();
        lcd.print("Press button to start");
      } else {
        time += key;
        lcd.setCursor(time.length() - 1, 1);
        lcd.print(key);
      }
    }
  }

  if (timeEntered && digitalRead(buttonPin) == LOW && !pumpStarted) {
    pumpStarted = true;
    startTime = rtc.now();
    myservo.write(90); // Start the servo
    lcd.clear();
    lcd.print("Pumping...");
  }

  if (pumpStarted) {
    DateTime currentTime = rtc.now();
    int elapsedTime = currentTime.secondstime() - startTime.secondstime();
    if (elapsedTime >= time.toInt()) {
      myservo.write(0); // Stop the servo
      digitalWrite(buzzerPin, HIGH); // Trigger the alarm
      lcd.clear();