Problem with MKR 1010 WiFi PWM pins

Hi all, I have a weird issue, when I set the PWM duty cycle on pins 2 or 3 to 100%, my code works great. When I switch one pin to be pin 4 or 5 I experience really odd behavior. My code gradually increases the duty cycle to 100% and when it hits 100 it drops to 0, on pins 4 and 5, but not pins 2 or 3. I've confirmed it's not my code as the only thing I changed was which pin I'm using. I've also confirmed the duty cycle is indeed dropping to 0% using my oscilloscope (very cheap DIY one, but it works for my needs). It's not entirely a huge deal as I only need 2 pins, I'm more curious if anyone has any insight into why this happens.

Please do this:

  • When you encounter an error, you’ll see a button on the right side of the orange bar “Copy error messages” in the Arduino IDE (or the icon that looks like two pieces of paper at the top right corner of the black console window in the Arduino Web Editor). Click that button…
  • In a forum reply here, click on the reply field.
  • Click the </> button on the forum toolbar. This will add the forum’s code tags markup to your reply.
  • Press “Ctrl + V”. This will paste the error between the code tags.
  • Move the cursor outside of the code tags before you add any additional text to your reply.

If the text exceeds the forum’s 9000 character limit, save it to a .txt file and post it as an attachment. If you click the “Reply” button here, you will see an “Attachments and other settings” link.

Hi Pert, it's not an error.

Hi. Very sorry about that. I copy/pasted the wrong reply from my collection of stock replies. Here’s what I meant to write:

Please post your full sketch.

If possible, you should always post code directly in the forum thread as text using code tags:

  • Do an Auto Format (Tools > Auto Format in the Arduino IDE or Ctrl + B in the Arduino Web Editor) on your code. This will make it easier for you to spot bugs and make it easier for us to read.
  • In the Arduino IDE or Arduino Web Editor, click on the window that contains your sketch code.
  • Press “Ctrl + A”. This will select all the text.
  • Press “Ctrl + C”. This will copy the selected text to the clipboard.
  • In a forum reply here, click on the reply field.
  • Click the </> button on the forum toolbar. This will add the forum’s code tags markup to your reply.
  • Press “Ctrl + V”. This will paste the sketch between the code tags.
  • Move the cursor outside of the code tags before you add any additional text to your reply.
  • Repeat the above process if your sketch has multiple tabs.

This will make it easy for anyone to look at it, which will increase the likelihood of you getting help.

If the sketch is longer than the 9000 characters maximum allowed by the forum, then it’s OK to add it as an attachment. After clicking the “Reply” button, you will see an “Attachments and other settings” link.

When your code requires a library that’s not included with the Arduino IDE please post a link (using the chain links icon on the forum toolbar to make it clickable) to where you downloaded that library from or if you installed it using Library Manger (Sketch > Include Library > Manage Libraries in the Arduino IDE or Libraries > Library Manager in the Arduino Web Editor) then say so and state the full name of the library.

No problem, I appreciate the replies. So my sketch is over 1300 lines long. I'm not sure if it's worth going through it. Certainly if you disagree then I'll gladly post it. Thing is if I switch the pin (via a variable so it's just one line) to pin 2 from 4 (or 5) it works. So I really don't think it's code related, it seems hardware related.

Edit: nm I'll post the sketch when I get a chance. You can decide if it's worth looking over :slight_smile:

You're welcome write a minimal, complete, verifiable example (MCVE) sketch that contains the minimum amount of code required to demonstrate the problem and then post it here. Often I find that by the time I'm done producing my MCVE, I've found the problem myself and no longer need to ask for help.

An MCVE I can do! And as I suspected it happens even with this minimal piece of code. Try it yourself, hook up your arduino to an oscilloscope (or PWM a fan, motor, LED), you’ll see that the duty cycle drops to 0% when 4096 is written to pins 4 or 5. Pins 2 and 3 work correctly, 4096 is 100% duty cycle. Note I haven’t tried any other pin besides these four.

const byte pin = 2; //works correctly
//const byte pin = 3; //works correctly
//const byte pin = 4; //doesn't work correctly
//const byte pin = 5; //doesn't work correctly
const byte pwmResolution = 12; //12 bits for 4096 levels of resolution

void setup() {
  analogWriteResolution(pwmResolution);
  pinMode(pin, OUTPUT);

  //When 4096 is "written" to the PWM pin that's 100% duty cycle, but on pins 4 and 5, 
  //upon 100%, the voltage drops back down to 0, or 0% duty cycle. 
  for(int i = 0; i <= 4096; i++)
  {
    analogWrite(pin, i);
    delay(5);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

I figured out the issue. It IS my code. I'm using values between 0 and 4096 (including 4096), instead of 4095. For some odd reason for pins 2 and 3 when exceeding the highest allowed value it just stays at 100% duty cycle, but for pins 4 and 5, it drops it down to 0 instead.

Nice work finding the bug! Thanks for taking the time to post an update.

I must admit I don't have an explanation for the different behavior between the pins. Maybe someone else here will have an answer. Otherwise, we can just chalk it up to "undefined behavior".

pins 2 and 3 use TCC type of timer on SAMD and 4 and 5 use TC type timer, so the timer setup for pwm is different.

Pert, welcome! Glad I was able to figure out more info.

Juraj, do you have a link that explains the difference between timers and why they act different? My curiosity is getting the best of me.

mnl1121:
Pert, welcome! Glad I was able to figure out more info.

Juraj, do you have a link that explains the difference between timers and why they act different? My curiosity is getting the best of me.

http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf
chapter 30. and 31.

Atmel’s timers behave in ways one would not expect when the compare match value or TOP is set to 0.

I spent many hours this weekend trying to figure out why TCB1 in periodic interrupt mode on the attiny3216 (it’s a megaAVR - a pretty baller chip too, now fully supported by megaTinyCore https://github.com/SpenceKonde/megaTinyCore ) wasn’t firing while trying to make Servo work. Turned out that I hadn’t set TCB1.CCMP (due to an < instead of <= in the initialization code), so it was 0 - and in that configuration, it never generates the interrupt (I’d have expected it to either run until it overflowed and then fire, or constantly fire - the former would have not even been noticed, while the latter would have taken minutes to figure out instead of hours)