|
|
@@ -25,6 +25,7 @@ |
|
|
|
#include "math.h" |
|
|
|
#include "stdbool.h" |
|
|
|
#include "string.h" |
|
|
|
#include <stdio.h> |
|
|
|
/* USER CODE END Includes */ |
|
|
|
|
|
|
|
/* Private typedef -----------------------------------------------------------*/ |
|
|
@@ -66,6 +67,11 @@ 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; |
|
|
|
int singleStepsFor180Deg = 100; // The stepper motor needs 200 single steps for 360 deg, equals 100 steps for 180 deg |
|
|
|
int leapsFor180Deg = 5; // Determines how big the amount of single steps is to complete 180 degrees of rotation |
|
|
|
bool alarmSunriseFlag = false; |
|
|
|
bool alarmSunsetFlag = false; |
|
|
|
bool makeStepFlag = false; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
int hours; |
|
|
@@ -77,6 +83,14 @@ typedef struct { |
|
|
|
int year; |
|
|
|
} timeAndDate; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
char *hours; |
|
|
|
char *minutes; |
|
|
|
char *seconds; |
|
|
|
} timeAndDateChar; |
|
|
|
|
|
|
|
timeAndDateChar time; |
|
|
|
|
|
|
|
/* USER CODE END PV */ |
|
|
|
|
|
|
|
/* Private function prototypes -----------------------------------------------*/ |
|
|
@@ -350,7 +364,7 @@ void calc_tomorrows_date(timeAndDate* initialDate, timeAndDate* tomorrowsDate) |
|
|
|
* Function Name : set_Alarm |
|
|
|
* Description : sets the wake up Alarm |
|
|
|
*******************************************************************************/ |
|
|
|
void set_Alarm(int h, int min, int weekDay, char* alarm, RTC_AlarmTypeDef* alarmInstance) |
|
|
|
void set_alarm(int h, int min, int weekDay, char* alarm, RTC_AlarmTypeDef* alarmInstance) |
|
|
|
{ |
|
|
|
/** Enable the Alarm A*/ |
|
|
|
|
|
|
@@ -379,23 +393,44 @@ void set_Alarm(int h, int min, int weekDay, char* alarm, RTC_AlarmTypeDef* alarm |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/*timeAndDateChar get_time(timeAndDateChar *time){ |
|
|
|
|
|
|
|
if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
sprintf(time->hours, "%d", sTime.Hours); |
|
|
|
sprintf(time->minutes, "%d", sTime.Minutes); |
|
|
|
sprintf(time->seconds, "%d", sTime.Seconds); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
*/ |
|
|
|
// sending to UART |
|
|
|
void transmit_uart(char *string){ |
|
|
|
//char divider[] = ":"; |
|
|
|
//get_time(time); |
|
|
|
uint8_t len = strlen(string); |
|
|
|
HAL_UART_Transmit(&huart2, (uint8_t*) string, len, 200); |
|
|
|
} |
|
|
|
|
|
|
|
void setTime(timeAndDate *time){ |
|
|
|
void set_time_and_date(timeAndDate *timeanddate){ |
|
|
|
|
|
|
|
if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
time->hours = sTime.Hours; |
|
|
|
time->minutes = sTime.Minutes; |
|
|
|
time->seconds = sTime.Seconds; |
|
|
|
timeanddate->hours = sTime.Hours; |
|
|
|
timeanddate->minutes = sTime.Minutes; |
|
|
|
timeanddate->seconds = sTime.Seconds; |
|
|
|
} |
|
|
|
|
|
|
|
if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
|
timeanddate->weekDay = sDate.WeekDay; |
|
|
|
timeanddate->month = sDate.Month; |
|
|
|
timeanddate->day = sDate.Date; |
|
|
|
timeanddate->year = 2000 + sDate.Year; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void setDate(timeAndDate *date){ |
|
|
|
/*void setDate(timeAndDate *date){ |
|
|
|
|
|
|
|
if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK) |
|
|
|
{ |
|
|
@@ -404,6 +439,21 @@ void setDate(timeAndDate *date){ |
|
|
|
date->day = sDate.Date; |
|
|
|
date->year = 2000 + sDate.Year; |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
int calc_interval_duration(timeAndDate *sunrise, timeAndDate *sunset){ |
|
|
|
int duration_h=0; |
|
|
|
int duration_m=0; |
|
|
|
|
|
|
|
duration_h = sunset->hours - sunrise->hours; |
|
|
|
duration_m = sunset->minutes - sunrise->minutes; |
|
|
|
|
|
|
|
if (duration_m < 0) { |
|
|
|
duration_h = duration_h - 1; |
|
|
|
duration_m = 60 - sunrise->minutes + sunset->minutes; |
|
|
|
} |
|
|
|
|
|
|
|
return (duration_h * 60 + duration_m) / leapsFor180Deg; |
|
|
|
} |
|
|
|
|
|
|
|
/* USER CODE END 0 */ |
|
|
@@ -444,14 +494,19 @@ int main(void) |
|
|
|
/* Set the L6208 library to use 1 device */ |
|
|
|
BSP_MotorControl_SetNbDevices(BSP_MOTOR_CONTROL_BOARD_ID_L6208, 1); |
|
|
|
BSP_MotorControl_Init(BSP_MOTOR_CONTROL_BOARD_ID_L6208, NULL); |
|
|
|
|
|
|
|
/* Attach the function MyFlagInterruptHandler (defined below) to the flag interrupt */ |
|
|
|
BSP_MotorControl_AttachFlagInterrupt(MyFlagInterruptHandler); |
|
|
|
|
|
|
|
/* Attach the function MyErrorHandler (defined below) to the error Handler*/ |
|
|
|
BSP_MotorControl_AttachErrorHandler(Error_Handler); |
|
|
|
|
|
|
|
/* Set Systick Interrupt priority highest to ensure no lock by using HAL_Delay */ |
|
|
|
HAL_NVIC_SetPriority(SysTick_IRQn, 0x0, 0x0); |
|
|
|
|
|
|
|
/* Configure KEY Button */ |
|
|
|
BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI); |
|
|
|
|
|
|
|
/* Disable the power bridges after initialization */ |
|
|
|
BSP_MotorControl_CmdDisable(0); |
|
|
|
|
|
|
@@ -466,8 +521,13 @@ int main(void) |
|
|
|
0 |
|
|
|
}; |
|
|
|
|
|
|
|
int32_t pos; |
|
|
|
uint32_t freqPwm, timeToNextStep; |
|
|
|
int32_t pos=0; |
|
|
|
uint32_t freqPwm=0; |
|
|
|
uint32_t timeToNextStep_m=0; |
|
|
|
uint32_t alarmB_h = 0; |
|
|
|
uint32_t alarmB_m = 0; |
|
|
|
uint32_t alarmB_wd = 0; |
|
|
|
uint32_t stepsToMake = singleStepsFor180Deg / leapsFor180Deg; // The amount of single steps to make to complete 180/5 degrees |
|
|
|
|
|
|
|
/* USER CODE END 2 */ |
|
|
|
|
|
|
@@ -475,76 +535,129 @@ int main(void) |
|
|
|
/* USER CODE BEGIN WHILE */ |
|
|
|
while (1) |
|
|
|
{ |
|
|
|
HAL_Delay(2000); |
|
|
|
freqPwm = BSP_MotorControl_GetBridgeInputPwmFreq(0); |
|
|
|
BSP_MotorControl_SetBridgeInputPwmFreq(0, freqPwm>>1); |
|
|
|
|
|
|
|
pos = BSP_MotorControl_GetPosition(0); |
|
|
|
HAL_Delay(2000); |
|
|
|
|
|
|
|
transmit_uart("Resetting motor position and calculating new dates and times.\r\n"); |
|
|
|
|
|
|
|
freqPwm = BSP_MotorControl_GetBridgeInputPwmFreq(0); |
|
|
|
|
|
|
|
BSP_MotorControl_SetHome(0, pos); |
|
|
|
BSP_MotorControl_SetBridgeInputPwmFreq(0, freqPwm>>1); |
|
|
|
|
|
|
|
BSP_MotorControl_SelectStepMode(0, STEP_MODE_FULL); |
|
|
|
pos = BSP_MotorControl_GetPosition(0); |
|
|
|
|
|
|
|
BSP_MotorControl_Move(0, FORWARD, 25); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
BSP_MotorControl_SetHome(0, pos); |
|
|
|
|
|
|
|
BSP_MotorControl_Move(0, FORWARD, 25); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
BSP_MotorControl_SelectStepMode(0, STEP_MODE_FULL); |
|
|
|
|
|
|
|
BSP_MotorControl_Move(0, FORWARD, 25); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
BSP_MotorControl_Move(0, FORWARD, stepsToMake); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
|
|
|
|
/* USER CODE END WHILE */ |
|
|
|
BSP_MotorControl_Move(0, FORWARD, stepsToMake); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
|
|
|
|
/* USER CODE BEGIN 3 */ |
|
|
|
setTime(&initialDate); |
|
|
|
setDate(&initialDate); |
|
|
|
leap_year_check(initialDate.year); |
|
|
|
BSP_MotorControl_Move(0, FORWARD, stepsToMake); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
|
|
|
|
calc_tomorrows_date(&initialDate, &tomorrowsDate); |
|
|
|
BSP_MotorControl_GoHome(0); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
|
|
|
|
//Calculate sunrise and sunset time for tomorrow |
|
|
|
calc_sunrise_sunset(&initialDate, &sunrise, &sunset, &tomorrowsDate); |
|
|
|
/* USER CODE END WHILE */ |
|
|
|
|
|
|
|
// 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 |
|
|
|
/* USER CODE BEGIN 3 */ |
|
|
|
set_time_and_date(&initialDate); |
|
|
|
|
|
|
|
leap_year_check(initialDate.year); |
|
|
|
|
|
|
|
set_Alarm(16, 18, 4, "A", &sAlarmA); |
|
|
|
set_Alarm(16, 20, 4, "B", &sAlarmB); |
|
|
|
calc_tomorrows_date(&initialDate, &tomorrowsDate); |
|
|
|
|
|
|
|
HAL_Delay(5000); |
|
|
|
//Calculate sunrise and sunset time for tomorrow |
|
|
|
calc_sunrise_sunset(&initialDate, &sunrise, &sunset, &tomorrowsDate); |
|
|
|
|
|
|
|
transmit_uart("A: Ich gehe schlafen!\r\n"); |
|
|
|
//Test code |
|
|
|
sunrise.hours = 14; |
|
|
|
sunrise.minutes = 0; |
|
|
|
sunrise.weekDay = 7; |
|
|
|
|
|
|
|
// Suspend Tick increment to prevent wake up by Systick interrupt |
|
|
|
HAL_SuspendTick(); |
|
|
|
sunset.hours = 14; |
|
|
|
sunset.minutes = 30; |
|
|
|
sunset.weekDay = 7; |
|
|
|
|
|
|
|
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //Interrupt for wake up |
|
|
|
//Calculate the time for next motor step in minutes |
|
|
|
timeToNextStep_m = calc_interval_duration(&sunrise, &sunset); |
|
|
|
|
|
|
|
HAL_ResumeTick(); |
|
|
|
// Set Alarm for sunrise |
|
|
|
|
|
|
|
transmit_uart("A: Bin wieder wach!\r\n"); |
|
|
|
transmit_uart("Setting alarm for sunrise.\r\n"); |
|
|
|
set_alarm(sunrise.hours, sunrise.minutes, sunrise.weekDay, "A", &sAlarmA); |
|
|
|
|
|
|
|
transmit_uart("B: Ich gehe schlafen!\r\n"); |
|
|
|
HAL_Delay(2000); |
|
|
|
|
|
|
|
// Suspend Tick increment to prevent wake up by Systick interrupt |
|
|
|
HAL_SuspendTick(); |
|
|
|
transmit_uart("Entering sleep mode.\r\n"); |
|
|
|
HAL_SuspendTick(); |
|
|
|
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); |
|
|
|
HAL_ResumeTick(); |
|
|
|
|
|
|
|
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //Interrupt for wake up |
|
|
|
if (alarmSunriseFlag == true) { |
|
|
|
|
|
|
|
HAL_ResumeTick(); |
|
|
|
transmit_uart("Sunrise statement entered.\r\n"); |
|
|
|
// Reset the flags |
|
|
|
alarmSunsetFlag = false; |
|
|
|
alarmSunriseFlag = false; |
|
|
|
|
|
|
|
transmit_uart("B: Bin wieder wach!\r\n"); |
|
|
|
// The alarm for the next step is incremented from sunrise as the initial time. |
|
|
|
alarmB_h = sunrise.hours; |
|
|
|
alarmB_m = sunrise.minutes; |
|
|
|
alarmB_wd = sunrise.weekDay; |
|
|
|
|
|
|
|
// Set Alarm for sunset, it overwrites the alarm for sunrise because the sunrise already happenend |
|
|
|
// The timeframes for both alarms dont overlap so 1 alarm is enough |
|
|
|
transmit_uart("Setting alarm for sunset.\r\n"); |
|
|
|
set_alarm(sunset.hours, sunset.minutes, sunset.weekDay, "A", &sAlarmA); |
|
|
|
|
|
|
|
HAL_Delay(2000); |
|
|
|
|
|
|
|
while (alarmSunsetFlag != true) { |
|
|
|
|
|
|
|
transmit_uart("|--------------------------------------------------------|\r\n\r\n"); |
|
|
|
// Increment alarm time with the precalculated timeToNextStep |
|
|
|
int minAdd_tmp=0; |
|
|
|
|
|
|
|
minAdd_tmp = alarmB_m + timeToNextStep_m; |
|
|
|
|
|
|
|
// Consider minutes overflow ^= hours + 1 |
|
|
|
if (minAdd_tmp > 60) { |
|
|
|
alarmB_h = alarmB_h + 1; |
|
|
|
alarmB_m = minAdd_tmp - 60; |
|
|
|
} else { |
|
|
|
alarmB_m = minAdd_tmp; |
|
|
|
} |
|
|
|
|
|
|
|
transmit_uart("Setting alarm for next step.\r\n"); |
|
|
|
set_alarm(alarmB_h, alarmB_m, alarmB_wd, "B", &sAlarmB); |
|
|
|
|
|
|
|
HAL_Delay(2000); |
|
|
|
|
|
|
|
transmit_uart("Entering sleep mode.\r\n"); |
|
|
|
HAL_SuspendTick(); |
|
|
|
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); |
|
|
|
HAL_ResumeTick(); |
|
|
|
|
|
|
|
if (makeStepFlag) { |
|
|
|
transmit_uart("Making a step.\r\n"); |
|
|
|
BSP_MotorControl_Move(0, FORWARD, stepsToMake); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
} |
|
|
|
|
|
|
|
makeStepFlag = true; |
|
|
|
|
|
|
|
transmit_uart("\r\n"); |
|
|
|
|
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
BSP_MotorControl_GoHome(0); |
|
|
|
BSP_MotorControl_WaitWhileActive(0); |
|
|
|
} |
|
|
|
/* USER CODE END 3 */ |
|
|
|
} |
|
|
@@ -641,55 +754,24 @@ static void MX_RTC_Init(void) |
|
|
|
|
|
|
|
/** Initialize RTC and set the Time and Date |
|
|
|
*/ |
|
|
|
sTime.Hours = 16; |
|
|
|
sTime.Minutes = 16; |
|
|
|
sTime.Seconds = 30; |
|
|
|
sTime.Hours = 13; |
|
|
|
sTime.Minutes = 56; |
|
|
|
sTime.Seconds = 10; |
|
|
|
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; |
|
|
|
sTime.StoreOperation = RTC_STOREOPERATION_RESET; |
|
|
|
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) |
|
|
|
{ |
|
|
|
Error_Handler(); |
|
|
|
} |
|
|
|
sDate.WeekDay = RTC_WEEKDAY_THURSDAY; |
|
|
|
sDate.WeekDay = RTC_WEEKDAY_SUNDAY; |
|
|
|
sDate.Month = RTC_MONTH_FEBRUARY; |
|
|
|
sDate.Date = 18; |
|
|
|
sDate.Date = 21; |
|
|
|
sDate.Year = 21; |
|
|
|
|
|
|
|
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) |
|
|
|
{ |
|
|
|
Error_Handler(); |
|
|
|
} |
|
|
|
/** Enable the Alarm A |
|
|
|
*/ |
|
|
|
/** |
|
|
|
sAlarm.AlarmTime.Hours = 0; |
|
|
|
sAlarm.AlarmTime.Minutes = 0; |
|
|
|
sAlarm.AlarmTime.Seconds = 0; |
|
|
|
sAlarm.AlarmTime.SubSeconds = 0; |
|
|
|
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; |
|
|
|
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET; |
|
|
|
sAlarm.AlarmMask = RTC_ALARMMASK_NONE; |
|
|
|
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; |
|
|
|
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; |
|
|
|
sAlarm.AlarmDateWeekDay = 1; |
|
|
|
sAlarm.Alarm = RTC_ALARM_A; |
|
|
|
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK) |
|
|
|
{ |
|
|
|
Error_Handler(); |
|
|
|
} |
|
|
|
/** Enable the Alarm B |
|
|
|
*/ |
|
|
|
/* |
|
|
|
sAlarm.AlarmDateWeekDay = 1; |
|
|
|
sAlarm.Alarm = RTC_ALARM_B; |
|
|
|
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK) |
|
|
|
{ |
|
|
|
Error_Handler(); |
|
|
|
} |
|
|
|
/* USER CODE BEGIN RTC_Init 2 */ |
|
|
|
|
|
|
|
/* USER CODE END RTC_Init 2 */ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@@ -767,13 +849,18 @@ static void MX_GPIO_Init(void) |
|
|
|
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) |
|
|
|
{ |
|
|
|
/* Alarm generation */ |
|
|
|
transmit_uart("A: Alarm!!!!\r\n"); |
|
|
|
alarmSunriseFlag = true; |
|
|
|
alarmSunsetFlag = true; |
|
|
|
transmit_uart("Alarm A Callback triggered.\r\n"); |
|
|
|
transmit_uart("Setting sunrise and sunset flags.\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc) |
|
|
|
{ |
|
|
|
/* Alarm generation */ |
|
|
|
transmit_uart("B: Alarm!!!!\r\n"); |
|
|
|
makeStepFlag = true; |
|
|
|
transmit_uart("Alarm B Callback triggered.\r\n"); |
|
|
|
transmit_uart("Setting makeStep flag.\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
/** |