Go Down

Topic: Changing PWM frequency (25kHz, 4-pin fan) (Read 558 times) previous topic - next topic

apchubey

Hi everyone, this is yet another 25kHz PWM question. I would like to use 3 PWM pins at 25kHz (other PWM pins are empty), I have read that it is doable with UNO by modifying the timer(s). However, since Nano 33 BLE Sense has a different microcontroller, I am not sure how to tweak the timer(or is it even possible).

tl;dr How can I change the PWM requency of Nano 33 BLE Sense?

thanks in advance!

Klaus_K

Arduino Nano 33 BLE uses mbedOS. You can use the mbed functions directly.

Here is an example for 4 pins. You can also define them individually.

Code: [Select]
#include "mbed.h"

#define PWM_PIN_COUNT 4

mbed::PwmOut pwmPin[PWM_PIN_COUNT]
{
  ( digitalPinToPinName( 2 ) ),
  ( digitalPinToPinName( 4 ) ),
  ( digitalPinToPinName( 6 ) ),
  ( digitalPinToPinName( 8 ) ),
};

void setup()
{
  for ( int p = 0; p < PWM_PIN_COUNT; p++ )
  {
    pwmPin[p].period( 0.00004 ); // 25kHz
    pwmPin[p].write( p * 0.2 + 0.1 ); // 10%, 30%, 50%, 70% duty cycle
  }
}

void loop()
{
  delay( 1000 );
}


Here is a link to the mbedOS API if you like to read more about it.

https://os.mbed.com/docs/mbed-os/v6.2/apis/pwmout.html

Please note: You cannot have more than 4 PWM pins at the same time, because the PWM module has four channels only. If you create more than 4, mbedOS will crash (shown by strange blink pattern of the LED, kind of SOS, not quite). You can however free a PWM channel and then assign the channel to another pin.

apchubey

Thank you very much for the reply! This helped a lot.

reefwing

Hi @Klaus_K (or anyone else!),

Do you know where it is documented that you can only use 4 pins for PWM using Mbed OS for the Nano 33 BLE?

How do you free a PWM channel? I can't find a destructor for PwmOut.

Klaus_K

Do you know where it is documented that you can only use 4 pins for PWM using Mbed OS for the Nano 33 BLE?
The PWM module of the Arduino Nano 33 BLE only has 4 channels (see datasheet). The PWM signal is created by hardware and not software. I think some older Arduino use software PWM and therefore can create PWM signals on more pins. But this has its own limitation (CPU load, jitter, lower max frequency). You can do this as well, but you would need to write your own software. For slow frequencies and resolution software PWM is fine e.g. to control LEDs.

How do you free a PWM channel? I can't find a destructor for PwmOut.
Here are two examples. They create a PWM signal on a different pin every second.

PwmOut is destroyed every time at loop exit.
Code: [Select]
#include "mbed.h"

void setup()
{
}

void loop()
{
  static unsigned int pinNumber = 2;

  pinNumber = ( ( pinNumber + 1 ) % 10 ) + 2;
  mbed::PwmOut pin( digitalPinToPinName( pinNumber ) );
  pin.period( 0.002 );
  pin.write( 0.5 );

  delay( 1000 );
}


PwmOut is destroyed and created inside loop.
Code: [Select]
#include "mbed.h"

void setup()
{
}

void loop()
{
  mbed::PwmOut *ptr;
  unsigned int pinNumber = 2;

  while ( 1 )
  {
    pinNumber = ( ( pinNumber + 1 ) % 10 ) + 2;

    ptr = new mbed::PwmOut( digitalPinToPinName( pinNumber ) );
    ptr->period( 0.002 );
    ptr->write( 0.5 );

    delay( 1000 );

    delete ptr;
  }
}


Note: The delay() function has only been used to limit the example to the necessary. In real application, delay should be avoided. The same is true for the while(1) in loop.

reefwing


Go Up