In de Volkskrant van 2 Juli kun je in mijn Maakbare Wereld bijdrage lezen dat ik een sprekend zwaard heb gemaakt. Ik zou hier wat onderdelen in meer detail willen uitleggen met name de elektronische delen.
Hardware
In het zwaard heb ik een
Teensy 3.2 met
Prop shield gebruikt. Daarnaast een
kleine metalen speaker en een
oplaadbare batterij via Adafruit. De Teensy en prop shield heb ik aan elkaar gesoldeerd en na wat forum leeswerk en het goed bekijken van onderstaande foto wist ik hoe dat moest.
Je kunt zien dat er aan drie zijdes pinnetjes verbonden moeten worden.
De batterij moet op een 5V (rode draad) en GND (zwarte draad) pin aangesloten worden. Ik heb dit pas helemaal aan het einde gedaan nadat ik alle software er al op had. De speaker moet de + en - pinnen worden aangesloten.
Software
Je kunt de Teensy programmeren door een USB kabel aan te sluiten en de
Arduino software te gebruiken met de
Teensyduino add-on. De prop shield beschrijvingspagina heeft eerst een mooie beschrijving hoe je de sensoren kunt ijken en dat is zeker de moeite om even te doen.
Daarna wilde ik het geluid testen en daarvoor heb ik de code bekeken in Examples van de Arduino omgeving onder Talkie. Hier kun je een soort robot stem wat woordjes laten zeggen. Om deze code te laten werken moet je het volgende veranderen. Vervang AudioOutputI2S door AudioOutputAnalog en haal alles weg waar SGTL5000 staat.
Om het volume harder te krijgen moet je de volgende regels toevoegen.
AudioMemory(20);
dac1.analogReference(EXTERNAL); // much louder!
delay(50); // time for DAC voltage stable
pinMode(5, OUTPUT);
digitalWrite(5, HIGH); // turn on the amplifier
delay(10); // allow time to wake up
Als je nu geluid kunt produceren kun je doorgaan om eigen geluiden af te spelen
Audio bestanden gereedmaken
Je kunt op de pc een geluid opnemen of een ander geluid gebruiken, maar voordat dat je het kunt gebruiken moet je het eerst omzetten in het RAW formaat. Hiervoor kun je het programma
Sox gebruiken. Dit programma moet je gebruiken vanaf de command line, daarvoor kun je zoeken in Windows naar cmd.exe (net als ms-dos vroeger :)). Ik heb er voor gekozen om de bestanden die ik wilde omzetten in dezelfde map als sox.exe te plaatsen.Bij mij was dat C:\Program Files (x86)\sox-14-4-2.
Als je deze gevonden hebt moet je een bestand omzetten met:
sox file.mp3 --bits 16 --rate 44100 --channels 1 file.raw
Hier moet je nog je eigen bestandsnamen invullen. Het eindresultaat moet compleet in hoofdletters om te werken op de Teensy, dus bijvoorbeeld GELUID.RAW
Audio bestanden kopiëren
Als het omzetten gelukt is wil je het resultaat kopiëren op de flash drive van de prop shield. Allereerst moet de Teensy weten dat er iets gekopieerd gaat worden. Download eerst het volgende programma
Teensytransfer. Je moet de usb mode op "Raw Hid" zetten in de Arduino omgeving. Om teensytransfertool.ino op je Teensy uploaden moet je ervoor zorgen dat het in een map staat samen met version.h, Teensytranser.h en Teensytranfer.cpp. Het ino bestand kun je dan uploaden op de Teensy.
In de map waar Teensytranser gedownload is vind je ook een teensytransfer.zip bestand waar in teensytransfer.exe te vinden is. Deze moet je uitpakken. In dezelfde map heb ik de gevonverteerde RAW bestanden geplaatst.
Hierna moet je weer de command line openen (cmd.exe) en naar de map gaan waar het teensytransfer.exe en RAW bestanden te vinden zijn.
Om te zien of alles in orde is tik je: teensytransfer -i teensy
Om een bestand te kopiëren tik je: teensytransfer -w eeprom GELUID.RAW
Om te zien of dat gelukt is tik je: teensytranser -l
Geluid afspelen
Nu is het toch eindelijk tijd om onze eigen geluiden af te spelen. Ik zal gelijk overgaan tot mijn eigen code. Hier zijn er drie bestanden die afgespeeld worden onder verschillende omstandigheden. Eentje bijvoorbeeld als er lang geen beweging is. De andere twee als opeens wel beweging of draaiing is. Aangezien we al genoeg gelezen hebben zal ik de code hier gewoon plaatsen.
#include <NXPMotionSense.h>
#include <Wire.h>
#include <EEPROM.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Audio.h>
NXPMotionSense imu;
NXPSensorFusion filter;
AudioPlaySerialflashRaw playFlashRaw1; //xy=145,62
AudioPlaySerialflashRaw playFlashRaw2; //xy=161,115
AudioMixer4 mixer1; //xy=390,210
AudioOutputAnalog dac1; //xy=740,251
AudioConnection patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection patchCord2(playFlashRaw2, 0, mixer1, 1);
AudioConnection patchCord3(mixer1, 0, dac1, 0);
AudioConnection patchCord4(mixer1, 0, dac1, 1);
int restTime = 0;
int yesTime = 10000;
int finallyTime = 10000;
void setup() {
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);//Enable Amplified PROP shield
delay(10);
if (!SerialFlash.begin()) {
while (1)
{
Serial.println ("Cannot access SPI Flash chip");
delay (1000);
}
}
AudioMemory(20);
dac1.analogReference(EXTERNAL); // much louder!
delay(50); // time for DAC voltage stable
pinMode(5, OUTPUT);
digitalWrite(5, HIGH); // turn on the amplifier
delay(10);
mixer1.gain(0, 0.4);
mixer1.gain(1, 0.4);
//Serial.begin(9600);
imu.begin();
//filter.begin(100);
}
void loop() {
float ax, ay, az;
float gx, gy, gz;
float mx, my, mz;
//float roll, pitch, heading;
float energy = 0;
float turn = 0;
if (imu.available()) {
// Read the motion sensors
imu.readMotionSensor(ax, ay, az, gx, gy, gz, mx, my, mz);
energy = sqrt(ax*ax+ay*ay+az*az);
turn = sqrt(gx*gx + gy*gy + gz*gz);
Serial.println("turn: " );
Serial.println(turn);
}
if (turn > 400)
{
if (finallyTime > 100000)
{
playFlashRaw1.play("FINALLY.RAW");
delay(2000);
}
restTime = 0;
finallyTime = 0;
}
if (energy> 3.5)
{
if(yesTime>10000)
{
playFlashRaw1.play("YES.RAW");
//Serial.println ("sound played?");
delay(2000);
}
restTime = 0;
yesTime = 0;
}
restTime = restTime + 1;
yesTime = yesTime +1;
finallyTime = finallyTime +1;
if (restTime > 1000000)
{
playFlashRaw1.play("EZKIEL.RAW");
delay(10000);
restTime = 0;
}
// Update the SensorFusion filter
// filter.update(gx, gy, gz, ax, ay, az, mx, my, mz);
// print the heading, pitch and roll
/*roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
Serial.print("Orientation: ");
Serial.print(heading);
Serial.print(" ");
Serial.print(pitch);
Serial.print(" ");
Serial.println(roll);*/
}
Final Notes
Ik heb nu nog maar beperkt gebruik gemaakt van de mogelijkheden van de prop shield. Je kunt er ook knoppen op aansluiten of gewoon pins als tastsensor gebruiken. Sensoren die voor Arduino bedoeld zijn zullen ook wel werken denk ik zo. De prop shield kun je natuurlijk in van alles en nog wat verwerken.
Ik hoop dat dit stukje mensen wat sneller op weg helpt, want persoonlijk vond ik het een flinke speurtocht.
En zoals altijd, heb je vragen stel ze gerust.