Nieuw: zang of spraak met de Emic 2

Spraak of ingewikkelde tonen laten horen

Met alleen de Arduino en een luidspreker

Het kan echt! De bibliotheek Talkie bevat een aantal vaste tekstfragmenten, die tamelijk goed verstaanbaar zijn. Er zit zelfs een liedje bij! Ik teste het door een simpele 8Ω luidspreker zonder versterker aan te sluiten tussen pin 3 en pin 11 van de Arduino Uno. Het kan zijn dat je met andere luidsprekers of een ander type Arduino wel een versterker nodig hebt. Leuk om gewoon een keer te proberen of als je een robot hebt die alleen DANGER hoeft te kunnen zeggen. Niet geschikt voor echte text-to-speech toepassingen. Ga als volgt te werk: kies in de Arduino IDE de bibliotheken beheerder via de toetscombinatie CRTL-SHIFT-i en type in het zoekraam Talkie in. Installeer de bibliotheek. Ga nu naar het menu Bestand→Voorbeelden en zoek naar de voorbeelden van Talkie. Diner_Toms_Diner is het liedje...

Een andere bibliotheek is Mozzi. Je kunt deze als zip-file downloaden van github. Gebruik niet de download op de Mozzi site, want dan krijg je een verouderde versie. Deze zeer uitgebreide bibliotheek is vooral bedoeld voor bijzondere geluiden, maar je kunt er ook samples mee afspelen.

Met alleen een (micro-)SD kaartlezer

