Mostrando entradas con la etiqueta voz. Mostrar todas las entradas
Mostrando entradas con la etiqueta voz. Mostrar todas las entradas

jueves, 4 de julio de 2024

ESP32 - Reproductor de WAV

  Página principal

ESP32
Reproductor de WAV

En el anterior proyecto ../vozmemo.html había realizado un reproductor de WAV desde una memoria Flash, utilizando el arduino.
Ahora me dispongo a realizar el mismo proyecto pero con el ESP32, y utilizando la memoria Flash que incorpora la placa, en este caso para la placa LOLIN 32 la memoria es  T25S32.
He utilizado la placa LOLIN 32 debido a que es más pequeña y la tenía cerca, pero el montaje funciona con cualquier placa ESP32.
En el caso del montaje con arduino, grabar la memoria Flash con un programador, en este montaje los datos de sonido WAV  se incorporan en el propio código.

Empezamos con el sonido grabado en formato de 11KHz y 8bits.

Una vez que tenemos el archivo WAV, debemos transformarlo a código C.
Utilizamos el programa HxD , es un editor hexadecimal que tiene la opción de exportarlo a código C.

Obtenemos un fichero con extensión .c , aunque lo he renombrado con extensión .h , es un gusto mio.

Ahora debemos editar el fichero para cambiar el tipo de dato.
Debemos cambiar de:
 unsigned char rawData[301892] = {
a
const char rawData[] = {

Con este cambio los datos se almacenan en la memoria Flash.

El fichero lo copiamos al mismo directorio del proyecto arduino y lo agregamos con:

#include "metro1.h"
long tamano=sizeof(rawData);


En el código  de programa del ESP32, creamos una interrupción cada 11KHz, que lo que hace es leer los datos WAV almacenados en la memoria Flash y mandarlos al convertidor D/A.

hw_timer_t *timer = NULL;

void IRAM_ATTR timerInterrupcion()
{
 if(dire>tama) { fin=1; dacWrite(25, 128);  } //
 if(fin==0) {  dacWrite(25, rawData[dire++]);  }
}

void setup()
{
  ....
  timer = timerBegin(1000000); // Timer 0, clock divider 80
  timerAttachInterrupt(timer, &timerInterrupcion); // Attach the interrupt handling function
  timerAlarm(timer, 90, true, 0); // ((1/11000)*1000000)
  ...
}


He creado dos programas, uno que utiliza el terminal para mandar el numero de trozo WAV a reproducir.




En el  segundo he añadido un display OLED y un mando rotatorio para elegir el sonido a reproducir, también se puede mandar los códigos desde consola.


Para leer el mando rotatorio utilizo las entradas en modo INPUT_PULLUP, debería funcionar tal como está en el código.
El problema es que algunos pin del ESP32 no se pueden poner en modo INPUT_PULLUP, si no os funciona con está configuración, deberéis colocar una resistencia de 10K desde las entradas hasta Vcc.

He tenido un problema con las librerías del ESP32.
Como yo utilizo Linux para programar, y tiene su propio Arduino en los repositorios, si mezcláis las librerías con la versión que viene de serie en Linux, saldrán errores.
Solución, desinstalar el Arduino que viene en Linux, y bajar de la página de arduino la versión arduino-1.8.19 y utilizar esta última.

Como en la versión de arduino, el leer byte a byte desde la memoria Flash no es del todo rápido, próximamente intentaré crear un buffer de 100 bytes para que sea más rápido.

PROGRAMA


09/07/02024
Como había prometido, he realizado una segunda versión, en esta la lectura de los datos desde la memoria Flash la hago de 100 datos cada vez.
En el arduino se notaba que aumentaba el rendimiento del programa, pero en este caso al ser un procesador 10 veces más rápido, no se nota mucho.
De todas formas he programado el cambio.
PROGRAMA2


VIDEO DEMOSTRATIVO


Saludos.
Juan Galaz




Bibliografía:

../vozmemo.html
voz2.html
arduvoz.html
arvoc.html .



sábado, 1 de febrero de 2014

Arduino reproductor de voz mediante tarjeta SD - Interface LCD

Página principal

Arduino reproductor de voz mediante tarjeta SD

Interface LCD

wav - 8bits -11KHz

xsetaseta@gmail.com

Continuando con mi anterior montaje  Arduino reproductor de voz mediante SD, ahora realizo un interface mediante 2 botones, un potenciómetro y un LCD.
La elección del potenciómetro para seleccionar las canciones es un motivo práctico, de fácil realización y sencillo.
Mediante el potenciómetro seleccionamos las canciones que deben estar creadas en la SD como números del 0 al 63 y con la extensión wav , ejemplo: 1.wav . Para su reproducción pulsamos el botón PLAY y para parar el botón STOP.
Las canciones tienen que estar en formato wav, mono , resolución 8bits y con una frecuencia de 11KHz.
En este formato cada minuto ocupa 0.65M, con lo cual con una tarjeta de 4G  tendremos 6153 minutos, unas 102 horas.
La tasa de frecuencia de muestreo de 11KHz es suficiente para la reproducción de voz .

Esquema del circuito.


Montaje del circuito.

Vídeo del funcionamiento



Muestra de una señal de 500Hz.


//SETA43
//xsetaseta@gmail.com
//arduvoc  Reproductor de audio con arduino
//01/02/2014


#include <LiquidCrystal.h>

LiquidCrystal lcd(7,6,5,4,3,2);

int sensorValue ;
int oldsensorValue=-1;

#include <SD.h>
File dataFile;

String inputString = ""; 
char fileplay[20] ;
boolean stringComplete = false; 

byte valor;
byte bufer0[100];
byte bufer1[100];
int din=0;
int dout=0;
byte nf=0;
byte vacio=1;
byte fin=1;

byte e1Pin=18;
byte e2Pin=19;

void setup()
{
  lcd.begin(16, 2);
  pinMode(9, OUTPUT); //Salida audio

 // pinMode(4, OUTPUT);    // si utilizamos la salida 4 como CS de la tarjeta SD
 // if(!SD.begin(4)){    // 
   pinMode(10, OUTPUT);    // si utilizamos la salida 4 como CS de la tarjeta SD
  if(!SD.begin(10))
  {
    lcd.print("ERROR Tarjeta ");    // Texto informativo
    return;
  }
  else
  {
    lcd.print("Tarjeta OK ");    // Texto informativo
  }   
  delay(900);
  lcd.clear();
  lcd.print("Arduino VOC");
  delay(500);
  lcd.clear();
   
 cli();//stop interrupts

  //timer1 PWM 31KHz
  TCCR1A = 0x81;
  TCCR1B = 0x01;
  OCR1A = 255;
  TIMSK1=0;

  //set timer2 interrupt at 11kHz
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  OCR2A = 182;
  TCCR2A =2;
  TCCR2B =2;     
  TIMSK2=2;
 
sei();//allow interrupts
 
}
//end setup


ISR(TIMER2_COMPA_vect)  //timer1 interrupt 11kHz toggles
{
 if(fin==0)
  {
  if(nf==0)
    valor=bufer1[dout];
   else
    valor=bufer0[dout];
   
  dout++;
  if(dout>99)
    {
     vacio=1;
     dout=0;
     if(nf==1)
       nf=0;
      else
       nf=1;      
    } 
  OCR1AH = 0;
  OCR1AL = valor;    
  }
}


void loop()
{
    if(!digitalRead(e2Pin))
        {
         clearBuffer();        
         lcd.clear();
         lcd.setCursor(0, 0); lcd.print("PLAY WAV "); lcd.print(inputString);
         inputString.toCharArray(fileplay,19);
         dataFile.close();
         dataFile = SD.open(fileplay,FILE_READ);
         //dataFile = SD.open("11.wav",FILE_READ);
         while(!digitalRead(e2Pin));
         if (dataFile)
          {          
           for(din=0;din<200;din++) dataFile.read(); //quita 200 bytes del wav
           fillBuffer(); 
           fin=0;         
          }
          else
          {
           lcd.setCursor(0, 0); lcd.print("NO   WAV ");          
          }                           
        }
       
    if(!digitalRead(e1Pin))
        {           
         clearBuffer();
         dataFile.close(); 
         lcd.setCursor(0, 0); lcd.print("STOP WAV ");  
         while(!digitalRead(e1Pin));        
        }

  sensorValue = analogRead(A0)>>4;
  if(oldsensorValue != sensorValue)
    {
    inputString=String(sensorValue,DEC);
    inputString+=".wav";
    lcd.setCursor(0, 1);
    lcd.print(inputString);
    lcd.print("    ");
    }
  oldsensorValue = sensorValue;
  fillBuffer();
}


//Borrar buffer
void clearBuffer()
{
   fin=1;
   for(din=0;din<100;din++){ bufer0[din]=128;  bufer1[din]=128;} //vacia bufer
}

//llenado de buffer
void fillBuffer()
{  
  if(vacio == 1 && fin == 0)
    {    
     if(nf==0)
       for(din=0;din<100;din++) bufer0[din] = dataFile.read();
      else
       for(din=0;din<100;din++) bufer1[din] = dataFile.read();
      
     vacio=0;
     if(!dataFile.available())
       {
         lcd.setCursor(0, 0); lcd.print("END  WAV ");
         fin=1;
         for(din=0;din<100;din++){ bufer0[din]=128;  bufer1[din]=128;} //vacia bufer        
       }
    }  
}

Código fuente.




Saludos
Juan Galaz



Bibliografía:
http://ravc00cs.blogspot.com.es/2012/07/pwm.html
https://github.com/TMRh20/TMRpcm/wiki
http://apcmag.com/arduino-project-5-digital-audio-player.htm
http://arduino-info.wikispaces.com/Arduino-PWM-Frequency
http://hykrion.com/?q=node/153
http://arduino.cc/es/Tutorial/SecretsOfArduinoPWM