Introduction: Nerf Connected Target on Steroids

Remember my first tutorial on Sigfox Connected Target for nerfs? Well few month have passed now and I decided to work a bit more on the project and I am now pleased to release a new tutorial: Nerf connected target on steroid. This version fixed few bugs, optimised the battery life and even count points depending how hard you hit the target. It also provides a visual integration using ArtikCloud.

For those who haven't read the first tutorial, it is using The AirBoard, an Arduino based dev kit, with a SigBee shield to send the results through Sigfox network. The advantage of The AirBoard is that it is very small and has battery integrated.

What is Sigfox?

Sigfox is a connectivity solution dedicated to the Internet of Things. The operated network is currently operating in +24 countries, on every continent. Focused on tiny messages (up to 12 bytes) & low energy consumption, it currently powers 7 million devices. Various Sigfox-compatible technical solutions are available, from different silicon vendors.

Step 1: Hardware Requirements

In this tutorial, we will be using:

Connection

You just need to plug the negative wire onto the GND port and the positive to the D3~ port

Step 2: Arduino Code

Installation

Run the code

  • Choose the Arduino Fio board
  • Upload this program to The AirBoard via the BLE-LINK/XBee shield
  • replace the BLE-LINK/XBee shield by the SIGFOX shield
  • connect to the SIGFOX backend: http://backend.sigfox.com

Basic understanding of Arduino programming
Before starting each program, we start with two "base" functions: void setup() and void loop().

  • void setup() is executed in first. It is used to initialise the card.
  • void loop() is executed infinitely (as long as power is provided)

See more on arduino.cc

Code

Now we can have a look at the Arduino file:

// ---------------------------------------------------------------------
// This file is a example for use the library armapi with
// The AirBoard using the SigBee shield module
//
// This software send periodically the digital value of the pin D3~ to Sigfox network.
//
// Created date: 06.09.2016
// Author: Louis Moreau
// Adapted from: <a href="https://github.com/atim-radiocommunications/armapi"> https://github.com/atim-radiocommunications/armap...</a>
// ---------------------------------------------------------------------

// ---------------------------------------------------------------------
// Include
// ---------------------------------------------------------------------
#include <arm.h>
#include <avr/sleep.h>
#include <TheAirBoard.h>
// ---------------------------------------------------------------------
// Define
// ---------------------------------------------------------------------
#define GREEN  5             // GREEN LED
#define BLUE   6              // BLUE LED
#define RED    9            // RED LED
#define PIEZO  3             //Digital Pin 
#define TIMEINTERVALL 900000  // 900 sec -> 15 min sleep time

// ---------------------------------------------------------------------
// Global variables
// ---------------------------------------------------------------------
//Instance of  the class Arm
Arm SigFox;

//Instance of the air board class
TheAirBoard board;

bool debug = false;

//The message to send at sigfox - Set the size of your message in bytes within the brackets
uint8_t msg[2];
//downlink received message
uint8_t data[8];

bool blue = false;
bool sigfoxOK = false;
bool trigger = false; 
int downlinkCounter = 0;
int points = 0;
int count = 0;

uint8_t rev;
armType_t armType;


// ---------------------------------------------------------------------
// Implemented functions
// ---------------------------------------------------------------------
void wakeUpNow()        // here the interrupt is handled after wakeup
{
  points++;
}

void setup()
{
  //Pin modes
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(PIEZO, INPUT);

  resetLeds();

  if(debug){
    Serial.begin(57600);
    digitalWrite(GREEN, HIGH);
  }else{
    //Init Arm and set LED to on if error
  	if (SigFox.Init(&Serial) != ARM_ERR_NONE){
  		digitalWrite(RED, HIGH);
      delay(1000);
      resetLeds();
  	}else{
      digitalWrite(GREEN, HIGH);
      delay(1000);
      resetLeds();
      SigFox.Info(&armType, &rev, 0, 0, 0);
      sigfoxOK=true; 
      SigFox.SetMode(ARM_MODE_SFX);
      //Set Sigfox mode in uplink.
      SigFox.SfxEnableDownlink(false);
      //If downlink
      /*
      if(SigFox.SfxEnableDownlink(true)!= ARM_ERR_NONE){
        digitalWrite(RED, HIGH);
      }else{
        digitalWrite(GREEN, HIGH);
      }
      */
      SigFox.UpdateConfig();
  	}
  }
  delay(1000);
  resetLeds();
  attachInterrupt(1, wakeUpNow, RISING);
}

void sleepNow()         // here we put the device to sleep
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
 
    sleep_enable();          // enables the sleep bit in the mcucr register
                             // so sleep is possible. just a safety pin
 
    attachInterrupt(1, wakeUpNow, RISING);
 
    sleep_mode();            // here the device is actually put to sleep!!
                             // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
 
    sleep_disable();         // first thing after waking from sleep:
                             // disable sleep...
    //detachInterrupt(digitalPinToInterrupt(PIEZO)); // disables interrupt so the
                             // wakeUpNow code will not be executed
                             // during normal running time.
 
}