Testopstelling met SD kaarlezer, Arduino Pro Micro en Luidspreker
Dè manier om spraak te laten horen is door de spraak vooraf op te nemen op een SD (of micro-SD) kaartje. Je kunt dan duizenden zinnen opslaan en op elk gewenst moment laten horen. Dit lukt niet zonder een geavanceerde bibliotheek, zoals TMRpcm. Deze bibliotheek doet dat zo goed dat zelfs spraak goed verstaanbaar is met een luidspreker die rechtsstreeks op de Arduino is aangesloten. De bibliotheek werkt niet met alle Arduino's. De opgeslagen bestanden moeten aan een aantal factoren voldoen. Zo moeten het mono wav-bestanden zijn, niet gecomprimeerd en 8 bits (unsigned) per sample gebruiken. De sample rate mag tussen 8 en 32 kHz liggen; 16 kHz voldoet uitstekend. Je kunt de geluiden natuurlijk zelf opnemen, maar als je een mooie stem wilt hebben dan kun je ook een van de vele gratis TextToSpeech programma's gebruiken. Helaas is er nog geen goede Nederlandse stem, maar de Engelse stemmen zijn erg goed. Ik heb goede ervaring met zowel "balabolka" als "texttowav". Als je uit meer stemmen wilt kiezen dan kun je een online text to speech programma gebruiken, zoals dit. De volgende stap is om het geluid terug te brengen tot het juiste formaat. Hiervoor kun je een gratis programma gebruiken als Audacity of dit online doen. Sla het bestand op met een naam van hooguit 8 letters (exclusief ".wav"). Als je het bestand opslaat dan laat Audacity nog alle gegevens van het bestand zien. Wis die allemaal, want anders zul je steeds een klik horen bij het afspelen.
Je kunt de TMRpcm bibliotheek direct installeren vanuit het menu Schets → Bibliotheek gebruiken → Bibliotheken beheren. De bibliotheek verplicht je de luidspreker op een bepaalde pin aan te sluiten (voor de meeste Arduino's pin 9). In plaats van spraak kun je ook ingewikkelde tonen maken, zoals van een sirene.
In dit programma gaat een led knipperen als de kaart niet goed gelezen kan worden. Vaak betekent dat, dat je de bedrading nog eens moet nalopen. Als je alleen het kaartje er nog in moet doen dan kan dat nog. In het voorbeeld worden drie stemmen gebruikt. Eigenlijk moeten deze zinnen door drie verschillende robots tegen elkaar gezegd worden, maar dat heb ik nog niet klaar. Als je meer wilt weten over de SD lezer/schrijver of deze voor andere doeleinden wilt gebruiken klik dan hier.

  Klik hier om het testprogramma te zien of te verbergen  

En zo klinkt de uitvoer van dit programma bij gebruik van een luidspreker. De micofoon hing vlak bij de luidspreker. Je kunt de gebruikte geluidsfragmenten en enkele andere, in het juiste formaat hier downloaden. Ik heb dit programma (in verschillende vormen) getest met de Arduino nano en met de Pro Micro en met diverse luidsprekers en buzzers. Mijn conclusies:

Betere oplossingen

Er zijn betere oplossingen, maar die vereisen extra componenten. Een van de mogelijkheden is een mini MP3 speler te koppelen aan de Arduino. Er zijn verschillende types in de markt. Ze kosten maar een paar euro's. Een van de beste is de DFPlayer Mini. Hij werkt goed en is makkelijk aan te sluiten.

Met de DFPlayer Mini

Alleen de blauw gekleurde aansluitingen zijn vereist
Met deze module kun je geluiden rechtstreeks op een luidspreker afspelen. Als de luidspreker niet meer dan 3 Watt trekt dan heb je geen versterker nodig. Er is een speciale audio uitgang voor als je wel wilt versterken. De module heeft 16 pinnen, alle zonder bijschrift. Gelukkig is op Internet vrij goed te vinden hoe je de module op een Arduino moet aansluiten. Hierbij heb je naast de voeding maar twee draadjes nodig. De luidspreker hoort tussen Speaker 1 en Speaker 2, maar bij mij is het geluid beter als ik deze aansluit tussen Speaker 1 en GND. Het grote voordeel van dit type module is dat ze nauwelijks iets van de rekencapaciteit of het geheugen van de Arduino vergen. Hierdoor kan hij ook werken op minder geavanceerde Arduino's en houd je veel ruimte over voor de rest van je programma. Een ander voordeel is dat de geluidskwaliteit vrij goed is en dat de module geluid in diverse bestandsformaten kan afspelen. Voor deze module kun je de bibliotheek DFRobotDFPlayerMini.h gebruiken. Deze bibliotheek heeft functies waarmee de bestanden op volgnummer van datum worden afgespeeld, ongeacht de bestandsnaam, maar ook functies die kijken naar het nummer waarmee de bestandsnaam begint. Dit heeft als voordeel dat je betekenisvolle bestandsnamen kunt gebruiken, zonder dat dat extra geheugen van je Arduino kost. Je kunt structuur aanbrengen door geluiden in mappen te verzamelen. Ik heb bijvoorbeeld in map 16 het bestand 007DaisyZegtHallo.mp3 staan. Dit bestand wordt afgespeeld door DFPlayer.playFolder(15, 7); aan te roepen. Als je een andere bibliotheek gebruikt dan worden wellicht andere eisen gesteld aan de namen van mappen en bestanden.

Deze module kun je ook zonder Arduino gebruiken en besturen via drukschakelaars op IO1 en IO2. Op de Adkeys kun je twee keer tien drukschakelaars aansluiten om de module te besturen. In de documentatie kun je zien welke weerstand je bij elke schakelaar moet aansluiten. Elke schakelaar moet je aan een kant verbinden met GND.
Let op: er zijn verschillende modules in omloop die sprekend op deze module lijken, maar die totaal anders moeten worden aangesloten en bestuurd. Inmiddels heeft de fabrikant, DFRobot, andere modules gemaakt: de DFR0768 en de DFR075. Beide hebben hun eigen bibliotheek nodig, maar die kunnen gemakkelijk gevonden en geïnstalleerd worden via de Arduino IDE. Beide modules hebben hun eigen geheugen, waardoor er geen micro SD kaartje meer nodig is. Met de DFR075 kun je geluiden opnemen en afspelen; ook zonder Arduino. Beide modules kun je aansluiten op je computer via een USB-C aansluiting en op die manier geluiden van je computer kopiëren. Ik verwachtte dat de voorbeeldprogramma's bij deze modules ongeveer hetzelfde zouden laten horen als die bij de originele DFPlayer, maar ik kreeg er afgebroken geluiden en niet kloppende volgordes uit. Ik moet hier nog eens dieper in duiken, want vooral de DFR0768 is erg handig door het ingebouwde geheugen van ca. 128 MB.

Met elektronische geheugens

De modules die ik hierna beschrijf hebben als voordeel dat ze nauwelijks geheugen en rekenkracht van de Arduino vergen en een goede geluidskwaliteit geven, ook voor spraak. Het nadeel is dat je maar erg weinig geluid kunt opnemen en dat je meestal niet kunt kiezen welk deel je van dat geluid laat horen. Er bestaan modules die dat allemaal beter doen, maar die zijn prijzig.

ISD1820

ISD1820 module (rechts onder)
Voor weinig geld kun je modules kopen die gebaseerd zijn op de ISD1820 chip (zie de foto). Deze kunnen met of zonder Arduino gebruikt worden. Deze modules zijn uitstekend geschikt om een Arduino robot een paar zinnetjes te laten zeggen. De maximum lengte is 10 seconden. Om de module met de Arduino te gebruiken verbind je GND en VCC van de module met die van de Arduino. Er lijkt niets te gebeuren, maar als je op de rec (record) knop drukt dan moet een rood lampje branden. Begin met een tekst (of ander geluid) op te nemen. Sommige uitvoeringen hebben een schuifschakelaar "repeat". Normaal staat deze links, zodat je de bootschap maar een keer hoort. Als de schakelaar rechts staat dan blijft de boodschap zich herhalen. Als je een Arduino gebruikt dan kun je in jouw programma de boodschap zo vaak herhalen als je zelf wilt en heb je de repeatstand niet nodig. De knoppen PLAYE en PLAYL spelen het opgenomen geluid af. Bij PlayL zolang de knop is ingedrukt; bij PLAYE eenmaal in zijn geheel. Het besturen met de Arduino is dan ook heel makkelijk: de pin waar PLAYE bij staat kort hoog zetten of de pin met PLAYL erop zolang aanzetten als je wilt dat het geluid duurt. Deze keer heb ik de module aangesloten op de Arduino Mini Pro en een ander exemplaar op de Arduino Uno. Het werkt perfect. In het voorbeeld herhaal ik de boodschap steeds na 8 seconden. Maar normaal zul je alleen een boodschap laten horen als er iets gebeurt, bijvoorbeeld als je Arduino robot vuur detecteert roept deze "Brand, brand..".
void setup() {
  pinMode(10, OUTPUT); // Sluit PLAYE aan op pin 10
}

void loop() {
  digitalWrite(10, HIGH); delay(40);
  digitalWrite(10, LOW); delay(8000);
}
Een andere uitvoering.
Zolang het lampje brandt neemt de recorder op.
Je kunt de module ook zo programmeren dat hij opneemt en afspeelt. Omdat het alleen een test is heb ik een lus gemaakt waarin twee seconden wordt opgenomen en afgespeeld. Je ziet in de listing hieronder dat er extra delays nodig zijn om dit goed te laten werken. In dit geval gebruik ik PLAYL, maar PLAYE werkt even goed. Als je liever PLAYE gebruikt, zet deze dan 50 ms hoog en daarna weer laag, gevolgd door een delay van 2 seconden. Bij normaal gebruik zul je het opnemen alleen doen na een gebeurtenis (of het indrukken van een toets); hoe dat moet wijst zich zelf.
LET OP: sommige uitvoeringen mogen NIET op 5 volt aangesloten worden want dan gaan ze stuk. Sluit deze op de 3,3 volt pin van de Arduino aan.
#define REC 2
#define PLAYL 3
void setup() {
  pinMode(REC, OUTPUT);
  pinMode(PLAYL, OUTPUT);
}

void loop() {
  digitalWrite(REC, HIGH);
  delay(2000); // Neem 2 sekonden op
  digitalWrite(REC, LOW);
  delay(100); // Schijnt nodig te zijn
  digitalWrite(PLAYL, HIGH);
  delay(2500); // Moet iets meer zijn dan 2 sekonden
  digitalWrite(PLAYL, LOW);
}

Zang of spraak met de Emic 2

Een van de beste mogelijkheden om je Arduino te laten spreken (of zingen) is met de Emic 2 van Parallax. Helaas is deze module niet goedkoop (ca. 80 euro bij Parallax of nog duurder bij Amazon, maar met flink zoeken kun je hem voor ca. 35 euro vinden).
Deze module kan tekst in het Engels of Spaans, omzetten in geluid. Ook zingen is mogelijk. Je kunt kiezen uit een aantal stemmen en je kunt het volume en de spreeksnelheid regelen. Deze module is heel erg eenvoudig te gebruiken. Sluit hem aan op de 5V uitgang van je Arduino en verbind SIN van de module met pin TX van de Arduino. Sluit een eenvoudige luidspreker aan op SP- an SP+ of gebruik de 3,5 mm koptelefoon ingang. Je kunt opdrachten naar de module sturen alsof je de Seriële monitor gebruikt. De eerste letter die je opstuurt bepaalt wat er gebeurt. In het voorbeeld hieronder zie je enkele mogelijkheden. Belangrijk is dat je de zinnen eindigt met een leesteken en dat je altijd een return opstuurt (bijvoorbeeld door println() te gebruiken). Als iets niet klopt dan kan de module behoorlijk in de war raken, maar anders werkt hij fantastisch.
void setup() {
  Serial.begin(9600);    // de default 8N1 is goed
}

void loop() {
  Serial.println("D1"); // zing de demo
  Serial.println("SHallo. Can you hear me?"); // eigen tekst
  delay(10000);
}
De module geeft ook een signaal terug. Dit kun je lezen via pin RX van je Arduino. Maar als je RX wilt gebruiken dan kun je bijna altijd beter SoftwareSerial gebruiken, omdat de Arduino bij het uploaden ook RX en TX gebruikt. Je zou de draden dan steeds tijdelijk los moeten maken. Met SofwareSerial en pinnen 3 en 4 is dit probleem er niet.In het programma hieronder zie je ook hoe je andere pinnen kunt gebruiken dan TX en RX en je ziet veel van de mogelijkheden van de Emic 2. Ik heb na uitgebreid testen, ook met een pyboard, de indruk gekregen dat er sowieso iets mis is met de module. Als ik met de hand een commando opstuur, dan werkt alles perfect, maar zodra ik exact hetzelfde in een programma doe dan reageert de module soms niet op de instructies.
#include <SoftwareSerial.h>
SoftwareSerial Emic(3, 2); // Digitale pin 3 gaat naar SOUT; pin 2 naar SIN
void setup() {
  Serial.begin(9600);
  Emic.begin(9600); // De default setting (= 8N1) is goed
  Emic.println(); // Stuur een return op. De Emic 2 antwoord met een dubbele punt
  Serial.println("Ik wacht tot de Emic 2 klaar is");
  while (!Emic.available()); // Ga pas luisteren als er een bericht is
  if (Emic.read() == ':') Serial.write("De Emic is klaar voor gebruik");
  Emic.println("V06"); // Zet geluidssterkte op 6; de maximale geluidssterkte is 18
}

String N = "N0";
void loop() {
  Emic.println("L0");
  while (Emic.read() != ':'); // Wacht tot de Emic 2 klaar is
  delay(1000);
  Serial.print("U hoort nu stem "); Serial.println(N);
  Emic.println(N); // Kies een andere stem
  while (Emic.read() != ':'); // Wacht tot de Emic 2 klaar is
  Emic.println("SHallo listener. Can you hear me."); // Zet hier je eigen Engelse tekst
  while (Emic.read() != ':'); // Wacht tot de Emic 2 klaar is
  delay(1000);
  Emic.println("L1");
  while (Emic.read() != ':');
  Emic.println("SBuenas noches a todos."); // Deze tekst klinkt niet goed met mijn Emic 2 rev. A
  N[1]++; if (N[1] > '8') N[1] = '0'; // Volgende stem
  delay(2000);
}

De module heeft nog veel meer mogelijkheden, want je kunt een andere geavanceerde parser gebruiken. Hiermee kun je allerlei eigenschappen van de stemmen optimaliseren. De eenvoudiger standaard parser heeft ook nog diverse extra mogelijkheden. Een voorbeeld: als je in de tekst een ## opneemt voor een woord dan zal dat woord gefluisterd worden.

ISD 1760: Langere geluiden

Als je langere geluiden wilt opnemen, dan kan dat met de goedkope, maar niettemin zeer geavanceerde ISD1760 Module. Deze werkt erg goed. Je kunt iets meer dan een minuut met deze module opnemen en afspelen. Deze module heeft ook meer mogelijkheden dan de ISD1820, zoals de mogelijkheid om meerdere geluiden op te nemen. Maar hij maakt gebruik van een SPI interface zodat het programmeren iets ingewikkelder wordt. Ik heb een bibliotheek getest waarmee ik in ieder geval een geluid kon afspelen.

Later meer over deze module.