|
|
@@ -21,6 +21,7 @@ |
|
|
|
#include "main.h" |
|
|
|
#include "math.h" |
|
|
|
#include "stdbool.h" |
|
|
|
#include "string.h" |
|
|
|
|
|
|
|
/* Private includes ----------------------------------------------------------*/ |
|
|
|
/* USER CODE BEGIN Includes */ |
|
|
@@ -49,7 +50,7 @@ RTC_TimeTypeDef sTime; |
|
|
|
RTC_DateTypeDef sDate; |
|
|
|
RTC_AlarmTypeDef sAlarm; |
|
|
|
|
|
|
|
//Nuernberg coordinates |
|
|
|
//Nuremberg coordinates |
|
|
|
int latitude_nbg = 49; |
|
|
|
int longitude_nbg = 11; |
|
|
|
|
|
|
@@ -58,6 +59,20 @@ int UTC_DER_sum = 2; |
|
|
|
int UTC_DER_win = 1; |
|
|
|
bool winterTime = true; |
|
|
|
|
|
|
|
int DaysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
|
|
|
int DaysInMonthLeapYear[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
|
|
|
bool leapYear = false; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
int hours; |
|
|
|
int minutes; |
|
|
|
int seconds; |
|
|
|
int weekDay; |
|
|
|
int month; |
|
|
|
int day; |
|
|
|
int year; |
|
|
|
} timeAndDate; |
|
|
|
|
|
|
|
/* USER CODE BEGIN PV */ |
|
|
|
|
|
|
|
/* USER CODE END PV */ |
|
|
@@ -100,13 +115,18 @@ double rad_to_deg(double rad) |
|
|
|
* Description : checks if year is a leap year |
|
|
|
* Return : false: no leap year, true: leap year |
|
|
|
*******************************************************************************/ |
|
|
|
int leap_year_check(int year) |
|
|
|
void leap_year_check(int initialyear) |
|
|
|
{ |
|
|
|
int year = initialyear; |
|
|
|
if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) |
|
|
|
{ |
|
|
|
return true; |
|
|
|
leapYear = true; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
leapYear = false; |
|
|
|
} |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/******************************************************************************* |
|
|
@@ -121,8 +141,8 @@ int calc_day_of_year(int day, int mon, int year) |
|
|
|
int doy = day; //day of year |
|
|
|
|
|
|
|
// check for leap year |
|
|
|
bool leap_year = leap_year_check(year); |
|
|
|
if(leap_year == true) |
|
|
|
//bool leap_year = leap_year_check(year); |
|
|
|
if(leapYear == true) |
|
|
|
{ |
|
|
|
days_in_feb = 29; |
|
|
|
} |
|
|
@@ -171,13 +191,12 @@ int calc_day_of_year(int day, int mon, int year) |
|
|
|
* Description : calculates the sunrise and sunset time of a specific date |
|
|
|
* Source : General Solar Position Calculations, NOAA Global Monitoring Division |
|
|
|
*******************************************************************************/ |
|
|
|
void calc_sunrise_sunset(int date, int month, int year, int sunrise_time[2], int sunset_time[2]) |
|
|
|
void calc_sunrise_sunset(timeAndDate* initialDate, timeAndDate* sunriseStruct, timeAndDate* sunsetStruct, timeAndDate* tomorrowsDate) |
|
|
|
{ |
|
|
|
double gamma = 0; |
|
|
|
bool leap_year; |
|
|
|
double eqtime = 0; |
|
|
|
double decl = 0; |
|
|
|
double decl_deg = 0; |
|
|
|
//double decl_deg = 0; |
|
|
|
double zenith_sun = 0; |
|
|
|
double lat_nbg_rad = 0; |
|
|
|
double ha = 0; |
|
|
@@ -191,13 +210,17 @@ void calc_sunrise_sunset(int date, int month, int year, int sunrise_time[2], int |
|
|
|
int int_sunrise_min = 0; |
|
|
|
int int_sunset_min = 0; |
|
|
|
|
|
|
|
int day = initialDate->day; |
|
|
|
int month = initialDate->month; |
|
|
|
int year = initialDate->year; |
|
|
|
|
|
|
|
//day of year calculation |
|
|
|
int day_of_year = calc_day_of_year(date, month, year); |
|
|
|
int day_of_year = calc_day_of_year(day, month, year); |
|
|
|
|
|
|
|
// fractional year (γ) in radians |
|
|
|
// check for leap year |
|
|
|
leap_year = leap_year_check(year); |
|
|
|
if(leap_year == false) |
|
|
|
//leap_year = leap_year_check(year); |
|
|
|
if(leapYear == false) |
|
|
|
{ |
|
|
|
//The back part of the formula was omitted, because there is no difference in the result |
|
|
|
gamma = ((2 * M_PI)/365)*(day_of_year - 1); |
|
|
@@ -213,7 +236,7 @@ void calc_sunrise_sunset(int date, int month, int year, int sunrise_time[2], int |
|
|
|
decl = 0.006918 - 0.399912*cos(gamma) + 0.070257*sin(gamma) - 0.006758*cos(2*gamma) + 0.000907*sin(2*gamma) - 0.002697*cos(3*gamma) + 0.00148*sin(3*gamma); |
|
|
|
|
|
|
|
//Solar declination angle in degrees |
|
|
|
decl_deg = rad_to_deg(decl); |
|
|
|
//decl_deg = rad_to_deg(decl); |
|
|
|
|
|
|
|
//Hour angle in degrees, positive number corresponds to sunrise, negative to sunset |
|
|
|
//special case of sunrise or sunset, the zenith is set to 90.833Deg |
|
|
@@ -262,10 +285,16 @@ void calc_sunrise_sunset(int date, int month, int year, int sunrise_time[2], int |
|
|
|
sunset_h = sunset_h + UTC_DER_sum; |
|
|
|
} |
|
|
|
|
|
|
|
sunrise_time[0] = sunrise_h; |
|
|
|
sunrise_time[1] = int_sunrise_min; |
|
|
|
sunset_time[0] = sunset_h; |
|
|
|
sunset_time[1] = int_sunset_min; |
|
|
|
sunriseStruct->hours = sunrise_h; |
|
|
|
sunriseStruct->minutes = int_sunrise_min; |
|
|
|
|
|
|
|
sunsetStruct->hours = sunset_h; |
|
|
|
sunsetStruct->minutes = int_sunset_min; |
|
|
|
|
|
|
|
sunriseStruct->day = sunsetStruct->day = tomorrowsDate->day; |
|
|
|
sunriseStruct->weekDay = sunsetStruct->weekDay = tomorrowsDate->weekDay; |
|
|
|
sunriseStruct->month = sunsetStruct->month = tomorrowsDate->month; |
|
|
|
sunriseStruct->year = sunsetStruct->year = tomorrowsDate->year; |
|
|
|
} |
|
|
|
|
|
|
|
/******************************************************************************* |
|
|
@@ -273,9 +302,20 @@ void calc_sunrise_sunset(int date, int month, int year, int sunrise_time[2], int |
|
|
|
* Description : calculates tomorrow's date |
|
|
|
* Source : https://github.com/vyacht/stm32/blob/master/vynmea/rtc.c |
|
|
|
*******************************************************************************/ |
|
|
|
void calc_tomorrows_date(int day, int wday, int month, int year, int DaysInMonth[12], int tomorrows_date[4]) |
|
|
|
void calc_tomorrows_date(timeAndDate* initialDate, timeAndDate* tomorrowsDate) |
|
|
|
{ |
|
|
|
bool leap_year; |
|
|
|
int yearToUse[12]; |
|
|
|
|
|
|
|
if (leapYear == true){ |
|
|
|
memcpy(yearToUse, DaysInMonthLeapYear, sizeof yearToUse); |
|
|
|
} else { |
|
|
|
memcpy(yearToUse, DaysInMonth, sizeof yearToUse); |
|
|
|
} |
|
|
|
|
|
|
|
int day = initialDate->day; |
|
|
|
int wday = initialDate->weekDay; |
|
|
|
int month = initialDate->month; |
|
|
|
int year = initialDate->year; |
|
|
|
|
|
|
|
day++; // next day |
|
|
|
wday++; // next weekday |
|
|
@@ -283,7 +323,7 @@ void calc_tomorrows_date(int day, int wday, int month, int year, int DaysInMonth |
|
|
|
{ |
|
|
|
wday = 1; // Monday |
|
|
|
} |
|
|
|
if(day > DaysInMonth[month-1]) |
|
|
|
if(day > yearToUse[month-1]) |
|
|
|
{ // next month |
|
|
|
day = 1; |
|
|
|
month++; |
|
|
@@ -295,10 +335,10 @@ void calc_tomorrows_date(int day, int wday, int month, int year, int DaysInMonth |
|
|
|
year++; |
|
|
|
} |
|
|
|
|
|
|
|
tomorrows_date[0] = day; |
|
|
|
tomorrows_date[1] = wday; |
|
|
|
tomorrows_date[2] = month; |
|
|
|
tomorrows_date[3] = year; |
|
|
|
tomorrowsDate->day = day; |
|
|
|
tomorrowsDate->weekDay = wday; |
|
|
|
tomorrowsDate->month = month; |
|
|
|
tomorrowsDate->year = year; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
@@ -306,9 +346,10 @@ void calc_tomorrows_date(int day, int wday, int month, int year, int DaysInMonth |
|
|
|
* Function Name : set_Alarm |
|
|
|
* Description : sets the wake up Alarm |
|
|
|
*******************************************************************************/ |
|
|
|
void set_Alarm(int h, int min, int weekDay) |
|
|
|
void set_Alarm(int h, int min, int weekDay, char* alarm) |
|
|
|
{ |
|
|
|
/** Enable the Alarm A*/ |
|
|
|
|
|
|
|
sAlarm.AlarmTime.Hours = h; |
|
|
|
sAlarm.AlarmTime.Minutes = min; |
|
|
|
sAlarm.AlarmTime.Seconds = 0; |
|
|
@@ -319,11 +360,19 @@ void set_Alarm(int h, int min, int weekDay) |
|
|
|
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; |
|
|
|
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY; |
|
|
|
sAlarm.AlarmDateWeekDay = weekDay; |
|
|
|
sAlarm.Alarm = RTC_ALARM_A; |
|
|
|
|
|
|
|
if (strcmp("A", alarm) == 0) { |
|
|
|
sAlarm.Alarm = RTC_ALARM_A; |
|
|
|
} else { |
|
|
|
sAlarm.Alarm = RTC_ALARM_B; |
|
|
|
} |
|
|
|
|
|
|
|
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK) |
|
|
|
{ |
|
|
|
Error_Handler(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// sending to UART |
|
|
@@ -332,6 +381,26 @@ void transmit_uart(char *string){ |
|
|
|
HAL_UART_Transmit(&huart2, (uint8_t*) string, len, 200); |
|
|
|
} |
|
|
|
|
|
|
|
void setTime(timeAndDate *time){ |
|
|
|
|
|
|
|
if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
time->hours = sTime.Hours; |
|
|
|
time->minutes = sTime.Minutes; |
|
|
|
time->seconds = sTime.Seconds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void setDate(timeAndDate *date){ |
|
|
|
|
|
|
|
if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
date->weekDay = sDate.WeekDay; |
|
|
|
date->month = sDate.Month; |
|
|
|
date->day = sDate.Date; |
|
|
|
date->year = 2000 + sDate.Year; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* USER CODE END 0 */ |
|
|
|
|
|
|
@@ -366,68 +435,52 @@ int main(void) |
|
|
|
MX_USART2_UART_Init(); |
|
|
|
MX_RTC_Init(); |
|
|
|
/* USER CODE BEGIN 2 */ |
|
|
|
int hours = 0; |
|
|
|
int minutes = 0; |
|
|
|
int seconds = 0; |
|
|
|
int weekDay = 0; |
|
|
|
int month = 0; |
|
|
|
int date = 0; |
|
|
|
int year = 0; |
|
|
|
|
|
|
|
int sunrise_h = 0; |
|
|
|
int sunset_h = 0; |
|
|
|
int int_sunrise_min = 0; |
|
|
|
int int_sunset_min = 0; |
|
|
|
int sunrise_time[2] = {0}; |
|
|
|
int sunset_time[2] = {0}; |
|
|
|
int tomorrows_date[4] = {0}; |
|
|
|
int DaysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
|
|
|
int DaysInMonthLeapYear[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
|
|
|
bool leap_year = false; |
|
|
|
|
|
|
|
|
|
|
|
timeAndDate sunrise, sunset, wakeUpTimeForStep, tomorrowsDate, initialDate; |
|
|
|
sunrise = sunset = wakeUpTimeForStep = tomorrowsDate = initialDate = (timeAndDate) {\ |
|
|
|
0, |
|
|
|
0, |
|
|
|
0, |
|
|
|
0, |
|
|
|
0, |
|
|
|
0, |
|
|
|
0 |
|
|
|
}; |
|
|
|
|
|
|
|
/* USER CODE END 2 */ |
|
|
|
|
|
|
|
/* Infinite loop */ |
|
|
|
/* USER CODE BEGIN WHILE */ |
|
|
|
|
|
|
|
while (1) |
|
|
|
{ |
|
|
|
setTime(&initialDate); |
|
|
|
setDate(&initialDate); |
|
|
|
leap_year_check(initialDate.year); |
|
|
|
|
|
|
|
//Get Time and Date |
|
|
|
if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
hours = sTime.Hours; |
|
|
|
minutes = sTime.Minutes; |
|
|
|
seconds = sTime.Seconds; |
|
|
|
} |
|
|
|
if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
weekDay = sDate.WeekDay; |
|
|
|
month = sDate.Month; |
|
|
|
date = sDate.Date; |
|
|
|
year = 2000 + sDate.Year; |
|
|
|
} |
|
|
|
|
|
|
|
// check for leap year |
|
|
|
leap_year = leap_year_check(year); |
|
|
|
if (leap_year) |
|
|
|
{ |
|
|
|
//Calculate tomorrow's date |
|
|
|
calc_tomorrows_date(date, weekDay, month, year, DaysInMonthLeapYear, tomorrows_date); |
|
|
|
} else { |
|
|
|
//Calculate tomorrow's date |
|
|
|
calc_tomorrows_date(date, weekDay, month, year, DaysInMonth, tomorrows_date); |
|
|
|
} |
|
|
|
calc_tomorrows_date(&initialDate, &tomorrowsDate); |
|
|
|
|
|
|
|
//Calculate sunrise and sunset time for tomorrow |
|
|
|
calc_sunrise_sunset(tomorrows_date[0], tomorrows_date[2], tomorrows_date[3], sunrise_time, sunset_time); |
|
|
|
calc_sunrise_sunset(&initialDate, &sunrise, &sunset, &tomorrowsDate); |
|
|
|
|
|
|
|
// Enter inner Loop with Alarm at sunrise |
|
|
|
// Loop: Make a step every x minutes (calculated) |
|
|
|
// 1. Calculate and Set Alarm for next step |
|
|
|
// 2. Go to sleep: uC, Motor |
|
|
|
// 3. Alarm: Make Step |
|
|
|
// 4. Go to 1 |
|
|
|
// Exit inner Loop with alarm at sunset |
|
|
|
// Make Calculations for the next day |
|
|
|
// Set alarm for sunrise |
|
|
|
// Go to Sleep |
|
|
|
|
|
|
|
|
|
|
|
set_Alarm(16, 22, 1); |
|
|
|
set_Alarm(16, 18, 4, "A"); |
|
|
|
set_Alarm(16, 20, 4, "B"); |
|
|
|
|
|
|
|
HAL_Delay(5000); |
|
|
|
|
|
|
|
transmit_uart("Ich gehe schlafen!\r\n"); |
|
|
|
transmit_uart("A: Ich gehe schlafen!\r\n"); |
|
|
|
|
|
|
|
// Suspend Tick increment to prevent wake up by Systick interrupt |
|
|
|
HAL_SuspendTick(); |
|
|
@@ -436,7 +489,19 @@ int main(void) |
|
|
|
|
|
|
|
HAL_ResumeTick(); |
|
|
|
|
|
|
|
transmit_uart("Bin wieder wach!\r\n"); |
|
|
|
transmit_uart("A: Bin wieder wach!\r\n"); |
|
|
|
|
|
|
|
transmit_uart("B: Ich gehe schlafen!\r\n"); |
|
|
|
|
|
|
|
// Suspend Tick increment to prevent wake up by Systick interrupt |
|
|
|
HAL_SuspendTick(); |
|
|
|
|
|
|
|
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //Interrupt for wake up |
|
|
|
|
|
|
|
HAL_ResumeTick(); |
|
|
|
|
|
|
|
transmit_uart("B: Bin wieder wach!\r\n"); |
|
|
|
|
|
|
|
} |
|
|
|
/* USER CODE END 3 */ |
|
|
|
} |
|
|
@@ -460,7 +525,8 @@ void SystemClock_Config(void) |
|
|
|
*/ |
|
|
|
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI; |
|
|
|
RCC_OscInitStruct.HSIState = RCC_HSI_ON; |
|
|
|
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; |
|
|
|
//RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; |
|
|
|
RCC_OscInitStruct.HSICalibrationValue = 16; |
|
|
|
RCC_OscInitStruct.LSIState = RCC_LSI_ON; |
|
|
|
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; |
|
|
|
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; |
|
|
@@ -529,7 +595,7 @@ static void MX_RTC_Init(void) |
|
|
|
/** Initialize RTC and set the Time and Date |
|
|
|
*/ |
|
|
|
sTime.Hours = 16; |
|
|
|
sTime.Minutes = 20; |
|
|
|
sTime.Minutes = 16; |
|
|
|
sTime.Seconds = 30; |
|
|
|
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; |
|
|
|
sTime.StoreOperation = RTC_STOREOPERATION_RESET; |
|
|
@@ -537,9 +603,9 @@ static void MX_RTC_Init(void) |
|
|
|
{ |
|
|
|
Error_Handler(); |
|
|
|
} |
|
|
|
sDate.WeekDay = RTC_WEEKDAY_MONDAY; |
|
|
|
sDate.Month = RTC_MONTH_JANUARY; |
|
|
|
sDate.Date = 11; |
|
|
|
sDate.WeekDay = RTC_WEEKDAY_THURSDAY; |
|
|
|
sDate.Month = RTC_MONTH_FEBRUARY; |
|
|
|
sDate.Date = 18; |
|
|
|
sDate.Year = 21; |
|
|
|
|
|
|
|
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) |
|
|
@@ -646,7 +712,13 @@ void Error_Handler(void) |
|
|
|
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) |
|
|
|
{ |
|
|
|
/* Alarm generation */ |
|
|
|
transmit_uart("Alarm!!!!\r\n"); |
|
|
|
transmit_uart("A: Alarm!!!!\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
void HAL_RTC_AlarmBEventCallback(RTC_HandleTypeDef *hrtc) |
|
|
|
{ |
|
|
|
/* Alarm generation */ |
|
|
|
transmit_uart("B: Alarm!!!!\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
|