_ Preliminary info _
Board: Arduino Uno
Involved protocols: Hardware SPI
Pins Involved:
Pin 3 - Output (Slow PWM)
Pin 7 - Output (chip select)
Pin 9 - Output (Slow PWM)
Pin 10 - Output (chip select)
Pin 11 - Output (hardware MOSI)
Pin 12 - Input (hardware MISO)
Pin 13 - Output (hardware SLK)
Hi All,
Here's the skinny: Will changing the timer for Pin 3 (OC2B) mess up hardware SPI communication? Basically, I don't have a strong understanding of the timer registers on the Arduino, so I'm not sure how modifying one will affect the rest of the system/ports/pins (or even what exactly constitutes "one" timer in terms of port/pin/register).
In detail:
I want to use slow PWM on Pin 3 and Pin 9 of the Arduino Uno to drive two separate solid state relays (each controlling its own heating element) as part of a temperature control PID loop - and by "slow", I mean slower than the Uno will natively go. I have been able to accomplish this for the timer on Pin 9 (OC1A), but my concern is that modifying the timer for Pin 3 might mess up my hardware SPI communication - in other words, I'm not sure if changing the timer for Pin 3 (OC2B) will affect the hardware SPI function of Pin 11 (OC2A). I can't alternatively modify OC0A or OC0B because they are tied to the uC's internal clock.
I have already modified the timer OC1A in the following way:
Before Setup:
// PWM setup declarations
float PWM_PERIOD = 1.0; // Period length; 1-second default
float PULSE_WIDTH = 500e-6; // Pulse width (active); 500e-6 (500uS) default
const uint16_t TIMER_PRESCALER = 256; // Alternative prescaler values: 1, 8, 64, 256, or 1024 (smaller makes faster; Fosc = Fcpu/prescaler)
const float F_TIMER = F_CPU / TIMER_PRESCALER; // With a 16 MHz clock and prescaler 256, the resolution is 16us and maximum period is 1.048576s.
Inside Setup:
DDRB |= _BV(PB1); // set PB1 = OC1A as output
ICR1 = round(PWM_PERIOD * F_TIMER) - 1; // implement pulse period
OCR1A = round(PULSE_WIDTH * F_TIMER) - 1; // implement pule width
TCCR1A = _BV(COM1A1) // non-inverting PWM on OC1A
| _BV(WGM11); // fast PWM mode, TOP = ICR1
TCCR1B = _BV(WGM12) // fast PWM mode, TOP = ICR1
| _BV(WGM13) // fast PWM mode, TOP = ICR1
| _BV(CS12); // clock at F_CPU/256 = 62.5 kHz
in Loop:
PULSE_WIDTH_0 = output_0 / 150; // Map pulse width variable to convenient PWM output range/scale
if (PULSE_WIDTH_0 == 0)PULSE_WIDTH_0 = 0.00001; // If pulse width is set to "0", it goes to full "on" instead. This keep it close enough to 0 to be useful.
else if (PULSE_WIDTH_0 > 1)PULSE_WIDTH_0 = 1; // Safety/sanity feature: limit pulse width to 1 in magnitude. This keep things from potentially getting funky.
OCR1A = round(PULSE_WIDTH_0 * F_TIMER) - 1; // Implement pulse width value
where "output_0" is the output value of the PID control loop.
I'm thinking I'd just do this same thing (duplicate all the code) but replace all instances of "OC1A" with "OC2B".