Members | Sign In
Legacy MOVI User Community Forum (readonly) > MOVI Projects
avatar

MOVI, Adafruit Music Maker shield (VS1053), Adafruit PN532 Shield and Mega 2560 R3

posted May 19, 2017 12:54:46 by bakerdaniel808@gmail.com
Although this works, I am not confident that I've coded this optimally.

I have:
- MOVI rev 1.1
- Adafruit "Music Maker" MP3 Shield for Arduino w/3W Stereo Amp (https://www.adafruit.com/product/1788)
- Adafruit PN532 NFC/RFID Controller Shield (https://www.adafruit.com/product/789)
- Elegoo Mega 2560 R3 (https://www.amazon.com/Elegoo-ATmega2560-ATMEGA16U2-Compatible-Arduino/dp/B01H4ZLZLQ)

Goal is to integrate these components.

I had to briefly pause music playing so that I could run the MOIV poll() method. I also had to place the NFC card read within a pause. Otherwise, weirdness occurred. I'm thinking that either there are pin conflicts or memory conflicts. Need to dig some more, but for now this works:

if (musicPlayer.playingMusic) { recognizerPause=true; musicPlayer.pausePlaying(true); }
// do this while briefly paused music
res=recognizer.poll();
// do this while briefly paused music
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
if (recognizerPause) { recognizerPause=false; musicPlayer.pausePlaying(false); }

Note:
- I jumped the MOVI TX and RX pins to pins A13 and A12 on the mega.
- On the Music Maker shield, I closed the three solder jumpers next to the ISP header. This configures the shield to use the ISP header for SPI communication (needed for the Mega). I also cut the mini wire between the other three jumpers to 'release' the digital #11, 12 and 13 pins from being tied to the SPI pins - so that I could use them for something else. (https://learn.adafruit.com/adafruit-music-maker-shield-vs1053-mp3-wav-wave-ogg-vorbis-player/assembly).

Full code is below:

#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
#include "MOVIShield.h" // Include MOVI library, needs to be *before* the next #include
#include <Wire.h>
#include <Adafruit_NFCShield_I2C.h>
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_PIC32)
#include <SoftwareSerial.h> // This is nice and flexible but only supported on AVR and PIC32 architecture, other boards need to use Serial1
#endif

// These are the pins used for the music maker shield
#define SHIELD_RESET -1 // VS1053 reset pin (unused!)
#define SHIELD_CS 7 // VS1053 chip select pin (output)
#define SHIELD_DCS 6 // VS1053 Data/command select pin (output)
// These are common pins between breakout and shield
#define CARDCS 4 // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin

#define NFC_IRQ 2
#define NFC_RESET 100 // Not connected by default on the NFC Shield

// Set volume for Music Maker left, right channels. lower numbers == louder volume!
#define MUSIC_LOUD 20
#define MUSIC_SOFT 40

Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);

/*
* MOVI TX (J2) -> Arduino A13 (Arduino Mega RX)
* MOVI RX (J3) -> Arduino A12 (Arduino Mega TX)
*/
const int led = 13;
MOVI recognizer(true, A13, A12); // Get a MOVI object, true enables serial monitor interface, rx and tx can be passed as parameters for alternate communication pins on AVR architecture

char *Tracks[] = {"TRACK001.MP3", "TRACK002.MP3", "TRACK003.MP3", "TRACK004.MP3"};
int track=0;

Adafruit_NFCShield_I2C nfc(NFC_IRQ, NFC_RESET);



void setup()
{

recognizer.init(); // Initialize MOVI (waits for it to boot)

recognizer.setVoiceGender(true);

recognizer.callSign("Arduino"); // Train callsign Arduino (may take 20 seconds)
recognizer.addSentence("Let there be light"); // Add sentence 1
recognizer.addSentence("Go dark"); // Add sentence 2
recognizer.addSentence("pause"); // Add sentence 3
recognizer.addSentence("next"); // Add sentence 4
recognizer.addSentence("resume"); // Add sentence 5
recognizer.addSentence("stop"); // Add sentence 6
recognizer.addSentence("soft"); // Add sentence 7
recognizer.addSentence("loud"); // Add sentence 8
recognizer.addSentence("play"); // Add sentence 9
recognizer.train(); // Train (may take 20seconds)

// Serial.begin(9600); // because we constructed with debug true

nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532. 0x01 will retry once. 0xFF will retry forever
nfc.setPassiveActivationRetries(0x01);
// configure board to read RFID tags
nfc.SAMConfig();

// initialise the music player
if (! musicPlayer.begin()) { // initialise the music player
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
while (1);
}
Serial.println(F("VS1053 found"));

musicPlayer.sineTest(0x44, 500); // Make a tone to indicate VS1053 is working

if (!SD.begin(CARDCS)) {
Serial.println(F("SD failed, or not present"));
while (1); // don't do anything more
}
Serial.println("SD OK!");

// list files
printDirectory(SD.open("/"), 0);

// Set volume for left, right channels. lower numbers == louder volume!
musicPlayer.setVolume(MUSIC_SOFT,MUSIC_SOFT);

if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT))
Serial.println(F("DREQ pin is not an interrupt pin"));

