Da es mich gereizt hat, den Analog Digital Converter des Teensys 3.2 zusammen mit Tönen zu nutzen, habe ich mit dem Programm wav2sketch eine WAV-Datei mit Klickgeräusch konvertiert1) und einen kleinen Metronom-Sketch geschrieben. Das 20x4 LC-Display mit I2C-Schnittstelle (5 V) ist direkt mit dem Teensy (3,3 V) verbunden, was zumindest bei mir funktioniert. Besser wäre ein I2C-Levelshifter zu verwenden. Der Kopfhörer ist über einen Kondensator (10 µF) mit dem DAC-Pin verbunden. Mit zwei Tastern kann aus einem Feld die Taktgeschwindigkeit in BPM (Beats per minute) gewählt werden.
// getestet mit Teensy 3.2 und LCD 20x4
#include <Wire.h>
#include <hd44780.h> // include hd44780 library header file
#include <hd44780ioClass/hd44780_I2Cexp.h> // i/o expander/backpack class
hd44780_I2Cexp lcd; // auto detect backpack and pin mappings
#include <Audio.h>
#include "AudioSampleMetrobar1.h" // Metronome sounds https://www.rncbc.org/drupal/node/566 konvertiert mit wav2sketch
// Create the Audio components. These should be created in the order data flows, inputs/sources -> processing -> outputs
AudioPlayMemory sound0;
AudioOutputAnalog dac; // play to on-chip DAC
// Create Audio connections between the components
AudioConnection c1(sound0, 0, dac, 0);
const unsigned long debounceDelay = 50;
struct Beats {
uint16_t bpm;
char titel[21];
};
Beats beats[] = {
// 12345678901234567890
{ 80, "Slow 80"},
{100, "Fox 100"},
{120, "Salsa 120"},
{160, "Fast 120"}
};
const byte anzahlBeats = sizeof(beats) / sizeof(beats[0]);
uint32_t jetzt = millis();
byte startIndex = 1;
class Taster // Struktur mit Konstanten, Variablen und Methoden
{ const byte pin;
const int8_t veraenderung;
bool aktZustand, altZustand;
unsigned long vorhin;
public:
Taster(const byte pin, const int8_t veraenderung): pin(pin), veraenderung(veraenderung), aktZustand(0), altZustand(0), vorhin(0) {}
void init()
{ pinMode(pin, INPUT_PULLUP);
aktZustand = digitalRead(pin);
altZustand = aktZustand;
vorhin = jetzt;
}
void run(byte &index)
{ altZustand = aktZustand;
if (jetzt - vorhin >= debounceDelay) // Entprellen
{ aktZustand = digitalRead(pin); // Tasterzustände aktualisieren
if (altZustand != aktZustand) vorhin = jetzt;
}
if (altZustand && !aktZustand) // fallende Flanke
{ index++;
index += veraenderung;
if (index < 1) index = 1;
if (index > anzahlBeats) index = anzahlBeats;
index--;
}
}
};
Taster taster[]
{ // Taster-Pin, Veränderung
{20, -1},
{21, 1}
};
void anzeige(byte index)
{ if (index < anzahlBeats)
{ lcd.setCursor(0, 2);
lcd.print(F(" "));
lcd.setCursor(0, 2);
lcd.print(beats[index].bpm);
lcd.print(F(" BPM"));
lcd.setCursor(0, 3);
lcd.print(F(" "));
lcd.setCursor(0, 3);
lcd.print(beats[index].titel);
}
}
void click(uint16_t bpm) {
static uint32_t vorher = jetzt;
if (bpm && (jetzt - vorher >= 60000UL / bpm)) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
vorher = jetzt;
sound0.play(AudioSampleMetrobar1);
}
}
void loop() {
static byte aktIndex = startIndex;
byte altIndex = aktIndex;
jetzt = millis();
for (Taster &t : taster) t.run(aktIndex);
if (altIndex != aktIndex) anzeige(aktIndex);
click(beats[aktIndex].bpm);
}
void setup() {
pinMode (LED_BUILTIN, OUTPUT);
for (Taster &t : taster) t.init();
AudioMemory(1); // Audio connections require memory to work. For more detailed information, see the MemoryAndCpuUsage example
//dac.analogReference(INTERNAL); // by default the Teensy 3.1 DAC uses 3.3Vp-p output if your 3.3V power has noise, switching to the internal 1.2V reference can give you a clean signal
lcd.begin(20, 4);
lcd.setCursor(0, 0);
lcd.print(F("Metronom"));
lcd.setCursor(0, 1);
lcd.print(F("Viel Erfolg!"));
anzeige(startIndex);
}
Anm.:
- siehe Anhang
AudioSampleMetrobar1.cpp (25.2 KB)
AudioSampleMetrobar1.h (110 Bytes)