How do sine Look up tables actually work?

You will be altering all 6. See Reply 47:

On each timer overflow interrupt, add the increment to the accumulator. Take the top byte of the accumulator for PhaseOneIndex. PhaseTwoIndex is PhaseOneIndex + 85. PhaseThreeIndex is PhaseOneIndex plus 171. All are one-byte variables so the math is naturally modulo 256.

For each phase:
If the index is <128:
Turn off the -PWM pin and set the +PWM pin to SineTable[index];
else
Turn off the +PWM pin and set the -PWM pin to SineTable[index-128];

From #1. Is this still what you are trying to do ultimately?

What frequency or range of frequencies are you hope to make?

Is it a requirement of your assignment or your employer or whyever you are trying to do this that you do so using the timer/counter availabilities of the microprocessor?

a7

yes thats the end goal, i would like to add a option where i could make this frequncy vairable using a potentiometer but thats way in the long run from now

I've done direct digital synthesis writing directly to a real D2A without any lower level stuff like y'all are getting into… I am watching to see how, if you do, analogWrite() will be part of the solution.

In my case, all at audio frequencies < 3000 Hz, and fairly fine ability to adjust.

Which is why I keep asking, sorry if I've missed your answer(s):

What frequency are you trying to make at this time?

When you get there, what range of frequencies might you be trying to adjust within? And what resolution, that is to say with what fineness do you need/want to be able to change the output frequency?

TIA

a7

so to start while im making this im just going for 30~32kHz but my needed range is 60kHz - 5kHz for the end project.
This code will be put into a H bridge with an extra 2 transistors also (like a 6 bridge?) to run a 3 phase motor

A 3-phase motor at 60kHz??? Are you sure you don't want a brushless motor instead?

16MHz / 60kHz = 266 processor clock cycles per output sine wave.

There's not much space for any PWM resolution.

And not much time to read an analog input for a potentiometer.

55 posts later, to get an answer to my question.

the motors not connected to anything, ive seen the demo piece in our lab and its just free spinning

Well, that is reassuring!

Well, I am def staying tuned. This will be interesting.

What RPM are you hoping to run this motor at?

Can you supply a link to the motor specifications, or a make and model numbers?

I know, I know, a thousand questions. But first the tranya.

a7

const static unsigned int sineLookUp[] {
125,127,129,132,134,136,138,140,142,145,
147,149,151,153,155,157,159,162,164,166,
168,170,172,174,176,178,180,182,184,186,
188,189,191,193,195,197,198,200,202,204,
205,207,209,210,212,213,215,216,218,219,
221,222,224,225,226,227,229,230,231,232,
233,234,235,236,237,238,239,240,241,242,
242,243,244,245,245,246,246,247,247,248,
248,248,249,249,249,250,250,250,250,250,
250,250,250,250,250,250,249,249,249,248,
248,248,247,247,246,246,245,245,244,243,
242,242,241,240,239,238,237,236,235,234,
233,232,231,230,229,227,226,225,224,222,
221,219,218,216,215,213,212,210,209,207,
205,204,202,200,198,197,195,193,191,189,
188,186,184,182,180,178,176,174,172,170,
168,166,164,162,159,157,155,153,151,149,
147,145,142,140,138,136,134,132,129,127,
125,123,121,118,116,114,112,110,108,105,
103,101,99,97,95,93,91,88,86,84,
82,80,78,76,74,72,70,68,66,64,
63,61,59,57,55,53,52,50,48,46,
45,43,41,40,38,37,35,34,32,31,
29,28,26,25,24,23,21,20,19,18,
17,16,15,14,13,12,11,10,9,8,
8,7,6,5,5,4,4,3,3,2,
2,2,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,2,
2,2,3,3,4,4,5,5,6,7,
8,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,23,24,25,26,28,
29,31,32,34,35,37,38,40,41,43,
45,46,48,50,52,53,55,57,59,61,
62,64,66,68,70,72,74,76,78,80,
82,84,86,88,91,93,95,97,99,101,
103,105,108,110,112,114,116,118,121,123,
};

const static unsigned int sineLookUp120[] {
233,232,231,230,229,227,226,225,224,222,
221,219,218,216,215,213,212,210,209,207,
205,204,202,200,198,197,195,193,191,189,
188,186,184,182,180,178,176,174,172,170,
168,166,164,162,159,157,155,153,151,149,
147,145,142,140,138,136,134,132,129,127,
125,123,121,118,116,114,112,110,108,105,
103,101,99,97,95,93,91,88,86,84,
82,80,78,76,74,72,70,68,66,64,
63,61,59,57,55,53,52,50,48,46,
45,43,41,40,38,37,35,34,32,31,
29,28,26,25,24,23,21,20,19,18,
17,16,15,14,13,12,11,10,9,8,
8,7,6,5,5,4,4,3,3,2,
2,2,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,2,
2,2,3,3,4,4,5,5,6,7,
8,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,23,24,25,26,28,
29,31,32,34,35,37,38,40,41,43,
45,46,48,50,52,53,55,57,59,61,
62,64,66,68,70,72,74,76,78,80,
82,84,86,88,91,93,95,97,99,101,
103,105,108,110,112,114,116,118,121,123,
125,127,129,132,134,136,138,140,142,145,
147,149,151,153,155,157,159,162,164,166,
168,170,172,174,176,178,180,182,184,186,
188,189,191,193,195,197,198,200,202,204,
205,207,209,210,212,213,215,216,218,219,
221,222,224,225,226,227,229,230,231,232,
233,234,235,236,237,238,239,240,241,242,
242,243,244,245,245,246,246,247,247,248,
248,248,249,249,249,250,250,250,250,250,
250,250,250,250,250,250,249,249,249,248,
248,248,247,247,246,246,245,245,244,243,
242,242,241,240,239,238,237,236,235,234,
};
int x;
int y;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);

  GTCCR = _BV(TSM) | _BV(PSRSYNC);
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR4A = 0; 
  TCCR4B = 0;

  TCNT1 = 0;
  TCNT4 = 0;
  
  ICR1 = (F_CPU/32000)/2; //ICR1 = 250
  ICR4 = (F_CPU/32000)/2; //ICR4 = 250

  OCR1B = ICR1/2; //Dutycycle is 50% pin 12
  OCR1A = ICR1/2; //Dutycycle is 50% pin 11
  OCR4C = ICR4/2; //Dutycycle is 50% pin 8
  OCR4B = ICR4/2; //Dutycycle is 50% pin 7
    
