i am trying to make an alarm clock with esp8266 and ws2812b leds. On alarm time it must call the sunrise() function. The sunrise() function works fine when i put it directly in the loop function. But it doesn't work in alarm trigger.
if (AlarmData.AlarmOn[Current.Day])
{
if (!AlarmActive)//do not enter this routine if alarm already active
{
if (Current.Hour == AlarmData.Hour[Current.Day])
{
if (Current.Minute == AlarmData.Minute[Current.Day])
{
if (Current.Second > 0 && Current.Second < 3)
{
AlarmActive = true;
sunrise();
alarmTriggerTime = micros();
Serial.println("Its time for your alarm!");
}
}
}
}
}
My code is below. thanks in advance for your help
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include "EEPROMAnything.h"
#include "get_time.h"
#include "OTA.h"
#include <stdio.h>
#include <stdint.h>
#include "web_portal.h"
#include "ESP8266TimerInterrupt.h"
#include "restore_factory_settings.h"
#include "FastLED.h"
#define NUM_LEDS 60
#define DATA_PIN 5
// Define the array of leds
CRGB leds[NUM_LEDS];
#define timeZone 3
#define TenSecs 10000000
#define OneMin 60000000
#define TenMins 600000000
#define TIMER_INTERVAL_MS 1000
ESP8266Timer ITimer;
int timer;
int alarmTriggerTime;
struct CurrentTime Current;
bool AlarmActive;
struct AlarmDataStruct AlarmData;
int WiFiTimer;
char factory_settings_stored [3];
bool OneSecoundPassed;
void ICACHE_RAM_ATTR TimerHandler(void)
{
OneSecoundPassed = true;
}
void setup() {
Serial.begin(115200);
Serial.println("Booting");
EEPROM.begin(512);
EEPROM_readAnything(150, factory_settings_stored);
if (memcmp(&factory_settings_stored, "YES", 3) != 0)
{
restore_factory_settings();
}
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(0);
WiFi.mode(WIFI_STA);
WiFiManager wm;
bool response;
response = wm.autoConnect("AutoConnectAP"); // anonymous ap
if (!response) {
Serial.println("Failed to connect");
// ESP.restart();
}
else {
//if you get here you have connected to the WiFi
Serial.println("Lets Go");
}
start_server();
SetupOTA();
setup_time(timeZone);
Current = Current_Time();
EEPROM_readAnything(100, AlarmData);
Serial.print("Alarm set for ");
Serial.print(AlarmData.Hour[Current.Day]);
Serial.print(":");
Serial.println(AlarmData.Minute[Current.Day]);
timer = micros();
WiFiTimer = timer;
// Interval in microsecs
if (ITimer.attachInterruptInterval(TIMER_INTERVAL_MS * 1000, TimerHandler))
{
Serial.println("Starting ITimer OK, millis() = " + String(millis()));
}
else
{
Serial.println("Can't set ITimer correctly. Select another freq. or interval");
}
}
void loop() {
if (!AlarmActive)
{
ArduinoOTA.handle();
handle_client();
if ((micros() - WiFiTimer) > TenMins) // check if wifi connection lost and if so try to reconnect
{
if (WiFi.status() != WL_CONNECTED)
{
ESP.restart(); //try to reconnect rather than resetting
}
WiFiTimer = micros();
}
if (OneSecoundPassed)
{
updateLocalTime();
OneSecoundPassed = false;
}
//update current hour from NTP server
if ((micros() - timer) > TenMins)
{
Current = Current_Time();
timer = micros();
}
}
if (AlarmActive)
{
if ((micros() - alarmTriggerTime) > TenMins)
{
AlarmActive = false; //if alarm active for 10mins and no one switches it off then do it auto
}
}
if (AlarmData.AlarmOn[Current.Day])
{
if (!AlarmActive)//do not enter this routine if alarm already active
{
if (Current.Hour == AlarmData.Hour[Current.Day])
{
if (Current.Minute == AlarmData.Minute[Current.Day])
{
if (Current.Second > 0 && Current.Second < 3)
{
AlarmActive = true;
sunrise();
alarmTriggerTime = micros();
Serial.println("Its time for your alarm!");
}
}
}
}
}
else
{
if (!AlarmActive)
{
}
}
}
void updateLocalTime () {
Current.Second++;
if (Current.Second >= 60)
{
Current.Second = 0;
Current.Minute++;
if (Current.Minute >= 60)
{
Current.Minute = 0;
Current.Hour++;
if (Current.Hour >= 24)
{
Current.Hour = 0;
Current.Day++;
if (Current.Day >= 7)
{
Current.Day = 0;
}
}
}
}
char tempTime[6];
if (Current.Minute < 10 && Current.Second < 10)
{
sprintf(tempTime, "0%d:0%d", Current.Minute, Current.Second);
}
else if (Current.Minute < 10)
{
sprintf(tempTime, "0%d:%d", Current.Minute, Current.Second);
}
else if (Current.Second < 10)
{
sprintf(tempTime, "%d:0%d", Current.Minute, Current.Second);
}
else
{
sprintf(tempTime, "%d:%d", Current.Minute, Current.Second);
}
}
void sunrise() {
static const uint8_t sunriseLength = 30; //(min)
static const uint8_t interval = (sunriseLength * 60) / 256;
static const uint8_t binterval = (sunriseLength * 60) / 256;
// current gradient palette color index
static uint8_t heatIndex = 0; // start out at 0
static uint8_t brIndex = 0;
// HeatColors_p is a gradient palette built in to FastLED
// that fades from black to red, orange, yellow, white
// feel free to use another palette or define your own custom one
CRGB color = ColorFromPalette(HeatColors_p, heatIndex);
fill_solid(leds, NUM_LEDS, color); // fill the entire strip with the current color
EVERY_N_SECONDS(binterval) {
if (brIndex < 255) {
FastLED.setBrightness(brIndex);
brIndex++;
}
}
EVERY_N_SECONDS(interval) {
if (heatIndex < 255) {
heatIndex++;
}
}
FastLED.show();
}
Your sunrise
function should be called over and over, every call changes the LED color a slight bit. This is why it works then you put it into the loop
function.
However, you have guarded it so that it is specifically only called once - so now it is called, sets the LEDs to the dimmest setting possible, and is not called again.
What you need to do is separate this out into two parts: One that detects when to activate sunrise
, and one that is continuously called when it is time. F.ex:
void loop()
{
/* stuff */
if (AlarmData.AlarmOn[Current.Day])
{
if (!AlarmActive) // do not enter this routine if alarm already active
{
if (Current.Hour == AlarmData.Hour[Current.Day])
{
if (Current.Minute == AlarmData.Minute[Current.Day])
{
if (Current.Second > 0 && Current.Second < 3)
{
AlarmActive = true;
alarmTriggerTime = micros();
Serial.println("Its time for your alarm!");
}
}
}
}
}
if (AlarmActive)
sunrise();
}