I should preface this by saying I'm very inexperienced with coding in Arduino.
So the goal of my code is to have a servo open a container door and pour coffee beans into a bin, where a load cell reads the weight of the beans poured in and once a certain predetermined weight is reached the servo closes the container door. However, I've run into two main issues. First the sample speed of the loadcell and hx711 are too slow for this application, by the time the loadcell recognizes that the required weight has been met, the actual weight of the beans in the bin is twice that of the goal weight.
Secondly, the code I 'wrote' for this is mainly pulled from the hx711 library, and I don't understand some of it. The end goal of the project is for this to run with out being plugged into a computer, so using the serial window won't be possible, but the code currently won't run unless the serial window is open.
The program works as intended besides these two main points, so any pointers on how to fix these would be greatly appreciated!
#include <HX711_ADC.h>
#include <Servo.h>
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif
//pins:
const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 5; //mcu > HX711 sck pin
const int servoPin = 3;
//Servo Stuff
int servoPosition = 0;
int servoInterval = 500;
int servoDegrees = 60;
int weight = 0;
unsigned long currentMillis = 0;
unsigned long previousServoMillis = 0;
// Create a servo object
Servo Servo1;
//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_eepromAdress = 0;
unsigned long t = 0;
void setup() {
Serial.begin(57600); delay(10);
Serial.println();
Serial.println("Starting...");
Servo1.write(0);
Servo1.attach(servoPin);
LoadCell.begin();
float calibrationValue; // calibration value (see example file "Calibration.ino")
#if defined(ESP8266)|| defined(ESP32)
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom
unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
while (1);
}
else {
LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
Serial.println("Startup is complete");
}
}
void loop() {
static boolean newDataReady = 0;
const int serialPrintInterval = 0; //increase value to slow down serial print activity
// check for new data/start next conversion:
if (LoadCell.update()) newDataReady = true;
// get smoothed value from the dataset:
if (newDataReady) {
if (millis() > t + serialPrintInterval) {
float i = LoadCell.getData();
Serial.print("Load_cell output val: ");
Serial.println(i);
newDataReady = 0;
t = millis();
}
}
// receive command from serial terminal, send 't' to initiate tare operation:
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
// check if last tare operation is complete:
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
float measurement = LoadCell.getData();
weight = measurement;
currentMillis = millis();
servoFunction();
}
void servoFunction() {
if (weight >= 20) {
if (currentMillis - previousServoMillis >= servoInterval) {
servoPosition = 0;
Servo1.write(servoPosition);
delay(2000);
exit(2000);
}
}
else {
if (currentMillis - previousServoMillis >= servoInterval) {
servoPosition = 60;
Servo1.write(servoPosition);
}
}
}
I don't have to type anything into the serial window, but the servo won't do the initial turn without the serial window being open. To be clear this initial turn is not dependent on anything, so it should happen immediately.
I haven't measured how long it takes to read the weight exactly, but I would estimate it takes it 1.5-2 seconds to read a 25g weight I use to calibrate it.
I can't see why that would be. However, servo problems are usually power related. Powering them from an Arduino is risky business - they need their own supply.
Yes - the Arduino can barely provide enough current to run a small servo with no load on it if it is powered through the USB port. If you are using the barrel jack, it's substantially worse.
Sorry I dont really get what you're asking, as I said I am fairly inexperienced with arduino.
I've used 'weight = LoadCell.getData();' to declare a variable, which is used to tell the servo when to stop. Is this causing a 500ms wait time every iteration? if so how do I fix it?
The OP's HX711 library function, getData(), returns the result of a moving average. The default sample size is 16.
So at 10 sps, the HX711 default rate, when there is a sudden change in weight, it will take about 1.6 seconds for the moving average to stabilize.
In the OP's application, as the coffee beans flow out, the weight will be increasing gradually, so it is not clear whether the moving average would significantly affect the device's performance.
I'd experiment with a smaller moving average sample size, or not use it at all.
Thanks, but that remains to be seen.
(The code @kolaha gave you in #14 is likely to be more helpful.)
My understanding of the library isn't all that great either. In fact, I've never used that one. So what I did was google the library name in your code: HX711_ADC.h
Presumably, that is the source of the library installed on your computer.
That website points out that a moving average is used. It also talks about the HX711 sampling rate.
The 2nd google hit was the .h file itself
(also in the "src" folder of the library on your computer) where, among other "public" functions (i.e., those available to the user, that's you, to use) is
void setSamplesInUse(int samples); //overide number of samples in use
So, it seems that if you want to change the number of moving average samples, then at the end of setup(), you should add:
setSamplesInUse(x);
where x = one of the valid sample sizes listed near the top of the .h file
PS: you could also use a different HX711 library, one that just returns a single (unaveraged) value with every call. But, since you're already down the path with this library, I guess you may as well stay with it.