void loop()
{ 
    if(debug){
      Serial.print("Awake for ");
      Serial.print(count);
      Serial.println(" sec");
      Serial.print("Digital value :");
      Serial.println(digitalRead(PIEZO));
      Serial.print("Points :");
      Serial.println(points);
    }
    blinkBlue();
    delay(500);
    count++;
    if(count>10){
      resetLeds();
      if(points>1){ //to avoid sending message when switching on the device + to avoid false positive
        sendMessage();
      }else{
        digitalWrite(RED, HIGH);
      }
      delay(1000);
      resetLeds();
      count = 0;
      points = 0;
      sleepNow();// sleep function called here
    }
  
  
}

void sendMessage(){
  if(sigfoxOK){    
      unsigned int i;
      digitalWrite(BLUE, HIGH);
      msg[0] = board.batteryChk() * 10; 
      msg[1] = points;
      //Only if you want to check the software revision
      /*
      msg[2] = rev;
      msg[3] = armType;
      */
      //Send the message to sigfox
      if(!debug){
        SigFox.Send(msg, sizeof(msg));
        resetLeds();
        //@TODO Ask Atim why downlink doesn't work
        /*SigFox.Receive(&data, sizeof(data), 60000);
        if(data[i]){
          digitalWrite(GREEN, HIGH);
        }else{
          digitalWrite(RED, HIGH);
        }*/
      }
      resetLeds();
      digitalWrite(GREEN, HIGH);   
    }else{
      digitalWrite(RED, HIGH);
    } 
}

void blinkBlue(){
  if(blue){
    digitalWrite(BLUE, LOW);
    blue = false;
  }else{
    digitalWrite(BLUE, HIGH);
    blue = true;
  }
}

void resetLeds(){
  digitalWrite(GREEN, LOW);
  digitalWrite(BLUE, LOW);
  digitalWrite(RED, LOW);
}

Step 3: Make the Target

This step is completely up to you.

I decided to make the target using some carton lunch box but you can use whatever support you want.

Step 4: Connect You're Device to Artik Cloud

Now it's time to connect your device to Artik Cloud:

Artik Cloud for developers

First of all, navigate to the Artik Cloud developer platform.

  • Sign up in or log in
  • Create a new Device Type:
    I filled:
    "DEVICE DISPLAY NAME": "Connected Target"
    "UNIQUE NAME": "sigfox.connected.target"
  • Create a manifest for this device type
  • Create some "Device Fields" and set:
    ID: String
    frame: String
    battery: Integer
    points: Integer
  • You can create some "Device Actions", we won't use the action for this device type. I still created a toggle action to see how it worked... :) Who knows, maybe in the future I will want to be able to shoot the target only for during a certain period...
  • Activate manifest
  • Fill the device info

Create your device in Artik Cloud

  • Go to https://artik.cloud/my
  • Log in your account (same credentials as the developers' platform)
  • Click on "connect a device"
  • Search for the "connected target" we just created
  • Name your device
  • Check its ID and copy it

Activate your device in the Sigfox Backend and configure it

  • Now you can activate your device on Sigfox backend. Here is a how-to I wrote some time ago: http://blog.sigfox.com/activate-dev-kits/
  • Go to your "DEVICE TYPE" and in the information tab, click on the upper right corner button "edit"
  • At the bottom, you should see "Display type"
  • Choose custom and add "battery::uint:8 points::uint:8"
  • Save and go to the "Callback" tab
  • Click on the upper right corner button "New"
  • Check that the custom payload config is set to: "battery::uint:8 points::uint:8"
  • Add the "https://api.artik.cloud/v1.1/messages" url to the url pattern
  • Change the "Content-type" to: "application/json"
  • Add the Body:
    {
        "data": {
            "frame": "{data}",
            "ID": "{device}",
            "battery": {customData#battery},
            "points": {customData#points}
        },
        "sdid": "theIdOfYourDeviceYouCopiedBefore",
        "type": "message"
    }

Check your credentials using the Artik Cloud developers API:

  • Go to https://developer.artik.cloud/api-console/
  • Go to user and click on GET and then on try it
  • You should see a field with the Authorization starting with Bearer plus some hexa characters.
  • Copy it and past it in the Headers part on the Sigfox Callback

Now go back on your Artik Cloud device, go to the logs, hit the connected target, wait few seconds, you should see that the message has been received in Artik.

You can also navigate to charts and add the "points" as an entry of the chart or the battery

Step 5: Connect to Slack

Now we want the target to send a message to slack when it has been hit.

  • Create a slack team or login your slack's team
  • Click on your team's name and expand the menu
  • Click on Apps & Integration
  • Now search for incoming web hooks app
  • Add a configuration
  • Choose the channel you want to post your message in.
  • You will see a Webhook URL, copy this link
  • Go back in Sigfox Backend and create a new callback (Device Type -> Callback )
  • Create a custom callback
  • Past your link
  • Add the content type: "application/json"
  • Add the body:
    {
    "text": "Aouch!!! \n I've been hit again \n You just made {customData#points} points!!"
    }

Go back to your slack channel, you will see a message posted with your points every time your target have been hit!!

Step 6: Bonus: Create a Rule to Send You an Email If Your Device Battery Is Low

Now we can add something that can be a plus. I want Artik Cloud to send me an email if my device battery is low so that I can recharge it.

Ready?

  • Go to https://artik.cloud/my/rules
  • Create a new rule
  • If Connected Target's battery is less than 31
  • Then, Send Email
  • Add your email address, subject and body
  • Save your rule

Step 7: Bravo

You made it!

Thank you for your attention and do not hesitate to contact me or post a comment if you have any question.