Go Down

Topic: SINE GENERATOR (Read 768 times) previous topic - next topic

profy

Hola!
Tengo este codigo que genera una señal sinusoidal en el pin 11 PWM
Lo que me interesa es si alguien puede modificar el codigo para que en en otro pin me salga otros pulsos sincronisados con el 11.
Con otras palavras .... tenemos el arry sine256[]  = {127,130,133,136,139,143,146,149.... y nesesito por ejemplo en el pin 4
como un reloj sincronizado con el sinus. Por ejemplo valor 127 .... pin 4 (0, 1)   valor 130 (0, 1)  por cada valor del sinus un pulso de 1 y 0

aqui le dejo el codigo!

#include "avr/pgmspace.h"
// table of 256 sine values / one sine period / stored in flash memory
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))

double dfreq;
// const double refclk=31372.549;  // =16MHz / 510
const double refclk=31376.6;      // measured

// variables used inside interrupt service declared as voilatile
volatile byte icnt;              // var inside interrupt
volatile byte icnt1;             // var inside interrupt
volatile byte c4ms;              // counter incremented all 4ms
volatile unsigned long phaccu;   // pahse accumulator
volatile unsigned long tword_m;  // dds tuning word m

void setup()
{
pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output
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=181.2;                    // initial output frequency = 1000.o Hz
  tword_m=pow(2,32)*dfreq/refclk;  // calulate DDS new tuning word

}
void loop()
{
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz 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 31372,550 KHz = 32uSec
// 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) {
phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
icnt=phaccu >> 24;     // use upper 8 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
OCR2A=pgm_read_byte_near(sine256 + icnt);
if(icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}   
}


Igor R

Hola,

¿Qué es lo que no entiendes del código para no poder hacerlo tu mismo?
Mira este tutorial que está muy bien (en inglés):
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106


Saludos


;)

profy

Hola Igor!
Me vuelvo loquito entre los timers... si me puedes ayudar modificame el codigo y segurisimo te voy agradeser mucho!
lo unico que necesito es un clock a uno de los pines que quieres tu y un pino por el start. Es decir ... empiesa el sinus .. un pulso 1 al pin 6 por ejemplo y luego 0 asta que se termina el sinus y otro pin que cambia a 0 y 1 por cada valor del sinus.
te dejo tambien mi mess proy2002@yahoo.com para una larga colaboratcion y no lo haces por nada. Igual como se va leyendo una memoria eprom donde tenemos el clock el counter y los datos paralelos que salga de la memoria. Entonses me interesa el START , El CLOCK , y los valores del sinus existe en el pin 11. Mucha Gracia!

ionhs


Hola,

¿Qué es lo que no entiendes del código para no poder hacerlo tu mismo?
Mira este tutorial que está muy bien (en inglés):
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106


Saludos


;)



Que buen tutorial Igor, (lastima lo del ingles, aunque con el google traductor y un poco de concentración es fácil) haber si hago un hueco y me pongo definitivamente con el tema de los timers. Muchas gracias


Hola Igor!
Me vuelvo loquito entre los timers... si me puedes ayudar modificame el codigo y segurisimo te voy agradeser mucho!


Profy deja de echarle jeta y trabajalo tu, ¿que te está costando? no pasa nada así se aprende. ¿Que tienes dudas puntuales tras consultar la página que ha puesto Igor? Pregúntalas seguro que Igor o algún otro te responde. Pero no creo que alguien te haga el código.

*

Ya ni preguntar dudas para intentar hacerlo uno mismo, directamente pedir que alguien te haga el código  :0


Sergegsx


Hola Igor!
Me vuelvo loquito entre los timers... si me puedes ayudar modificame el codigo y segurisimo te voy agradeser mucho!
lo unico que necesito es un clock a uno de los pines que quieres tu y un pino por el start. Es decir ... empiesa el sinus .. un pulso 1 al pin 6 por ejemplo y luego 0 asta que se termina el sinus y otro pin que cambia a 0 y 1 por cada valor del sinus.
te dejo tambien mi mess proy2002@yahoo.com para una larga colaboratcion y no lo haces por nada. Igual como se va leyendo una memoria eprom donde tenemos el clock el counter y los datos paralelos que salga de la memoria. Entonses me interesa el START , El CLOCK , y los valores del sinus existe en el pin 11. Mucha Gracia!


para que te hagan tu trabajo te recomiendo esta web
http://www.freelancer.com/  o esta  http://www.guru.com/


fm

Pero mira que sois...

Hay que publicar directamente la cuenta de paypal, hombre.
   

Igor R

Si quereis en castellano un mini manual de introducción, escribí esto sobre el timer 2 => http://real2electronics.blogspot.com/2011/01/timer-2.html

;)

curro92

Hola,
gracias, Igor, me ha gustado el tutorial de avrfreaks, tan claro y didáctico. Ya sé lo que voy a empollarme este invierno: los timer, los puertos, las operaciones a nivel de bits... todo eso que suelo ver en el código de algunos programas, pero que nunca lo entendí detalladamente.

profy

Hola a todos!
Primero tengo que agradecerle muchisimo a Igor porque de verdad me ayudo mucho.
No puedo decir que controlo los timers, despues de una noche de estudio pero he entendido leyendo su publicacion de que se trata y he echo los primeros pasos en cambiar mi codigo.
AQUI http://www.carpinteriaaluminioypvc.com/SINE_PULSE.jpg tienes una foto del osciloscopio y mas abajo le dejo el codigo, mas limpio y mas simple.

#include "avr/pgmspace.h"

// table of 256 sine values / one sine period / stored in flash memory
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))
double dfreq;
// const double refclk=31372.549;  // =16MHz / 510
const double refclk=31376.6;      // measured

// variables used inside interrupt service declared as voilatile
volatile byte puls; 
volatile byte icnt;              // var inside interrupt

volatile byte c4ms;              // counter incremented all 4ms
volatile unsigned long phaccu;   // pahse accumulator
volatile unsigned long tword_m;  // dds tuning word m

void setup()
{
pinMode (4, OUTPUT);
pinMode (7, OUTPUT);
pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output
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=40;                    // initial output frequency = 1000.o Hz
  tword_m=pow(2,32)*dfreq/refclk;  // calulate DDS new tuning word

}
void loop()
{

 
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz 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 31372,550 KHz = 32uSec
// 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,7);          // Test / set PORTD,7 high to observe timing with a oscope
  cbi(PORTD,4);
  phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
  icnt=phaccu >> 24;     // use upper 8 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
  OCR2A=pgm_read_byte_near(sine256 + icnt);
  //if (bitRead(icnt++,7) == 0){sbi(PORTD,7);}
  if(icnt >= 192) {cbi(PORTD,7);}
  if (icnt % 2 == 0) // verificando paridad
  {
    sbi (PORTD,4);
  }
   
             // reset PORTD,7
}

Igor R

Hola profy,

Me alegro que vayas progresando en tu proyecto.

Ánimo!


;)

Go Up