Go Down

### Topic: help for programming an arduino uno (Read 2230 times)previous topic - next topic

#### Loopi

##### Apr 19, 2016, 07:42 am
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

#### pert

#1
##### Apr 19, 2016, 01:57 pm
However, the code has line numbers that should not be there.
I fixed that issue for you(n++ block select is a life saver!):
Code: [Select]
`#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 calculatedPROGMEM  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 11int PWM_OUT_2 = 10; // PWM output on pin 10int PWM_OUT_3 = 12; // PWM output on pin 9int LED_PIN = 13; // LED status on pin 13int TEST_PIN = 7; // Scope trigger on pin 7int POTEN_IN = A0; // Potentiometer on pin 0int OFFSET_1 = 85; // Offset for second-phaseint OFFSET_2 = 170; // Offset for third-phasedouble dfreq;const double refclk = 31376.6; // measuredconst uint64_t twoTo32 = pow(2, 32); // compute value at startup and use as constant// variables used inside interrupt service declared as voilatilevolatile uint8_t icnt; // var inside interruptvolatile uint8_t icnt1; // var inside interruptvolatile uint8_t c4ms; // counter incremented every 4msvolatile uint32_t phase_accum; // pahse accumulatorvolatile 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 clockvoid 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 clockvoid 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:
Code: [Select]
`PROGMEM  prog_uchar sine256[]  = {`
to:
Code: [Select]
`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.

#### Loopi

#2
##### Apr 20, 2016, 04:15 pm
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

#### pert

#3
##### Apr 20, 2016, 10:35 pm
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: http://forum.arduino.cc/index.php?topic=272313.msg1919623#msg1919623. 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
Code: [Select]
`const unsigned char sine256[] PROGMEM  = {`
or
Code: [Select]
`const uint8_t sine256[] PROGMEM  = {`
But byte seems to be considered a more beginner friendly type name in the Arduino world.

#### Loopi

#4
##### Apr 22, 2016, 06:09 am
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: http://forum.arduino.cc/index.php?topic=272313.msg1919623#msg1919623. 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
Code: [Select]
`const unsigned char sine256[] PROGMEM  = {`
or
Code: [Select]
`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

#### Pvprajapati

#5
##### Jan 02, 2018, 12:55 pm
I have same program
But i need 50 hz frequency output.
Which type change i do in program

Go Up