// Start playing a file, then we can do stuff while waiting for it to finish
if (! musicPlayer.startPlayingFile(Tracks[track])) {
Serial.print("Could not open file ");
Serial.println(Tracks[track]);
while (1);
}
Serial.println(F("Started playing"));
delay(250); // Give the music maker a moment to get going
}

void loop() // run over and over
{
signed int res;
bool recognizerPause=false;

uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)


if (musicPlayer.playingMusic) { recognizerPause=true; musicPlayer.pausePlaying(true); }

// do this while briefly paused music
res=recognizer.poll(); // Get result from MOVI, 0 denotes nothing happened, negative values denote events (see docs)
// do this while briefly paused music
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);

if (recognizerPause) { recognizerPause=false; musicPlayer.pausePlaying(false); }

if (success) {
// Display some basic information about the card
Serial.println("Found an ISO14443A card");
Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
Serial.print(" UID Value: ");
nfc.PrintHex(uid, uidLength);
Serial.println("");
}

switch (res) {
case 1: //"Let there be light"
Serial.println("and there was light!");
recognizer.say("and there was light!"); // Speak a sentence
break;
case 2: //"Go dark"
Serial.println(F("and there was darkness!"));
recognizer.say("and there was darkness!");
break;
case 3: //"pause"
Serial.println("pause");
recognizer.say("Pausing music.");
musicPlayer.pausePlaying(true);
break;
case 4: //"next"
Serial.println("next");
recognizer.say("I will play the next song.");
musicPlayer.stopPlaying();
if (track<3) track++; else track=0;
if (! musicPlayer.startPlayingFile(Tracks[track])) {
Serial.print("Could not open file ");
Serial.println(Tracks[track]);
while (1);
}
Serial.print("Started playing ");
Serial.println(Tracks[track]);
break;
case 5: //"continue"
Serial.println("resume");
recognizer.say("I will resume playing the music.");
musicPlayer.pausePlaying(false);
break;
case 6: //"stop"
Serial.println("stop");
recognizer.say("I will stop playing music.");
musicPlayer.stopPlaying();
break;
case 7: //"soft"
Serial.println("I will play softly.");
recognizer.say("I will play softly.");
musicPlayer.setVolume(MUSIC_SOFT,MUSIC_SOFT);
break;
case 8: //"loud"
Serial.println("I will play loudly.");
recognizer.say("I will play loudly.");
musicPlayer.setVolume(MUSIC_LOUD,MUSIC_LOUD);
break;
case 9: //"play"
Serial.println("I will play music.");
recognizer.say("I will begin playing music.");
musicPlayer.stopPlaying();
musicPlayer.startPlayingFile(Tracks[track]);
break;

}

}


/// File listing helper
void printDirectory(File dir, int numTabs) {
while(true) {

File entry = dir.openNextFile();
if (! entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
page   1
3 replies
avatar
GeraldFriedland said May 20, 2017 04:10:46
You say "it works" but are obviously not satisfied with the solution. What behavior would you like to have changed?

Gerald
avatar
bakerdaniel808@gmail.com said May 20, 2017 13:28:47
Hi Gerald,

I'm dissatisfied with my own lack of knowledge about why I need to pause playing music before calling the MOVI poll() method. If I do not pause playing music, MOVI is unable to recognize vocal input and the debug output is garbled.

I've read the documentation for MOVI and for the Adafruit Music Maker shield. I've also examined the library files (.cpp, and .h) for each, and still can't figure out how to identify the specific conflicts. I suspect that it has something to do with interrupts(just a guess).

When I added in the NFC shield, I found that I also needed to place the nfc.readPassiveTargetID() method within the pause section in order for the NFC reader to work. I have not tried just the NFC shield and the MOVI shield - I will do that next.

Ultimately, I want MOVI to accept vocal commands when an object is placed near the Adafruit PN532 NFC reader, and use the Adafruit Music Maker breakout to provide pre-recorded audio feedback and additional audio effects, while running some solenoids and servos.

BTW, the MOVI shield is very cool!

Daniel

[Last edited May 20, 2017 13:34:39]
avatar
GeraldFriedland said May 23, 2017 01:56:35
Without knowing the AdaFruit shield, my guess is that SoftwareSerial is not able to handle both boards at the same time very well. If you are using an Uno, maybe try a Mega board or something else more powerful? It's a pure guess though.

Another thing to do is to listen in the communication of both boards using a USBSerial cable and see if that brings up any ideas.

Gerald
Login below to reply: