Closed CandraSN closed 3 years ago
Thank you for you contribution.
Please allow me to introduce @YoannBo who will comment your post and provide you with more details about this topic.
With regards,
Hello,
When the system has nothing to do, the system calls the idle task: UTIL_SEQ_Idle is located into sys_app.c.
In the CubeWL package, the UTIL_SEQ_Idle
calls directly UTIL_LPM_EnterLowPower
Functions in PWR_EnterStopMode
, PWR_ExitStopMode
and equivalent SleepMode (PWR_EnterSleepMode
, PWR_ExitSleepMode
) are defined in stm32_lpm_if.c
. They can be re-written depending on the application.
Now in our system, this is already managed. If you want to periodically wake-up, you can create a timer, for instance toggling a LED
/**
* @brief User timer callback function
* @param context
* @retval none
*/
static void OnUserTimerEvent(void *context);
/**
* @brief Timer to handle the application Join Led to toggle
*/
static UTIL_TIMER_Object_t UserTimer;
void yourFunction(void)
{
/*Create a UserTimer toggling every 5 seconds*/
UTIL_TIMER_Create(&UserTimer, 5000, UTIL_TIMER_PERIODIC, OnUserTimerEvent, NULL);
/* Starts UserTimer*/
UTIL_TIMER_Start(&UserTimer);
}
/* OnUserTimerEvent */
static void OnUserTimerEvent(void *context)
{
BSP_LED_Toggle(LED_RED) ;
}
Please be aware, that you should not call APP_PRINTF before entering to stop mode. Indeed, any time everything is printed out, it will wake up the system. and enter sleep/stop again. This will generate an infinite loop.
Best Regards
Hi @YoannBo
Thank you very much for this helpful instruction
Maybe, I want to tell in detail about the system work flow that I want is like this, when the node is turned on, it will join to the gateway/server the first time. After that, it will send the data frame 1 time. After sending the data frame, the node will enter stop 2 mode (Radio sleep too) for 30 minutes (can change) and then the system wake up (Radio standby too) via the RTC or get a trigger from the push button.
I'm little confused about where I can put the stop 2 mode function after node sends data frame to the gateway and then wake up ? Should I put my custom sleep system in the sequencer task ?
note: join -> send data frame -> sleep -> wake-up -> send data frame -> infinite loop until the system reset
Best Regards
Hello @CandraSN ,
from what I read, this is already done in the LoRaWAN_End_Node project :
Join -> send data frame -> stop2-> wake-up -> send data frame -> stop2
by default, the LoRaWAN_End_Node project sends a Tx frame every 10 seconds (when Duty Cycle allows)
Duty cycles can be updated in lora_app.h
#define APP_TX_DUTYCYCLE 10000
Also, by default, a timer triggers the send_request. But it can also be triggered by nucleo button sw1 by change line 195 in lora_app.c from
/ send will be done if on timer/
static TxEventType_t EventType = TX_ON_TIMER;
to
/ send will be done if you push sw1 /
static TxEventType_t EventType = TX_ON_EVENT;
let me know
additionnal note:
The RTC is used (in binary mode new!) directly by the timer (stm32_timer.c) and used by the stack I would advise not to override it.
Hi @YoannBo
After I follow your instructions and did some little experiments, I understand how to modify the code based on my system. Thank you very much, your informations are very clear.
Best Regards
btw, sorry out of topic how can I print float/double data with APP_PRINTF ?
Hi @CandraSN
in file _utilitiesconf.h line
#define UTIL_ADV_TRACE_VSNPRINTF(...) tiny_vsnprintf_like(__VA_ARGS__)
Can you change tiny_vsnprintf_like
to vsnprintf
(bigger in size) from stdio.h ?
I believe it should be ok,
Best Regards
Hi @YoannBo Yes, problem solved using sprintf and transmit to serial with APP_PRINTF
Thank you
Hi,
@YoannBo Thank you for these clarifications.
@CandraSN Since the issue is answered and the problem is solved, please allow me to close this thread. Thank you once more for your contribution.
With regards,
Hi @YoannBo
Can we change " static TxEventType_t EventType = TX_ON_TIMER; " Line dynamically inside the code based on condition?
I want to make Node in sleep mode with respect to some condition and wakeup by external interrupt on GPIO Pin.
Flow : Join -> send data frame -> stop2-> wake-up -> send data frame -> backup mode condition trigger -> Set TX_ON_Event -> Wakeup on intruppt -> Set TX_ON_TIMER -> send data frame -> stop2
thanks to this info. i can use in on st lorawan SDK
Hello,
Thanks to friends for sharing the information about the LoRaWAN_End_Node code. I am also using it to develop a project here at the company. I would like to ask some questions please... 1st Question: I am using this example to wake up the module in loop mode. I would like to exit the loop module by pressing a button and keep the module constantly awake. Could you help me with an example, please. 2nd Question: Being in loop mode, I would like to transmit (uplink) data to the network server each time the module wakes up. Could you also help me with an example, please.
Thank you!
Tiago, your problem now is that 40uA consumption, right ?
Yes. In addition to these 2 questions above, I also have this problem with consumption remaining around 40uA.
Hello @TiagoFernandes271089 and @tcpipchip , i have the same issue with stop2mode and consumption at around 40uA.
Did you manage to solve the current consumption problem?
My application is based on a Lora-E5 and i have verified with the factory firmware that it can run on approx. 3uA(@3.6V). When using following code below i reach a 40uA(@3.6V) current consumption.
#include "main.h"
#include "stm32wlxx_hal_pwr_ex.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_All;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOH_CLK_DISABLE();
}
Hello @e3dz ,
I managed to resolve it here. In my case, whenever I pressed the button (PA12), the module woke up and never returned to sleep mode (+/-5uA). I was calling the "void EXTI1_IRQHandler(void)" interrupt function. I modified my function to "void EXTI15_10_IRQHandler(void)"
/ EXTI interrupt initialization / HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI1_IRQn); HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
Also check if any portal is not connected in sleep mode. In my case, I had to call the function to disable UART2: HAL_UART_DeInit(&huart2);
Thiago solved...i will ask him to see your question....
haha...the answered when i was typing :)
@TiagoFernandes271089 Thanks for the quick answer!
I am trying that but can't get it to work, would you mind sharing the example that works for you?
Hello,
Follows as requested:
/ Private includes ----------------------------------------------------------/ / USER CODE BEGIN Includes / static void OnUserTimerEvent(void *context); static UTIL_TIMER_Object_t UserTimer;
/ USER CODE END Includes / extern void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
extern UART_HandleTypeDef huart2;
void SystemClock_Config(void);
int main(void) { / Reset of all peripherals, Initializes the Flash interface and the Systick. / HAL_Init(); / Configure the system clock / SystemClock_Config(); / Initialize all configured peripherals / //MX_LoRaWAN_Init(); SystemApp_Init(); //Tiago: Aqui inicia o Hall MX_GPIO_Init(); MX_I2C1_Init(); MX_TIM16_Init(); HAL_TIM_Base_Start_IT(&htim16);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_UART_DeInit(&huart2);
while (1)
{
MX_LoRaWAN_Process();
}
}
void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;//RCC_MSIRANGE_8
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
// RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV10;//DIV10 = 4,8MHz
//RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim16) { //HAL_GPIO_TogglePin(DEF_LED_BLUE_GPIO_Port, DEF_LED_BLUE); if(St_Timer.t_200ms)St_Timer.t_200ms--; if(St_Timer.t_1s)St_Timer.t_1s--; if(St_Timer.t_3s)St_Timer.t_3s--; if(St_Timer.t_5s)St_Timer.t_5s--; if(St_Timer.t_6s)St_Timer.t_6s--; if(St_Timer.t_10s)St_Timer.t_10s--; if(St_Timer.t_out)St_Timer.t_out--;
}
}
/ USER CODE END 4 /
/**
/**
Hi, I am a bit confused on the lora STM32WL sequence protocol system, I want my device to sleep and wakeup according to the periodic values I want. I have made my own sleep function (stop 2 mode & radio sleep) with wake up triggered using RTC (in seconds) and push button. Where can I put my function (PLB_SleepMode) into the sequencer utility lora end node STM32WL ?
Thank you
Here my code for custom sleep and wake up system: