Probar una aplicación de audio PWM. No puedo entender por qué recibo un pitido fuerte que se superpone a mi sonido

5

Quiero reproducir algunos clips de audio cortos (que van desde 50 ms a 100 ms) desde mi microcontrolador atmega168 y enviarlos a un altavoz barato.

Estaba siguiendo este tutorial pero porque estoy usando un atmega168 y no atmega2560, tuve que modificar mi código y reemplazar el sonido.

Al igual que en el tutorial, estoy usando un oscilador interno de 8MHz (configuro LFUSE = 0xE2 en el Makefile) y todas las configuraciones de PWM son las mismas ... lo que significa

  • Usando un 16 Timer / Counter1 con resolución PWM de 8 bits
  • Establezca OC1A en comparación de coincidencias (y desactive en la parte inferior)
  • Sin preescalado

En cuanto al clip de sonido, lo probé a 15.625 kHz y lo exporté a un archivo wav PCM de 8 bits. Luego obtengo un volcado hexadecimal a través de xxd -i que me da el archivo c de salida. No eliminé el encabezado porque pensé que solo podía saltearlo yendo a la 44ª posición de la salida array como es la posición de los datos.

El problema que tengo es que, si bien recibo mi sonido (distorsionado y suave), hay un pitido fuerte que se superpone con mi sonido y no tengo idea de qué lo está causando.

Lamentablemente, no tengo acceso a un osciloscopio, así que realmente no puedo determinar si es la forma en que probé mi sonido, o si mi sonido es demasiado corto o algo que está más allá de mi comprensión actual.

Main.c

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/power.h>
#include <util/setbaud.h>
#include <avr/interrupt.h>

#include "switch.h"
#define WAV_DATA_POSITION 44 
#define BASE_LEVEL 0xff

unsigned int  count=WAV_DATA_POSITION;;
volatile uint16_t timerOverflowCount;
unsigned char sample_count =2;

// This interrupt service reads new data, 
ISR(TIMER1_OVF_vect){

    sample_count--;

    if(sample_count ==0)
    {
        sample_count = 2;
        if (count < switchResampled_len){
            OCR1A= pgm_read_byte(&switch_raw[count]);
            count++;
        }
    }
    else{
        OCR1A= BASE_LEVEL;
    }
}

void pwm_init()
{

    SREG |=0x80;

    //select Fast PWM with 8-bit resolution,set OC1A on compare match and clear at bottom
    TCCR1A|=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM10);  

    //No prescaling therefore timer frequency = 8 MHz and PWM frequency = 31250 Hz
    TCCR1B|=(1<<WGM12)|(1<<CS10);          

    TCNT1=0x00;

    OCR1A=BASE_LEVEL;
    //Enable the timer interrupt
    TIMSK1 |= ( 1 <<TOIE1); 

    //Clear all interupt flags
    TIFR1|=(1<<ICF1)|(1<<OCF1B)|(1<<OCF1A)|(1<<TOV1); 

    //Enable interrupts
    sei(); 

}


int main(void)
{
    //PB1 is OC1A. Use this for output
    DDRB |= (1 << PB1);
    pwm_init();

    /* insert your hardware initialization here */
    for(;;){

        /* insert your main loop code here */
    }
    return 0;   /* never reached */
}

Switch.h (archivo de sonido)

const unsigned char switch_raw[] PROGMEM = {
  0x52, 0x49, 0x46, 0x46, 0x0d, 0x04, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
  0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
  0x09, 0x3d, 0x00, 0x00, 0x09, 0x3d, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00,
  0x64, 0x61, 0x74, 0x61, 0x4b, 0x03, 0x00, 0x00, 0x80, 0x7f, 0x7f, 0x7e,
  0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x80, 0x7f, 0x7e, 0x7e,
  0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x7f, 0x81, 0x7e, 0x7e, 0x7f, 0x7f,
  0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7d, 0x80, 0x81, 0x7e, 0x7b, 0x7e, 0x7f,
  0x7f, 0x81, 0x7e, 0x7e, 0x7d, 0x80, 0x80, 0x7e, 0x7e, 0x7e, 0x7d, 0x7e,
  0x80, 0x80, 0x7e, 0x7c, 0x7d, 0x7f, 0x81, 0x7f, 0x7e, 0x81, 0x7d, 0x7b,
  0x80, 0x7f, 0x7f, 0x83, 0x7f, 0x7b, 0x7f, 0x80, 0x7f, 0x82, 0x7f, 0x7e,
  0x80, 0x7e, 0x81, 0x7f, 0x7f, 0x81, 0x7d, 0x7e, 0x80, 0x7e, 0x80, 0x7e,
  0x7f, 0x85, 0x80, 0x83, 0x7b, 0x77, 0x83, 0x81, 0x86, 0x7e, 0x7b, 0x7e,
  0x81, 0x83, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x82, 0x7f, 0x7e, 0x7e, 0x7e,
  0x81, 0x83, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x7e, 0x7e, 0x80, 0x83,
  0x7f, 0x7d, 0x7b, 0x80, 0x80, 0x94, 0x79, 0x68, 0x87, 0x75, 0x98, 0x87,
  0x6e, 0x7f, 0x8c, 0x81, 0x54, 0x7c, 0xc4, 0x8a, 0x46, 0x31, 0x72, 0xe2,
  0xc1, 0x8a, 0x41, 0x2f, 0x71, 0xb3, 0xc8, 0x96, 0x51, 0x41, 0x67, 0x9c,
  0xb1, 0x98, 0x74, 0x57, 0x5f, 0x76, 0x99, 0xa8, 0x96, 0x72, 0x5b, 0x64,
  0x7e, 0x97, 0xa1, 0x8f, 0x6f, 0x56, 0x66, 0x89, 0xa0, 0x9d, 0x7e, 0x62,
  0x5c, 0x78, 0x93, 0x9d, 0x90, 0x70, 0x58, 0x68, 0x88, 0x9c, 0x95, 0x7c,
  0x66, 0x64, 0x7c, 0x90, 0x95, 0x82, 0x6f, 0x6b, 0x75, 0x86, 0x8e, 0x88,
  0x79, 0x72, 0x75, 0x80, 0x88, 0x89, 0x81, 0x78, 0x74, 0x78, 0x84, 0x85,
  0x84, 0x7d, 0x7b, 0x7c, 0x7b, 0x80, 0x85, 0x87, 0x81, 0x76, 0x74, 0x7e,
  0x82, 0x89, 0x84, 0x7c, 0x77, 0x78, 0x84, 0x83, 0x84, 0x7c, 0x78, 0x7b,
  0x83, 0x83, 0x80, 0x83, 0x80, 0x7d, 0x7a, 0x7e, 0x83, 0x87, 0x82, 0x79,
  0x78, 0x7e, 0x87, 0x8b, 0x80, 0x76, 0x79, 0x7e, 0x87, 0x87, 0x80, 0x7a,
  0x7a, 0x80, 0x82, 0x84, 0x81, 0x7f, 0x7e, 0x7d, 0x7a, 0x82, 0x88, 0x7f,
  0x7a, 0x79, 0x7f, 0x85, 0x85, 0x7f, 0x7d, 0x7a, 0x7d, 0x83, 0x87, 0x7e,
  0x78, 0x7e, 0x7d, 0x83, 0x7e, 0x81, 0x81, 0x80, 0x7f, 0x81, 0x81, 0x7c,
  0x7e, 0x7a, 0x81, 0x82, 0x81, 0x84, 0x82, 0x79, 0x78, 0x84, 0x86, 0x7d,
  0x7b, 0x7e, 0x7f, 0x7c, 0x7d, 0x7d, 0x82, 0x80, 0x80, 0x7e, 0x7d, 0x85,
  0x84, 0x7b, 0x75, 0x7c, 0x7d, 0x84, 0x88, 0x84, 0x7b, 0x7b, 0x7d, 0x7c,
  0x88, 0x88, 0x7b, 0x78, 0x78, 0x78, 0x88, 0x8d, 0x80, 0x78, 0x7f, 0x86,
  0x86, 0x83, 0x7c, 0x71, 0x76, 0x84, 0x97, 0x93, 0x70, 0x6d, 0x68, 0x78,
  0xc5, 0xb6, 0x5f, 0x37, 0x2a, 0x69, 0xc1, 0xc9, 0xa0, 0x7a, 0x52, 0x50,
  0x71, 0x8a, 0x9d, 0xa0, 0x8b, 0x69, 0x67, 0x68, 0x79, 0x94, 0x96, 0x87,
  0x7b, 0x81, 0x84, 0x7e, 0x7d, 0x7e, 0x75, 0x72, 0x89, 0x8e, 0x88, 0x86,
  0x6d, 0x6d, 0x7a, 0x82, 0x8d, 0x8e, 0x78, 0x76, 0x7f, 0x7d, 0x7e, 0x82,
  0x80, 0x7b, 0x7d, 0x7a, 0x7b, 0x86, 0x89, 0x80, 0x7b, 0x75, 0x77, 0x7f,
  0x83, 0x84, 0x86, 0x81, 0x81, 0x7e, 0x73, 0x7c, 0x83, 0x7f, 0x85, 0x82,
  0x7d, 0x83, 0x7d, 0x7d, 0x80, 0x7b, 0x7c, 0x86, 0x85, 0x7e, 0x7b, 0x74,
  0x7d, 0x86, 0x85, 0x8b, 0x81, 0x76, 0x78, 0x78, 0x7e, 0x89, 0x83, 0x7e,
  0x80, 0x78, 0x7f, 0x84, 0x81, 0x84, 0x7a, 0x77, 0x7f, 0x81, 0x84, 0x81,
  0x78, 0x7a, 0x7e, 0x84, 0x8e, 0x81, 0x72, 0x75, 0x77, 0x83, 0x8b, 0x84,
  0x84, 0x7b, 0x72, 0x7a, 0x83, 0x84, 0x85, 0x7e, 0x78, 0x7e, 0x7d, 0x7f,
  0x82, 0x80, 0x7f, 0x7e, 0x7f, 0x81, 0x7e, 0x7b, 0x80, 0x85, 0x84, 0x82,
  0x7d, 0x7a, 0x7d, 0x7f, 0x84, 0x84, 0x7f, 0x79, 0x7b, 0x82, 0x80, 0x80,
  0x81, 0x80, 0x81, 0x81, 0x7f, 0x7e, 0x79, 0x79, 0x81, 0x86, 0x85, 0x82,
  0x7d, 0x77, 0x7a, 0x7e, 0x86, 0x8b, 0x84, 0x7a, 0x7a, 0x7d, 0x7e, 0x83,
  0x83, 0x80, 0x7e, 0x7c, 0x7c, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x7e,
  0x7f, 0x80, 0x7f, 0x7c, 0x80, 0x7d, 0x7e, 0x85, 0x81, 0x7c, 0x7d, 0x7b,
  0x7c, 0x81, 0x80, 0x7d, 0x7f, 0x80, 0x7d, 0x82, 0x84, 0x7e, 0x7a, 0x7e,
  0x7e, 0x7f, 0x82, 0x7d, 0x7e, 0x81, 0x7f, 0x7d, 0x7e, 0x81, 0x83, 0x83,
  0x80, 0x79, 0x77, 0x7c, 0x83, 0x87, 0x86, 0x7f, 0x75, 0x79, 0x7e, 0x85,
  0x86, 0x80, 0x7a, 0x78, 0x7c, 0x7f, 0x83, 0x81, 0x82, 0x7d, 0x7a, 0x7f,
  0x81, 0x80, 0x80, 0x7c, 0x7b, 0x80, 0x7e, 0x80, 0x85, 0x84, 0x7d, 0x7b,
  0x7a, 0x7f, 0x83, 0x82, 0x80, 0x7c, 0x7e, 0x7e, 0x80, 0x81, 0x7f, 0x7f,
  0x7e, 0x7f, 0x82, 0x7f, 0x7c, 0x7b, 0x7b, 0x82, 0x84, 0x83, 0x7e, 0x7c,
  0x7b, 0x7e, 0x83, 0x81, 0x7f, 0x7d, 0x7e, 0x7f, 0x83, 0x81, 0x7e, 0x7d,
  0x7b, 0x7d, 0x80, 0x82, 0x81, 0x80, 0x7f, 0x7d, 0x7f, 0x80, 0x7f, 0x80,
  0x81, 0x80, 0x7f, 0x7d, 0x7d, 0x7e, 0x81, 0x82, 0x80, 0x7d, 0x7f, 0x81,
  0x80, 0x7f, 0x7d, 0x7c, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7e, 0x7f,
  0x7d, 0x7e, 0x80, 0x81, 0x80, 0x7f, 0x7e, 0x7c, 0x7f, 0x81, 0x80, 0x80,
  0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x80, 0x7d,
  0x7c, 0x7f, 0x80, 0x83, 0x81, 0x7c, 0x7b, 0x7c, 0x7f, 0x82, 0x82, 0x7f,
  0x7d, 0x7c, 0x7e, 0x80, 0x81, 0x81, 0x7f, 0x7f, 0x7d, 0x7d, 0x80, 0x82,
  0x7f, 0x7e, 0x7d, 0x7d, 0x80, 0x83, 0x82, 0x7f, 0x7f, 0x7a, 0x7d, 0x80,
  0x81, 0x81, 0x80, 0x7e, 0x7f, 0x80, 0x7e, 0x7e, 0x7f, 0x80, 0x7f, 0x80,
  0x7f, 0x7e, 0x7d, 0x7f, 0x7e, 0x80, 0x81, 0x81, 0x80, 0x80, 0x7e, 0x7e,
  0x7e, 0x7d, 0x80, 0x7f, 0x80, 0x81, 0x7f, 0x7e, 0x7e, 0x7c, 0x7f, 0x82,
  0x7f, 0x80, 0x7f, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x7e, 0x7f,
  0x7f, 0x7f, 0x80, 0x7e, 0x7f, 0x7f, 0x80, 0x81, 0x7f, 0x7e, 0x7d, 0x7d,
  0x81, 0x82, 0x80, 0x7e, 0x7d, 0x7e, 0x80, 0x81, 0x7f, 0x80, 0x80, 0x7f,
  0x7f, 0x7d, 0x7f, 0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7d, 0x7e, 0x4c,
  0x49, 0x53, 0x54, 0x48, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x46, 0x4f, 0x49,
  0x43, 0x52, 0x44, 0x12, 0x00, 0x00, 0x00, 0x32, 0x30, 0x31, 0x36, 0x2d,
  0x31, 0x30, 0x2d, 0x31, 0x37, 0x20, 0x31, 0x37, 0x3a, 0x32, 0x37, 0x00,
  0x00, 0x49, 0x53, 0x46, 0x54, 0x22, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x76,
  0x66, 0x35, 0x37, 0x2e, 0x37, 0x32, 0x2e, 0x31, 0x30, 0x31, 0x20, 0x28,
  0x6c, 0x69, 0x62, 0x73, 0x6e, 0x64, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x31,
  0x2e, 0x30, 0x2e, 0x32, 0x34, 0x29, 0x00, 0x69, 0x64, 0x33, 0x20, 0x46,
  0x00, 0x00, 0x00, 0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x3c, 0x54, 0x58, 0x58, 0x58, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
  0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x00, 0x4c, 0x61, 0x76,
  0x66, 0x35, 0x37, 0x2e, 0x37, 0x32, 0x2e, 0x31, 0x30, 0x31, 0x54, 0x44,
  0x52, 0x43, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x32, 0x30, 0x31,
  0x36, 0x2d, 0x31, 0x30, 0x2d, 0x31, 0x37, 0x20, 0x31, 0x37, 0x3a, 0x32,
  0x37

};

const long switchResampled_len = 1045;
    
pregunta cheunste

2 respuestas

6

Un generador PWM de 4MHz (8MHz / 2) a 8 bits tiene un fundamental de 15.625kHz. Si no está filtrando esto con al menos un paso bajo de alto orden de 7 kHz, lo oirá fuerte y claro.

Necesitas llevar este fundamental al menos por encima de los 20kHz o más, para que salga de tu rango de audición, sin embargo, seguirá molestando a tu perro.

    
respondido por el Edgar Brown
4

El código que copió tiene un error, que probablemente causó los problemas sobre los que también escribe.

sample_count--;

if(sample_count ==0)
{
    sample_count = 2;
    if (count < switchResampled_len){
        OCR1A= pgm_read_byte(&switch_raw[count]);
        count++;
    }
}
else{
    OCR1A= BASE_LEVEL;
}

Cada otra marca de verificación establece OCR1A = BASE_LEVEL y la siguiente marca de verificación lo establece en su nivel de muestra, pero los comentarios en el código de ejemplo indican que la declaración else está fuera de lugar. Prueba esto:

sample_count--;

if(sample_count ==0)
{
    sample_count = 2;
    if (count < switchResampled_len){
        OCR1A= pgm_read_byte(&switch_raw[count]);
        count++;
    }
    else{
        OCR1A= BASE_LEVEL;
    }
}

(¡Fue difícil no reformatear esto para usar sangrías consistentes y la colocación de corchetes!)

    
respondido por el pipe

Lea otras preguntas en las etiquetas