help for programming an arduino uno

i already post this problem in " Programming Questions "


i want to generate 3 PWM 120 degrees out of phase with arduino uno because i want to control six pulse igbt to control 3 phase motor ( 220v/380v // f=50hz // rpm = 1430 ) and display the frequency in LCD


i found a code (Unknown Language or 'C' as i think) #it's attached to this topic# but i have some problems with output frequency

can you help me to fix the code for my arduino uno and thx.


that was a reply of "vaj4088" : >>

The language is C so it is compatible with Arduino (Uno or otherwise). However, the code has line numbers that should not be there.

The code depends upon refclk (line 25) which you have to measure.
The frequency is currently set to 1000 Hz at line 50, but the frequency probably depends upon refclk as well.

The code is NOT set up for 0, 120 degrees and 240 degrees.


this is helping me but i can not understand correctly the steps to find out the lines that must be removed

any help for that please ???

Capture.PNG

include.doc (37.5 KB)

Loopi:
However, the code has line numbers that should not be there.

I fixed that issue for you(n++ block select is a life saver!):

#include "avr/pgmspace.h"
#include "avr/io.h"

// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM  prog_uchar sine256[]  = {
  127, 130, 133, 136, 139, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 178, 181, 184, 187, 190, 192, 195, 198, 200, 203, 205, 208, 210, 212, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 234, 236, 238, 239, 240,
  242, 243, 244, 245, 247, 248, 249, 249, 250, 251, 252, 252, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 252, 252, 251, 250, 249, 249, 248, 247, 245, 244, 243, 242, 240, 239, 238, 236, 234, 233, 231, 229, 227, 225, 223,
  221, 219, 217, 215, 212, 210, 208, 205, 203, 200, 198, 195, 192, 190, 187, 184, 181, 178, 176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 146, 143, 139, 136, 133, 130, 127, 124, 121, 118, 115, 111, 108, 105, 102, 99, 96, 93, 90, 87, 84, 81, 78,
  76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31,
  33, 35, 37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 115, 118, 121, 124
};


#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
int PWM_OUT_1 = 11; // PWM output on pin 11
int PWM_OUT_2 = 10; // PWM output on pin 10
int PWM_OUT_3 = 12; // PWM output on pin 9
int LED_PIN = 13; // LED status on pin 13
int TEST_PIN = 7; // Scope trigger on pin 7
int POTEN_IN = A0; // Potentiometer on pin 0
int OFFSET_1 = 85; // Offset for second-phase
int OFFSET_2 = 170; // Offset for third-phase
double dfreq;
const double refclk = 31376.6; // measured
const uint64_t twoTo32 = pow(2, 32); // compute value at startup and use as constant
// variables used inside interrupt service declared as voilatile
volatile uint8_t icnt; // var inside interrupt
volatile uint8_t icnt1; // var inside interrupt
volatile uint8_t c4ms; // counter incremented every 4ms
volatile uint32_t phase_accum; // pahse accumulator
volatile uint32_t tword_m; // dds tuning word m
//******************************************************************
void setup()
{
  pinMode(LED_PIN, OUTPUT); // sets the digital pin as output
  Serial.begin(115200); // connect to the serial port
  Serial.println("DDS Test");

  pinMode(TEST_PIN, OUTPUT); // sets the digital pin as output
  pinMode(PWM_OUT_1, OUTPUT); // PWM output / frequency output
  pinMode(PWM_OUT_2, OUTPUT); // PWM output / frequency output
  pinMode(PWM_OUT_3, OUTPUT); // PWM output / frequency output
  // Setup the timers
  setup_timer1();
  setup_timer2();
  // disable interrupts to avoid timing distortion
  cbi (TIMSK0, TOIE0); // disable Timer0 !!! delay() is now not available
  sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt
  dfreq = 1000.0; // initial output frequency = 1000.0 Hz
  tword_m = twoTo32 * dfreq / refclk; // calulate DDS new tuning word
}
//******************************************************************
void loop()
{
  if (c4ms > 250) // timer / wait for a full second
  {
    c4ms = 0;
    dfreq = analogRead(POTEN_IN); // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz
    cbi (TIMSK2, TOIE2); // disble Timer2 Interrupt
    tword_m = twoTo32 * dfreq / refclk; // calulate DDS new tuning word
    sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt
    Serial.print(dfreq);
    Serial.print(" ");
    Serial.println(tword_m);
  }
}
//******************************************************************
// timer1 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/512 = 31.25kHz clock
void setup_timer1(void)
{
  // Timer1 Clock Prescaler to : 1
  sbi (TCCR1B, CS10);
  cbi (TCCR1B, CS11);
  cbi (TCCR1B, CS12);
  // Timer0 PWM Mode set to Phase Correct PWM
  cbi (TCCR1A, COM1A0); // clear Compare Match
  sbi (TCCR1A, COM1A1);
  cbi (TCCR1A, COM1B0); // clear Compare Match
  sbi (TCCR1A, COM1B1);
  sbi (TCCR1A, WGM10); // Mode 1 / Phase Correct PWM
  cbi (TCCR1A, WGM11);
  cbi (TCCR1B, WGM12);
  cbi (TCCR1B, WGM13);
}

