Adafruit ESP32 Feather SPI, I2C and HX711

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);
}

Is the card initialized or does it fail?

The initialisation already fails.

Are you using USB power or battery power?

Right now USB.
Final deployment should be on battery.
You think 500mA isnt enough for the sd-card?

Some cards can draw more than 100mA but I don't think that is the problem.

Since it was not detected when you did the SD.begin(), I suspect it's something else but what I don't know.

The default SS (CS) pin is 33. Try using that pin instead of 4

Hi there.
I tried it today but unfortunally it resolved the to the same.
SD-Card cant be initialised...
Everyone else has an idea for me?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.