This is my current code which I am using for that(the main file is just for testing at the moment):
#include <Arduino.h>
#include "SimpleTimer.h"
// #define DEBUGGING
SimpleTimer timer;
// Pin to switch the device on and off
int8_t outputPin = 2;
int8_t currenState = LOW;
int8_t getNextState()
{
currenState = currenState == HIGH ? LOW : HIGH;
return currenState;
}
void testAddAlerts()
{
timer.addAlert(00, 00, 05, B01111111);
timer.setAllAlertsActive(true);
}
void setup()
{
#ifdef DEBUGGING
Serial.begin(115200);
#endif
pinMode(outputPin, OUTPUT);
testAddAlerts();
timer.setTimer(0, 0, 0);
digitalWrite(outputPin, getNextState() );
unsigned long future = millis() + 2000;
while (future > millis())
{
delay(100);
}
digitalWrite(outputPin, getNextState());
}
void loop()
{
if (timer.update() == 1)
{
// Serial.println("Alert");
digitalWrite(outputPin, getNextState());
// Resets the timer so there is an output every alert
timer.setTimer(0,0,0);
timer.setAllAlertsActive(true);
}
}
And the classes used for it :
#include <Arduino.h>
#pragma once
// #define CHECKONLYEVERYSECOND
// #define DEBUGGING
struct Alert
{
Alert(int32_t time, uint8_t executionDays)
{
executionTime = time;
setExecutionDays(executionDays);
activate(true);
}
/**
* @brief Set the execution time
*
* @param time
*/
void setExecutionTime(uint32_t time)
{
executionTime = time;
}
uint8_t getExecutionDays()
{
return data >= 128 ? data - 128 : data;
}
void setExecutionDays(uint8_t bitmask)
{
boolean active = isActive();
data = bitmask;
activate(active);
}
/**
* @brief Activates or deactivates the alert
*
* @param activate
*/
void activate(bool activate)
{
if (isActive())
{
if (!activate)
{
data -= 128;
}
}
else
{
if (activate)
{
data += 128;
}
}
}
/**
* @brief Returns if the alert is currently active or not
*
* @return true The alert is active
* @return false The alert is deactivated
*/
bool isActive()
{
if (data >= 128)
{
return true;
}
else
{
return false;
}
}
Alert *nextAlert = nullptr;
/**
* @brief data saves multiple differnt data in an 8 bit integer
* The first bit indcates if the alert is active
*
*
*/
uint8_t data;
uint32_t executionTime = 0;
};
/**
* @brief Keeps track of time and triggers when an alert occures
* (Use the update function for that)
*
*/
class SimpleTimer
{
public:
SimpleTimer();
~SimpleTimer();
/**
* @brief Updates the time with the elapsed time and checks if an alert is triggered. Also it resets the time and the alerts when "a day" is passed.
*
* @return returns 1 if an alert was triggered and 0 if noting happend
*/
int update();
/**
* @brief Converts the time given as normal time like 18:30:30 in milliseconds
*
* @param hours A value between 0-23
* @param minutes A value between 0-59
* @param seconds A value between 0-59
* @return The time in milliseconds
*/
uint32_t convertTimeToMilliSec( uint8_t hours, uint8_t minutes, uint8_t seconds);
/**
* @brief Adds an alert to the timer
*
* @param time The time when the alert should trigger
*/
void addAlert(uint32_t time, uint8_t weekdays);
/**
* @brief Adds an alert to the timer
*
* @param hours A value between 0-23
* @param minutes A value between 0-59
* @param seconds A value between 0-59
*/
void addAlert( uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t weekdays);
/**
* @brief Remove the alert on the given index
*
* @param index the position of the alert
* @return boolean which indicates if the removing was succesfull
*/
boolean removeAlert(int index);
/**
* @brief Remove the alert with the time
*
* @param time the time which should get removed
* @return boolean which indicates if the removing was succesfull
*/
boolean removeAlert(uint32_t time);
/**
* @brief Get the alert with the given index
*
* @param index An positive integer which is the desired index of the alert
* @return Returns an Alert if it exists. If there is no Alert on this index it returns nullptr.
*/
Alert *getAlert( uint8_t index);
/**
* @brief Sets all alerts inactive or active ´
*
* @param active Value which defines if all alerts should be active or inactive
*/
void setAllAlertsActive(bool active);
/**
* @brief Sets the current time
*
* @param hours A value between 0-23
* @param minutes A value between 0-59
* @param seconds A value between 0-59
*/
void setTimer( uint8_t hours, uint8_t minutes, uint8_t seconds);
// Used for debugging
void printTime(uint32_t time)
{
#ifdef DEBUGGING
// Uses too mutch resources so it will only used to debug
int hours = time / (1000 * 60 * 60);
time = time - hours * (1000 * 60 * 60);
int minutes = time / (1000 * 60);
time = time - minutes * (1000 * 60);
int seconds = time / 1000;
time = time - seconds * 1000;
Serial.print(hours);
Serial.print(":");
Serial.print(minutes);
Serial.print(":");
Serial.print(seconds);
Serial.print(":");
Serial.println(time);
#endif
}
protected:
uint32_t lastTimeUpdate = 0;
/**
* @brief Represents the current daytime in milliseconds if it synced before, else it is just a virtual day with 24h
*
*/
uint32_t time = 0;
/**
* @brief Saves all alerts
*
*/
Alert *rootAlert = nullptr;
// Saves the current time just here so the microncontroller does not need to reserve always new storage
uint32_t currentTime;
#ifdef CHECKONLYEVERYSECOND
/**
* @brief Stores the milliseconds elapesed since the last full second was reached
* Only use when CHECKONLYEVERYSECOND is defined
*
*/
int16_t lastSecUpdate;
#endif
};
#include "SimpleTimer.h"
SimpleTimer::SimpleTimer()
{
time = 0;
}
SimpleTimer::~SimpleTimer()
{
}
uint32_t SimpleTimer::convertTimeToMilliSec(uint8_t hours, uint8_t minutes, uint8_t seconds)
{
return ((((hours * 60) + minutes) * 60) + seconds) * 1000;
}
void SimpleTimer::setTimer(uint8_t hours, uint8_t minutes, uint8_t seconds)
{
// TODO check if params are valid not negativ or to high
// Calculates the time in milli seconds
time = convertTimeToMilliSec(hours, minutes, seconds);
}
void SimpleTimer::setAllAlertsActive(bool activ)
{
Alert *currentAlert = rootAlert;
while (currentAlert != nullptr)
{
currentAlert->activate(activ);
currentAlert = currentAlert->nextAlert;
}
}
void SimpleTimer::addAlert(uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t weekdays)
{
addAlert(convertTimeToMilliSec(hours, minutes, seconds), weekdays);
}
void SimpleTimer::addAlert(uint32_t time, uint8_t weekdays)
{
if (rootAlert != nullptr)
{
Alert *currentAlert = rootAlert;
while (currentAlert->nextAlert != nullptr)
{
currentAlert = currentAlert->nextAlert;
}
currentAlert->nextAlert = new Alert(time, weekdays);
currentAlert->nextAlert->activate(true);
}
else
{
rootAlert = new Alert(time, weekdays);
}
}
int SimpleTimer::update()
{
uint8_t returnValue = 0;
currentTime = millis();
time += currentTime - lastTimeUpdate;
#ifdef CHECKONLYEVERYSECOND
lastSecUpdate += currentTime - lastTimeUpdate;
if (lastSecUpdate >= 1000)
{
printTime(time);
lastSecUpdate = lastSecUpdate - 1000;
#endif
if (rootAlert != nullptr)
{
Alert *currentAlert = rootAlert;
while (currentAlert != nullptr)
{
if (currentAlert->isActive() && currentAlert->executionTime <= time)
{
currentAlert->activate(false);
returnValue = 1;
}
else
{
currentAlert = currentAlert->nextAlert;
}
}
}
// Test if "a day" has passed
if (time >= 86400000)
{
time = time - 86400000;
setAllAlertsActive(true);
}
#ifdef CHECKONLYEVERYSECOND
}
#endif
lastTimeUpdate = currentTime;
return returnValue;
}
Alert *SimpleTimer::getAlert(uint8_t index)
{
if (index < 0)
{
return nullptr;
}
Alert *askedAlert = rootAlert;
for (int i = 0; i <= index; i++)
{
if (index == i)
{
return askedAlert;
}
if (askedAlert->nextAlert != nullptr)
{
askedAlert = askedAlert->nextAlert;
}
else
{
return nullptr;
}
}
return askedAlert;
}
The odd thing is that the code works with the esp32S2 but with the attiny202 it just turns the LED on and of which happens in the setup but not in the loop.
Is there a possibility, that the RAM is not enough for it so it just does nothing?
If it would work,it should turn the LED for 5 sec on and then turn it off for 5 sec. (And then repeat that)