#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
#include <HX711_ADC.h>
// This is a goal for the weight that should be added to the mixer,
// this value would be communicated from the mobile app
const int goal = 10000;
const int stepsPerRev = 200; // The steps per revolution the motor takes
const int speedFactor = 30; // The rate at which the speed of the motor will be incremented at
// Defining the pins as constants
const int RedPin = 6;
const int GreenPin = 5;
const int BluePin = 3;
const int potpin = 0; // Potentiometer Pin
const int buttonPin = 2;
// Defining the objects being used
LiquidCrystal_I2C lcd(0x27, 20, 4); // LCD I2C
Stepper myStepper(stepsPerRev, 8, 9, 10, 11); // Stepper
HX711_ADC LoadCell(A1, A2); // Load sensor
int val; // To read the value from the analog pin
bool locked = false; // Controlling the locked state of the stand mixer
bool current = !locked; // To determine if there was a state change, initially the opposite of locked
volatile byte buttonReleased = false; // Used to deal with interrupts
// Set up function
void setup() {
// LCD Set up
lcd.init();
lcd.backlight();
lcd.print("Let's Bake!");
// Load Cell Set up
LoadCell.begin();
LoadCell.start(1000);
LoadCell.setCalFactor(0.42);
// RGB LED Set up
pinMode(RedPin, OUTPUT);
pinMode(BluePin, OUTPUT);
pinMode(GreenPin, OUTPUT);
// Button Set up
pinMode(buttonPin, INPUT);
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonReleasedInterrupt, FALLING);
}
void loop() {
// Checking the Locked state of the mixer
// If the mixer is locked then the mixer can run and there can be no ingredient weighing
if (locked) {
// This indicates that there was a state change and the mixer has just been locked
if (current != locked) {
// Updating the LCD appropriately
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Get Mixing!");
// Turn off LED by setting the values to 0
setColor(0, 0, 0);
// Setting current to locked since the states are now aligned
current = locked;
}
val = analogRead(potpin); //reads the value of the potentiometer (between 0 & 1023)
val = map(val, 0, 1023, 0, 8); //scale it down for speed level (between 0 & 8)
if (val > 0) {
myStepper.step(stepsPerRev);
myStepper.setSpeed(val * speedFactor); // Setting the actual speed of the motor based on the speed level
}
else {
myStepper.step(0); // stop the motor from turning
}
}
// If the mixer is not locked then the mixer cannot run and there can be ingredient weighing
else {
// This indicates that there was a state change and the mixer has just been unlocked
if (current != locked) {
// Updating the LCD appropriately
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Weighing Scale");
// Set RGB LED to green
setColor(0, 255, 0);
// Resets the scale to 0
LoadCell.tare();
// Setting current to locked since the states are now aligned
current = locked;
}
LoadCell.update(); // Updates the load cell object with the weight
float weightGrams = LoadCell.getData(); // gets the weight on the load cell in grams
// Displaying the weight of contents on LCD
lcd.setCursor(4, 1); // Setting the cursor in the second row of the LCD
lcd.print(weightGrams, 0);
lcd.println("g");
int warningPoint = goal * 0.7; // Warning point is at 70% of the goal value
// Setting the colour of the LED based on the weight of contents
if (weightGrams > goal) {
setColor(255, 0, 0); // Set to Red if goal exceeded
}
else if (weightGrams == goal) {
setColor(0, 0, 255); // Set to Blue if goal exactly achieved
}
else if (weightGrams >= warningPoint) {
setColor(255, 255, 0); // Set to Yellow if warning point matched or exceeded
}
else {
setColor(0, 255, 0); // Set to green if none of the above achieved, indicates less than warning point
}
}
}
// Supporting function to write the RGB values for the LED
void setColor(int red, int green, int blue) {
analogWrite(RedPin, 255 - red);
analogWrite(GreenPin, 255 - green);
analogWrite(BluePin, 255 - blue);
}
// Supporting function to attach to the button to handle the interrupt
void buttonReleasedInterrupt() {
buttonReleased = true;
locked = !locked; // Toggles the stand mixer's locked state
}