Electric Longboard First Assembly

My next project an electric motor powered longboard.

DIY longboard

Electric Longboard Parts

Bill of Materials for this project (Prices as at Jan 2014)

  • Single Motor Mechanical Electric Longboard Kit USD223
  • Turnigy Aerodrive SK3-6364-245kv Brushless Outrunner Motor USD70.68
  • HobbyKing 150A High Performance Brushless Car ESC USD68.99
  • ZIPPY Flightmax 5000mAh battery X 2 USD31.99 each
  • HXT4mm Battery Harness 14AWG for 2 Packs in Series USD2.43
  • HXT 4mm Gold Connector with Protector (10pcs/set) USD4.44
  • Netduino 2 Plus (may replace this with a Netduino) USD59.95
  • Grove Base Shield V2 USD 8.90
  • Grove Nunchuck Adaptor USD2.90
  • Wireless Nunchuck NZD25.00
  • Moose 9.5×42 Longboard Flush Mount Deck Green Stain NZ57

Initial trials of the Wireless Nunchuck have not been very positive. As the Netduino device starts the connection to the handset is dropped. Need to do some more investigation to see if I can get this to work otherwise I will have to use a wired Nunchuck.

Netduino Crazyflie Wii Nunchuk Remote Control V1.0

After flying the Crazyflie for a couple of days with the Joystick shield based remote control I figured an alternate user interface based on a Wii Nunchuk could be interesting. (It might also make the Crazyflie easier to operate for novice pilots). After a couple of hours coding I have a proof of concept Netduino based Crazyflie Nanocopter Wii Nunchck remote control unit.

Initially the nanocopter was difficult to fly, bouncing up and down (thrust control issues) and swaying side to side (roll & pitch control issues). After some digging I found that every so often the Wii nunchuk (my cheap clone) would return a buffer full of 0xFF or 0x00 bytes.  The 0xFF case had been handled but not the 0x00 one. I added a second test into the GetData  method (around line 335) to catch the 0x00 scenario and this appeared to fix the problem.

cnt = 0;
for (int i = 0; i < inputBuffer.Length; i++)
   if (inputBuffer[i] == 0x0) cnt++;
if (cnt == inputBuffer.Length)
{
   return false;
}
CrazyFlie Netduino Wiichuck based Remote

CrazyFlie Netduino Wiichuck based Remote

Bill on Materials (Prices as at Jan 2014)

This software was built using tooling created and shared by others.

Big thanks to

Jakub Bartkowiak – Gralin.NETMF.Nordic.NRF24L01Plus

Szymon Kobalczyk – Wiichuck I2C driver

Antao Almada – HydraMF.BitConverter

The nunchuck accelerometer provides roll and pitch, the joystick is for thrust and yaw. The first version of the CrazyFlieWiiChuckV1.0 is pretty basic and I have intentionally reduced the maximum roll, pitch, thrust and yaw values to make it easier to fly. (Need to set the Grove Base Shield to 3V3 for my code to work)

Currently I only calculate offset values for thrust & yaw. After a couple of test flights some visual indication of the pitch and roll values from the nunchuk would be helpfull.

Netduino Crazyflie Joystick Shield Remote Control V1.0

Sometimes you start with a goal in mind then a couple of days later you have built something interesting but totally unrelated to what you originally intended to do….

I have several devices (both Netduino & Arduino) which I want to use to collect and upload data to the cloud so I can monitor the resource usage of my house.

I had read Clemens Vaster post on Service Assisted Communication and I was planning to use a Windows Server Essentials 2012 box I have running 24/7 in the hallway to forward updates to the cloud.

I wanted to connect the remote data acquisition nodes directly to the server using their baked in nRF24L01+ support. On the server end the Crazyradio 2.4 Hhz nRF24LU1 USB dongle looked ideal. After some initial positive results I found that the CrazyRadio firmware had been implemented in a way that made it not suitable for my application. (I even considered downloading the BitCraze development VM and building my own custom firmware)

