Freaduino MP3 Music Shield

For code club one of the projects I had been considering was an MP3 player with a simple user interface (UI) based on a joystick providing track next/previous , volume up/down, and pause/play. I looked for suitable Arduino shields which had Netduino driver support. I narrowed the list down to (Prices as at April 2014) these VS1053 based shields

For Code Club I purchased 5 of the Elecfreaks Freaduino shields as the price and on-board joystick made it ideal for our application. The Freaduino MP3 Shield wiki page indicated that the following pins were used by the SPI bus

D10 – Used for SPI Chip Select.
D11 – Used for SPI MOSI.
D12 – Used for SPI MISO.
D13 – Used for SPI SCK.

I initially tried the NetduinoVS1053 library from SoftElectoTech but found that no sound was produced. I tried different pin configurations, format and bitrate music files but nothing worked. I then had a look at the shield schematic and noticed that D11/D12/D13 were not connected to the VS1053, only D10 which is used for chip selected on the MicroSD card socket was connected.

I soldered some jumpers to the board and connected the SPI pins on the ICSP socket to the D11,D12 & D13 on the edge connector and the shield now works. It would be good if elecfreaks could make the pins the SPI bus uses configurable using jumpers or similar.

Modified Freaduino Music Shield

Modified Freaduino Music Shield

The library needs to be initialised with the following pins

Player = newVs1053B(Pins.GPIO_PIN_A1, Pins.GPIO_PIN_A3, Pins.GPIO_PIN_A2, Pins.GPIO_PIN_A0);

The joystick operations can be handled with Interrupts with the following configuration

InterruptPort volumeDownButton = newInterruptPort(Pins.GPIO_PIN_D7, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);

InterruptPort volumeUpButton = newInterruptPort(Pins.GPIO_PIN_D3, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);

InterruptPort nextSongButton = newInterruptPort(Pins.GPIO_PIN_D4, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);

InterruptPort previousSongButton = newInterruptPort(Pins.GPIO_PIN_D6, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);

InterruptPort playStopButton = newInterruptPort(Pins.GPIO_PIN_D5, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);

volumeUpButton.OnInterrupt += new NativeEventHandler(volumeUpButton_OnInterrupt);

volumeDownButton.OnInterrupt += new NativeEventHandler(volumeDownButton_OnInterrupt);

nextSongButton.OnInterrupt += new NativeEventHandler(nextSongButton_OnInterrupt);

previousSongButton.OnInterrupt += new NativeEventHandler(previousSongButton_OnInterrupt);

playStopButton.OnInterrupt += new NativeEventHandler(playStopButton_OnInterrupt);

I could now play MP3 files off the SD card on my Netduino Plus 2 but couldn’t adjust the volume or change the track being played. Using an interrupt based approached for the UI also highlighted some problems with the driver code which I will discuss in a future post.

Ultrasonic Ranger Distance Measurement

I had been thinking about an Ultrasonic Tape measure as one of the projects for code club. One of the “challenges” we start each evening with was measuring how long the Netduino on board button was pressed using an InterruptPort triggering on both the leading and trailing edges. This challenge implements the core of the code required to use an Ultrasonic Ranger.

Ultrasonic Ranger connected to Netduino Plus 2

Ultrasonic Ranger Test Rig bill of Materials (April 2014)

A plug and play option would be

To make a measurement the trigger pin is strobed high, then the duration of the pulse on the echo pin represents the distance from the object. The NetMF DataTime structure represents tick as one hundred nanoseconds or one ten-millionth of a second. (There are 10,000 ticks in a millisecond) so the duration in ticks/58 is the distance in millimetres.

public UltraSonicRanger(Cpu.Pin triggerPin, Cpu.Pin echoPin)
{
   #region Diagnostic Assertions
   Debug.Assert(echoPin != Cpu.Pin.GPIO_NONE);
   Debug.Assert(triggerPin != Cpu.Pin.GPIO_NONE);
   Debug.Assert(echoPin != triggerPin);
   #endregion

   triggerOutput = new OutputPort(triggerPin, false);

   echoInterrupt = new InterruptPort(echoPin, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
   echoInterrupt.OnInterrupt += new NativeEventHandler(echoInterruptPort_OnInterrupt);
   echoInterrupt.DisableInterrupt();
}

void echoInterruptPort_OnInterrupt(uint data1, uint data2, DateTime time)
{
   if (data2 == 0) // falling edge, end of pulse
   {
      pulseWidthTicks = time.Ticks - pulseStartTicks;
      measurementComplete.Set();
   }
   else
   {
      pulseStartTicks = time.Ticks;
   }
}

Ultrasonic Ranger module source

I was pleasantly surprised by the sub 0.5 cm accuracy of the sensor