trying to code a project i'm working on (my first ever serious attempt on arduino so i'm a comlpleat noob) and got stuck.
i have a temperature transmitter that i want in realtime millis();
then i have a stepper motor i want to run xx steps every 3,5h under a 14h duration.
then i want a longer (10h) pause on the stepper motor.
const unsigned long readtemp = 1000; //every sec
const unsigned long feed = 5000; //every 5 sec
const unsigned long night = 30000; //every 30 sec
unsigned long previousTime_readtemp = 0; // vairable to save the last executed time
unsigned long previousTime_feed = 0;
unsigned long previousTime_night = 0;
#include <OneWire.h>
#include <LiquidCrystal.h>
#include <DallasTemperature.h>
#include <Stepper.h>
#define ONE_WIRE_BUS 13
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal lcd(2,3,4,5,6,7);
float tempC = 0;
// Define number of steps per rotation:
const int stepsPerRevolution = 942;
// Create stepper object called 'revolver', note the 6+/pin order:
Stepper revolver = Stepper(stepsPerRevolution, 9, 11, 10, 12);
int time = 0;
void setup() {
sensors.begin();
lcd.begin(16,2);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Cubes");
lcd.setCursor(11,0);
lcd.print("of 28");
revolver.setSpeed(50); // Set the speed to 5 rpm:
pinMode(3, OUTPUT);
time = 1;
Serial.begin(9600);
}
void loop() {
unsigned long currentTime = millis(); // store the current time
//read and write temp to lcd
sensors.requestTemperatures();
tempC = sensors.getTempCByIndex(0);
//tempF = sensors.toFahrenheit(tempC);
Serial.println(tempC);
lcd.setCursor(5,1); //set cursor to center line #2
lcd.print(tempC); lcd.print((char)223); lcd.print("C"); //lcd.setCursor(0,1);//lcd.print(tempC); lcd.print(""); lcd.print("C");
millis();
//feed 08:00/10:30/14:00
if (currentTime - previousTime_feed >= feed){
Serial.println("feed");
revolver.step(stepsPerRevolution);
lcd.setCursor(6,0);
lcd.print(time++);
previousTime_feed = currentTime;
}
//feed 17:30 and wait 10h
if (currentTime - previousTime_night >= night){
Serial.println("night");
revolver.step(stepsPerRevolution);
lcd.setCursor(6,0); //set cursor to center line #1
lcd.print(time++); //print nubers used
previousTime_night = currentTime;
}
}
this is what i get from serial monitor under the 2 min duration after that thre is no break probably a small error but i cant find it
Its a bit hard to understand what the problem is -- Is it that feed and night are supposed to interact over a 24 hour cycle?
If so, I might feed every 3.5 hours unless I was in the night portion, determining night based off of something like:
int half_hour_of_day = (millis()/1000UL/1800UL) % 48; // susceptible to 70 day rollover
...
if (currentTime - previousTime_feed >= feed){
previousTime_feed += feed;
if (half_hour_of_day <= 28 ) { // only feed during the daytime
Serial.println("feed");
revolver.step(stepsPerRevolution);
lcd.setCursor(6,0);
lcd.print(time++);
}
}
I like using the previousTime_feed += feed; over previousTime_feed = currentTime; so you stay in sync with millis(), rather than drifting later with the processing involved in each cycle.
The first conditional attempts to feed every 3.5 hours, and the inner conditional chooses only the portions of days in the first 14 hours of each day (as measured in half-hours)
The int half_hour_of_day = (millis()/1000UL/1800UL) % 48; line makes a 0-47 number indicating which half-hour of successive days after the arduino boots up.
If it were (millis()/1000UL/3600UL) % 24; it would be a 0-23 hour_of_day, and the inner conditional could be:
hi the problem is that it should feed... lets say 08:00 am / 10:30 am / 02:00 pm and 05:30 pm
after that it should wait until 08:00 am to start over again but it continues after "night"
ah... the way you coded it is that it happens every ∆t
you have a couple issues, the first one being that millis() will loose precision over time and you never know it's 8:30... millis() is just the number of ms since you booted the Arduino.
You should get an RTC, like the DS3231, it's a cheap component that maintain time like your watch.
yes i'm aware of that and its not that big deal. my thought was to start it when i wanted the first feed. then it last for 28 feeds until i have to reset and reload
here is a demo-code that shows how a software-RTC can be used with function millis(). This software-RTC still has the problem of beeing unprecise as the timing is derivated from the microprocessors system-clock
For intergrating the times you want to activate the next feeding calculate minutes of the day by
hours * 60 + minutes
this means 08:00 am / 10:30 am / 02:00 pm and 05:30 pm
8:00 is equal to 8 * 60 = 480
10:30 is equal to 10 * 60 + 30 = 630
02:00 pm is equal to 14 * 60 = 840
5:30 pm is equal to 17 * 60 + 30 = 1050
minuteOfDay is always calculated
hour * 60 + minute
and this is repeated for all times of the day you want to feed
This is the software-RTC-code
unsigned long RTC_Timer = 0;
unsigned long MyTestTimer;
int RTC_Hour = 0;
int RTC_Minute = 0;
int RTC_Second = 0;
int RTC_10nth_Seconds = 0;
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
void PrintRTC_Data() {
Serial.print(RTC_Hour);
Serial.print(":");
Serial.print(RTC_Minute);
Serial.print(":");
Serial.print(RTC_Second);
Serial.println();
}
void SoftRTC() {
if ( TimePeriodIsOver(RTC_Timer,100) ) {
RTC_10nth_Seconds ++;
if (RTC_10nth_Seconds == 10) {
RTC_10nth_Seconds = 0;
RTC_Second++;
if (RTC_Second == 60) {
RTC_Minute++;
RTC_Second = 0;
}
}
if (RTC_Minute == 60) {
RTC_Hour++;
RTC_Minute = 0;
}
if (RTC_Hour == 24) {
RTC_Hour = 0;
}
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
PrintRTC_Data();
}
}
}
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
}
void loop() {
SoftRTC(); // this must be called faster than every 0,1 seconds as this very simple Software-RTC is based on a fast running loop
// to say it explicit: Your code is NOT allowed to stay more than 0,1 seconds in any function
// you could deviate from this 0,1 seconds if the basic "heartBeat" is increased to a higher value with an according modified counting of the seconds
// another solution would be to use a hardware-timer that invokes a timer-interrupt
}
This is a library that provides a software-RTC that is based on a hardware-timer
You have to check if this library wants to use the same hardware-timer than your stepper-motor-library
If you switch over to an ESP32 as the microcontroller which has WLAN onboard you can connect the ESP32 to your local WLAN to sync with internet-time. And additionally an ESP32 has an RTC onboard. No extra hardware needed.
ESP32 can be programmed just the same way as an arduino Uno etc.
its a tropic fish feeder im working on. the container fit's 28 portions of food after that i have to reload it. the food last's for a week if i feed 4 times a day. feeding under the time lights are on 08:00am-10:00pm
with such a DC-DC-step-down-converter placed next to any microcontroller you only need some very short wiring from the DC-DC-step-down-converter to the microcontroller
Ah, this code initializes at zero, so it would wait the feed time before starting. To start off the sketch with a feed due, put a line like this in setup:
previousTime_feed = millis() - feed;
I figured you had some way of syncing your code with physical day-night. Maybe a cheap lamp timer or something. If you want your code to do it, you might look into a RTC module.
millis()/1000UL is seconds, millis()/1000UL/1800UL is half-hours and millis()/1000UL/1800UL %48 gives a index of a half hour each day. This way of determining a particular half hour is a bit sloppy -- it is susceptible to the millis() rollover at and will start giving bad results after 49.7 days, when it rolls back over to zero.
Then the (half_hour_of_day <= 28 ) are the indexes of half hours in the first 14 hours of the day.