How to Play a MP3 File with Programmable Wireless, Go and the Arduino MKR GSM 1400

December 10, 2018
Written by

arduinomkr1400.jpg

The new MKR family of Arduino boards are going to change the landscape of rapid prototyping IoT solutions. The Arduino MKR GSM 1400 is a great solution for anyone looking to expand the scope of their IoT projects using cellular connectivity. By integrating a modem with a microcontroller a new all-in-one communication solution has started to emerge. This paired with the Twilio Programmable Wireless SIM makes it possible to communicate around the globe using Machine-to-Machine commands. “Things” can now be connected in ways previously impossible with WiFi or Bluetooth.

This tutorial demonstrates how to send a Machine-to-Machine Command from the Arduino MKR GSM 1400 to a server written in Go. When the Machine-to-Machine Command is received server-side an audio file will play a .mp3 saying “hello”. If you want to jump ahead the completed project can be found on the TwilioIoT GitHub.

What is the Arduino MKR GSM 1400?

The Arduino MKR GSM 1400 is a development board that combines the functionality of the Arduino Zero with global GSM connectivity using the u-blox SARAU201 modem. Traditionally communicating with a modem is done using AT commands using a separate module. This model board ships with a library that makes AT commands more accessible via function calls.

Hardware Requirements

Software Requirements

TwilioSIM.png

Remove the Twilio SIM from it’s packaging. Next register and activate your SIM in the Twilio Console.

Software side of things

Before programming the hardware we need to install a few pieces of software to make it work. To be able to send M2M Commands using the on-board modem we will need the MKRGSM library.

Open the Arduino IDE and go to Sketch > Manage Libraries. This is where Arduino and 3rd party libraries can be installed into the Arduino IDE.

arduinogsm-managerlibrary.png

When the Library Manager window pops up search for the MKRGSM library and press install. The MKRGSM library wraps AT commands into functions, making it easier to communicate with the modem. It’s phonetabulous trust me.

arduinogsm-librarymanager.png

After the library is installed we need to install the Arduino MKR GSM 1400 board cores. The Arduino MKR GSM 1400 uses a different chipset than traditional Arduinos that use AVR ATmega chipsets. This board uses the SAMD21 Cortex-M0+ and it requires a different set of cores. The cores do not come with the Arduino IDE and they are needed for the computer to recognize the board when connected.

Locate the Board Manager under Tools > Board > Board Manager.

arduino-boardsmanager.png

When the Board Manager window appears search for the Arduino SAMD Boards and install the cores.  

arduinogsm-boardselect.png

Restart the Arduino IDE to complete the installation.

Great! Time to move on to the hardware setup.

Hardware side of things

To send M2M Commands over the network we need to install the Twilio SIM. Break out the Micro SIM from the Twilio SIM card

arduinogsm-SimSize.png

Insert the Twilio SIM into the SIM slot underneath the board.

arduinogsm-sim.JPG

Next, attach the GSM antenna to the board.

arduinogsm-antenna.JPG

Connect the board to the computer using a Micro-USB cable and you are geared up to connect to the network.

arduinogsm-gif01.gif

In the Arduino IDE create a new Arduino sketch (File > New). A template is provided that look something like this.

arduino

void setup(){

}

void loop(){

}

Instantiate the base class GSM for all of the GSM functions. To send and receive SMS messages the GSM SMS class needs to be instantiated as well. This happens before the setup() function.

#include <MKRGSM.h>

GSM gsmAccess;
GSM_SMS sms;

In the setup() function create a serial connection with a baud rate of 115200. The baud rate determines the speed of data over a specific communication channel.

arduino
Serial.begin(115200);

Use the gsmAccess.begin() function to connect to the cellular network that is identified on the Twilio SIM.

gsmAccess.begin();
Serial.println("GSM initialized");

In the loop() function define the phone number where the M2M Command will be sent using the beginSMS function. The number we will use is “2936”. This is a special Twilio shortcode that is reserved for exchanging M2M Commands between Twilio SIMs. It uses the SMS transport to send M2M Commands over a cellular network. When a Twilio SIM creates a M2M Command a Webhook is generated, we will discuss this shortly.

arduino
sms.beginSMS("2936");

Pass a char array to the function sms.print() to create a new message to be queued.


sms.print("hello world");
Serial.println(“Sending M2M Command”);

After a message is created and queued use the endSMS() function to tell the modem the process is complete. Once this happens the “hello world” message will then be sent.

sms.endSMS();
Serial.println("M2M Command Sent!");

The last bit of code is a while loop that will capture the program and place it in an infinite loop. The purpose of this is to ensure the M2M Command is only sent once.

arduino
while(1) {
    delay(4000);
}

Complete Arduino sketch:

#include <MKRGSM.h>

GSM gsmAccess;
GSM_SMS sms;

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

	gsmAccess.begin();
	Serial.println("GSM initialized");
}

void loop(){
	sms.beginSMS("2936");

        sms.print("hello world");
        Serial.println(“Sending M2M Command”);

       sms.endSMS();
       Serial.println("M2M Command Sent!");

       while(1) {
               delay(4000);
       }  
}

Double check that the board has been selected under Tools > Board. If it is not selected the compiler will throw an error when you try to upload the code.

