No podemos generar una señal sinusoidal correctamente utilizando un microcontrolador MC68HC908GP32 . La descripción de PWM comienza en la página 349. La frecuencia del reloj es de 2.4MHz, mientras que hemos usado PWM de 7 kHz usando el preescalador y configurando el módulo del temporizador a 350 de la siguiente manera:
T1SC = 0x60; // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01; // High
T1MODL = 0x5E; // Low
La salida PWM se filtra mediante el siguiente filtro RLC, y luego se elimina la CC con una tapa de serie 1uF. La frecuencia de corte está muy por debajo de los 7kHz de PWM.
Primero, hemos intentado usar un LUT, cuyas muestras se generaron usando este sitio (100 muestras, amplitud = 250). Esto comprende un solo período.
int seno[100]={ 125, 133, 141, 148, 156, 164, 171, 178, 185, 192, 198, 205, 211, 216, 221, 226, 231, 235, 238, 241, 244, 246, 248, 249, 250, 250, 250, 249, 248, 246, 244, 241, 238, 235, 231, 226, 221, 216, 211, 205, 198, 192, 185, 178, 171, 164, 156, 148, 141, 133, 125, 117, 109, 102, 94, 86, 79, 72, 65, 58, 52, 45, 39, 34, 29, 24, 19, 15, 12, 9, 6, 4, 2, 1, 0, 0, 0, 1, 2, 4, 6, 9, 12, 15, 19, 24, 29, 34, 39, 45, 52, 58, 65, 72, 79, 86, 94, 102, 109, 117};
El ancho del siguiente pulso se calcula en cada ciclo PWM:
interrupt 4 void rsi_t1ch0 (void)
{
//-- disable interruption flag
T1SC0&=(~0x80);
//-- pwm to '0'
PTB&=0xFD;
//some sensor measures are done here.... 100 out of the 350 cycles are left for this
}
/************************************************************/
/* TIM1 overflow rutine */
/************************************************************/
interrupt 6 void rsi_ov1 (void)
{
T1SC&=(~0x80);
//-- set PWM to 1
PTB|=0x02;
T1CH0H = ((seno[fase])>>8); // high bits
T1CH0L = (seno[fase])&0xFF; // low bits
fase+=1;
if (fase >= 99)
fase=0;
}
void main(void)
{
float temp;
int i;
CONFIG1|=0x01;
DDRB=0xFF; //-- Port B is set as output
PTB=0x00;
//Timer setup
T1SC = 0x60; // Prescaler: Div by 64
T1MODH = 0x01; //Counter modulo
T1MODL = 0x5E;
T1SC0 = 0x50; //Comparator setup
//-- Initial width
T1CH0H = 0x00;
T1CH0L = 0x53;
EnableInterrupts;
T1SC&=~(0x20); //Run timer forever
for(;;);
}
Cuando lo conectamos al alcance, obtenemos la siguiente señal. No podemos evitar ese pico extraño cerca del mínimo.
Al hacer zoom alrededor de ese pico, podemos ver cómo la salida PWM (arriba) es de hecho incorrecta.
Entonces, después de jugar un rato y no poder deshacernos de él, hemos intentado calcular la señal sinusoidal en la MCU, en lugar de codificar el valor de cada muestra. Hemos agregado el siguiente código en la función principal, justo antes de toda la configuración del contador:
for(i=0;i<99;i++) {
temp=100*(sin(2*3.14159*i/100)+1);
seno[i]=(int)temp;
}
Pero los resultados ni siquiera parecen una sinusoide:
Después de horas luchando con eso, no hemos podido encontrar nuestro error. Agradeceríamos un consejo.