Code It

Our code is fairly simple -- it really just does two things: play a looping static file, and then when the magnet is detected, play a different file.

You already got the Feather up and running in the Feather Prep section of the guide, so now we need to add code to read the Hall effect sensor and play the second track.

You'll needs two audio .mp3 files on the SD card. I've named my files STATIC.MP3 and TUNED.MP3. Load your files onto the card and then put the card in the FeatherWing's SD slot. You can find more info on loading music files here.

Copy this code below, paste it into a new Arduino sketch, save the sketch as hauntedRadio.ino in your Arduino sketches library, and then upload it to the Feather board which is plugged in via USB.

//Haunted Radio
//by John Park for Adafruit Industries
//based on feather_player by Limor Fried
//
//Uses hall sensor to detect magnet attached to radio tuner dial
//Plays static file and radio play files from Music Maker FeatherWing
//connected to Feather microcontroller
//
//MIT License

/*/////////// Hardware ////////////////////////////////

 Feather (of any variety, in this case ESP8266 Huzzah)
 Music Maker MP3 FeatherWing
 Hall sensor connected to digital input pin 4

Wiring is left (pin 1) to Vin, middle (2) to GND, right (3) to digital input
  -place 10K resistor between voltage in Pin 1 and voltage out Pin 3
  _______
 |\_____/|  
 | |   | |
 | |   | |
  -------
  /  |  \
 |   |   |
 |   |   |
 |   |   |
 |   |   |
 +  GND  Output
 |   |   |
 |       |
 \-[|||]-/ 10k resistor


/////////////////////////////////////////////////////*/

#include <SPI.h>
#include <SD.h>
#include <Adafruit_VS1053.h>


// These are the pins used
#define VS1053_RESET   -1     // VS1053 reset pin (not used!)

// Feather M0 or 32u4
#if defined(__AVR__) || defined(ARDUINO_SAMD_FEATHER_M0)
  #define VS1053_CS       6     // VS1053 chip select pin (output)
  #define VS1053_DCS     10     // VS1053 Data/command select pin (output)
  #define CARDCS          5     // Card chip select pin
  // DREQ should be an Int pin *if possible* (not possible on 32u4)
  #define VS1053_DREQ     9     // VS1053 Data request, ideally an Interrupt pin

// Feather ESP8266
#elif defined(ESP8266)
  #define VS1053_CS      16     // VS1053 chip select pin (output)
  #define VS1053_DCS     15     // VS1053 Data/command select pin (output)
  #define CARDCS          2     // Card chip select pin
  #define VS1053_DREQ     0     // VS1053 Data request, ideally an Interrupt pin

// Feather ESP32
#elif defined(ESP32)
  #define VS1053_CS      32     // VS1053 chip select pin (output)
  #define VS1053_DCS     33     // VS1053 Data/command select pin (output)
  #define CARDCS         14     // Card chip select pin
  #define VS1053_DREQ    15     // VS1053 Data request, ideally an Interrupt pin

// Feather Teensy3
#elif defined(TEENSYDUINO)
  #define VS1053_CS       3     // VS1053 chip select pin (output)
  #define VS1053_DCS     10     // VS1053 Data/command select pin (output)
  #define CARDCS          8     // Card chip select pin
  #define VS1053_DREQ     4     // VS1053 Data request, ideally an Interrupt pin

// WICED feather
#elif defined(ARDUINO_STM32_FEATHER)
  #define VS1053_CS       PC7     // VS1053 chip select pin (output)
  #define VS1053_DCS      PB4     // VS1053 Data/command select pin (output)
  #define CARDCS          PC5     // Card chip select pin
  #define VS1053_DREQ     PA15    // VS1053 Data request, ideally an Interrupt pin

#elif defined(ARDUINO_FEATHER52)
  #define VS1053_CS       30     // VS1053 chip select pin (output)
  #define VS1053_DCS      11     // VS1053 Data/command select pin (output)
  #define CARDCS          27     // Card chip select pin
  #define VS1053_DREQ     31     // VS1053 Data request, ideally an Interrupt pin
#endif


Adafruit_VS1053_FilePlayer musicPlayer = 
  Adafruit_VS1053_FilePlayer(VS1053_RESET, VS1053_CS, VS1053_DCS, VS1053_DREQ, CARDCS);

const int HALLPIN = 4;   // hall effect sensor pin (since we aren't using I2C)
int hallState = 0;       // variable for reading the hall sensor status

int staticOn = 1;  // variable to store state of static being played
int stationOn = 0; // variable to store state of station being selected

/////////////////////////// Setup /////////////////////////////////////////////

void setup() {
  Serial.begin(115200);

  pinMode(HALLPIN, INPUT_PULLUP); //so we can read the Hall sensor


  // if you're using Bluefruit or LoRa/RFM Feather, disable the BLE interface
  //pinMode(8, INPUT_PULLUP);

  // Wait for serial port to be opened, remove this line for 'standalone' operation
  //while (!Serial) { delay(1); }

  Serial.println("\n\nAdafruit Music Maker VS1053 Feather Haunted Radio");
  
  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!");
  
  
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(40,40);
  
#if defined(__AVR_ATmega32U4__) 
  // Timer interrupts are not suggested, better to use DREQ interrupt!
  // but we don't have them on the 32u4 feather...
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int
#elif defined(ESP32)
  // no IRQ! doesn't work yet :/
#else
  // If DREQ is on an interrupt pin we can do background
  // audio playing
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
#endif
  


}


/////////////////////////  Loop  //////////////////////////////////////////////



void loop(){

  hallState = digitalRead(HALLPIN); // the magnet is on 1500AM, 
  //check to see if we're tuned in to this station

  if(staticOn == 1) {
    Serial.println("Playing STATIC.MP3.\n");
    musicPlayer.startPlayingFile("STATIC.MP3");
    staticOn = 0; //flip the flag so it doesn't start playing over again
  }

  if (hallState == HIGH){ //this is HIGH when we don't sense a magnet
    Serial.println("No magnet.\n");
    delay(200);
  }

  else if(hallState == LOW){ //when this goes LOW, we're seeing the magnet
    Serial.println("\t Magnet has been sensed!");
    if(stationOn==0){
      Serial.println("\t Playing file TUNED.MP3\n");
      musicPlayer.setVolume(30,30);
      musicPlayer.stopPlaying();
      musicPlayer.startPlayingFile("TUNED.MP3");
      stationOn=1;
    }  
    delay(200);
  }


  if(musicPlayer.stopped()) {
    Serial.println("Player has stopped.\n");
    staticOn=1; //reset counter so static will start again
    //stationOn=0; //reset counter so station can be restarted when sensor is
    //over the magnet again, comment this line out if you don't want the station file to loop or play multiple times
  }
}

Now, when you turn on the Haunted Radio it will begin immediately playing the static track. As you tune the dial and reach the cursed station, it will play back the second track!

Last updated on 2017-06-15 at 06.36.19 PM Published on 2017-06-16 at 03.21.44 PM