After spending a few hours trying to get the CrazyRadio dongle working I looked at my Crazyflie Nano QuadCopter sitting on the bookshelf.

Then I realised what I really needed is a more portable Crazyflie remote control unit so I didn’t have to unpack my laptop. So two nights later I have a proof of concept Netduino based Crazyflie Nanocopter remote control unit.

CrazyFlie nano copter and Netduino Based Remote

CrazyFlie Netduino based Remote

Bill on Materials (Prices as at Jan 2014)

This software was built using tooling created and shared by others.

Big thanks to

Jakub Bartkowiak – Gralin.NETMF.Nordic.NRF24L01Plus

Antao Almada – HydraMF.BitConverter

Mike McCauley – NRF24 library for Arduino.

I used the NRF24 CrazyFlie emulator to debug my project. No doubt stopping me crashing my Crazyflie many times while debugging.

The Joystick shield has to be modified to work with the common Netduino nRF24L01 libraries which use interrupts rather than polling.

The joystick on the shield is for roll and pitch, the external joystick is for thrust and yaw. The first version of the JoystickShieldnRF24l01V1.0 is pretty basic but I’ll try and enhance it over the next couple of posts.

Netduino Water flow Sensor

A few months ago I purchased 1/2” and 3/4″ inch water flow sensors from SeeedStudio. My plan was to monitor our water and power consumption data to see what environmental impact my house has.

To see how the sensor works I built a simple proof of concept Netduino application which counted the pulses produced by the sensor and calculated the instantaneous water flow.

The next steps are to upload the water flow data to the cloud over a cabled then wireless connections.

public class Program
{
   private static int waterFlowCounter = 0;

