Kick-O-Meter IoT Project – Software

In the last post, I explained the general idea behind Kick-O-Meter and went into some detail on how to wire up the LED strip with the Arduino.

With the hardware wired up, this post will now focus on the software that makes it work.

Phone App

As this was my first IoT project, I decided to use the Microsoft Maker libraries on GitHub because they are Arduino compatible and I wasn’t sure the level of magic required to communicate. At the time of writing, these libraries aren’t on NuGet and will need to be cloned and built.

Link: https://github.com/ms-iot/remote-wiring

For the Phone app, I created a new Windows 10 project in Visual Studio 2015 then added references to the Microsoft.Maker.Serial library built from the remote-wiring repository above.

Simplified code looks something like this:

using Microsoft.Maker.Serial;
using System;
using Windows.Devices.Sensors;

namespace Kickometer
{
	public class Kickometer
	{
		private BluetoothSerial _Bluetooth;
		private AccelerometerReading _BaseReading;
		private readonly int MASS_CONSTANT = 50;

		public Kickometer()
		{
			_Bluetooth = new BluetoothSerial("Replace-with-actual-BT-device-identifier");
				
			//SerialConfig param apparently doesn't matter for BT, only for USB connection
			_Bluetooth.begin(115200, SerialConfig.SERIAL_8N1);

			var accelerometer = Accelerometer.GetDefault();
			_BaseReading = accelerometer.GetCurrentReading();
			uint minReportInterval = accelerometer.MinimumReportInterval;

			accelerometer.ReportInterval = minReportInterval > 16 ? minReportInterval : 16;
			accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
		}

		private void Accelerometer_ReadingChanged(Accelerometer sender, AccelerometerReadingChangedEventArgs args)
		{
			var xAcceleration = Math.Abs(args.Reading.AccelerationX - _BaseReading.AccelerationX);
			var yAcceleration = Math.Abs(args.Reading.AccelerationY - _BaseReading.AccelerationY);
			var zAcceleration = Math.Abs(args.Reading.AccelerationZ - _BaseReading.AccelerationZ);

			var acceleration = Math.Max(Math.Max(xAcceleration, yAcceleration), zAcceleration);
			var force = MASS_CONSTANT * acceleration;

			_Bluetooth.write((byte)force);

			//reset the base reading so the next calculation uses values relative to the new starting position of the accelerometer
			_BaseReading = args.Reading;
		}
	}
}

The app is watching for changes to the accelerometer, which it then sends via Bluetooth using the Microsoft.Maker.Serial library.

Note: An alternative implementation to the Microsoft.Maker.Serial library would be to use the normal Windows Runtime APIs for Bluetooth

Arduino Sketch

At the Arduino, we’re coding up a single Sketch and making use of the Adafruit NeoPixel library that works with the LED strip.

Get the Adafruit NeoPixel library here: https://github.com/adafruit/Adafruit_NeoPixel

Simplified code looks something like this:

#include <Adafruit_NeoPixel.h>
#define NUM_PIXELS 30 // total number of LED pixels
#define NEOPIXEL_PIN 6 // Digital control pin for NeoPixels

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() 
{
    Serial.begin(115200);
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'
}

void loop() 
{
    if (Serial.available() > 0) 
    {
        int kickVal = Serial.read();
        
        //calculate the uppermost light
        int topLight = ((float)kickVal / (float)100) * (float)NUM_PIXELS;    

        for (int i = 0; i < topLight; i++) {
            strip.setPixelColor(i, strip.Color(0, 255, 0)); //set each pixel to green
            strip.show(); // This sends the updated pixel color to the hardware.
            delay(500); //wait 500ms so they progressively light up
    }     
}

Important: The NEOPIXEL_PIN define must match the pin the wire from the Din on the LED strip is connected to on the Arduino.

That’s pretty much all there is to it – the phone has a communication channel with the Arduino via Bluetooth and the Arduino uses the NeoPixel library to switch on the LEDs according to the force observed by the accelerometer and sent to it.

Finished Product

The finished product was slightly more advanced than shown above, with a simple analytics module that stores the force and time of each kick, analysis of which I’ll cover in a future post.

Here’s a video of it in action: