Xilofono Digital

Hola queridos compañeros. Estoy trabajando en un proyecto sobre un xilófono digital, este consiste en tener un módulo como si fuera un xilófono pero en vez de teclado tiene una fila de sensores, receptor y emisor, los cuales detectan una interrupción entre ellos y generan un sonido determinado.

Ahora bien, mi gran duda consiste en mirar que tipo de código me sirve para un dspic30F que me permita llamar nota por nota (estas notas son do, re, mi , fa sol) y están guardadas en una SD o memoria, pero necesito que una vez que haga una interrupción determinada en cualquiera de los sensores, me suene la nota respectiva a esa posición del sensor, es decir, que si interrumpo la señal en el primer par de sensores suene por ejemplo la nota DO.

Gracias.

Encontré un código así, pero no estoy seguro de lo que me quiere decir.

Código:
* Name : ReadFmt *
* Purpose : Reads header of WAV file and checks compatibility *
************************************************** ******************************
} 
Function ReadFmt() As Boolean // read fmt block of WAV file
Dim Index As Byte
ReadFmt = True
Index = 0
Repeat // skip over RIFF header
SD.ReadLongWord
Inc(Index)
Until Index = 3
If SD.ReadChar <> "f" Then // check in fmt block
ReadFmt = False
EndIf
If SD.ReadChar <> "m" Then
ReadFmt = False
EndIf
If SD.ReadChar <> "t" Then
ReadFmt = False
EndIf
If SD.ReadChar <> " " Then
ReadFmt = False
EndIf
SD.ReadLongWord // skip over fmt size
If SD.ReadWord <> 1 Then // check PCM (un-compressed) file
ReadFmt = False
EndIf
If SD.ReadWord <> 1 Then // check 1 channel (mono) file
ReadFmt = False
EndIf
If SD.ReadLongWord <> 16000 Then // check sample rate (16kHz)
ReadFmt = False
EndIf
Index = 0
Repeat // skip to data size
SD.ReadByte
Inc(Index)
Until Index = 12
DataSize = SD.ReadLongWord
SD.ReadLongWord // skip to data section
ProgressIncrement = DataSize / 16
End Function
{
 
Última edición por un moderador:
Ahora bien, mi gran duda consiste en mirar que tipo de código me sirve para un dspic30F que me permita llamar nota por nota (estas notas son do, re, mi , fa sol) y están guardadas en una SD o memoria, pero necesito que una vez que haga una interrupción determinada en cualquiera de los sensores, me suene la nota respectiva a esa posición del sensor, es decir, que si interrumpo la señal en el primer par de sensores suene por ejemplo la nota DO.
Ese código te puede servir, pero no para un DSPIC30F
Esa rutina pertenece a un código en Basic para SwordFish y sólo trabaja con PIC18
Encontré un código así, pero no estoy seguro de lo que me quiere decir.
El mismo código tiene descrito el propósito de esa función:

Código:
* Purpose : Reads header of WAV file and checks compatibility *
Propósito: Lee la cabecera de un archivo WAV y se verifica la compatibilidad.
Es decir, se comprueba que el archivo a leer contenga en la cabecera "fmt".
Por norma general siempre existe esto en la cabecera de un archivo WAV "WAVfmt" (Sin comillas)
Esa rutina comprueba la existencia de los caracteres fmt y que sea un archivo WAV con 16KHz. de muestreo.

Si quieres generar notas musicales con el PIC, puedes usar MicroCode Studio o Proton IDE.
Ambos tienen instrucciones nativas para la generación de tonos y frecuencias.
Así te evitas el uso de librerías y de la memoria SD, aparte puedes realizar el programa con pocas líneas de código.
 
ok, muchas gracias por aclararmelo, pero mira tengo el DSPIC30F y tengo las notas musicales que comentaba en varios archiivo, crees entonces de que es mas facil hacerlo propiamente con ese programa?, lo que pasa es que la idea de la SD era porque tenia esas nota del xilofono, para que cada vez de que hiciera la interrupcion de un sensor determinado este me generara por decir algo la nota DO y luego otro RE y asi sucecivamente.
 
yo no entiendo por que usar un DSpic y una SD para hacer un juguete no me cabe en la cabeza

yo lo que haria es hacer las notas con pulsos cuadrados y sacar las octavas lo que hace las cajitas musicales navideñas.

no se trata de tener una idea ingenua, rebuscada y bajar lo primero que encuentres en internet.
las escalas mucicales van por octavas y las puedes calcular y meter eso en un tren de pulsos dentro de un timer.

si no te gusta que sean tonos cuadrados pues usa un integrador con un OPAM la integral de la unidad es la pendiente t ahi tienes señal triangular la integral de la pendiente es la curva t^2 ahi tienes señal senoidal.

hasta con un Ne555 puedes hacerlo :LOL:
 
Si tengo ya discretizado las notas, es decir cada nota por separada la tengo discretizada, como haria para cargar esas notas a la memoria del dspic33fj128mc? he estado buscando pero no veo la forma yo propuse una primera opcion pero me comentaron de que no me servia. existe algun codigo en C?
 
como dije no se trata de buscar cualquier cosa que hay en internet y tratarlo de meter

para leer un archivo en una SD debes saber como funciona una SD que es SPI si sabes de SPI no creo que se te dificulte leer una SD, ahora tratar de leer archivo tipo FAT16 para poder accerder a la memoria y leer los archivos.

despues saber interpretear los.WAV como dice D@rkbytes hay que interpretar el archivo.

no es cosa de le pongo un chicle y un alambrito y tengo una maquina del tiempo claro que no.

yo digo que tienes una idea algo ingenua de los archivos y el protocolo de una tarjeta SD

no se por que tanto interez en ese micro en particular. yo lo que haria es usar pulsos generarlos a la frecuencia de cada nota y vualá
 
pues el interes radica en que debo trabajar con ese micro, entiendo todos los puntos de vista, pero ese es el interes por algo escribo para solicitar ayuda en que camino es el mejor, y lo unico que dispongo para trabajar es ese micro, dije de que tengo ya cada nota individual, entonces como hago para meterla al micro ya no a una SD.

gracias
 
pues es que cada nota ocupa mucha memoria por el muestreo, meterla en una eeprom externa no se si quepa, meterla al micro seria declarar un buffer y cuando se cargue una nota llene el buffer con datos tipo binario algo asi:

unsigned char nota[512];

lo que hago es declarar un buffer de 512 bytes que es mucha memoria sin usar y al mismo tiempo poca para cargar una nota.

yo sacaria la nota por PWM para hacer sonido por PWM
 
entiendo. sim embargo como seria hacerlo con simples pulsos como tu dices, aun sabiendo de que son notas de xilofono se puede? como se podria hacer?.

que codigo me seriviria para hacerlo mediante ese DSPIC, teniendo las notas como te dijo, porque una mvez discretas el tamaño disminuye.



a ver yo estuve viendo por internet y mostraban la manera de como sacar los puntos como dices tu de manera "const char DO[1270]={ };" asi tengo para la primera nota pero me tocaria hacer varios codigos para sacar eso por pwm? o como podria asociar todas esas notas.
 
Última edición:
bueno eso que pusiste

"const char DO[1270]={ };"
no hace mas que reservar 1270 bytes en RAM osea no genera nada pero si cargamos esos regsistros con los datos de la nota muscial si podemos reproducirlo como seria un wav.

ahora lo del PWM no es tan dificil digamos que hacemos un PWM a una frecuencia de 10ms por ejemplo
dentro de esos 10ms lo dividimos en 255 partes que sera nuestra resolucion de 8 bits
el ciclo de trabajo del PWM se ve afectada por el valor dividido en partes de 255 y a la salida tendremos un PWM que se comportaria como un DAC , ahora ese PWM se le coloca un filtro RC pasa bajos para generar audio

el PWM lo puedes hacer con un modulo CCP que traen los PIC
 
pues el numero obviamente no va a hacer nada sinoo que son muchos numeros y no pude ponerlos en el ejemplo por eso los parentesis no hay nada.



no pude subir el bloc de notas con el ejemplo porque me aparecia archivo no valido no se por que.



no tendrias un ejemplo para hacerlo por PWM entiendo de que deben de haber unos numeros pero como lo podria hacer
 
Última edición:
mira en lo que pones vi que pusiste

const char do[1270]={};

ahi solo reservaron memoria con 1270 bytes casi 1kb de ram hay pic que no tienen tanta RAM y se quedan sin memoria reservando tanta memoria , si reservamos casi 1kb para do, re, mi ,fa, sol ,fa#,etc. cuanta RAM usariamos reservando tanta memoria.

un truco que usan para no hacer tanta reserva de memoria que aun es bastante es reservar 512 bytes en RAM , es decir usan una variable generica para ir llenandola con datos y trabajar con esa variable.

eso lo usan en una lectura de la memoria SD, esta lectura de memoria SD no es facil debes leer pues debes estudiar la lectura de una memoria SD estandar , hay informacion en internet de manera limitada, no es para principiantes , hay que tener practica y experiencia programando.

si existe una libreria llamada FAT16.h y es generica para CCS, C18 y hitech C.
esta libreria no solo es la FAT16.h sino que contiene mas librerias que trabajan entre si para funcionar y ocupan mucha memoria pues contienen funciones para hacer DEBUG por RS232 pues la iibreria no garantiza que funcionara a la primera con cualquier pic , debe tener buena memoria ,SPI ,y que ho haya conflictos en tu manera de programar, por eso le metieron el modo debug para poder saber que pasa al momento de programar.

esta libreria si tiene un conflicto en PICS que comparten el PIN SPI por hardware con el del UART por hardware y hay que hacer modificaciones
 
Pues no sé que lenguaje uses exactamente, pero en CCS con un módulo CCP

Este es un ejemplo para leer con el ADC una señal de audio para procesarla y generar audio con PWM

La idea es que una vez el dato sea convertido se almacene en una variable de 1 byte y ese mismo byte es el ciclo de trabajo del PWM.


Código:
void main()
{

unsigned int16 duty_cicle;


setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);

setup_ccp1(CCP_PWM);

set_adc_channel(1); //uso el puerto en A0
//   The cycle time will be (1/clock)*4*t2div*(period+1)
          //   In this program clock=10000000 and period=127 (below)
          //   For the three possible selections the cycle time is:
          //     (1/10000000)*4*1*128 =  51.2 us or 19.5 khz
          //     (1/10000000)*4*4*128 = 204.8 us or 4.9 khz
          //     (1/10000000)*4*16*128= 819.2 us or 1.2 khz
          
setup_timer_2(T2_DIV_BY_16, 75, 1);





while(1)
{




delay_us(2);        //retardo de 5 us
duty_cicle=read_adc();   //el ADC se guarda en leido

set_pwm1_duty(duty_cicle);



} 


}
 
Última edición por un moderador:
¿Cómo sería un ejemplo con PWM?
Mira estos dos ejemplos, uno está realizado en C de CCS y el otro en PICBasic de Proton IDE.
Ambos generan las notas musicales (DO, RE, MI, FA, SOL, LA, SI)
La diferencia radica en que en PICBasic los tonos se generan con una instrucción nativa. "Sound"
Y en C, se crea una tabla con valores de retardo para generar las notas musicales.

El problema en PICBasic, es que no soporta DSPIC, en PIC C Compiler parece que si, pero no los he programado.

Espero te sirva al menos el programa en C para que veas una forma de generar sonidos simples con PIC.
 

Adjuntos

  • 16F628A Notas musicales.rar
    42.9 KB · Visitas: 15
Es muy fácil generar notas musicales mediante código, usando para ello resonadores digitales. Aquí pongo un código en pseudo C que genera las notas musicales que adjunto en el archivo comprimido:

Código:
#define FM 44100
#define R 0.9998
#define PI 3.14159265
#define RESOLUCION 32767

const float R2=R*R;
const float Nota[8]={261.62557, 293.66477, 329.62756, 349.22823, 391.99544, 440, 493.8833, 523.25113};

float B[8],A[8];

void setup()
{
int i;

for(i=0;i<8;i++) {
	 B[i]=sin(2*PI*Nota[i]/FM);
	 A[i]=R*2*cos(2*PI*Nota[i]/FM);
               }
}

void tocanota(int n)
{
int i;
float Y2=0,Y1=B[n],Y0;

for(i=0;i<44100;i++){
 	Y0=A[n]*Y1-R2*Y2;
	Salida_DAC(Y0*RESOLUCION);
	Y2=Y1;
	Y1=Y0;
	}
}

Para mí que estas notas ya suenan lo suficientemente parecidas a las de un xilofono, ¿no?
 

Adjuntos

  • Notas.zip
    432 KB · Visitas: 11
yo uso lenguaje C, no me queda muy claro ese ejemplo, mira yo segui estos paso que decian en internet para convertir los vectores, no se si este en lo correcto.

Primero digo cómo he resampleado
Con matlab:
Uso esta instrucción para cargar el wav original (44100Hz, 8 bits)
[datos,Fs,NBits,Opts]=wavread('E:\Proyectos_carpeta_seguridad\PIC\PWM en C18\bocina3.wav')
La instrucción directa para resamplear es esta:
datos =resample(datos,p,q)
donde “datos ” es el resultado del resample( se sobreescribe), datos el archivo del array ( aún no es un array en C propiamente dicho) , y p y q son dos parámetros del resampleo, p/q veces el sampleo original.
Como no sabemos qué números son esos, hay que usar una instrucción previa:
[p,q]=rat(8000/Fs,0.0001), donde Fs es la frecuencia de sampleo original, del archivo bocina3 (44100Hz), 8000 es el resultado del sampleo que queremos, y el vector [p,q] como resultado para poner en la instrucción anterior.
datos=resample(datos,39,215)
Ahora queda adecuar esos datos, para ponerlos en una tabla y “migrarlos” a C, del modo siguiente:
datos = datos *127
datos = datos +127
datos = fix(datos)
csvwrite('E:\Proyectos_carpeta_seguridad\PIC\PWM en C18\datos.csv',datos);
Con Excel
Ahora abrimos el ficherocreado “ datos.csv “
Aparece una columna con el array de datos, en forma de columna. En opción “buscar y reemplazar”, en la casilla “buscar” la dejamos en blanco ( busca los espacios) y en reemplazar añadimos una coma “,”. Seleccionamos la columna ( entera) de la derecha de la columna de datos, y hacemos el cambio ( damos aceptar a buscar y reemplazar).
Con Notepad.
Ahora abrimos un archivo txt , previa copia de esas dos columnas de Excel, y cambiamos un poco para adecuarlo a C, es decir, poner al principio const char nombre[número de columnas de la columna en Excel] ={los números mas la coma añadida}. Ese archivo lo guardamos con extensión “.h” y ya tenemos el archivo de sonido resampleado a 8000 Hz y en forma de array de chars, para leerlo en C.

no entiendo bien, es como asociar por ejemplo de que yo toque determinada sensor y se oiga cierta nota, pero aun cargar esa nota como se realiza
 
aver deja si entendi si me equivoco dame una patada en los bajos

hisiste la señal en MATLAB la generaste a 8 bits y su frecuencia de muestreo y todo ya quedo

hasta aqui me quedo claro

y despues te genero un archivo de texto con los datos binarios a 8 bits por cada nota

y esas notas estan en un archivo de Texto y se las quieres meter al micro de algun modo pero no sabes como hacerlo :LOL: disculpame huvieras empezado por aqui.

bueno lo que yo haria es lo siguiente:
si ya tienes el archivo de texto con tus notas deberias medirlo cuanto mide
digamos los bytes que tengan de longitud.

en tu micro deberias recervar la memoria que consume cada nota

ejemplo:

mi nota DO midio 150bytes entonces recervo 150 bytes en mi micro asi:

char DO[150];

y asi para cada nota.
ahora lo siguiente seria llenar cada nota dentro del micro yo lo haria asi si no me siento muy ducho en las SD.

1.-meter las notas en una EEPROM externa no es dificil aprender a grabar y leer en una EEPROM
y reproducir las notas directamente de la EEPROM o dentro de la memoria reservada.
yo opartia por la EEPROM mas que de la memoria reservada ya que desperdiciamos RAM.

una vez que tengamos el PIC armado con sus EPROM seria grabar la EEPROM .

yo lo que haria seria leer el archivo de texto y mandarlo por RS232 al micro y que el micro por RS232 escriba las memorias con lo que viene de la computadora. una simple rutina de leer un archivo de texto en la PC y escribir en el puerto COM.

y en el PIC seria leer lo que llega e ir llenando bloques de memoria .

mas facil que aprender a leer y escribir en una SD
 
ok, mira la eprom seria externa o la misma del dspic?

Y como haria para realizar un main en C, que me ayude a verificar el estado de los sensores , ya que el xilofono esta diseñado asi, es decir como haria para verificar que por ejemplo la el sensor, llamemoslo DO, esta en alto, el sensor RE, esta en alto o bajo y asi sueceuvamente hasta mirar el estado de cada sensor segun su nota correspondiente.



las notas ya las tengo discretizadas por matlab

la memoria del dspicdspic33fj128mc802 es de 128KB
 
Última edición:
mm no se desconosco tal pic pero leer un boton es por poleo pues hacer interrupciones es viable pero digamos que tienes 30 teclas por ejemplo

no todas las teclas estan disponibles en un micro de 40 pines por ejemplo.

la eprom es externa eso te consumes algunos pines, hacer un DAC no se si lo vas a hacer R2R a una resolucion de 8 bits adivina cuantos pines se va a llevar no :LOL: no hay que ser un genio para saberlo

digamos que la eeprom te consume 3 pines si es SPI digamos que usas 2 o 3 eprom externas 3 pines + las 3 eproms unos 6 pines y su DAC R2R 8 pines y falta el oscilador , voltaje , Rs232 para cargar las notas 2 pines mas

en total para no hacer el cuento largo apenas y unos cuantos pines libres para el teclado.
el teclado lo puedes hacer de 3 maneras:

1.-matricial que ocupa 8 pines y obtienes 16 teclas ;)
2.-1 solo pin, usas el ADC y por divisores de voltaje obtienes las teclas que necesitas
3.-con un extensor de puerto un circuito barato es el CD4021 que es un convertidor de paralelo a serie
es decir 2 de estos circuitos en cascada obtienes 16 entradas
 
Atrás
Arriba