Hola a todos.
Este hilo va porque se me vino el siguiente experimento: realizar algo tipo "pitch bending" con algún sonido corto pero en bucle infinito (como por ejemplo, el efecto de sonido de un motor).
El programa era así:
/*
* Probado en un ATmega328P a 16 MHz. En otros microcontroladores puede no funcionar correctamente.
*
* Usar timer0 implica sacrificar delay y millis. Usar timer2 implica sacrificar tone.
* Este programa require el uso del timer1, lo cuál no se recomienda utilizar los pines 9 y 10; tampoco servos.
*/
#include <TimerOne.h> // https://github.com/PaulStoffregen/TimerOne
#include "engine.h" // Adjuntado en el post por si quieren oírlo también. Necesario para compilar.
// engine.h es como el archivo WAV que contiene el sonido.
// Muestras de 8 bits, monoaurales (un único canal), sin signo (0x7F es el "punto cero"), a una velocidad de 44100 Hz (periodo de 22.7 us).
//#define USE_TIMER2 // Descoméntalo para usar el timer2 y no el timer0; así salvamos a delay y a millis, en caso de ser necesarios.
#define SAMPLE_RATE 44100 // Frecuencia de muestreo a la que normalmente se escucharía el sonido.
// NO TOCAR ESTAS TRES DEFINICIONES
#define PERIOD (int)(1000000 / SAMPLE_RATE)
#define MIN (int)(PERIOD / 2)
#define MAX (PERIOD * 2)
volatile unsigned int count = 0; // Índice del array que contiene las muestras del sonido
void setup() {
#ifdef USE_TIMER2
TCCR2B = TCCR2B & 0b11111000 | 0x01;
#else
TCCR0B = TCCR0B & 0b11111000 | 0x01;
#endif
// Prescaler en 1; así consigo una frecuencia de PWM de hasta 65 KHz (CPU @ 16 MHz).
// Ayuda al filtro RC pasa-bajos a convertir la señal PWM en un "pseudo-DAC" (pero que funciona y muy bien).
#ifdef USE_TIMER2
analogWrite(3, 1);
analogWrite(11, 1);
#else
analogWrite(5, 1);
analogWrite(6, 1);
#endif
// Digamos que es para inicializar el modo PWM en el par de pines.
// Si el sonido es monoaural, se podría utilizar solo un pin de la pareja; pero implicaría modificar un poco el código.
Timer1.initialize(); // La inicialización que siempre pide la librería
Timer1.attachInterrupt(writeSample, PERIOD); // A partir de aquí comienza la reproducción del sonido, a manera de bucle infinito.
}
void loop() {
Timer1.setPeriod(map(analogRead(A0), 0, 1023, MIN, MAX));
// Aquí es donde la magia ocurre: el "pitch" (tono+velocidad) del sonido se altera con base en las lecturas analógicas de A0.
}
void writeSample() {
// Lee una muestra del array definido en 'engine.h', para cambiar el ciclo de trabajo del PWM; y por ende, el nivel del voltaje en la salida.
#ifdef USE_TIMER2
OCR2A = OCR2B = pgm_read_byte(&data[count++]);
#else
OCR0A = OCR0B = pgm_read_byte(&data[count++]);
#endif
if (count == data_len) count = 0; // Se acabó el array, vuelve al principio otra vez.
}
En resumen: reproduce un sonido corto, en bucle; y con el "pitch" controlado por A0. A mayor voltaje, menor velocidad ("pitch").
Una vez aclarado el tema, podré ir al grano.
Lo subo, y todo funciona como debería. El detalle es que no tenía a mano un potenciómetro, así que decidí experimentar con el ruido que recibe el ADC en estado "flotante" (conectado a nada).
Si no lo mueves por nada, las lecturas eventualmente se estabilizan (relativamente); si lo golpeteas, empujas o simplemente lo mueves, las lecturas vuelven a oscilar.
Aquí viene el clímax del tema: de repente me da por tocar el pin A0 con un dedo índice (tengo Arduino Nano, así que era fácil hacerlo sin necesidad de cables); y noté que el "pitch" había caído casi al mínimo establecido; lo que quiere decir que... A0 estaba recibiendo los 5v completos desde mi dedo??? :o
Y ESO NO ES TODO, también intenté acercar ese dedo al punto de soldadura del pin, sin tocarlo; y noté que cuanto más cerca lo tenía, más bajaba el "pitch"; en otras palabras, le entraba voltaje a medida que iba acercando el dedo. Por alguna razón, eventualmente ese efecto desapareció; pero el efecto con el contacto físico persistía.
Recuerda: la entrada analógica estaba conectada a nada; pero de todas formas me sorprende la forma en que un simple dedo altere el ruido que le entra.
De ahí la pregunta: es alguna propiedad de cuerpo humano? O es que acabo de descubrir que tengo superpoderes?
PD: razón del adjunto:
#include "engine.h" // Adjuntado en el post por si quieren oírlo también. Necesario para compilar.
engine.h (93.8 KB)