Hello!
I will be testing locked antiphase drive on this ebay h-bridge (when I get it). I am using Atmega 328p. So far, I have used sign and magnitude technique and basic non-inverted pwm for my needs, but I was told that locked anti-phase provides better control (motor has more control over the load).
I have successfuly configured the MCU timers to give me 20kHz pwm output, but now I need two channel pwm (inverted and non-inverted one). I know how to set inverted output on channel B, but I have another issue: for same duty cycle, I have to set OCR1A and OCR1B to the same value. Is it possible for both channels to use just one register? Or atleast to set them both at the same time? I don't know for sure but probably in the time between those two instructions they could go out of sync and cause short circuit.
My code:
#define BIT(x) (0x01 << (x))
#define TOP (401) // Is TOP+1. Top for Timer1, this value sets PWM frequency to 20kHz
void timer1_correctPWM_20kHz_Setup()
{
// Set Phase-Correct PWM, use ICR1 as TOP
// Set prescaler to 1
TCCR1A = BIT(WGM11);
TCCR1B = BIT(WGM13) | BIT(CS10);
// Set TOP to 400 + 1 for 20kHz PWM
ICR1 = TOP;
// Reset Timer/Counter to 0
TCNT1 = 0;
// Set duty-cycle to 0
OCR1A = 0;
OCR1B = 0;
// Disable interrupts for this timer
TIMSK1 = 0;
}
// Copied from analogWrite and modified
void connectPWM(int val)
{
// connect pwm to pins on timer 1, channels A and B
// Clear OC1A on Compare Match when upcounting. Set OC1A on Compare Match when downcounting.
// Set OC1B on Compare Match when upcounting. Clear OC1B on Compare Match when downcounting.
TCCR1A |= BIT(COM1A1) | BIT(COM1B1) | BIT(COM1B0);
OCR1A = val; // set pwm duty
OCR1B = val; // set pwm duty
}
// Copied from analogWrite and modified, removed the port connection part because I know I won't use it for anything else in-between
void changePWM(int val)
{
OCR1A = val; // set pwm duty
OCR1B = val; // set pwm duty
}
// Copied from digitalWrite
void disconnectPWM()
{
// Disconnect pins from timer
TCCR1A &= ~(BIT(COM1A1) | BIT(COM1B1) | BIT(COM1B0));
// Set pins 9 and 10 to LOW
PORTB &= ~(BIT(PORTB4) | BIT(PORTB3));
}
And then in setup I call
cli(); // Disable interrupts
timer1_correctPWM_20kHz_Setup(); // Sets timer1 to Phase-Correct PWM at 20kHz
sei(); // Enable interrupts
and when using it
cli();
connectPWM(0); // Connect pins to timer and set duty cycle to 0
sei();
...
changePWM((int)duty_cycle);
...
cli();
disconnectPWM(); // Disconnect pins from timer1
duty_cycle = 0; // Reset the duty cycle
sei();
Would it be wise to also set timer value to new BOTTOM before changing duty cycle? I want to do things the right way but I dont exactly know what is good practice and safety precautions here.
Note that I will be changing duty cycle VERY often, on occasions even roughly every millisecond.
Thanks for any help!