Analog Write issue

Hi everyone,

I’m trying to implement a simple LED state using analog write in a LoraWAN context, so I’m using system timer and create a main routine. The default void loop() is disabled in this case. The analog write is triggered periodically from the main routine but once is executed the LED become off.
Pin that i’m using is PA_15

The relevant code looks like:


#define ONBOARD_LED PA_15
....

void main_routine();

void setup() { 
......
  pinMode(ONBOARD_LED, OUTPUT);
  analogWrite(ONBOARD_LED, 0);
......

if (api.system.timer.create(RAK_TIMER_0, (RAK_TIMER_HANDLER)main_routine, RAK_TIMER_PERIODIC) != true) {
        Serial.printf("LoRaWan OTAA_PERIOD - Creating timer failed.\r\n");
        return;
    }

 if (api.system.timer.start(RAK_TIMER_0, OTAA_PERIOD, NULL) != true) {
      Serial.printf("LoRaWan OTAA_PERIOD - Starting timer failed.\r\n");
      return;
    }
.....
}

void main_routine() {
analogWrite(ONBOARD_LED, 100); 
}

void loop() {
   api.system.scheduler.task.destroy();
  }

What I’m doing wrong?
Many thanks for you suport.

Firmware Version: RUI_4.0.5_RAK3172-T

What are you doing in the main_routine()?

@beegee - I’m doing just some calculation. and as shown in the example, I set the value to the analog pin.
analogWrite(ONBOARD_LED, 100);

Not sure, when using the example code from the RUI3 BSP it works on the built-in LED’s of the WisBlock.

PA15 is declared as analog input, it might be that after setup() the pin mode is changed by RUI3.

Any chance you can use a different GPIO? On WisBlock, the two LED’s are defined as PA0 and PA1.

Here is the code I used:

int val = 0; // variable to write the LED pin
bool state = false;
bool ledSwitch = false;

void valChage()
{
	state = !state;
	if (val == 0)
		ledSwitch = !ledSwitch;
}

void setup()
{
	// put your setup code here, to run once:
	pinMode(GREEN_LED, OUTPUT);
	pinMode(BLUE_LED, OUTPUT);
}

void loop()
{
	// put your main code here, to run repeatedly:
	if (val == 0 || val == 255)
		valChage();

	// To determine to make the led lighter or darker
	if (state)
		val++;
	else
		val--;
	// To switch the lighting led
	if (ledSwitch)
		analogWrite(GREEN_LED, val); // Light the green led
	else
		analogWrite(BLUE_LED, val); // Light the blue led

		delay(10);
}

20230821_131150_edit_edit

Driving a simple LED is working fine on my side as well. As I have mentioned, the problem is when I’m implementing the whole LoraWAN functionality and start using api.system.timer to create a time handler and disabling the mail loop.
The question is if in the power saving mode, the periferial keeps running on the set value or not.

I played around a little bit with the code and put the LED control into a timer callback and it is still working, even if I call api.system.sleep.all() into the loop()

Here is the code that works for me.

int val = 0; // variable to write the LED pin
bool state = false;
bool ledSwitch = false;

void main_routine(void)
{
	// put your main code here, to run repeatedly:
	if (val == 0 || val == 255)
		valChage();

	// To determine to make the led lighter or darker
	if (state)
		val++;
	else
		val--;
	// To switch the lighting led
	if (ledSwitch)
		analogWrite(GREEN_LED, val); // Light the green led
	else
		analogWrite(BLUE_LED, val); // Light the blue led
}

void valChage()
{
	state = !state;
	if (val == 0)
		ledSwitch = !ledSwitch;
}

void setup()
{
	// put your setup code here, to run once:
	pinMode(GREEN_LED, OUTPUT);
	pinMode(BLUE_LED, OUTPUT);

	if (api.system.timer.create(RAK_TIMER_0, (RAK_TIMER_HANDLER)main_routine, RAK_TIMER_PERIODIC) != true)
	{
		Serial.printf("LoRaWan LED - Creating timer failed.\r\n");
		return;
	}
	if (api.system.timer.start(RAK_TIMER_0, 10, NULL) != true)
	{
		Serial.printf("LoRaWan LED - Starting timer failed.\r\n");
		return;
	}
	api.system.sleep.all();
}

void loop()
{
	// // put your main code here, to run repeatedly:
	// if (val == 0 || val == 255)
	// 	valChage();

	// // To determine to make the led lighter or darker
	// if (state)
	// 	val++;
	// else
	// 	val--;
	// // To switch the lighting led
	// if (ledSwitch)
	// 	analogWrite(GREEN_LED, val); // Light the green led
	// else
	// 	analogWrite(BLUE_LED, val); // Light the blue led

	api.system.sleep.all();
	// api.system.scheduler.task.destroy();
}

However, with the PWM running on the LED’s, the power consumption is ~6mA. If I disable the timer to control the PWM, the same code goes down to 25uA.
RUI3-LED-PWM.ino (1.9 KB)

Could you please change the line: if (api.system.timer.start(RAK_TIMER_0, 10, NULL) != true) with

if (api.system.timer.start(RAK_TIMER_0, 6000, NULL) != true) and have a look. On my end does not work properly.

Many thanks for your assistance.

Yes, you are correct.
And somehow it makes sense. To achieve lowest power consumption all functions inside the STM32WL5 have to be shut down. So the PWM will not work anymore.

When using the power profiler, I can see a peak every 6 seconds, that’s when the timer triggers and the PWM is activated, but then it is immediately shut down again. I can see the LED blinking for a very short time only.

Many thanks for the investigation. It looks I need find a workaround for this. I need to check the Digital IO pin as well, but I guess will not keep its state.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.