TheThingsIndustries / generic-node-se

Generic Node Sensor Edition
https://www.genericnode.com
Other
108 stars 31 forks source link

Buzzer only works during HAL_Delay function #167

Closed mcserved closed 3 years ago

mcserved commented 3 years ago

Summary:

The buzzer seems to only work in certain circumstances. The basic app seems to work fine, with the buzzer playing at the end. However, when integrating it into another application, it seems to be more difficult. It will not produce sounds at all if HAL_Delay is not initiated. The sounds seem to start when HAL_Delay is running and will stop after HAL_Delay is fixed.

Steps to Reproduce:

Add this to stm32wlxx_it.c void TIM2_IRQHandler(void) { HAL_TIM_IRQHandler(&GNSE_BSP_buzzer_timer); }

Then to reproduce the issue:

  1. Call BUZZER_Init and BUZZER_SetState at the start of the program
  2. Do not call HAL_Delay afterwards
  3. See if the buzzer can be heard

To ring the buzzer:

  1. Call BUZZER_Init and BUZZER_SetState at the start of the program
  2. Call HAL_Delay, can be anywhere in the program and on multiple occasions
  3. The buzzer will beep for the duration of the delay, but stops (without calling BUZZER_SetState with BUZZER_STATE_OFF)

What do you see now?

This snippet BUZZER_Init(); BUZZER_SetState(BUZZER_STATE_RING); HAL_Delay(1000);

Produces this power graph image It seems to only work whilst HAL_Delay is initiated, it should still ring but it just stops after HAL_Delay. Also, the power consumption afterwards is noticeably higher while the buzzer is off (15 mA). Without this delay, the buzzer will not do anything at all.

Not handling the interrupt by not setting TIM2_IRQHandler also makes the buzzer work (but this disables most other functionalities). So it seems that not handling the interrupts will make the buzzer work as expected

What do you want to see instead?

A buzzer that can make sounds whilst the program is running normally.

How do you propose to implement this?

Improve the interrupt handling of the buzzer.

Environment:

Bare metal

What can you do yourself and what do you need help with?

All

elsalahy commented 3 years ago

I think this can be fixed by doing a minor adjustment of the interrupt priority as it seems the system is starved by the RTC

elsalahy commented 3 years ago

Adjusting this config flag might fix this issue

mcserved commented 3 years ago

Small update: The interrupt priority does not fix the issue. This bug seems to be related to the LoRa library, the delay only halted LoRa code to be initiated for some time. There was only one instance where I got it working after LoRa was activated, but it required for the interrupt handler for timer 2 to not be defined (causing the code to break and loop in the interrupt handler). Basic app seems to work fine if the buzzer is kept on during its while loop.

mcserved commented 3 years ago

Extra update: I did get the buzzer to work when simply toggling the pin with the sequencer, so the issue seems to be related to the PWM timer during a LoRa message.

azerimaker commented 3 years ago

@marnixcro with the PWM timer, please make sure the GPIO line stays LOW before and after each PWM burst, otherwise the driver transistor (Q2) will stay ON and there will be quite significant leakage through the buzzer.

buzzer

mcserved commented 3 years ago

Update: Can't believe I didn't think of this sooner, but the problem lies with the low power mode. This peripheral turns of the timer used in the PWM mode, HAL_Delay only delayed this timer. Apparently the low power mode kicks in just before the transmission but almost immediately wakes up to connect to the LoRAWAN, so that's why it turns off before the sending. It also explains why I could toggle it manually as the mode does allow for the pin state to be kept. I hoped setting LOW_POWER_DISABLE would be enough but sadly it doesn't.

Here an image for reference of the stop mode capabilities (default used is stop mode) image

TIM2 can't be remapped to LSI, only LSE, which I believe doesn't work for us since we did not connect any external oscillator. TIM16, which also has PWM generation does have the option to be sourced from LSI, but it's used for MISO (and would require hardware edits of course). image

Maybe a discussion point is needed as there are quite a few ways to handle this. I could to one of these things:

  1. Try different sleep modes and see if the PWM does work in another one.
  2. Use a simple manual configuration for the buzzer (setting tasks to turn it on and off), without using the buzzer library.
  3. Don't use the buzzer at all.
  4. Temporarily turn off sleep mode during the buzzer beeping (it was consuming a lot of power anyways) and turning it on afterwards.
  5. Try to create buzzer options where LSI is used (would require an interrupt handler as the PWM generation only specific timers).
elsalahy commented 3 years ago

@marnixcro what do you mean by

I hoped setting LOW_POWER_DISABLE would be enough but sadly it doesn't.

Please explain it clearly, does LOW_POWER_DISABLE config flag not function as expected?

mcserved commented 3 years ago

@marnixcro what do you mean by

I hoped setting LOW_POWER_DISABLE would be enough but sadly it doesn't.

Please explain it clearly, does LOW_POWER_DISABLE config flag not function as expected?

It probably went into another mode, but the PWM didn't work in sleep mode either I believe. It was one test, I'll try again and see if I can make it work.

elsalahy commented 3 years ago

@marnixcro Please trace what the flag does before coming to a conclusion and raising a discussion. I assumed you are aware of the fact that freefall app (developed by you) doesn't support low power mode yet.

elsalahy commented 3 years ago

You can invoke UTIL_LPM_GetMode and you will observe active mode. Check UTIL_LPM_EnterLowPower and you will see that the node defaults to a sleep mode if stop and off mode are disabled.

mcserved commented 3 years ago

Tested free fall app again with the flag set to one and the buzzer seemed to work (accidentally changed the wrong app_config before). Here is an overview of the different power consumptions. image

About UTIL_LPM_GetMode, i tested with the normal configurations and got this: image Placed it at the very end of SystemApp_Init image 1 is UTIL_LPM_STOPMODE. When setting LOW_POWER_DISABLE=1 then this happened: image 0 is UTIL_LPM_SLEEPMODE

elsalahy commented 3 years ago

@marnixcro what is the current state on this?

elsalahy commented 3 years ago

If this issue doesn't describe the main problem, it should be closed to avoid confusing GN users. We have multiple sleep related issues that are WIP.

mcserved commented 3 years ago

@elsalahy The issue indeed does not describe the actual issue properly anymore. I believe that my tests show that the buzzer will not work due to the low power mode being enabled, which is probably caused by it disabling the timer. The buzzer will probably never work in this mode which is fine since the buzzer working in low power mode would be pointless as its by far the largest consumer so having the chip in active mode wouldn't change that much.

That's not really the issue at hand, which is: how can we properly handle the buzzer sending periodic beeps? Which is probably just setting a sequencer that can be enabled to periodically make buzzer sounds and return to low power mode. It failed to produce sounds when I tried this before, but I believe this is caused by it immediately turning the low power mode on (so I have to find a way to postpone this during beeping). I'll close the issue to avoid confusion.

elsalahy commented 3 years ago

@marnixcro this code shows how we disable stop mode when wanting to perform a specific functionality