Hi everybody,
i am trying to build an Iot Scale using the Adafruit ESP32 Huzzah Feather board, an genuine HX711 amplifier, an 1.3 inch i2c display (SSD1306) and a sd card where the readings should be safed. Everything should then be controlled by a website, which is the ESP32 providing.
I got the Screen, the HX711 and the website working, but i cant figure out how the hell i have to connect the SD-Card breakoutboard to get it to work.
I have tried both adafruits Breakouts (the Black micro SD SPI or SDIO and the blue 3 and 5v ready Micro-SD-Breakout board).
I have connectet the HX711 like this:
SCK: Pin12
DT: pin 13
The Display:
SCK: Pin SCL(22)
SDA: Pin SDA(23)
The Cardslot:
CS: 4
DI: MOSI (18)
DO: MISO (19)
CLK: Pin 5
Is there anything i've overlooked? Can someone gie me a hint on what i am missing?
The Code i am using:
#include <Wire.h>
#include <HX711.h>
#include <U8g2lib.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPI.h>
#include <SD.h>
const char *ssid = "XXXXXXX";
const char *password = "xxxxx";
const int DOUT_PIN = 13;
const int SCK_PIN = 12;
const int TARE_BUTTON_PIN = A0;
const int SAVE_BUTTON_PIN = A1;
HX711 scale;
const float calibration_factor = -7050.0;
float tareValue = 0.0;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
AsyncWebServer server(80);
const int MAX_SAVED_VALUES = 20;
float savedWeights[MAX_SAVED_VALUES];
int savedCount = 0;
int maxSavedCount = MAX_SAVED_VALUES;
File dataFile;
bool isSDCardInitialized = false;
void setup() {
Serial.begin(9600);
// Setup WiFi
WiFi.softAP(ssid, password);
IPAddress ip = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(ip);
scale.begin(DOUT_PIN, SCK_PIN);
scale.set_scale();
Serial.println("HX711 Scale ready!");
pinMode(TARE_BUTTON_PIN, INPUT_PULLUP);
pinMode(SAVE_BUTTON_PIN, INPUT_PULLUP);
u8g2.begin();
// Initialize SD card
if (!SD.begin(4)) { // CS pin
Serial.println("SD Card initialization failed!");
isSDCardInitialized = false;
} else {
Serial.println("SD Card initialized!");
isSDCardInitialized = true;
}
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
String html = "<html><body>";
html += "<h2>Deula Waage</h2>";
html += "<p id='weight'>Weight: </p>";
html += "<p id='tareValue'>Tare: </p>";
html += "<p id='savedCount'>Saved Count: <span id='savedCountValue'>" + String(savedCount) + "</span></p>";
html += "<label for='maxSavedCount'>Max Saved Count:</label>";
html += "<input type='number' id='maxSavedCount' name='maxSavedCount' value='" + String(maxSavedCount) + "' min='1' max='" + String(MAX_SAVED_VALUES) + "'>";
html += "<button onclick='setSavedCount()'>Set Max Saved Count</button>";
html += "<table style='width:100%; border-collapse: collapse;'>";
html += "<tr><th style='border: 1px solid black;'>Index</th>";
for (int i = 0; i < maxSavedCount; i++) {
html += "<th style='border: 1px solid black;'>Saved Weight " + String(i) + " (g)</th>";
}
html += "</tr><tr><td style='border: 1px solid black;'></td>";
for (int i = 0; i < maxSavedCount; i++) {
html += "<td style='border: 1px solid black;' id='savedWeight" + String(i) + "'>-</td>";
}
html += "</tr></table>";
html += "<button onclick='tare()'>Tare</button>";
html += "<button onclick='saveValue()'>Save Value</button>";
html += "<script>setInterval(updateValues, 1000);";
html += "function updateValues() { fetch('/data').then(response => response.json()).then(data => {";
html += "document.getElementById('weight').innerHTML = 'Weight: ' + data.weight + ' g';";
html += "document.getElementById('tareValue').innerHTML = 'Tare: ' + data.tareValue + ' g';";
html += "document.getElementById('savedCountValue').innerHTML = data.savedCount;";
for (int i = 0; i < maxSavedCount; i++) {
html += "document.getElementById('savedWeight" + String(i) + "').innerHTML = data.savedWeights[" + String(i) + "] + ' g';";
}
html += "}); }</script>";
html += "<script>function tare() { fetch('/tare').then(updateValues); }</script>";
html += "<script>function saveValue() { fetch('/save').then(updateTable); }</script>";
html += "<script>function updateTable() { fetch('/data').then(response => response.json()).then(data => {";
for (int i = 0; i < maxSavedCount; i++) {
html += "document.getElementById('savedWeight" + String(i) + "').innerHTML = data.savedWeights[" + String(i) + "] + ' g';";
}
html += "}); }</script>";
html += "<script>function setSavedCount() { var newCount = document.getElementById('maxSavedCount').value; fetch('/setmaxcount?count=' + newCount).then(updateTable); }</script>";
html += "</body></html>";
request->send(200, "text/html", html);
});
server.on("/data", HTTP_GET, [](AsyncWebServerRequest *request){
float raw = scale.get_units(10);
float weight = (raw - tareValue) / calibration_factor;
String json = "{\"weight\": " + String(weight) + ", \"tareValue\": " + String(tareValue / calibration_factor) + ", \"savedCount\": " + String(savedCount) + ", \"savedWeights\": [";
for (int i = 0; i < savedCount; i++) {
json += String(savedWeights[i]);
if (i < savedCount - 1) {
json += ",";
}
}
json += "], \"isSDCardInitialized\": " + String(isSDCardInitialized) + "}";
request->send(200, "application/json", json);
});
server.on("/tare", HTTP_GET, [](AsyncWebServerRequest *request){
tareValue = scale.get_units(10);
request->send(200, "text/plain", "Tare performed");
});
server.on("/save", HTTP_GET, [](AsyncWebServerRequest *request){
if (savedCount < maxSavedCount) {
savedWeights[savedCount] = (scale.get_units(10) - tareValue) / calibration_factor;
savedCount++;
request->send(200, "text/plain", "Value saved");
} else {
request->send(200, "text/plain", "Max saved values reached");
}
});
server.on("/setmaxcount", HTTP_GET, [](AsyncWebServerRequest *request){
String countParam = request->getParam("count")->value();
maxSavedCount = countParam.toInt();
if (maxSavedCount > MAX_SAVED_VALUES) {
maxSavedCount = MAX_SAVED_VALUES;
}
request->send(200, "text/plain", "Max count set");
});
server.begin();
}
void loop() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_profont11_tf);
u8g2.setCursor(0, 15);
u8g2.print("Weight: ");
u8g2.print((scale.get_units(10) - tareValue) / calibration_factor);
u8g2.print(" g");
u8g2.setCursor(0, 30);
u8g2.print("Tare: ");
u8g2.print(tareValue / calibration_factor);
u8g2.print(" g");
u8g2.setCursor(0, 45);
u8g2.print("IP: ");
u8g2.print(WiFi.softAPIP());
u8g2.setCursor(0, 60);
if (isSDCardInitialized) {
u8g2.print("SD Card: Connected");
} else {
u8g2.print("SD Card: Not Connected");
}
u8g2.sendBuffer();
if (digitalRead(SAVE_BUTTON_PIN) == LOW) {
float valueToSave = (scale.get_units(10) - tareValue) / calibration_factor;
if (savedCount < maxSavedCount) {
savedWeights[savedCount] = valueToSave;
savedCount++;
// Save value to SD card
if (isSDCardInitialized) {
dataFile = SD.open("data.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(valueToSave);
dataFile.close();
Serial.println("Value saved to SD card");
} else {
Serial.println("Error opening data file on SD card");
}
}
}
delay(500); // Debouncing delay
}
delay(1000);
}