Hi,
I'm trying to get a view on how analogWrite and digitalWrite work together for the Nano 33 IOT.
If I look at the page detailing analogWrite, I see the following text:
After a call to
analogWrite(), the pin will generate a steady rectangular wave of the specified duty cycle until the next call toanalogWrite()(or a call todigitalRead()ordigitalWrite()) on the same pin.
When I look at the actual implementation of analogWrite inside of C:\Users\...\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.13\cores\arduino\wiring_analog.c , I can see that the timers for the PWMs are being enabled/updated based on whether they were already active.
So indeed, when I do an analogWrite, PWM will be running. Everything fine up to this point.
For the second part of the quote I need to look at a different part of the code.
(or a call to
digitalRead()ordigitalWrite()) on the same pin.
Inside C:\Users\...\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.13\cores\arduino\wiring_digital.c we find the source:
void digitalWrite( pin_size_t ulPin, PinStatus ulVal )
{
// Handle the case the pin isn't usable as PIO
if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
{
return ;
}
EPortType port = g_APinDescription[ulPin].ulPort;
uint32_t pin = g_APinDescription[ulPin].ulPin;
uint32_t pinMask = (1ul << pin);
if ( (PORT->Group[port].DIRSET.reg & pinMask) == 0 ) {
// the pin is not an output, disable pull-up if val is LOW, otherwise enable pull-up
PORT->Group[port].PINCFG[pin].bit.PULLEN = ((ulVal == LOW) ? 0 : 1) ;
}
switch ( ulVal )
{
case LOW:
PORT->Group[port].OUTCLR.reg = pinMask;
break ;
default:
PORT->Group[port].OUTSET.reg = pinMask;
break ;
}
return ;
}
PinStatus digitalRead( pin_size_t ulPin )
{
// Handle the case the pin isn't usable as PIO
if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
{
return LOW ;
}
if ( (PORT->Group[g_APinDescription[ulPin].ulPort].IN.reg & (1ul << g_APinDescription[ulPin].ulPin)) != 0 )
{
return HIGH ;
}
return LOW ;
}
Nowhere in this code do I find any part that actually disables the PWM timers and thus disables the PWM output on the pin.
Indeed, if I actually test this behavior with f.e. digital pins 9 - 12 (which support PWM on the Nano 33 IOT), I see the behavior that is derived from the code (PWM continues after digitalWrite) which clashes with the behavior one would expect from the documentation (and from a usage standpoint).
Testcode for Nano 33 IOT:
const int pwm12 = 12;
const int pwm11 = 11;
const int pwm10 = 10;
const int pwm09 = 9;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(5000);
Serial.write("Setup started\n");
pinMode(pwm12, OUTPUT);
pinMode(pwm11, OUTPUT);
pinMode(pwm10, OUTPUT);
pinMode(pwm09, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.write("Main code started\n");
Serial.write("Set pwm for pin 12\n");
analogWrite(pwm12, 51);
analogWrite(pwm11, 102);
analogWrite(pwm10, 153);
analogWrite(pwm09, 204);
delay(1000);
digitalWrite(pwm12, LOW);
delay(1000);
digitalWrite(pwm11, LOW);
delay(1000);
digitalWrite(pwm10, LOW);
delay(1000);
digitalWrite(pwm09, LOW);
delay(1000);
analogWrite(pwm12, 51);
analogWrite(pwm11, 102);
analogWrite(pwm10, 153);
analogWrite(pwm09, 204);
delay(2000);
while(1);
}
I took some measurements of my arduino running this code with my logic analyzer. At no time did the actual output go back to 0/LOW after the digitalWrites.
So either
a. this is a bug in arduino core (which I expect as I would expect the output to go low after I do a digitalWrite(pin, LOW) to a pin)
or
b. the documentation does not line up
Until this is fixed I'll have to use my own implementation of digitalRead/digitalWrite which actually turns of the timers/PWM when doing a digitalRead or digitalWrite.

