#include <HX711.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <SD.h>
#include <EEPROM.h>
// Pin Definitions
#define LOADCELL1_DOUT_PIN 4
#define LOADCELL1_SCK_PIN 5
#define LOADCELL2_DOUT_PIN 16
#define LOADCELL2_SCK_PIN 17
#define LOADCELL3_DOUT_PIN 18
#define LOADCELL3_SCK_PIN 19
#define LOADCELL4_DOUT_PIN 21
#define LOADCELL4_SCK_PIN 22
#define SD_CS_PIN 15
// I2C LCD Setup
#define I2C_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(I2C_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Wi-Fi Credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// Cloud Endpoint
const char* serverUrl = "http://your-cloud-endpoint.com/api/data";
// HX711 Setup
HX711 scale1, scale2, scale3, scale4;
// Variables
float totalWeight = 0;
int sackCount = 0;
bool sackDetected = false;
String flourCategory = "Default"; // Default category, updated via web app
bool wifiConnected = false;
void setup() {
Serial.begin(115200);
// Initialize I2C LCD
lcd.begin(16,2);
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Initializing...");
// Initialize HX711 Load Cells
scale1.begin(LOADCELL1_DOUT_PIN, LOADCELL1_SCK_PIN);
scale2.begin(LOADCELL2_DOUT_PIN, LOADCELL2_SCK_PIN);
scale3.begin(LOADCELL3_DOUT_PIN, LOADCELL3_SCK_PIN);
scale4.begin(LOADCELL4_DOUT_PIN, LOADCELL4_SCK_PIN);
// Calibrate Load Cells (adjust calibration factor as needed)
scale1.set_scale(2280.f); // Replace with your calibration factor
scale2.set_scale(2280.f);
scale3.set_scale(2280.f);
scale4.set_scale(2280.f);
scale1.tare();
scale2.tare();
scale3.tare();
scale4.tare();
// Initialize SD Card
if (!SD.begin(SD_CS_PIN)) {
Serial.println("SD Card initialization failed!");
lcd.setCursor(0, 1);
lcd.print("SD Card Error!");
} else {
Serial.println("SD Card initialized.");
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
Serial.println("Connecting to Wi-Fi...");
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi...");
int retries = 0;
while (WiFi.status() != WL_CONNECTED && retries < 10) {
delay(1000);
Serial.print(".");
retries++;
}
if (WiFi.status() == WL_CONNECTED) {
wifiConnected = true;
Serial.println("\nConnected to Wi-Fi!");
lcd.setCursor(0, 0);
lcd.print("WiFi Connected! ");
} else {
Serial.println("\nFailed to connect to Wi-Fi.");
lcd.setCursor(0, 0);
lcd.print("WiFi Failed! ");
}
}
void loop() {
// Read weight from all load cells
float weight1 = scale1.get_units(10); // Average of 10 readings
float weight2 = scale2.get_units(10);
float weight3 = scale3.get_units(10);
float weight4 = scale4.get_units(10);
// Calculate total weight
totalWeight = weight1 + weight2 + weight3 + weight4;
Serial.print("Total Weight: ");
Serial.println(totalWeight);
// Display total weight on LCD
lcd.setCursor(0, 1);
lcd.print("Weight: ");
lcd.print(totalWeight);
lcd.print(" kg ");
// Detect a 40kg sack
if (totalWeight >= 39.5 && totalWeight <= 40.5 && !sackDetected) { // Tolerance of ±0.5kg
sackCount++;
sackDetected = true;
Serial.print("Sack detected! Total sacks: ");
Serial.println(sackCount);
} else if (totalWeight < 1.0) { // Reset detection when weight is removed
sackDetected = false;
}
// Store data locally if Wi-Fi is not connected
if (!wifiConnected) {
storeDataOnSD(sackCount, flourCategory);
} else {
// Send data to the cloud
if (sendDataToCloud(sackCount, flourCategory)) {
Serial.println("Data sent to cloud.");
} else {
Serial.println("Failed to send data to cloud. Storing locally.");
storeDataOnSD(sackCount, flourCategory);
}
}
delay(5000); // Wait 5 seconds before next reading
}
bool sendDataToCloud(int sackCount, String flourCategory) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(serverUrl);
http.addHeader("Content-Type", "application/json");
String payload = "{\"sackCount\":" + String(sackCount) + ",\"flourCategory\":\"" + flourCategory + "\",\"totalWeight\":" + String(totalWeight) + "}";
int httpResponseCode = http.POST(payload);
http.end();
if (httpResponseCode == 200) {
return true;
}
}
return false;
}
void storeDataOnSD(int sackCount, String flourCategory) {
File file = SD.open("/data.txt", FILE_APPEND);
if (file) {
file.println("Sacks: " + String(sackCount) + ", Category: " + flourCategory + ", Weight: " + String(totalWeight) + " kg");
file.close();
Serial.println("Data stored on SD card.");
} else {
Serial.println("Failed to open file on SD card.");
}
}
void recoverDataFromSD() {
File file = SD.open("/data.txt");
if (file) {
while (file.available()) {
String data = file.readStringUntil('\n');
if (sendDataToCloud(parseSackCount(data), parseFlourCategory(data))) {
Serial.println("Recovered data sent to cloud: " + data);
} else {
Serial.println("Failed to send recovered data: " + data);
}
}
file.close();
SD.remove("/data.txt"); // Clear the file after recovery
} else {
Serial.println("No data to recover from SD card.");
}
}
int parseSackCount(String data) {
int start = data.indexOf("Sacks: ") + 7;
int end = data.indexOf(",", start);
return data.substring(start, end).toInt();
}
String parseFlourCategory(String data) {
int start = data.indexOf("Category: ") + 10;
int end = data.indexOf(",", start);
return data.substring(start, end);
}