Generación de señal sinusoidal utilizando PWM

16

No podemos generar una señal sinusoidal correctamente usando un MC68HC908GP32 microcontroller. La descripción de PWM comienza en la página 349. La frecuencia del reloj es 2.4MHz, mientras que hemos usado PWM de 7 kHz usando el prescaler y configurando el módulo de 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 por el siguiente filtro RLC, y luego se elimina DC utilizando una tapa de 1uF de la serie. La frecuencia de corte está muy por debajo de los 7kHz de PWM.

Primero,hemosintentadousarunaLUT,cuyasmuestrassegeneraronusandoestesitio(100muestras,amplitud=250).Estocomprendeunsoloperíodo.

intseno[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};

ElanchodelsiguientepulsosecalculacadacicloPWM:

interrupt4voidrsi_t1ch0(void){//--disableinterruptionflagT1SC0&=(~0x80);//--pwmto'0'PTB&=0xFD;//somesensormeasuresaredonehere....100outofthe350cyclesareleftforthis}/************************************************************//*TIM1overflowrutine*//************************************************************/interrupt6voidrsi_ov1(void){T1SC&=(~0x80);//--setPWMto1PTB|=0x02;T1CH0H=((seno[fase])>>8);//highbitsT1CH0L=(seno[fase])&0xFF;//lowbitsfase+=1;if(fase>=99)fase=0;}voidmain(void){floattemp;inti;CONFIG1|=0x01;DDRB=0xFF;//--PortBissetasoutputPTB=0x00;//TimersetupT1SC=0x60;//Prescaler:Divby64T1MODH=0x01;//CountermoduloT1MODL=0x5E;T1SC0=0x50;//Comparatorsetup//--InitialwidthT1CH0H=0x00;T1CH0L=0x53;EnableInterrupts;T1SC&=~(0x20);//Runtimerforeverfor(;;);}

Alinsertarloenelalcance,obtenemoslasiguienteseñal.Nopodemosevitaresepicoextrañocercadelmínimo.

Al hacer zoom alrededor de ese pico, podemos ver cómo la salida de PWM (arriba) en realidad es incorrecta.

Entonces,despuésdeperdereltiempoporuntiempoydenopoderdeshacernosdeél,hemosintentadocalcularlaseñalsinusoidalenlaMCU,enlugardecodificarelvalordecadamuestra.Hemosagregadoelsiguientecódigoenlafunciónprincipal,justoantesdelaconfiguracióndelcontador:

for(i=0;i<99;i++){temp=100*(sin(2*3.14159*i/100)+1);seno[i]=(int)temp;}

Perolosresultadosnisiquieraparecenunasinusoide:

Después de horas luchando con esto, no hemos podido encontrar nuestro error. Agradeceríamos un consejo.

    
pregunta Serge

1 respuesta

16

En la parte inferior de la página 350 de la hoja de datos del microcontrolador, se menciona que escribir un valor pequeño en el registro de valores del temporizador durante la interrupción de desbordamiento podría hacer que la siguiente interrupción se dispare solo en la próxima iteración pwm, ya que el temporizador continúa contar mientras se ejecuta la rutina de interrupción.

  

Una escritura no sincronizada en los registros del canal TIM para cambiar un pulso   el valor de ancho podría causar una operación incorrecta por hasta dos períodos PWM.   Por ejemplo, escribiendo un nuevo valor antes de que el contador llegue al antiguo   valor, pero después de que el contador alcanza el nuevo valor evita cualquier comparación   durante ese período PWM. Además, utilizando una rutina de interrupción de desbordamiento de TIM para   escribir un nuevo valor de ancho de pulso más pequeño puede hacer que la comparación sea   perdido El TIM puede pasar el nuevo valor antes de que se escriba.

Esto se confirma por el hecho de que el valor de pwm se mantiene alto durante todo un período de reloj pwm + lo que parece ser la longitud del temporizador (según las longitudes circundantes). El valor que se escribe en el registro de longitud del temporizador es probablemente cercano a 0 en el momento del error, por lo que es bastante viable que el contador haya pasado el valor más pequeño durante la interrupción y solo se activaría en el siguiente ciclo.

Esto podría solucionarse aumentando el nivel mínimo de sinusoides a un nivel más alto que el tiempo necesario para ejecutar el ISR, o cambiando el mecanismo por el cual se establece el nuevo nivel. La parte superior de la página 351 detalla cómo se puede hacer esto.

    
respondido por el stanri

Lea otras preguntas en las etiquetas