diff --git a/RTC/Core/Src/main.c b/RTC/Core/Src/main.c index c13ba53..c24c2e1 100644 --- a/RTC/Core/Src/main.c +++ b/RTC/Core/Src/main.c @@ -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; } - return false; + else + { + leapYear = 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); - set_Alarm(16, 22, 1); + // 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, 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"); } diff --git a/RTC/RTC.ioc b/RTC/RTC.ioc index ec5f3a4..a6039e9 100644 --- a/RTC/RTC.ioc +++ b/RTC/RTC.ioc @@ -175,4 +175,4 @@ VP_SYS_VS_Systick.Mode=SysTick VP_SYS_VS_Systick.Signal=SYS_VS_Systick board=NUCLEO-F401RE boardIOC=true -isbadioc=false +isbadioc=true