Arduino Nano 33 BLE mbed os crashes when PWM on more than 3 digital pins.
We are using ARDUINO NANO 33 BLE, Model NINA-8306
This is a relatively long post.
We are evaluating Nano 33 BLE for a project. The project requires 8 digital PWM outputs.
According to the documentation, pins D2 to D13 are PWM capable. We chose pins D2 to D9.
First we discovered that PWM on more than 4 digital pins crashed the mbed os (4 long, 4 short yellow blinks). Going over the nordic documentation we discovered that more than 4 pwm at a time seems like a HW limitation. Having a modern silicon with such a limitation is something I’d rather not comment on. Fine. I went over the github cpp code, RE’d it and found wiring_analog.cpp. Inside we found someone already discovered the problem and made a change to it. Being rather lazy I made a similar change directly in my wiring_analog.cpp and recompiled. All digital pins can now be used one at a time provided we destroy them after use. Next we tried to run 4 pins simultaneously and this is where we hit a wall. We could not run more than 3 at a time, adding the fourth again crashes the mbed os.
Has anyone encountered a similar problem and if you did and solved it, what is the solution?
Below I am attaching my test code. Inside I also added the cpp mod in a comment if you want to reproduce the first problem.
I know this is whining but having such a good silicon with the rest of the hw on the pcb, BT, acc, etc, and not being able to use pwm on more than 4 pins at a time as a hw limit and more than 3 pins simultenously is a ridiculous deal-breaker. I’d be very happy someone to point out that I am wrong and full of sh**. Even the old atmega nano could beat that (though it has 6 pwm 8 bit pins only).
We are using the latest IDE and libraries as of time of this post.
Home someone could chime in.
Cheers.
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#define SYS_VOL 3.3
#else
#define SERIAL Serial
#define SYS_VOL 5
#endif
// Duty cycle PWM pin assignment
int FL_RPWM_Output = D2; // Arduino PWM duty output
int FL_LPWM_Output = D3; // Arduino PWM duty output
int FR_RPWM_Output = D4; // Arduino PWM duty output
int FR_LPWM_Output = D5; // Arduino PWM duty output
int RL_RPWM_Output = D6; // Arduino PWM duty output
int RL_LPWM_Output = D7; // Arduino PWM duty output
int RR_RPWM_Output = D8; // Arduino PWM duty output
int RR_LPWM_Output = D9; // Arduino PWM duty output
void setup()
{
}
void loop()
{
// Seems that Nano 33 BLE cannot simultaneously PWM on more than 4 digital pins which is a severe design deficiency. Who the **** made this decision. Is it baked into the silicon? Or mbed os?
// In order to workaround this sh***** design the wiring_analog.cpp was updated to destroy any digital pin which value was set to <= 0 (in the case below I set it to -1).
// Any time you need to move the pwm from pin to pin, you must analogWrite(DIGITAL_PIN, -1); What a load of manure. I am lucky I need to use only 4 at a time.
/* Below is the change I made.
float duty = (float)val/(float)(1 << write_resolution);
mbed::PwmOut* pwm = digitalPinToPwm(pin);
if (pwm == NULL)
{
pwm = new mbed::PwmOut(digitalPinToPinName(pin));
digitalPinToPwm(pin) = pwm;
pwm->period_ms(2);
}
if (duty <= 0)
{
delete pwm;
digitalPinToPwm(pin) = NULL;
}
else
{
pwm->write(duty);
}
}
*/
// TEST ALL 8 INDIVIDUALY
// D2 FRONT LEFT FORWARD
pinMode(FL_RPWM_Output, OUTPUT);
analogWrite(FL_RPWM_Output, 255);
delay(1000);
analogWrite(FL_RPWM_Output, 0);
delay(1); // For physical stability
analogWrite(FL_RPWM_Output, -1);
delay(1000);
// D3 FRONT LEFT BACKWARD
pinMode(FL_LPWM_Output, OUTPUT);
analogWrite(FL_LPWM_Output, 255);
delay(1000);
analogWrite(FL_LPWM_Output, 0);
delay(1); // For physical stability
analogWrite(FL_LPWM_Output, -1);
delay(1000);
// D4 FRONT RIGHT FORWARD
pinMode(FR_RPWM_Output, OUTPUT);
analogWrite(FR_RPWM_Output, 255);
delay(1000);
analogWrite(FR_RPWM_Output, -1);
delay(1); // For physical stability
analogWrite(FR_RPWM_Output, -1);
delay(1000);
// D5 FRONT RIGHT BACKWARD
pinMode(FR_LPWM_Output, OUTPUT);
analogWrite(FR_LPWM_Output, 255);
delay(1000);
analogWrite(FR_LPWM_Output, 0);
delay(1); // For physical stability
analogWrite(FR_LPWM_Output, -1);
delay(1000);
// D6 REAR LEFT FORWARD
pinMode(RL_RPWM_Output, OUTPUT);
analogWrite(RL_RPWM_Output, 255);
delay(1000);
analogWrite(RL_RPWM_Output, 0);
delay(1); // For physical stability
analogWrite(RL_RPWM_Output, -1);
delay(1000);
// D7 REAR LEFT BACKWARD
pinMode(RL_LPWM_Output, OUTPUT);
analogWrite(RL_LPWM_Output, 255);
delay(1000);
analogWrite(RL_LPWM_Output, 0);
delay(1); // For physical stability
analogWrite(RL_LPWM_Output, -1);
delay(1000);
// D8 REAR RIGHT FORWARD
pinMode(RR_RPWM_Output, OUTPUT);
analogWrite(RR_RPWM_Output, 255);
delay(1000);
analogWrite(RR_RPWM_Output, 0);
delay(1); // For physical stability
analogWrite(RR_RPWM_Output, -1);
delay(1000);
// D9 REAR RIGHT BACKWARD
pinMode(RR_LPWM_Output, OUTPUT);
analogWrite(RR_LPWM_Output, 255);
delay(1000);
analogWrite(RR_LPWM_Output, 0);
delay(1); // For physical stability
analogWrite(RR_LPWM_Output, -1);
delay(1000);
//////////////////////////////////
// 4 SIMULTENEOUS
// D2 FRONT LEFT FORWARD
pinMode(FL_RPWM_Output, OUTPUT);
analogWrite(FL_RPWM_Output, 255);
// D4 FRONT RIGHT FORWARD
pinMode(FR_RPWM_Output, OUTPUT);
analogWrite(FR_RPWM_Output, 255);
// D6 REAR LEFT FORWARD
pinMode(RL_RPWM_Output, OUTPUT);
analogWrite(RL_RPWM_Output, 255);
// D8 REAR RIGHT FORWARD
// this crashes mbed os
pinMode(RR_RPWM_Output, OUTPUT);
analogWrite(RR_RPWM_Output, 255);
delay(1000);
analogWrite(FL_RPWM_Output, -1);
analogWrite(FR_RPWM_Output, -1);
analogWrite(RL_RPWM_Output, -1);
analogWrite(RR_RPWM_Output, -1);
delay(1000);
//////////////////////////////////
}
nano33blepwmcrashtest.ino (4.4 KB)