//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/512 = 31.25kHz clock
void setup_timer2()
{
  // Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);
  // Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0); // clear Compare Match
  sbi (TCCR2A, COM2A1);
  sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);
}
//******************************************************************
// Timer2 Interrupt Service at 31.25kHz = 32us
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect)
{
  sbi(PORTD, TEST_PIN); // Test / set PORTD,TEST_PIN high to observe timing with a oscope
  phase_accum += tword_m; // soft DDS, phase accu with 32 bits
  icnt = phase_accum >> 24; // use upper 8 bits for phase accu as frequency information
  OCR2A = pgm_read_byte_near(sine256 + icnt); // read value fron ROM sine table and send to PWM DAC
  OCR1A = pgm_read_byte_near(sine256 + (uint8_t)(icnt + OFFSET_1));
  OCR1B = pgm_read_byte_near(sine256 + (uint8_t)(icnt + OFFSET_2));
  if (icnt1++ == 125) // increment variable c4ms every 4 milliseconds
  {
    c4ms++;
    icnt1 = 0;
  }
  cbi(PORTD, TEST_PIN); // reset PORTD,TEST_PIN
}

There is still a possible problem that will make the code not compile on recent versions of the Arduino IDE. So if it won't compile for you then change line 5 from:

PROGMEM  prog_uchar sine256[]  = {

to:

const byte sine256[] PROGMEM  = {

After doing that it compiles for Uno with Arduino IDE 1.6.8 fine for me. Hopefully that will give you a start towards getting this working for your application.

i have arduino 1.6.8 >> i changed for "const byte sine256[] PROGMEM = {" then it compiled correctly..

THANK YOU so much for your help

but can i ask you a real favor ... coz i want to learn not just do the work

I want to understand this code correctly and what you fixed and why.... please

Loopi:
what you fixed and why.... please

The only thing I changed from the code you posted was to remove the line numbers and a Tools > Auto Format to automatically indent the code to make it easier to read.

As for the PROGMEM change, there is a good explanation of why this change was required here: compile error since IDE 1.5.8 - #5 by bperrybap - Programming Questions - Arduino Forum. So basically the code you posted in include.doc was written for older versions of the Arduino IDE, probably it would work with 1.0.6 and previous but more recent versions of the Arduino IDE changed to using a newer compiler version so that required changes from the previously recommended way of using PROGMEM. Instead of using types like prog_uchar you need to use the standard types and the const keyword. So prog_uchar means an unsigned char in program memory(progmem) unsigned char is an unsigned 8 bit type(uint8_t) which is commonly called a byte in Arduino sketches. So you could also use

const unsigned char sine256[] PROGMEM  = {

or

const uint8_t sine256[] PROGMEM  = {

But byte seems to be considered a more beginner friendly type name in the Arduino world.

pert:
The only thing I changed from the code you posted was to remove the line numbers and a Tools > Auto Format to automatically indent the code to make it easier to read.

As for the PROGMEM change, there is a good explanation of why this change was required here: compile error since IDE 1.5.8 - #5 by bperrybap - Programming Questions - Arduino Forum. So basically the code you posted in include.doc was written for older versions of the Arduino IDE, probably it would work with 1.0.6 and previous but more recent versions of the Arduino IDE changed to using a newer compiler version so that required changes from the previously recommended way of using PROGMEM. Instead of using types like prog_uchar you need to use the standard types and the const keyword. So prog_uchar means an unsigned char in program memory(progmem) unsigned char is an unsigned 8 bit type(uint8_t) which is commonly called a byte in Arduino sketches. So you could also use

const unsigned char sine256[] PROGMEM  = {

or

const uint8_t sine256[] PROGMEM  = {

But byte seems to be considered a more beginner friendly type name in the Arduino world.

i'm really grateful man .. thank you very much pert

I have same program
But i need 50 hz frequency output.
Which type change i do in program