1

I need to drive a LED strip via MOSFET module. The module needs a high resolution PWM for very dim conditions. How can I set my pin to a 16 bit PWM resolution on an Arduino Nano Every?

asked Jul 1, 2023 at 16:24

2 Answers 2

4

It's possible for D5 (TCA0-WO2) + D9 (TCA0-WO0) + D10 (TCA0-WO1) all three of them will be 16bit if you change TCA0 top value, but you can't use analogWrite.

void setup() {
 // change period of TCA0 (already configured and started by arduino core)
 TCA0.SINGLE.PER = 0xFFFF; // change top value from 255 to 65535
 // set PWM value of D9 (channel 0)
 TCA0.SINGLE.CMP0 = 0; // initial value
 // enable PWM output (needed only once in setup)
 pinMode(9, OUTPUT); // setup pin as an output
 TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP0EN_bm; // enable pwm->pin
 // D5
 TCA0.SINGLE.CMP2 = 1; // initial value
 pinMode(5, OUTPUT);
 TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP2EN_bm;
 // D10
 TCA0.SINGLE.CMP1 = 65530; // initial value
 pinMode(10, OUTPUT);
 TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP1EN_bm;
}

and in the code you'll use only TCA0.SINGLE.CMPn = val; where n is 0..2

(untested, but should be working)

EDIT: I forgot the period will be 3.8Hz, so you'll need to change also TCA0 prescaller or use smaller precision like 10b or so. Changing prescaller will mess up the all the TCB counters periods along with the one used for millis counter so you'd need also change that

EDIT2: for classic UNO/nano it'll look like this:

TCCR1B = 0; // stop timer
ICR1 = 0xFFFF; // f = 16MHz / (2*N*ICR1) = 16MHz / (2*65536) => ~122Hz
OCR1A = 1; // PB2 -> D9 (PWM value)
TCCR1A = _BV(COM1A1); // enable PWM output on PB2
TCCR1B = _BV(WGM13) | _BV(CS10); // mode=8 (phase and freq correct, ICR1 as top) and start timer with prescaller /1
answered Jul 2, 2023 at 15:22
3
  • Thanks for the detailed code. Will try these days. I used an analogWrite function on the Uno, which wrote uint16_t to OCR1A (pin9). Is this still the same? Commented Jul 3, 2023 at 15:43
  • No, classic uno/nano (with Atmega328) has different settings for timer1 - but on the other side it has independent prescaller, so you won't break anything. Commented Jul 3, 2023 at 16:15
  • @awado added changes for classic uno (pinMode omitted) Commented Jul 3, 2023 at 16:33
0

Thanks again for your help KIIV. I can confirm it works. This an example of a low light PWM for an LED on Pin 10. Maybe it helps others.

int brightness = 0; // how bright the LED is
int fadeAmount = 1; // how many points to fade the LED by
void setup() {
 TCA0.SINGLE.PER = 0x4000;
 TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV16_gc | 1 << TCA_SINGLE_ENABLE_bp
 TCA0.SINGLE.CMP1 = 65530; // initial value
 pinMode(10, OUTPUT);
 TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP1EN_bm;
}
void loop() {
 // set the brightness of LED pin:
 TCA0.SINGLE.CMP1 = brightness;
 // change the brightness for next time through the loop:
 brightness = brightness + fadeAmount;
 // reverse the direction of the fading at the ends of the fade:
 if (brightness <= 0 || brightness >= 64) {
 fadeAmount = -fadeAmount;
 }
 // wait to see the dimming effect
 delay(50);
}
answered Jul 29, 2023 at 14:42

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.