// Arduino DS3232RTC Library
// https://github.com/JChristensen/DS3232RTC
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
//
// Example sketch to display the date and time from a DS3231
// or DS3232 RTC every second. Display the temperature once per
// minute. (The DS3231 does a temperature conversion once every
// 64 seconds. This is also the default for the DS3232.)
//
// Set the date and time by entering the following on the Arduino
// serial monitor:
// year,month,day,hour,minute,second,
//
// Where
// year can be two or four digits,
// month is 1-12,
// day is 1-31,
// hour is 0-23, and
// minute and second are 0-59.
//
// Entering the final comma delimiter (after "second") will avoid a
// one-second timeout and will allow the RTC to be set more accurately.
//
// No validity checking is done, invalid values or incomplete syntax
// in the input will result in an incorrect RTC setting.
//
// Jack Christensen 08Aug2013
#include <DS3232RTC.h> // https://github.com/JChristensen/DS3232RTC
#include <Streaming.h> // https://github.com/janelia-arduino/Streaming
#include <Servo.h>
#include <HX711_ADC.h>
#include <EEPROM.h>
//pins:
const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 5; //mcu > HX711 sck pin
//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_eepromAdress = 0;
unsigned long t = 0;
int bfd1;
int lfd1;
int dfd1;
int stablecount = 0;
unsigned long preMillis = 0;
const int shold = 10;
const long checkint = 50;
unsigned long previousMillis = 0;
float lastweight = 0;
DS3232RTC myRTC;
Servo s1;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("Starting...");
s1.attach(9);
LoadCell.begin();
//LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
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() || LoadCell.getSignalTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
while (1);
}
else {
LoadCell.setCalFactor(1.0); // user set calibration value (float), initial value 1.0 may be used for this sketch
Serial.println("Startup is complete");
}
while (!LoadCell.update());
calibrate(); //start calibration procedure
Serial << F( "\n" __FILE__ "\n" __DATE__ " " __TIME__ "\n" );
myRTC.begin();
// setSyncProvider() causes the Time library to synchronize with the
// external RTC by calling RTC.get() every five minutes by default.
setSyncProvider(myRTC.get);
Serial << F("RTC Sync");
if (timeStatus() != timeSet) Serial << F(" FAIL!");
Serial << endl;
}
void loop()
{
static time_t tLast;
time_t t;
tmElements_t tm;
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();
unsigned long currentmillis = millis();
if(abs(i-lastweight) <0.1){
stablecount++;
} else{
stablecount = 0;
}
lastweight = i;
Serial.println(stablecount);
Serial.println(checkint);
if(stablecount >= checkint){
if((i >= 11)&&(i <= 15)){
if((hour(t) >= 5)&& (hour(t)<=11)){
if( bfd1 == 0){
for (int food = 0; food < 8; food++){
s1.write(0);
delay(1000);
s1.write(60);
delay(1000);
s1.write(0);
}
}
bfd1++;
dfd1=0;
}
}
if((i >= 11)&&(i <= 15)){
if((hour(t) >= 12)&& (hour(t)<=15)){
if( lfd1 == 0){
for (int food = 0; food < 8; food++){
s1.write(0);
delay(1000);
s1.write(60);
delay(1000);
s1.write(0);
}
}
lfd1++;
bfd1=0;
}
}
if((i >= 11)&&(i <= 15)){
if((hour(t) >= 17)&& (hour(t)<=22)){
if( dfd1 == 0){
for (int food = 0; food < 8; food++){
s1.write(0);
delay(1000);
s1.write(60);
delay(1000);
s1.write(0);
}
}
dfd1++;
lfd1=0;
}
}
}
}
}
// receive command from serial terminal
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay(); //tare
else if (inByte == 'r') calibrate(); //calibrate
else if (inByte == 'c') changeSavedCalFactor(); //edit calibration value manually
}
// check if last tare operation is complete
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
// check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
if (Serial.available() >= 12) {
// note that the tmElements_t Year member is an offset from 1970,
// but the RTC wants the last two digits of the calendar year.
// use the convenience macros from the Time Library to do the conversions.
int y = Serial.parseInt();
if (y >= 100 && y < 1000)
Serial << F("Error: Year must be two digits or four digits!") << endl;
else {
if (y >= 1000)
tm.Year = CalendarYrToTm(y);
else // (y < 100)
tm.Year = y2kYearToTm(y);
tm.Month = Serial.parseInt();
tm.Day = Serial.parseInt();
tm.Hour = Serial.parseInt();
tm.Minute = Serial.parseInt();
tm.Second = Serial.parseInt();
t = makeTime(tm);
myRTC.set(t); // use the time_t value to ensure correct weekday is set
setTime(t);
Serial << F("RTC set to: ");
printDateTime(t);
Serial << endl;
// dump any extraneous input
while (Serial.available() > 0) Serial.read();
}
}
t = now();
if (t != tLast) {
tLast = t;
printDateTime(t);
if (second(t) == 0) {
float c = myRTC.temperature() / 4.;
float f = c * 9. / 5. + 32.;
Serial << F(" ") << c << F(" C ") << f << F(" F");
}
Serial << endl;
}
if((hour(t) == 1) &&(minute(t)==12)){
s1.write(0);
delay(1000);
s1.write(180);
delay(1000);
s1.write(0);
}
}
// print date and time to Serial
void printDateTime(time_t t)
{
printDate(t);
Serial << ' ';
printTime(t);
}
// print time to Serial
void printTime(time_t t)
{
printI00(hour(t), ':');
printI00(minute(t), ':');
printI00(second(t), ' ');
}
// print date to Serial
void printDate(time_t t)
{
printI00(day(t), 0);
Serial << monthShortStr(month(t)) << _DEC(year(t));
}
// Print an integer in "00" format (with leading zero),
// followed by a delimiter character to Serial.
// Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
{
if (val < 10) Serial << '0';
Serial << _DEC(val);
if (delim > 0) Serial << delim;
return;
}
void calibrate() {
Serial.println("***");
Serial.println("Start calibration:");
Serial.println("Place the load cell an a level stable surface.");
Serial.println("Remove any load applied to the load cell.");
Serial.println("Send 't' from serial monitor to set the tare offset.");
boolean _resume = false;
while (_resume == false) {
LoadCell.update();
if (Serial.available() > 0) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
}
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
_resume = true;
}
}
Serial.println("Now, place your known mass on the loadcell.");
Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");
float known_mass = 0;
_resume = false;
while (_resume == false) {
LoadCell.update();
if (Serial.available() > 0) {
known_mass = Serial.parseFloat();
if (known_mass != 0) {
Serial.print("Known mass is: ");
Serial.println(known_mass);
_resume = true;
}
}
}
LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct
float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value
Serial.print("New calibration value has been set to: ");
Serial.print(newCalibrationValue);
Serial.println(", use this as calibration value (calFactor) in your project sketch.");
Serial.print("Save this value to EEPROM adress ");
Serial.print(calVal_eepromAdress);
Serial.println("? y/n");
_resume = false;
while (_resume == false) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
#endif
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
Serial.print("Value ");
Serial.print(newCalibrationValue);
Serial.print(" saved to EEPROM address: ");
Serial.println(calVal_eepromAdress);
_resume = true;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
_resume = true;
}
}
}
Serial.println("End calibration");
Serial.println("***");
Serial.println("To re-calibrate, send 'r' from serial monitor.");
Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
Serial.println("***");
}
void changeSavedCalFactor() {
float oldCalibrationValue = LoadCell.getCalFactor();
boolean _resume = false;
Serial.println("***");
Serial.print("Current value is: ");
Serial.println(oldCalibrationValue);
Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
float newCalibrationValue;
while (_resume == false) {
if (Serial.available() > 0) {
newCalibrationValue = Serial.parseFloat();
if (newCalibrationValue != 0) {
Serial.print("New calibration value is: ");
Serial.println(newCalibrationValue);
LoadCell.setCalFactor(newCalibrationValue);
_resume = true;
}
}
}
_resume = false;
Serial.print("Save this value to EEPROM adress ");
Serial.print(calVal_eepromAdress);
Serial.println("? y/n");
while (_resume == false) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
#endif
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
Serial.print("Value ");
Serial.print(newCalibrationValue);
Serial.print(" saved to EEPROM address: ");
Serial.println(calVal_eepromAdress);
_resume = true;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
_resume = true;
}
}
}
Serial.println("End change calibration value");
Serial.println("***");
}