   public static void Main()
   {
      InterruptPort flowCounterSensor = new InterruptPort(Pins.GPIO_PIN_D5, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
      flowCounterSensor.OnInterrupt += new NativeEventHandler(flowCounter_OnInterrupt);

      Timer waterFlowUpdate = new Timer(waterFlowUpdateProc, null, 0, 1000);
      Thread.Sleep(Timeout.Infinite);
   }

   static void flowCounter_OnInterrupt(uint data1, uint data2, DateTime time)
   {
      Interlocked.Increment(ref waterFlowCounter);
   }

   static void waterFlowUpdateProc(object status)
   {
      int flowCount = Interlocked.Exchange(ref waterFlowCounter, 0);
      double flowLitresMinute = flowCount / 5.5 ; // The q value from documentation
      Debug.Print(flowLitresMinute.ToString("F1") + "L/m";);
    }
}
Netduino based water flow sensor

water flow sensor

Bill of Materials (Prices as at 12-2014)

Netduino Plus 2 USD60 NZD108

Grove Base Shield V2 USD8.90

G3/4″ Water Flow Sensor USD14.90

G1/2″ Water Flow Sensor USD9.50 NZD8.30

CodeClub Mashup 2014 @ Epic Innovation

On the 8th of November  I was an industry mentor at CodeClub Mashup 2014 which was held at Epic Innovation in Christchurch.

The event was sponsored by Environment Canterbury (ECAN), Land Information New Zealand (LINZ) and Code Club Aotearoa.

Mashup 2014 was a “concept to cash” in one day competition for local high schools. We had roughly 40 students turn up and we started the day with introductions to hardware/software based product development and basic business skills.

Mashup2014 Judging begins

Mashup2014 Judging begins

A team from a Selwyn House an Independent School for Girls from year 1 – 8 explained in a blog post what is mashup.

Some students from Burnside High School produced the official video about the day

Thinking about “Internet of Things” and/or “Farm of Things” mashups in Q1 2015

 

Azure Event Hub Updates from a NetMF Device

I had read about how Azure Event Hubs supported both Advanced Message Queuing Protocol(AMQP) & Hypertext Transfer Protocol (HTTP) access and was keen to see how easy the REST API was to use from a .Net Microframework (NetMF) device.

My initial concept was an exercise monitoring system with a Global Positioning System (GPS) unit and a pulse oximeter connected to a FEZ Spider device. My posting GPS Tracker Azure Service Bus has more info about GPS Drivers  and Azure Service Bus connectivity.

FEZ Spider, GPS and PulseOximeter

Fez spider and sensors for exercise monitoring device

The software was inspired by the Service Bus Event Hubs Getting started, Scale Out Event Processing with Event Hubs,Service Bus Event Hubs Large Scale Secure Publishing and OBD Recorder for .Net Micro Framework with ServiceBus, AMQP (for IoT) samples. I created an Event Hub and associated device access keys and fired up Service Bus Explorer so I could monitor and tweak the configuration.

I started by porting the REST API SendMessage implementation of Service Bus Event Hubs Large Scale Secure Publishing sample to NetMF. My approach was to get the application into my local source control and then cut ‘n’ paste the code into a NetMF project and see what breaks. I then modified the code over several iterations so it ran on both the desktop and NetMF clients.

The next step was to download the HTTPS certificates and add them to the project as resources so the requests could be secured. See this post for more detail.

For the connection to be secured you need to set the local time (so the certificate valid to/from can be checked) and load the certificates so they can be attached to the HTTP requests

void ProgramStarted()
{
   ...
   Microsoft.SPOT.Hardware.Utility.SetLocalTime(NtpClient.GetNetworkTime());
   caCerts = new X509Certificate[] { new X509Certificate(Resources.GetBytes(Resources.BinaryResources.Baltimore)) };

I used the Network Time Protocol (NTP) library from the OBD Recorder for .Net Micro Framework sample to get the current time.

The Service Bus Event Hubs Large Scale Secure Publishing uses an asynchronous HTTP request which is not available on the NetMF platform. So I had to replace it with a synchronous version.

static void EventHubSendMessage(string eventHubAddressHttps, string token, string messageBody)
{
   try
   {
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(eventHubAddressHttps + "/messages" + "?timeout=60" + ApiVersion);
      {
         ...
         request.Headers.Add("Authorization", token);
         request.Headers.Add("ContentType", "application/atom+xml;type=entry;charset=utf-8");
         byte[] buffer = Encoding.UTF8.GetBytes(messageBody);
         request.ContentLength = buffer.Length;

         // request body
         using (Stream stream = request.GetRequestStream())
         {
            stream.Write(buffer, 0, buffer.Length);
         }
         using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
         {
            Debug.Print("HTTP Status:" + response.StatusCode + " : " + response.StatusDescription);
         }
      }
   }
   catch (WebException we)
   {
      Debug.Print(we.Message);
   }
}

The code to generate the SAS Token also required some modification as string.format, timespan, and SHA256 functionality are not natively available on the .NetMF platform. The GetExpiry, and SHA256 implementations were part of the OBD Recorder for .Net Micro Framework sample.

static string CreateSasToken(string uri, string keyName, string key)
{
   // Set token lifetime to 20 minutes. When supplying a device with a token, you might want to use a longer expiration time.
   uint tokenExpirationTime = GetExpiry(20 * 60);

   string stringToSign = HttpUtility.UrlEncode(uri) + "\n" + tokenExpirationTime;
   var hmac = SHA.computeHMAC_SHA256(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(stringToSign));

   string signature = Convert.ToBase64String(hmac);
   signature = Base64NetMf42ToRfc4648(signature);

   string token = "SharedAccessSignature sr=" + HttpUtility.UrlEncode(uri) + "&sig=" + HttpUtility.UrlEncode(signature) + "&se=" + tokenExpirationTime.ToString() + "&skn=" + keyName;
   return token;
}

static uint GetExpiry(uint tokenLifetimeInSeconds)
{
   const long ticksPerSecond = 1000000000 / 100; // 1 tick = 100 nano seconds</code>

   DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
   TimeSpan diff = DateTime.Now.ToUniversalTime() - origin;

   return ((uint)(diff.Ticks / ticksPerSecond)) + tokenLifetimeInSeconds;
}

private static string Base64NetMf42ToRfc4648(string base64netMf)
{
   var base64Rfc = string.Empty;
   for (var i = 0; i < base64netMf.Length; i++)
   {
      if (base64netMf[i] == '!')
      {
         base64Rfc += '+';
      }
      else if (base64netMf[i] == '*')
      {
         base64Rfc += '/';
      }
      else
      {
         base64Rfc += base64netMf[i];
      }
   }
return base64Rfc;
}

The HttpUtility class came from the OBD Recorder for .Net Micro Framework sample. The Base64NetMf42ToRfc4648 functionality is still necessary on NetMF 4.3.

After a couple of hours I had data upload working.(No GPS data as the device was running on my desk where GPS coverage is poor)

ServiceBusExplorerEventHub

Netduino Galvanic Skin Response(GSR)

One of CodeClub’s sponsors is Orion Health so I have been evaluating sensors suitable for health focused projects. We already use the SeeedStudio Grove Heart rate sensor and Grove EMG Detector, so I purchased a Grove GSR sensor for testing. Galvanic Skin Response(GSR) is a method of measuring the electrical conductivity of the skin, which depends on the amount of sweat on the skin.

Netduino with Grove GSR sensor

Netduino with Grove GSR sensor

The GSR detector outputs a single analog signal which I connected to A0. For the evaluation I averaged the first 3000 samples to determine the initial offset, then sampled roughly every 100mSec.

I’m a bit worried about the robustness of the wires connecting the two probes to the black cable so it will be interesting to see how long they last at Code Club.

I also updated the Minimum and Maximum values with each sample as this appeared to make the display more reliable.

I found the display responded well to me holding my breath for as long as I could.

Pulse rate + EMG + GSR = Polygraph or DIY lie detector maybe a project for next term.

for (int sampleCounter = 0; sampleCounter < calibrationSampleCount; sampleCounter++)
{
   double value = gsr.Read();
   sampleSum += value;
}
offset = sampleSum / calibrationSampleCount ;

I then displayed the magnitude of the adjusted signal on a Seeedstudio LED bar using code written by Famoury Toure

while(true)
{
   double value = emg.Read() - offset;

   if (value < valueMinimum)
   {
      valueMinimum = value;
   }

   if (value > valueMaximum)
   {
      valueMaximum = value;
   }
   range = valueMaximum - valueMinimum;
   if (value < 0)
   {
      value = value / valueMaximum * 10.0;
   }
   else
   {
      value = value / valueMinimum * 10.0;
   }
   Debug.Print("Val " + value.ToString("F3") + " Max " + valueMaximum.ToString("F3") + " Min " +valueMinimum.ToString("F3"));

   int bar = 1;
   value = 10.0 - value;
   bar = bar << (int)value ;
   ledBar.setLED((uint)bar);
   Thread.Sleep(100);
}

Bill of Materials (Prices as at October 2014)

Netduino Electromyograph (EMG)

One of CodeClub’s sponsors is Orion Health so I had been looking for some reasonably priced sensors for health focused projects. We already use the SeeedStudio Heart rate sensor for one of our projects so I ordered a Grove EMG Detector for evaluation.

Netduino with Seeedstudio EMG

Netduino with Grove EMG Detector

The EMG detector outputs a single analog signal which we connected to analog input 0. For the proof of concept we averaged for 500 samples to determine the steady state offset.

for (int sampleCounter = 0; sampleCounter < calibrationSampleCount; sampleCounter++)
{
   double value = emg.Read();
   sampleSum += value;
}
offset = sampleSum / calibrationSampleCount ;

We then read the analog input applied the offset and displayed the magnitude of the signal on a Seeedstudio LED bar using code written by Famoury Toure

while(true)
{
   double value = emg.Read() - offset;

   if (value < valueMinimum) { valueMinimum = value; } if (value > valueMaximum)
   {
      valueMaximum = value;
   }
   range = valueMaximum - valueMinimum;

   if (value < 0)
   {
      value = value / valueMaximum * 10.0;
   }
   else
   {
      value = value / valueMinimum * 10.0;
   }

   Debug.Print("Val " + value.ToString("F3") + " Max " + valueMaximum.ToString("F3") + " Min " +valueMinimum.ToString("F3"));

   int bar = 1;
   value = 10.0 - value;
   bar = bar << (int)value ;
   ledBar.setLED((uint)bar);
   Thread.Sleep(100);
   }
}

Bill of Materials (Prices as at October 2014)

The proof of concept worked surprisingly well, the LED illuminated on the LED bar appeared to move in response to arm movements and when I clenched my fist.

TechEd 2014 Auckland Presentation online

My TechEd INO204 presentation in now online at on MSDN Channel 9.

INO204  The Things of the Internet of Things
Speaker Rating
3.54 / 4  84.7%

Overall Rating
3.44 / 4 81.29%

The presenters desk had my laptop, document camera, 2 Fez spiders, 9 Netduinos, 2 devDuinos and an Arduino Uno R3 device so it was pretty busy.

TechEdPresentersDesk[1]

While preparing for the presentation I had some problems with the EMG stick on sensors

EMGStickOnPadMarks[1]

GPS Tracker Azure Service Bus

After a break from the GPSTracker samples I dug out my FEZ Spider devices, upgraded them to .NetMF 4.3 and downloaded the discontinued module drivers so my SeeedStudio GPS would work.

 

GPS Tracker using FEZ Spider mainboard

GPS Tracker built using FEZ Spider mainboard

I updated the root certificates in the Microsoft.ServiceBus.Micro resources to the current “Baltimore CyberTrust Root” ones using the process described here

The code is based on the OBD Recorder for .Net Micro Framework with ServiceBus, AMQP (for IoT)

The GPS is initialised with handlers for valid & invalid positions.

gpsStatusLED.TurnRed();
gps.InvalidPositionReceived += gps_InvalidPositionReceived;
gps.PositionReceived += gps_PositionReceived;

void gps_InvalidPositionReceived(GPS sender, EventArgs e)
{
   gpsStatusLED.TurnRed();
}

<code>void gps_PositionReceived(GPS sender, GPS.Position e)
{
   gpsStatusLED.TurnGreen();
}

Once the network interface has an IP address, the time on the FEZ Spider is set (so the certificate from and until times can be checked) and then the ServiceBus connection is initialised

IPAddress ip = IPAddress.GetDefaultLocalAddress();

// Setup the device time
if (ip != IPAddress.Any)
{
   ....
   DateTime networkTime = NtpClient.GetNetworkTime();
   Microsoft.SPOT.Hardware.Utility.SetLocalTime(networkTime);
...

   SASTokenProvider tp = new SASTokenProvider("device", "YourTopSecretKey=");
   messagingClient = new MessagingClient(new Uri(@"https://YourEndpoint.servicebus.windows.net/YourQueueName"), tp);</code>

   Once the GPS returns a valid position every so often a message is sent to the service bus queue

   SimpleMessage message = new SimpleMessage()
   {
      BrokerProperties = { { "SessionId", Guid.NewGuid().ToString()}, { "Label", "NMEAPositionData" } },
      Properties =
      {
         { "Latitude", gps.LastPosition.Latitude.ToString("F4") },
         { "Longitude", gps.LastPosition.Longitude.ToString("F4") },
      },
   };
   try
   {
      Debug.Print("Message send");
      messagingClient.Send(message);
      Debug.Print("Message sent OK");
   }
   catch (Exception ex)
   {
      Debug.Print(ex.Message);
   }

The send appeared to be quite slow (even on my home LAN so some further investigation is required)

6462mSec
6399mSec
6471mSec
6346mSec
7403mSec

6325mSec
6188mSec
6426mSec
6493mSec
6555mSec

Average 6506mSec