Spraakherkenning & Synthese Meesteren op Arduino Due
Onderdelen en benodigdheden
| Arduino Due | × | 1 |
| SparkFun Electret Microfoon Breakout | × | 1 |
| SparkFun Mono Audio Amp Breakout | × | 1 |
| Luidspreker: 0.25W, 8 ohm | × | 1 |
| Breadboard (generiek) | × | 1 |
| 5mm LED: Rood | × | 3 |
| Weerstand 330 ohm | × | 3 |
| Draadjes (jumper wires, generiek) | × | 1 set |
Benodigde tools en machines
| Solderbout (generiek) |
Apps en online services
| BitVoicer Server 1.0 |
Over dit project
In mijn vorige project toonde ik hoe je een paar LEDs kunt besturen met een Arduino-bord en BitVoicer Server. In dit project ga ik een stap verder: ik synthetiseer spraak met de Arduino Due digitale-naar-analoge omzetter (DAC). Als je geen Arduino Due hebt, kun je andere Arduino-borden gebruiken, maar je hebt dan een externe DAC en extra code nodig (de BVSSpeaker-bibliotheek helpt daar niet mee).
In de video zie je dat de Arduino een klein liedje speelt en de LEDs laat knipperen alsof het piano-toetsen zijn. Excuses voor mijn pianovoordracht, maar dat is het beste wat ik kan :) . De LEDs knipperen in dezelfde volgorde en timing als echte C, D en E toetsen, dus als je een piano hebt, kun je de LEDs volgen en hetzelfde liedje spelen. Het is een jingle van een oude detailhandelaar (Mappin) die niet meer bestaat.
Werkproces: van stemcommando tot LED-actie en gesyntheserde spraak
- Gelakgolven worden opgevangen en versterkt door de SparkFun Electret Breakout board.
- Het versterkte signaal wordt gedigitaliseerd en gebufferd in de Arduino via de ADC (analoge-naar-digitale omzetter).
- De audiomonsters worden via de seriële poort naar BitVoicer Server gestreamd.
- BitVoicer Server verwerkt de audiostroom en herkent de spraak.
- De herkende spraak wordt gemapt op vooraf gedefinieerde commando's die terug naar de Arduino worden gestuurd. Als een commando spraaksynthese vereist, bereidt BitVoicer Server de audiostroom voor en stuurt deze naar de Arduino.
- De Arduino identificeert de commando's en voert de juiste actie uit. Bij een audiostroom worden de monsters in de
BVSSpeaker-klasse gequeue'd en afgespeeld via de Due DAC en DMA. - De SparkFun Mono Audio Amp versterkt het DAC-signaal zodat het een 8-ohm luidspreker kan aansturen.
Materiaallijst met prijzen
- Arduino Due: ~$50,00
- SparkFun Electret Microfoon Breakout: $7,95
- SparkFun Mono Audio Amp Breakout: $7,95
- BitVoicer Server 1.0: $9,90
- 8 Ohm luidspreker: ~$2,00
- Breadboard: ~$10,00
- 3× LEDs: ~$1,00
- 3× 330 Ohm weerstanden: ~$0,75
- Draadjes: ~$0,50
Stap 1: Bedrading
Bedraad de Arduino en het breadboard met de componenten zoals getoond in de afbeeldingen. Ik plaatste een klein rubberje onder de luidspreker omdat het veel trilt; zonder rubber is de geluidskwaliteit aanzienlijk slechter.
Belangrijk verschil met mijn vorige project: De meeste Arduino's draaien op 5V, maar de Due op 3.3V. Omdat ik betere resultaten kreeg met de SparkFun Electret Breakout op 3.3V, raad ik aan een jumper te plaatsen tussen de 3.3V-pin en de AREF-pin ALS je 5V Arduino-borden gebruikt. De Due gebruikt al een 3.3V analoge referentie, dus geen jumper naar AREF nodig. Feitelijk is de AREF-pin op de Due via een weerstandsbrug met de microcontroller verbonden. Om AREF te gebruiken, moet weerstand BR1 van de PCB gedesoldeerd worden.
Stap 2: Code uploaden naar de Arduino
Upload de onderstaande code naar je Arduino. De sketch is ook beschikbaar in de bijlagen. Installeer eerst de BitVoicer Server bibliotheken in de Arduino IDE (Importeren .zip Bibliotheek).
Arduino Sketch: BVS_Demo2.ino
Deze sketch heeft zeven belangrijke delen:
- Bibliotheekreferenties en variabele declaraties: De eerste vier regels includeren referenties naar de
BVSP,BVSMic,BVSSpeakerenDACbibliotheken (van BitSophia, te vinden in de BitVoicer Server installatiemap). De DAC-bibliotheek wordt automatisch meegenomen bijBVSSpeaker. De overige regels declareren constanten en variabelen. DeBVSP-klasse communiceert met BitVoicer Server,BVSMicvangt en buffer audiomonsters,BVSSpeakerspeelt audio af via de Due DAC. - Setup-functie: Stelt pin-modes en beginstatus in; initialiseert seriële communicatie; initialiseert
BVSP,BVSMicenBVSSpeakerklassen. Stelt event handlers in voorframeReceived,modeChangedenstreamReceivedevents van deBVSP-klasse. - Loop-functie: Voert vijf acties uit: statusinformatie opvragen bij server (
keepAlive()); controleren of server data gestuurd heeft en verwerken (receive()); opname en verzending van audiostromen regelen (isSREAvailable(),startRecording(),stopRecording(),sendStream()); audiomonsters inBVSSpeakerafspelen (play());playNextLEDNote()aanroepen voor LED-synchronisatie naplayLEDNotescommando. - BVSP_frameReceived functie: Wordt aangeroepen bij ontvangst van een compleet frame. Hier worden commando's van BitVoicer Server uitgevoerd. LED-commando's bevatten 2 bytes: pin-nummer en pin-waarde.
analogWrite()stelt de waarde in. Controleert ook ofplayLEDNotes(byte-type) ontvangen is – danplayLEDNotes = truezetten en huidige tijd markeren voor synchronisatie. - BVSP_modeChanged functie: Wordt aangeroepen bij moduswijziging in uitgaande richting (Server → Arduino). BitVoicer Server kan geframeerde data of audiostromen sturen. Voor overgang stuurt de server een signaal.
BVSPdetecteert dit en triggermodeChanged. Als communicatie van stream-modus naar frame-modus gaat, is audio klaar –BVSSpeakerstopt met afspelen. - BVSP_streamReceived functie: Wordt aangeroepen bij ontvangst van audiomonsters. Haalt monsters op en queue't ze in
BVSSpeakervoor afspelen viaplay(). - playNextLEDNote functie: Draait alleen als
BVSP_frameReceivedhetplayLEDNotescommando detecteert. Beheert en synchroniseert LEDs met audio van BitVoicer Server. Voor timing gebruikte ik Sonic Visualizer (gratis software) om audiogolven te zien en te bepalen wanneer een pianotoets ingedrukt werd. Het toont een tijdlijn – zo kreeg ik de milliseconden voor deze functie. Klinkt als een trucje, en dat is het ook. Het analyseren van de audiostroom en de bijbehorende LED aansturen is mogelijk, maar buiten mijn bereik.
Stap 3: BitVoicer Server Solution Objecten importeren
Stel BitVoicer Server in voor de Arduino. Vier hoofdsolution-objecten: Locations, Devices, BinaryData, Voice Schemas.
- Locations: Fysieke locatie van device. Ik maakte
Home. - Devices: BitVoicer Server clients. Ik maakte een
Mixeddevice, naamArduinoDUE, communicatie-instellingen ingevoerd. BELANGRIJK: De Due heeft beperkt geheugen voor audiobuffers. Zonder bandbreedte-limiet heb je een veel grotere buffer nodig. Ik had buffer overflows, dus Data Rate beperken tot 8000 samples per seconde in communicatie-instellingen. - BinaryData: Commando-type dat BitVoicer Server naar clients stuurt – byte-arrays gekoppeld aan commando's. Ik maakte een BinaryData-object per pin-waarde:
ArduinoDUEGreenLedOn,ArduinoDUEGreenLedOff, etc. Totaal 18 objecten. Download en importeer vanuitVoiceSchema.sof. - Voice Schemas: Waar alles bijeenkomt. Definiëren welke zinnen herkend worden en welke commando's uitgevoerd worden. Per zin zoveel commando's en volgorde als je wilt, met vertragingen. Zo realiseerde ik de actie-sequenties in de video.
Een van de zinnen in mijn Voice Schema is "play a little song". Deze bevat twee commando's: eerste stuurt een byte die aangeeft dat het volgende commando een audiostroom is. De Arduino start dan het "spelen" van de LEDs terwijl audio wordt overgedragen. De audio is een zelf opgenomen piano-jingle, ingesteld als audiobron van het tweede commando. BitVoicer Server ondersteunt alleen 8-bit mono PCM audio (8000 samples/sec). Voor conversie: audio.online-convert.com.
Importeer alle solution-objecten uit de bestanden:
Device.sofVoiceSchema.sof
Stap 4: Conclusie
Je kunt nu alles aanzetten en de zaken uit de video nabootsen.
Net als in mijn vorige project, startte ik de spraakherkenning door het Arduino-device in de BitVoicer Server Manager in te schakelen. Zodra ingeschakeld, detecteert de Arduino een beschikbare Speech Recognition Engine en begint met streamen van audio naar BitVoicer Server. Nu zie je veel meer activiteit op de Arduino RX LED tijdens audiostroom van BitVoicer Server naar de Arduino.
In mijn volgende project ga ik ambitieuzener te werk: WiFi-communicatie toevoegen aan één Arduino en twee andere Arduinos samen per stem besturen. Ik denk aan een soort spel tussen ze. Suggesties zijn welkom!
Code
Arduino Sketch Arduino
#include <BVSP.h>
#include <BVSMic.h>
#include <BVSSpeaker.h>
#include <DAC.h>
#define BVSM_AUDIO_INPUT 7
#define RED_LED_PIN 6
#define YELLOW_LED_PIN 9
#define GREEN_LED_PIN 10
const unsigned long STATUS_REQUEST_TIMEOUT = 3000;
const unsigned long STATUS_REQUEST_INTERVAL = 4000;
const int MIC_BUFFER_SIZE = 64;
const int SPEAKER_BUFFER_SIZE = 128;
const int RECEIVE_BUFFER_SIZE = 2;
BVSP bvsp = BVSP();
BVSMic bvsm = BVSMic();
BVSSpeaker bvss = BVSSpeaker();
byte micBuffer[MIC_BUFFER_SIZE];
byte speakerBuffer[SPEAKER_BUFFER_SIZE];
byte receiveBuffer[RECEIVE_BUFFER_SIZE];
bool playLEDNotes = false;
unsigned int playStartTime = 0;
void setup() {
pinMode(RED_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, LOW);
digitalWrite(GREEN_LED_PIN, LOW);
Serial.begin(115200);
bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL);
bvsp.frameReceived = BVSP_frameReceived;
bvsp.modeChanged = BVSP_modeChanged;
bvsp.streamReceived = BVSP_streamReceived;
bvsm.begin();
bvss.begin(DAC);
}
void loop() {
bvsp.keepAlive();
bvsp.receive();
if (bvsp.isSREAvailable()) {
if (!bvsm.isRecording) {
bvsm.setAudioInput(BVSM_AUDIO_INPUT, DEFAULT);
bvsm.startRecording();
}
if (bvsm.available) {
if (bvsp.inboundMode == FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE);
int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE);
bvsp.sendStream(micBuffer, bytesRead);
}
} else {
if (bvsm.isRecording) bvsm.stopRecording();
}
bvss.play();
if (playLEDNotes) playNextLEDNote();
}
void BVSP_frameReceived(byte dataType, int payloadSize) {
if (dataType == DATA_TYPE_BINARY) {
if (bvsp.getReceivedBytes(receiveBuffer, RECEIVE_BUFFER_SIZE) == RECEIVE_BUFFER_SIZE) {
analogWrite(receiveBuffer[0], receiveBuffer[1]);
}
} else if (dataType == DATA_TYPE_BYTE) {
if (bvsp.getReceivedByte() == 255) {
playLEDNotes = true;
playStartTime = millis();
}
}
}
void BVSP_modeChanged() {
if (bvsp.outboundMode == FRAMED_MODE) bvss.finishPlaying();
}
void BVSP_streamReceived(int size) {
int bytesRead = bvsp.getReceivedStream(speakerBuffer, SPEAKER_BUFFER_SIZE);
bvss.enqueue(speakerBuffer, bytesRead);
}
void playNextLEDNote() {
unsigned long elapsed = millis() - playStartTime;
allLEDsOff();
if (elapsed >= 11500) {
analogWrite(RED_LED_PIN, 0);
playLEDNotes = false;
} else if (elapsed >= 9900) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 9370) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 8900) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 8610) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 8230) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 7970) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 7470) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 6760) analogWrite(GREEN_LED_PIN, 255);
else if (elapsed >= 6350) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 5880) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 5560) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 5180) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 4890) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 4420) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 3810) analogWrite(GREEN_LED_PIN, 255);
else if (elapsed >= 3420) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 2930) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 2560) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 2200) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 1930) analogWrite(YELLOW_LED_PIN, 255);
else if (elapsed >= 1470) analogWrite(RED_LED_PIN, 255);
else if (elapsed >= 1000) analogWrite(GREEN_LED_PIN, 255);
}
void allLEDsOff() {
analogWrite(RED_LED_PIN, 0);
analogWrite(YELLOW_LED_PIN, 0);
analogWrite(GREEN_LED_PIN, 0);
}
Schema
Productieproces
- Betrouwbaar Arduino RFID Aanwezigheidssysteem Aangedreven door Python
- DHT11 Temperatuur- & Vochtigheidsensor Project met LED-indicatoren en Piezo-luidspreker
- Interactieve gyroscoop LED-display met NeoPixel-ring en Arduino
- Arduino Temperatuurbewaking & Realtime Klok met 3.2" TFT-display
- Bestuur Je Roomba Create 2 Met Arduino En Android: Stapsgewijze Handleiding
- Bouw een DIY Voltmeter met Arduino en Nokia 5110 Display – Stap-voor-Stap Handleiding
- Arduino & MPU6050: Precieze Servomotor Besturing met SG90 & MG996R
- u-blox LEA‑6H GPS Module: Arduino & Python Integratie Handleiding
- Temperatuur en Vochtigheid met DHT11 op Blynk - Stap-voor-Stap Arduino Tutorial
- Bouw een 4x4x4 LED-kubus met Arduino Uno & 1Sheeld – Interactief LED-project
- Arduino GPS en TFT Touchscreen Shield Project: Real-Time Locatieweergave