Added main loop with stepper functionality

Added working alarms
Code currently working with modified sunrise, sunset and steps for debugging purposes
This commit is contained in:
Gregor Wüst 2021-02-21 16:31:17 +01:00
parent c3e9aea1b9
commit 367c294f1c

View File

@ -25,6 +25,7 @@
#include "math.h" #include "math.h"
#include "stdbool.h" #include "stdbool.h"
#include "string.h" #include "string.h"
#include <stdio.h>
/* USER CODE END Includes */ /* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/ /* 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 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}; int DaysInMonthLeapYear[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool leapYear = false; 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 { typedef struct {
int hours; int hours;
@ -77,6 +83,14 @@ typedef struct {
int year; int year;
} timeAndDate; } timeAndDate;
typedef struct {
char *hours;
char *minutes;
char *seconds;
} timeAndDateChar;
timeAndDateChar time;
/* USER CODE END PV */ /* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
@ -350,7 +364,7 @@ void calc_tomorrows_date(timeAndDate* initialDate, timeAndDate* tomorrowsDate)
* Function Name : set_Alarm * Function Name : set_Alarm
* Description : sets the wake up 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*/ /** 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 // sending to UART
void transmit_uart(char *string){ void transmit_uart(char *string){
//char divider[] = ":";
//get_time(time);
uint8_t len = strlen(string); uint8_t len = strlen(string);
HAL_UART_Transmit(&huart2, (uint8_t*) string, len, 200); 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) if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK)
{ {
time->hours = sTime.Hours; timeanddate->hours = sTime.Hours;
time->minutes = sTime.Minutes; timeanddate->minutes = sTime.Minutes;
time->seconds = sTime.Seconds; 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) if (HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN) == HAL_OK)
{ {
@ -404,6 +439,21 @@ void setDate(timeAndDate *date){
date->day = sDate.Date; date->day = sDate.Date;
date->year = 2000 + sDate.Year; 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 */ /* USER CODE END 0 */
@ -444,14 +494,19 @@ int main(void)
/* Set the L6208 library to use 1 device */ /* Set the L6208 library to use 1 device */
BSP_MotorControl_SetNbDevices(BSP_MOTOR_CONTROL_BOARD_ID_L6208, 1); BSP_MotorControl_SetNbDevices(BSP_MOTOR_CONTROL_BOARD_ID_L6208, 1);
BSP_MotorControl_Init(BSP_MOTOR_CONTROL_BOARD_ID_L6208, NULL); BSP_MotorControl_Init(BSP_MOTOR_CONTROL_BOARD_ID_L6208, NULL);
/* Attach the function MyFlagInterruptHandler (defined below) to the flag interrupt */ /* Attach the function MyFlagInterruptHandler (defined below) to the flag interrupt */
BSP_MotorControl_AttachFlagInterrupt(MyFlagInterruptHandler); BSP_MotorControl_AttachFlagInterrupt(MyFlagInterruptHandler);
/* Attach the function MyErrorHandler (defined below) to the error Handler*/ /* Attach the function MyErrorHandler (defined below) to the error Handler*/
BSP_MotorControl_AttachErrorHandler(Error_Handler); BSP_MotorControl_AttachErrorHandler(Error_Handler);
/* Set Systick Interrupt priority highest to ensure no lock by using HAL_Delay */ /* Set Systick Interrupt priority highest to ensure no lock by using HAL_Delay */
HAL_NVIC_SetPriority(SysTick_IRQn, 0x0, 0x0); HAL_NVIC_SetPriority(SysTick_IRQn, 0x0, 0x0);
/* Configure KEY Button */ /* Configure KEY Button */
BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI); BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI);
/* Disable the power bridges after initialization */ /* Disable the power bridges after initialization */
BSP_MotorControl_CmdDisable(0); BSP_MotorControl_CmdDisable(0);
@ -466,8 +521,13 @@ int main(void)
0 0
}; };
int32_t pos; int32_t pos=0;
uint32_t freqPwm, timeToNextStep; 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 */ /* USER CODE END 2 */
@ -475,76 +535,129 @@ int main(void)
/* USER CODE BEGIN WHILE */ /* USER CODE BEGIN WHILE */
while (1) while (1)
{ {
HAL_Delay(2000);
freqPwm = BSP_MotorControl_GetBridgeInputPwmFreq(0);
BSP_MotorControl_SetBridgeInputPwmFreq(0, freqPwm>>1);
pos = BSP_MotorControl_GetPosition(0); HAL_Delay(2000);
BSP_MotorControl_SetHome(0, pos); transmit_uart("Resetting motor position and calculating new dates and times.\r\n");
BSP_MotorControl_SelectStepMode(0, STEP_MODE_FULL); freqPwm = BSP_MotorControl_GetBridgeInputPwmFreq(0);
BSP_MotorControl_Move(0, FORWARD, 25); BSP_MotorControl_SetBridgeInputPwmFreq(0, freqPwm>>1);
BSP_MotorControl_WaitWhileActive(0);
BSP_MotorControl_Move(0, FORWARD, 25); pos = BSP_MotorControl_GetPosition(0);
BSP_MotorControl_WaitWhileActive(0);
BSP_MotorControl_Move(0, FORWARD, 25); BSP_MotorControl_SetHome(0, pos);
BSP_MotorControl_WaitWhileActive(0);
/* USER CODE END WHILE */ BSP_MotorControl_SelectStepMode(0, STEP_MODE_FULL);
/* USER CODE BEGIN 3 */ BSP_MotorControl_Move(0, FORWARD, stepsToMake);
setTime(&initialDate); BSP_MotorControl_WaitWhileActive(0);
setDate(&initialDate);
leap_year_check(initialDate.year);
calc_tomorrows_date(&initialDate, &tomorrowsDate); BSP_MotorControl_Move(0, FORWARD, stepsToMake);
BSP_MotorControl_WaitWhileActive(0);
//Calculate sunrise and sunset time for tomorrow BSP_MotorControl_Move(0, FORWARD, stepsToMake);
calc_sunrise_sunset(&initialDate, &sunrise, &sunset, &tomorrowsDate); BSP_MotorControl_WaitWhileActive(0);
// Enter inner Loop with Alarm at sunrise BSP_MotorControl_GoHome(0);
// Loop: Make a step every x minutes (calculated) BSP_MotorControl_WaitWhileActive(0);
// 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 END WHILE */
set_Alarm(16, 18, 4, "A", &sAlarmA); /* USER CODE BEGIN 3 */
set_Alarm(16, 20, 4, "B", &sAlarmB); set_time_and_date(&initialDate);
HAL_Delay(5000); leap_year_check(initialDate.year);
transmit_uart("A: Ich gehe schlafen!\r\n"); calc_tomorrows_date(&initialDate, &tomorrowsDate);
// Suspend Tick increment to prevent wake up by Systick interrupt //Calculate sunrise and sunset time for tomorrow
HAL_SuspendTick(); calc_sunrise_sunset(&initialDate, &sunrise, &sunset, &tomorrowsDate);
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //Interrupt for wake up //Test code
sunrise.hours = 14;
sunrise.minutes = 0;
sunrise.weekDay = 7;
HAL_ResumeTick(); sunset.hours = 14;
sunset.minutes = 30;
sunset.weekDay = 7;
transmit_uart("A: Bin wieder wach!\r\n"); //Calculate the time for next motor step in minutes
timeToNextStep_m = calc_interval_duration(&sunrise, &sunset);
transmit_uart("B: Ich gehe schlafen!\r\n"); // Set Alarm for sunrise
// Suspend Tick increment to prevent wake up by Systick interrupt transmit_uart("Setting alarm for sunrise.\r\n");
HAL_SuspendTick(); set_alarm(sunrise.hours, sunrise.minutes, sunrise.weekDay, "A", &sAlarmA);
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //Interrupt for wake up HAL_Delay(2000);
HAL_ResumeTick(); transmit_uart("Entering sleep mode.\r\n");
HAL_SuspendTick();
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
HAL_ResumeTick();
transmit_uart("B: Bin wieder wach!\r\n"); if (alarmSunriseFlag == true) {
transmit_uart("Sunrise statement entered.\r\n");
// Reset the flags
alarmSunsetFlag = false;
alarmSunriseFlag = false;
// 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 */ /* USER CODE END 3 */
} }
@ -641,55 +754,24 @@ static void MX_RTC_Init(void)
/** Initialize RTC and set the Time and Date /** Initialize RTC and set the Time and Date
*/ */
sTime.Hours = 16; sTime.Hours = 13;
sTime.Minutes = 16; sTime.Minutes = 56;
sTime.Seconds = 30; sTime.Seconds = 10;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET; sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{ {
Error_Handler(); Error_Handler();
} }
sDate.WeekDay = RTC_WEEKDAY_THURSDAY; sDate.WeekDay = RTC_WEEKDAY_SUNDAY;
sDate.Month = RTC_MONTH_FEBRUARY; sDate.Month = RTC_MONTH_FEBRUARY;
sDate.Date = 18; sDate.Date = 21;
sDate.Year = 21; sDate.Year = 21;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{ {
Error_Handler(); 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) void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{ {
/* Alarm generation */ /* 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) void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{ {
/* Alarm generation */ /* 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");
} }
/** /**