/**
* @file 01_무게에다른led변화.ino
* @brief Control 3 LEDs based on weight value from HX711 load cell module.
*
* Green LED: weight < 600
* Yellow LED: 600 <= weight < 900
* Red LED: weight >= 900
* Only one LED is on at a time.
*
* @author
* @date 2025-05-19
*/
#include <HX711.h>
// Pin assignments (use ALL_CAPS for pin constants by convention)
constexpr uint8_t HX711_DOUT_PIN = 6; ///< HX711 data pin
constexpr uint8_t HX711_SCK_PIN = 7; ///< HX711 clock pin
constexpr uint8_t GREEN_LED_PIN = 10; ///< Green LED pin
constexpr uint8_t YELLOW_LED_PIN = 9; ///< Yellow LED pin
constexpr uint8_t RED_LED_PIN = 8; ///< Red LED pin
// Weight thresholds
constexpr long GREEN_THRESHOLD = 600;
constexpr long YELLOW_THRESHOLD = 900;
// Debug macro
#define DEBUG 1
#if DEBUG
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif
HX711 scale;
long scaleZeroOffset = 0; ///< HX711 zero offset (tare)
float scaleCalibrationFactor = 0.0f; ///< Calibration factor (adjust for your load cell)
long lastStableWeight = 0;
unsigned long lastStableTime = 0;
constexpr unsigned long STABLE_INTERVAL_MS = 200; ///< ms to consider value stable
constexpr long WEIGHT_HYSTERESIS = 10; ///< Ignore changes smaller than this
/**
* @brief Initialize pins and HX711 module.
*/
/**
* @brief Initialize pins, serial, and HX711 module with calibration.
*/
void setup()
{
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
#if DEBUG
Serial.begin(9600);
Serial.println("HX710B Demo with HX711 Library");
Serial.println("Initializing the scale");
#endif
scale.begin(HX711_DOUT_PIN, HX711_SCK_PIN);
delay(100); // Allow HX711 to power up
// Check if HX711 is ready
if (!scale.is_ready()) {
#if DEBUG
Serial.println("HX711 is not ready!");
#endif
while (true); // Halt if not ready
}
#if DEBUG
Serial.println("Before setting up the scale:");
Serial.print("read: \t\t");
Serial.println(scale.read());
Serial.print("read average: \t\t");
Serial.println(scale.read_average(20));
Serial.print("get value: \t\t");
Serial.println(scale.get_value(5));
Serial.print("get units: \t\t");
Serial.println(scale.get_units(5), 1);
#endif
scale.set_scale(scaleCalibrationFactor); // Set calibration factor
scale.tare(); // Zero the scale (remove all weight)
scaleZeroOffset = scale.get_offset();
#if DEBUG
Serial.println("After setting up the scale:");
Serial.print("read: \t\t");
Serial.println(scale.read());
Serial.print("read average: \t\t");
Serial.println(scale.read_average(20));
Serial.print("get value: \t\t");
Serial.println(scale.get_value(5));
Serial.print("get units: \t\t");
Serial.println(scale.get_units(5), 1);
Serial.println("Readings:");
#endif
}
/**
* @brief Set the LED state. Only one LED is on at a time.
* @param greenOn Green LED state
* @param yellowOn Yellow LED state
* @param redOn Red LED state
*/
/**
* @brief Set the LED state. Only one LED is on at a time.
* @param greenOn Green LED state
* @param yellowOn Yellow LED state
* @param redOn Red LED state
*/
void setLedState(bool greenOn, bool yellowOn, bool redOn)
{
// For clarity, use array and loop
const uint8_t ledPins[3] = {GREEN_LED_PIN, YELLOW_LED_PIN, RED_LED_PIN};
const bool ledStates[3] = {greenOn, yellowOn, redOn};
for (uint8_t i = 0; i < 3; ++i)
{
digitalWrite(ledPins[i], ledStates[i] ? HIGH : LOW);
}
}
/**
* @brief Update LEDs based on the measured weight.
* Uses non-blocking logic (no delay in loop).
*/
/**
* @brief Get a stable weight value using simple hysteresis and time filtering.
* @return long Stable weight value
*/
unsigned long lastSerialPrintTime = 0;
/**
* @brief Get a stable weight value using simple hysteresis and time filtering.
* Serial output is printed every 1 second.
* @return long Stable weight value
*/
long getStableWeight()
{
long currentWeight = scale.get_units();
unsigned long now = millis();
#if DEBUG
if (now - lastSerialPrintTime >= 1000) {
Serial.print("currentWeight: ");
Serial.println(currentWeight);
lastSerialPrintTime = now;
}
#endif
if (abs(currentWeight - lastStableWeight) > WEIGHT_HYSTERESIS)
{
lastStableTime = now;
lastStableWeight = currentWeight;
}
else if (now - lastStableTime > STABLE_INTERVAL_MS)
{
// Value is stable
return lastStableWeight;
}
return lastStableWeight;
}
/**
* @brief Update LEDs based on the measured weight (with stability filtering).
* Uses non-blocking logic (no delay in loop).
*/
unsigned long lastWeightPrintTime = 0;
/**
* @brief Update LEDs based on the measured weight (with stability filtering).
* Serial output for weight is printed every 1 second.
* Uses non-blocking logic (no delay in loop).
*/
void updateLedsByWeight()
{
long weight = getStableWeight();
unsigned long now = millis();
#if DEBUG
if (now - lastWeightPrintTime >= 1000) {
Serial.print("Weight: ");
Serial.println(weight);
lastWeightPrintTime = now;
}
#endif
if (weight < GREEN_THRESHOLD)
{
setLedState(true, false, false);
}
else if (weight < YELLOW_THRESHOLD)
{
setLedState(false, true, false);
}
else
{
setLedState(false, false, true);
}
}
/**
* @brief Main loop. Only calls feature functions for readability.
*/
void loop()
{
updateLedsByWeight();
}