PWM on Arduino Zero Questions

Ok I'm having a bit of a discrepancy with PWM on the Arduino Zero. Looking at the Main Page for the Zero: http://www.arduino.cc/en/Main/ArduinoBoardZero

I see that it states "General purpose I/O Pins 20, all of which can do digital I/O and all except for 2 and 7 can be used as PWM output" But then I see lower on the page in the Input/Output section "Each of the 20 general purpose I/O pins on the Zero can be used for digital input or digital output using pinMode(), digitalWrite(), and digitalRead() functions, Pins that can be used for PWM output are:
3, 4, 5, 6, 8, 9, 10, 11, 12, 13".

With that said I see the ATMEL SAMD21 datasheet says this chip has 12 PWM outputs attached to TC's. I have done some playing and I'm able to get 11PWM's working on the following Pins. I really need all 12 PWM's working for a project I wanted to use the Zero for.

So from the Arduino Web page it says it's either 18 or 10? PWM pins Atmel says the chip has 12 PWM pins. And I've found 11 PWM pins.

I've found the following pins work for PWM.
3,4,5,6,8,9,10,11,12,13, and A0 (digital 14). Does anyone know what pin the 12th PWM is attached to or if it is even broke out and functional in the Arduino IDE?

PWM works on A0? Are you sure? That's the DAC. Depending on how you're testing it it might appear to support PWM but the DAC is a true analog output.

The variant.cpp file doesn't indicate PWM support on that pin either. Have a look in that in the hardware directory for the Zero and you'll see pin definitions.

Try the ATN pin. Pin 38. That appears to be one.

Your correct I miss spoke (A0) is a True analog output using the DAC. (verified with a scope really quick).

I just spoke with the Atmel Rep in my area and in informed me all 12 ADC pins can be driven at the same time on the SAMD21 using atmel studios and codeing there. He was unaware of how the Arduino would handle it.

But then that leads to my other question where are the other 2 PWM pins that are mentioned in the Atmel Datasheet? Are they even on the Zero?

Did you check ATN like I suggested?

The other pins may be used to interface with the EDBG The ATN pin is one of them, and I noticed in the variant.cpp file that those pins all mentioned PWM support. But the other PWM pins mention being on a timer as well, which is probably a requisite for being a hardware PWM pin, so it's odd that they have one attribute but not the other. It could be something left over from an earlier version.

It may be that the reason they had to remove PWM on a couple pins was that whatever timer was being used had to be allocated to something else, like time keeping, and whatever they were doing with that made it incompatible with or difficult to support PWM.

I took a look at the variants.cpp for the Zero Pro to see what might have changed...

Zero:

  // 2..12
  // Digital Low
  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
  { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },

Zero Pro:

  // 2..12
  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // TCC0/WO[0]
  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
  { PORTA, 14, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_14 }, // TC3/WO[0]
  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
  { PORTA, 21, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_5 }, // TCC0/WO[7]

I don't know how to interpret all that, or why it was changed, but there you go.

Tested PA13/ ATN pin as pin 38 and I"m not getting anything out of it even a digital signal. I can't find the variant.cpp file on my windows computer anywhere. Sorry for the ignorance there.

I am leading to believe the same thing as you scswift. That the Arduino team did not implement all 12 of them for one reason or another. I was hoping one of the core Arduino Team would be able to chime in on this for me.

Variant.cpp is in a hidden appdata/roaming/arduino15/hardware?/variants? directory under your user directory in Windows, it's not in the main Arduino dir.

stealthtransam:
Tested PA13/ ATN pin as pin 38 and I"m not getting anything out of it even a digital signal. I can't find the variant.cpp file on my windows computer anywhere. Sorry for the ignorance there.

I am leading to believe the same thing as you scswift. That the Arduino team did not implement all 12 of them for one reason or another. I was hoping one of the core Arduino Team would be able to chime in on this for me.

I modified the Blink sketch to use pin 38 and used a scope to watch the ATN connection. Seems to work fine for me on OS X.

Wayne

[edit: added TC3 on the table below]

The following timers are available on the SAMD21G18A (the CPU used on the Zero):

TCC0, TCC1, TCC2, TC3, TC4, TC5

they have a different number of "channels" and "waveform outputs" that can be mixed together in a variety of ways here a summary with a brief note on how they are currently used:

Timer Channels Outputs Note
TCC0 4 8 Fully used for PWM (outputs 0..3 are replicated on 4..7)
TCC1 2 4 Fully used for PWM (outputs 0..1 are replicated on 2..3)
TCC2 2 2 Fully used for PWM
TC3 2 2 Fully used for PWM
TC4 2 2 Used by Servo
TC5 2 2 Used by Tone

Please note that TCC0 and TCC1 have 8 and 4 outputs respectively, but half of them are replicated so they cannot be used independently, this means that only half of them are useful for PWM generation.

We can get 2 more PWMs from timer TC4 for example on pins A1, A2 at the price that the Servo library must not be used together with them.

I've put in place a PR here:

This PR shows that the use of PIO_ANALOG and pin mapping is still not optimal.
I'll write some notes about that on a different github issue BTW.

cmaglie:
I've put in place a PR here:
Enabling PWM on pins A1/A2 by cmaglie · Pull Request #8 · arduino/ArduinoCore-samd · GitHub

sorry I can't figure it out from this thread:
now we have already 6 Pins that we can use simultaneously to generate PWM on the Zero Board ?
and the goal is:
to have 8 pins that can do PWM at the same time on the Zero Board ?

Dirk I've missed TC3 on the table above, now I've edited the post and added it, I guess this helps a bit more to understand the issue.

Currently we have 10 PWMs:

4 from TCC0
2 from TCC1
2 from TCC2
2 from TC3

and those are working as expected.

Now the topic is how to get 2 more PWM by exploiting TC4 or TC5.

and then,
those 12 pins are all accessible on the zero board pins to do PWM simultaneously ?
wow :o

Yes, the trade-off is that when using the timer TC4 we can't use the Servo library (because the Servo library uses TC4 to do his job too).

I notice TC5 is on the SPI port's MOSI and SCK pins. Could those also be used as PWM, at the cost of the Tone library? I'd sooner lose Tone than Servos.* We have a DAC after all for proper sound reproduction. :slight_smile:

(* In case it's not clear, I realize that allowing TC4 to be used for PWM doesn't mean we have to give up the Servo lib; we just can't use it at the same time as PWM.)

Awesome cmaglie! That should get me to the 12 PWM pins I need to get my project working. I'll try it out this weekend and go from there. Shouldn't be a problem interfering with the Servo library because I won't be using a servo with the project. I'll be using 12 PWM's and a ESP8266 Wifi Module and that is about it.

Ah, darn, seems like TC5 is used by the DAC's audio player lib:

So we couldn't have PWM on the SPI pins and use the DAC at the same time, I think.

But still, enabling the use of PWM on those pins if needed would be useful.

Finally got back around to testing it. I have PWM now working on A1(15) and A2(16). They work like a champ. What I haven't done yet is set different PWM values on each of the 12 PWM pins at the same time to see how it responds. That is next.