#include <HX711.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
LiquidCrystal_I2C LCD(0x27, 16, 2);
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { 0, 2, 15, 12 };
uint8_t rowPins[ROWS] = { 19, 18, 17, 16 };
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
const int HX711_DOUT = 4; // Data Out pin
const int HX711_SCK = 5; // Clock pin
HX711 scale;
float calibration_factor = 420.0;
float weight;
float lb;
boolean Button;
char key;
void Task1(void *parameter) { // Sampling Input
static long lastStartTime = 0; // Static variable to store the last start time
while (true) {
long startTime = millis();
if (lastStartTime != 0) {
long periodTime = startTime - lastStartTime;
Serial.print("Task 1 Period Time: ");
Serial.println(periodTime);
}
lastStartTime = startTime;
// Task processing
weight = scale.get_units(); // Fetch analog value
key = keypad.getKey();
vTaskDelay(333 / portTICK_PERIOD_MS); // Adjust delay as needed
}
}
void Task2(void *parameters) { // Control & Compute
static long lastStartTime = 0; // Static variable to store the last start time
while (true) {
long startTime = millis();
if (lastStartTime != 0) {
long periodTime = startTime - lastStartTime;
Serial.print("Task 2 Period Time: ");
Serial.println(periodTime);
}
lastStartTime = startTime;
// Task processing
lb = weight * 2.205; // Convert kg to pounds
vTaskDelay(333 / portTICK_PERIOD_MS); // Adjust delay as needed
}
}
void Task3(void *parameters) { // Indicate & Display
static long lastStartTime = 0; // Static variable to store the last start time
LCD.init();
LCD.backlight();
while (true) {
long startTime = millis();
if (lastStartTime != 0) {
long periodTime = startTime - lastStartTime;
Serial.print("Task 3 Period Time: ");
Serial.println(periodTime);
}
lastStartTime = startTime;
// Task processing
if (key) {
if (key == '1') {
displayWeight();
} else if (key == '2') {
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Calibrating...");
calibrate();
displayMenu();
} else if (key == '3') {
displayMenu();
}
}
vTaskDelay(333 / portTICK_PERIOD_MS); // Adjust delay as needed
}
}
void setup() {
Serial.begin(115200); // Start serial communication
pinMode(18, INPUT);
for (int i = 0; i < 6; i++) {
Serial.println(" ");
}
Serial.println("Initializing Setup");
for (int i = 0; i < 6; i++) {
Serial.println(" ");
}
Serial.println("STARTING CALIBRATION PLEASE REMOVE ANY LOAD");
LCD.init();
LCD.backlight();
LCD.setCursor(0, 0);
displayMenu();
vTaskDelay(1000 / portTICK_PERIOD_MS); // 1 second
scale.begin(HX711_DOUT, HX711_SCK); // Initialize the scale
scale.set_scale(calibration_factor); // Set the calibration factor
scale.tare(); // Tare the scale (reset to zero)
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
Task1, // Function to be called
"Sampling_Input", // Name of task
4096, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
1, // Task priority
NULL, // Task handle
1); // Run on one core for demo purposes (ESP32 only)
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
Task2, // Function to be called
"Control&Compute", // Name of task
4096, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
1, // Task priority (must be same to prevent lockup)
NULL, // Task handle
1); // Run on one core for demo purposes (ESP32 only)
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS
Task3, // Function to be called
"Indicate_Display", // Name of task
4096, // Stack size (bytes in ESP32, words in FreeRTOS)
NULL, // Parameter to pass
1, // Task priority (must be same to prevent lockup)
NULL, // Task handle
1); // Run on one core for demo purposes (ESP32 only)
// Delete "setup and loop" task
vTaskDelete(NULL);
}
void loop() {}
void displayMenu() {
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("1: Show Weight ");
LCD.setCursor(0, 1);
LCD.print("2: Calibrate ");
}
void displayWeight() {
while (true) {
LCD.setCursor(0, 0);
LCD.print("Kg: ");
LCD.print(weight);
LCD.print(" ");
LCD.setCursor(0, 1);
LCD.print("lb: ");
LCD.print(lb);
LCD.print(" ");
Serial.print("Kg: ");
Serial.print(weight);
Serial.print("kg |");
Serial.print(" Pound: ");
Serial.print(lb);
Serial.println(" lb");
char key = keypad.getKey();
if (key == '3') {
displayMenu();
break;
}
delay(500); // Small delay between readings
}
}
void calibrate() {
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Remove all wt");
LCD.setCursor(0, 1);
LCD.print("Press # to cont");
while (true) {
char key = keypad.getKey();
if (key == '#') {
break;
}
}
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Taring...");
scale.tare(20); // Average 20 measurements
uint32_t offset = scale.get_offset();
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Offset: ");
LCD.setCursor(0, 1);
LCD.print(offset);
delay(2000); // Display the offset value for 2 seconds
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Place weight and");
LCD.setCursor(0, 1);
LCD.print("enter kg value:");
uint32_t weight = getKeypadInput();
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Weight: ");
LCD.setCursor(0, 1);
LCD.print(weight);
delay(2000); // Display the entered weight for 2 seconds
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Calibrating...");
scale.calibrate_scale(weight, 20);
float scale_factor = scale.get_units();
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Scale: ");
LCD.setCursor(0, 1);
LCD.print(scale_factor, 6);
delay(2000); // Display the scale factor for 2 seconds
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Use offset:");
LCD.setCursor(0, 1);
LCD.print(offset);
delay(2000); // Display the offset instruction for 2 seconds
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Use scale:");
LCD.setCursor(0, 1);
LCD.print(scale_factor, 6);
delay(2000); // Display the scale instruction for 2 seconds
LCD.clear();
LCD.setCursor(0, 0);
LCD.print("Calibration");
LCD.setCursor(0, 1);
LCD.print("Complete");
delay(2000); // Display calibration completion message for 2 seconds
}
uint32_t getKeypadInput() {
String input = "";
while (true) {
char key = keypad.getKey();
if (key) {
if (key == '#') {
break;
} else if (key == '*') {
input = "";
LCD.setCursor(0, 1);
LCD.print(" "); // Clear the input line
LCD.setCursor(0, 1);
LCD.print(input);
} else {
input += key;
LCD.setCursor(0, 1);
LCD.print(" "); // Clear the input line before displaying
LCD.setCursor(0, 1);
LCD.print(input);
}
}
}
return input.toInt();
}