#include <avr/io.h>
#include <util/delay.h>
#include <math.h>
#include <stdint.h>
#define F_CPU 16000000 // 16Mhz system clock
// Sine lookup-table. One full cycle.
volatile int8_t sineTable[256];
// Accumulator (signal phase) for Direct Digital Synthesis (DDS)
volatile uint16_t accumulator;
// Increment value for DDS. This defines the signal frequency
volatile uint16_t increment;
void main(void)
{
// Initialize the sine table
for (int i=0; i<256; i++)
{
sineTable[i] = (int8_t)(127.0 * sin(6.283*((float)i)/256.0));
}
// TODO 1
/* Setup 8bit PWM.
Rest of the code assumes that duty cycle is defined by OCR register. Values [0, 255] */
// .. initialization omitted
// TODO 2
/* Setup interrupt for duty cycle update.
ISR must execute at constant frequency Fs */
// .. initialization omitted
/* Calculate increment for constant sine frequency */
// increment = (Frequency*(2^16)) / Fs;
/* Infinite loop */
for(;;)
{
}
}
/******************************************************************************/
/*
Interrupt service routine executes at constant frequency.
(sine wave sample frequency). Do not confuse this with pwm frequency.
*/
ISR()
{
accumulator += increment; // Increment accumulator
OCR = 128 + sineTable[accumulator>>8]; // Update PWM duty cycle
}
/******************************************************************************/
/*
Interrupt service routine executes at constant frequency.
(sine wave sample frequency). Do not confuse this with pwm frequency.
*/
ISR()
{
accumulator += increment; // Increment accumulator
// PWM Channel A 0-phase
OCRA = 128 + sineTable[accumulator>>8]; // Update PWM duty cycle
// PWM Channel B 120-phase
OCRB = 128 + sineTable[(accumulator+21845)>>8]; // Update PWM duty cycle
// PWM Channel C 240-phase
OCRC = 128 + sineTable[(accumulator+43691)>>8]; // Update PWM duty cycle
}
/******************************************************************************/
Hello
misterT : I have been able to generate a single phase sinewave already.For this i o/p a PWM resembling a Full rectified sinewave using the LUT (look up table) shared in my original post.I intend to vary the base frequency of the sinewave.
My PWM is 16KHz = 62.5us, so 32 x 62.5us = 2ms but i need a 180 degree at 10ms , so i have to somehow convert this 2ms into 10ms.
I call each LUT value 5 times.If i want a higher frequency, i call each value less times and vice-versa.
I assumed a could use the same LUT for generating 3-phases by offsetting LUT values to each PWM channel by 120 degrees, for this i changed the TimerOverflowISR thus
TimerOverflowISR ()
{
Firstchannel = sintable(duty);
Secondchannel = sintable(duty+22); //120deg
Thirdchannel = sintable(duty+11); //240deg
}
But this scheme has problems, since each limb cross conducts so what i though was that my LUT is wrong.
Hi misterT
Thanks for the reply.
For the moment forget motor control, my basic question was, how to generate 3 phases of sinewaves 120 degrees apart, to drive a 6 transistor bridge?
Since i can generate 3 waves independently, what i assumed was creating an index in the LUT but this scheme has cross over conduction written all over it.
Thanks anyways, appreciated!
6 transistor bridge is build using 3 half bridges.
Half bridge is just a high-side and low-side FET (transistor).
Simplest way to drive this is to drive one half bridge with one pwm channel. When the PWM signal is high, the high-side transistor conducts, when the PWM signal is low, the low-side signal conducts. If you have 6 output channels, I assume that you have 3 PWM channels and each channel outputs a complementary pair of signals.
if (sineTable[i] >= 0) {
direction = 1;
PWM = sineTable[i];
} else if (sineTable[i] < 0) {
direction = 0;
PWM = -sineTable[i];
}
Hi i got what you are saying , i had forgotten that you add 128 at the update.- You can have a table like that, sure. But note that the values do not fit in a 8-bit variable.
- If you have 8-bit PWM, the values need to be between -127 and 127.
- Pulse width modulation can have a duty cycle from 0 to 100%, so you can't have negative values. So you need to add 127 to all values.
Hi i got what you are saying , i had forgotten that you add 128 at the update.
Likewise i have changed my table thus
0, 24, 48, 69, 88, 104, 115, 123, 125, 123, 115, 104, 88, 69, 48, 24, 0, -24, -48, -69, -88, -104, -115, -123, -125, -123, -115, -104, -88, -69, -48, -24
-125 to +125
so that i add an offset of 125 to make it at 250 max which would mean a 100% duty at 16KHz
Does this sound right?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?