IoT Weight Logging Scale
ESP32 Example Code
The code for the ESP32 is relatively simple. It's basically a mash-up of examples from the ESP32 core and the HX711 library.
First, it configures the hardware and software in the ESP32. This is where you'll use the calibration factor you discovered on the previous section. Here, it's set to 10920, which is what my scale needs. Replace that number with the one you discovered.
language:cpp
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <HX711_ADC.h>
WiFiMulti wifiMulti;
HX711_ADC LoadCell(5,4); //HX711 constructor (dout pin, sck pin)
long scaleTick, httpTick;
HardwareSerial Serial2(2); // Enable the third hw serial port on the ESP32
void setup()
{
Serial.begin(115200);
Serial2.begin(9600);
Serial.println();
Serial.println();
Serial.println();
// Give background processes a few seconds to complete
for(uint8_t t = 4; t > 0; t--)
{
Serial.printf("[SETUP] WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
wifiMulti.addAP("ssid_goes_here", "password_goes_here");
// Set up the HX711 library
LoadCell.begin();
LoadCell.start(10); // Start up the HX711 library with 10ms delay
LoadCell.setCalFactor(10920); // user set calibration factor (float)
Serial.println("Startup + tare is complete");
}
Next, it enters loop()
. where it checks the weight every 250ms and keeps a running average of the weight over the last four cycles. If the average over the last four cycles is close enough (less than 0.1lb off) of the current reading, it posts the weight data to the internet. Some checking is done to make sure that a large-ish (greater than 30lbs) weight is present on the scale, and that only one update happens per stabilized weight (i.e. the weight returns to zero before another weight is posted to the website).
language:cpp
void loop()
{
static float history[4];
static float ave = 0;
static bool stable = false;
static bool webUpdated = false;
static float weightData = 0.0;
// Update the website with weight data IF the weight data is stable AND the
// website hasn't been updated yet.
if (stable && !webUpdated)
{
// Only try if the wireless network is connected
if((wifiMulti.run() == WL_CONNECTED))
{
HTTPClient http;
Serial.print("[HTTP] begin...\n");
Serial.println(weightData);
// Replace 0.0.0.0 in address with your IP address
String address = "http://0.0.0.0:5000/post_weight/";
// Create a string with one decimal point of the average of the weights
// collected
String weight = String(weightData, 1);
// cat the two together
String fullAddress = String(address + weight);
// Connect to the server with the address you've created
http.begin(fullAddress);
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if(httpCode > 0)
{
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server, response 200
if(httpCode == HTTP_CODE_OK)
{
// clear the stable flag as the data is no longer valid
stable = false;
// Set the webUpdated flag as we've successfully updated the website
webUpdated = true;
Serial.println("Web updated");
// Dim the LED display for 500ms, then turn it back on
Serial2.write(0x7a);
Serial2.write(0);
delay(500);
Serial2.write(0x7a);
Serial2.write(255);
}
}
else
{
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
}
// Check the weight measurement every 250ms
if (millis() - scaleTick > 250)
{
scaleTick = millis();
// Read from the HX711. Must do this before attempting to use data!
LoadCell.update();
// We take the abs of the data we get from the load cell because different
// scales may behave differently, yielding negative numbers instead of
// positive as the weight increases. This can be handled in hardware by
// switching the A+ and A- wires, OR we can do this and never worry about it.
weightData = abs(LoadCell.getData());
// Calculate our running average
history[3] = history[2];
history[2] = history[1];
history[1] = history[0];
history[0] = weightData;
ave = (history[0] + history[1] + history[2] + history[3])/4;
// IF the average differs from the current by less than 0.3lbs AND
// the average weight is greater than 30 pounds AND
// we haven't recently updated the website, set the stable flag so
// we know that the weight is stable and can be reported to the web
if ((abs(ave - weightData) < 0.1) &&
(ave > 30) &&
!webUpdated)
{
stable = true;
}
// IF we've updated the website AND
// the average weight is close to zero, clear the website updated flag
// so we are ready for the next weight reading
if (webUpdated && ave < 1)
{
webUpdated = false;
}
Serial.print("Load_cell output val: ");
Serial.println(weightData);
// Create a string which is the integer value of the weight times 10,
// to remove the decimal point.
String weight = String(int(weightData*10));
Serial2.write(0x76); // Clear the display
Serial2.print(weight); // Write out the weight value to the display
// Identify which decimal point to set, and set it.
int shiftBy = 5-weight.length();
int decimalPoint = 0x08>>(shiftBy);
Serial2.write(0x77);
Serial2.write(decimalPoint & 0x0F);
}
}