//set mode 10 with
  TCCR1A = _BV(WGM11)  | _BV(COM1A1) | _BV(COM1B0)| _BV(COM1B1); //Enable the PWM outputs OC1A, OC1B and OC1C on digital pins 11, 12 and 13
  TCCR4A = _BV(WGM41) | _BV(COM4C1) | _BV(COM4B0) | _BV(COM4B1); // Enable the PWM outputs OC4A, OC4B and OC4C on digital pins 6, 7 and 8
  TCCR1B = _BV(WGM13) | _BV(CS10); //No prescaling
  TCCR4B = _BV(WGM43) | _BV(CS40);
  GTCCR = 0;
}


void loop() {
  //delay(100);
  for(x=0; x<360; x++) {
    for(y=0;y<360;y++)  {
      sineWrite(sineLookUp[x], sineLookUp120[y]);
    }
}
//for(y=0; y<360; y++) {
  //delayMicroseconds(45);
//  sineWrite(sineLookUp120[y]);
// }
 
}

void sineWrite(int sine1, int sine2) {
  OCR4C = sine1;
  OCR4B = sine1 + 2;
  OCR1A = sine2;
  OCR1B = sine2 +2;
}
//void sineWrite120(int sine2)  {
  // OCR1A = sine2;
   //OCR1B = sine2 +2;
//}

So this is my code now after i attended one of my labs and this is super close to what i want now. Theres still a few issues present though.
turns out i need the output frequency of the sine wave to be able to change between 5-60Hz but i might put in a MicrosecondDelay on a analogue input to achieve this.

one issue is my pin 7 while inverted so thats good has a weird spike present in the wave that pin 8 doesnt have?

and also my pins 11 and 12 which are 120 degree phase shifted by having a different lookup table have a much larger frequency and pin 12 also seems a bit unstable?

any ideas as to why?

Because that's what this code does. You have a nested loop.

Also, sticking a delay in there to accomplish the desired result is a bit of a hack, there are good ways to have a timed event happen, um, on time.

At least you are no longer needing to do 60 kHz.

a7

so do you think having un nested for loops should do the trick?

I don't see why you need two loops at all.

for(x=0; x<360; x++) {

      sineWrite(sineLookUp[x], sineLookUp120[x]);
 
}

And maybe you can see also why you don't need two tables… the second is just offset from the first, so would be available at

 SineLookUp[(x + 120) % 360];

Which I am pretty sure has been mentioned a few times upthread.

a7

for(x=0; x<360; x++) {

      sineWrite(sineLookUp[x], sineLookUp120[x]);
 
}

Ive used this and it seems to work nicely, il try the next code to see how it works soon but im still getting a fuzzy output on the inverted waveform.
ive given it a +2 so it should count two points ahead of its pair so i have a deadband as to not short the H bridge.
Photo of normal wave pin 8


photo of its inverted wave pin 7

[quote="samba3305, post:77, topic:962738"]

void loop(){
  for(x=0; x<360; x++) {
      sineWrite(sineLookUp[x], sineLookUp120[x])
  }
}

Let loop() do the looping instead of for(;;) and you can unblock things for better frequency control and flexibility as per BWOD, etc.:

void loop(){
  if (x >= 360){
    x = 0;
  }
  sineWrite(sineLookUp[x], sineLookUp120[x])
  x++;
}

...then:

void loop(){
  const unsigned long stepInterval = 46; // = 1e6/60Hz/360step/cycle  
  static unsigned long lastStep = 0;
  if(micros() - lastStep >= stepInterval){
     lastStep += stepInterval;
     if (x >= 360){
       x = 0;
     }
     sineWrite(sineLookUp[x], sineLookUp120[x])
     x++;
  }
  // 
  // The 46us micros() trick frees up time for about 4 free loops per step
  // per https://wokwi.com/arduino/projects/324577967909896787
  // ...
}

You can do better than that - lookup the angle, angle+120, then the third phase can be calculated from the first two dirrectly, since u+v+w = 0 for a 3-phase balanced system, so w = -u-v

If you are generating a fixed frequency you can use a digital quadrature oscillator to get x and y directly without trig or lookups, then use the inverse Clarke transform to get the three phase output.

Here's a good paper on iterative techniques for such oscillators. https://vicanek.de/articles/QuadOsc.pdf

Which now has been nicely provided by @DaveX, by the book.

Be sure to put a link to this thread in your final report.

a7