arduinogsm-selectboard.png

Save the new sketch as "SayHelloArduinoGSM.ino". Before uploading the new sketch to the board let’s create a server to receive the M2M Command using Go.

Spinning up an audio response server with Go and Beep

arduinogsm-gif02.gif

Create a new Go program named “SayHelloArduinoGSM.go” using the template below.

go
package main

import ( 

)

func main(){
}

Next add the following libraries to the import section. This is where you link external libraries like Beep to a Go program. If you haven't installed Go yet do so now using Homebrew

package main

import (
        "fmt"
	"github.com/faiface/beep"
	"github.com/faiface/beep/mp3"
	"github.com/faiface/beep/speaker"
	"log"
	"net/http"
	"os"
	"time"
)

Inside the main function create a new server route using HandleFunc() from the net/http library. This will generate a new server-side route (“/helloworld”) for receiving M2M Commands from the “2936” shortcode. When an M2M Command is received it will then be funneled to the helloworld function. Open up a port and listen for incoming connections using the ListenAndServe() function on port 9999.

func main(){
	http.HandleFunc("/helloworld", helloworld)
	http.ListenAndServe(":9999", nil)
}

Fantastic. Now we have to create the helloworld function. The HTTP request received by this function will be represented by the http.Request type.

func helloworld(w http.ResponseWriter, r *http.Request) {

}

When the request is received the M2M Command needs to be parsed. Use the ParseForm() function to parse the request body as a form.

	if err := r.ParseForm(); err != nil {
		log.Printf("Error parsing form: %s", err)
		return
	}

The data from the body can be extracted using the PostFormValue() function by passing it a key. The key will give you the value associated with the named component in the JSON response. In this case we are looking for the value of the “Command” key.

	pwCommand := r.PostFormValue("Command")
	fmt.Println("pwCommand : ", pwCommand)

And to add a little spice let’s at some Beep code to play an audio file through your system’s audio when the Command successfully reaches the server.

	f, err := os.Open("helloworld.mp3")
	if err != nil {
		log.Fatal(err)
	}
	s, format, _ := mp3.Decode(f)
	speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
	playing := make(chan struct{})
	speaker.Play(beep.Seq(s, beep.Callback(func() {
		close(playing)
	})))
	<-playing

Complete Go program:

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/faiface/beep"
	"github.com/faiface/beep/mp3"
	"github.com/faiface/beep/speaker"
)

func main() {
	http.HandleFunc("/helloworld", helloworld)
	http.ListenAndServe(":9999", nil)
}

func helloworld(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		log.Printf("Error parsing form: %s", err)
		return
	}

	pwCommand := r.PostFormValue("Command")
	fmt.Println("incoming Command from Arduino MKR GSM 1400 : ", pwCommand)

	fmt.Println("Playing audio file!")
	f, err := os.Open("helloworld.mp3")
	if err != nil {
		log.Fatal(err)
	}
	s, format, _ := mp3.Decode(f)
	speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
	playing := make(chan struct{})
	speaker.Play(beep.Seq(s, beep.Callback(func() {
		close(playing)
	})))
	<-playing
}

Start the server.


go run SayHelloArduinoGSM.go

Constructing the bridge with ngrok

Currently the hardware and software pieces exist individually. ngrok will be used to bridge the gap.

arduinogsm-gif04.gif

When the SIM sends a M2M Command to Twilio a Webhook is sent to a user-defined url called the Commands Callback Url. We will use ngrok to receive this Webhook and then route it to the server running on our own machine. To make the connection, start a new ngrok instance on the same port where the server is running.

bash
ngrok http 9999

Copy the Forwarding url that was created with ngrok (http://xxxxxxxx.ngrok.io)

arduinomkrgsm-ngrok.png

Navigate to Programmable Wireless in the Twilio console. Locate the SIM that you previously registered under SIMs. Under the Configure tab you will find the Commands Callback Url. Paste the ngrok Forwarding address into text box and add the previously created server route to the end of the url.
http://xxxxxxxx.ngrok.io/helloworld 

arduinogsm-wirelessconsole.png

Press Save.

Send messages through the sky

Go back to the Arduino IDE and press upload.

arduinogsm-upload.png

Once uploaded, double check to see if the Command was sent properly using the Serial Monitor.

  • Navigate to Tools > Serial Monitor

arduinogsm-send.png

Once the M2M Command is sent from the “2936” shortcode it is then routed to ngrok and onto the go application using the Commands Callback Url.

arduinogsm-ngrok2.png

And finally the M2M Command reaches the server and the “helloworld.mp3”

arduinogsm-server.png

Celltactular!

Continue to connect things

You just sent your first M2M Command using magic.

arduinogsm-magic.gif

This M2M Command model is a foundational piece of how to use Twilio to send M2M Commands from a remote hardware device. With the integrated modem and software for sending AT commands as functions, it makes the Arduino MKR GSM 1400 an ideal piece for any IoT prototyping kit.

If you are interested in learning about other pieces of hardware that can send M2M Commands check out the Wireless Machine-to-Machine Quickstarts. This project, along with other projects, can be found on the TwilioIoT GitHub.

Feel free to reach out with any questions or curiousity. If you have any cool IoT projects you have built or are planning on building drop me a line.