Software apps and online services

Story

Playing with a radio controlled toy is much fun. When is comes to water vehicle, we love them maneuvering whole day. If you are passionate for Windows and are a good hacker, this article is for you.

This article reveal the technique to modify RC Boat that will be controlled using Windows Phone. In addition, the source code contains libraries to develop application for Windows based OS, too.

Whats new in this article?

Arduino Wiring Project for Windows IoT Core

Microsoft has released awesome features to the Windows IoT build 10.0.10556 (Insider Preview). With this build, now you can write Arduino sketch for Windows IoT Core directly from Visual Studio 2015 (Refer this article for more information).

Overcome Existing Limitation of Windows IoT Core (Serial-UART, PWM)

RPi2 supports for PWM and UART on board but current release of Windows IoT Core (10.0.10556) doesn't. Regarding to this project, we need PWM to control motor speed and serial (UART) for ESP8266-01 and GPS.

As per Windows IoT Release notes, ADC and PWM is supported via external chips but I'm not sure about the availability of that chips in all regions. While Arduino is widely available worldwide. So why not to chose Arduino. In addtion, it is a full-fledged microcontroller having its own benefits.

Lightning is a set of providers to interface with GPIO, I2C and SPI through the lightning Direct Memory Access driver. In short, it is the new driver which provides high performance against default inbox drive by accessing direct memory mapped driver. By default Windows IoT Core is configured for default inbox driver.

Each boat have different hardware configuration to maneuver it. Let's explore three basic configuration mode:

The source code for the project is only developed for Mode 2. With minor changes you can program for Mode 1 as well as 3 if you really understood the concept of Gateway.

Gateway (for ADC, PWM & Serial Communication)

With the release of Windows IoT build 10531, ADC and PWM are supported via external chips. That means there is no direct support for on-board pins. Even, on-board Serial Port is useless because it may be used by kernel debugger.

In this project, WiFi (ESP8266) and GPS module (uBlox Neo6mV2) uses Serial Communication (UART). PWM is going to be used for motor speed control as well as to control servo for configuration mode 3. Thus some extra components will be required to accomplish goal. Arduino Nano or Arduino Pro Mini (16MHz) will be used to provide Serial Port as well as PWM signals. It will work as gateway:

Now, Windows IoT can access to ADC, PWM and Serial devices via gateway. To access any peripheral connected to the gateway device, it just need to access gateway chip via I2C bus.

If major peripherals are connected to the gateway (Arduino), then what will be the responsibility of Raspberry Pi 2 and Windows IoT?>Raspberry Pi and Windows IoT can be called the brain. It gets data via ESP8266, process them and controls the peripheral via gateway. Arduino is limited to its memory and processing power, thus its not capable to deliver real-time application. For ex: The real power comes when you wanna use Windows IoT for video processing, sound processing, autonomous system, etc.

Let's explore gateway programming:

You don't need to modify ESP8266-01 and Gateway sketch. You just need to upload it. Once you have uploaded, it will work like charm. You just have to code for Windows IoT.

Sketches

This project is a bit complicated. Thus the code is divided into three parts:

ESP8266 Sketch

Gateway Sketch

Windows IoT Sketch

Main objective of ESP8266 Sketch is to create Access Point and listen for incoming GET request. Request will be consists of arguments that must be placed into global argument buffer. Once arguments are copied, respond back with plain text which consists of data sent from Windows IoT via Gateway. Thus ESP8266 Sketch is responsible to communicate with remote device.

Gateway Sketch provides ADC, PWM and Serial service to Windows IoT on demand. It is also responsible to exchange data with ESP (using UART) as well as Windows IoT sketch via I2C.

Windows IoT Sketch is the brain. You can use it for complex processing such as autonomous guidance system. Windows IoT Sketch can get arguments that are passed by remote device to ESP8266 on demand. It can also send string to the remote device using ESP8266 via Gateway.

The following diagram will helps you to better understand how data is exchanged:

Deploy

ESP8266-01 Sketch

To flash or reprogram ESP8266-01, you need to wire-up ESP8266-01 as shwon below:

;

;

1 / 2

Once you are done with wiring, open Arduino IDE and follow:

;

;

1 / 7

Gateway Sketch (Arduino Nano)

Upload the Gateway sketch to the Arduino Nano. Gateway sketch is provided at the end of the article.

Windows IoT Sketch

After successful deployment, we need to register this app as startup app. You can register as startup app in two way:

Web management portal

PowerShell

But due to bug in current release of Insider Preview (10.0.10556), web management portal won't works at this time and don't try to register using web management portal because RPI2 won't boot up after reboot. And finally you will have to re-flash your Windows IoT.

Known Issues

Do not use space or any special symbol when creating Arduino Wiring project for Windows IoT. It will generate compile time error like:

Compass (HMC5883L) Jitter

HMC5883L is much sensitive to the electromagnetic waves. Thus you must need to place it as far as away from such electromagnetic emitting device like motors, communication modules, etc.

Windows Phone Application won't start

In order to run provided WP application, your phone must have built-in GPS. If your phone does not have built-in GPS, you can disable code block that retrieves the WP's location.

Conclusion

Day by day Windows IoT team is providing rich set of new features. With the current release 10.0.10556, a new driver "Direct Memory Mapped" is integrated which is far better than the Inbox driver. Performance is also significant improved over the old one. By combining other microcontrollers, we can overcome limitation of the Windows IoT or Raspberry Pi 2 as I have given concept of Gateway which serves ADC, PWM and Serial to the RPi2. In addition, such gateway can be called as co-processor because it saves a lot of time of the RPi2 by doing some task for it and interrupts the RPi2 when task completed.

Hydroflyer - Circuit Reference

Hydroflyer - Circuit Reference (Fritzing)

Hydroflyer - Circuit Reference

Hydroflyer - Circuit Reference (Fritzing)

Code

ESP8266-01 (Arduino Sketch)

C/C++

/* ESP8266-01 sketch for Hydroflyer (Boat) (RPi2 + WinIoT) https://www.hackster.io/AnuragVasanwala/windows-10-iot-core-hydroflyer-f83190 NOTE: This sketch is tested and meant for ESP8266-01. Objectives: + Create Access Point (Act as WiFi) + Listen for 'Maneuver' GET requests + Fetch arguments from GET request and store them in global 'Arguments' + Respond back plain-text from global buffer 'ReplyBuffer_100' which was received from gateway + On root or index GET request, send back project description html page + Initialize serial port and listen for incoming data + When data is received from gateway and send it back global 'Arguments' + Gateway will send character array to ESP which will be store in global buffer 'ReplyBuffer_100' + ESP will send back character array 'ReplyBuffer_100' to requested remote device via 'Maneuver' GET request + Auto-reset global Arguments if no device connects for more than 'AutoReset_Timeout' : WARNING : + 'Argument_Size' AND 'SensorBuffer_Size' MUST BE IDENTICAL ON GATEWAY SKETCH. + SERIAL BAUD RATE MUST BE SAME ON BOTH SIDE (GATEWAY & ESP). + 'SEND_DATA_STRUCTURE' MUST BE IDENTICAL ON GATEWAY SIDE (WITH NAME OF 'RECEIVE_DATA_STRUCTURE'). + 'RECEIVE_DATA_STRUCTURE' MUST BE IDENTICAL ON GATEWAY SIDE (WITH NAME OF 'SEND_DATA_STRUCTURE'). + YOU MUST HAVE 'EasyTransfer' LIBRARY IN YOUR ARDUINO FOLDER. TO INSTALL 'EasyTransfer', REFER: https://github.com/madsci1016/Arduino-EasyTransfer THIS REPOSITORY CONTAINS: + EasyTransfer + EasyTransferI2C + EasyTransferVirtualWire + SoftEasyTransfer BUT YOU ONLY HAVE TO COPY FIRST FOLDER 'EasyTransfer' TO YOUR ARDUINO's LIBRARY FOLDER*//* Global Includes */#include <ESP8266WiFi.h>#include <EasyTransfer.h>#include <ESP8266WebServer.h>#include <WiFiClient.h> /* Arguments sizes and Timeout constants */#define AutoReset_Timeout 500 // If no device connects for this milliseconds, ESP will reset 'Arguments'#define Argument_Size 6 // Number of arguments to be fetch and store in global 'Arguments'#define SensorBuffer_Size 100 // Max number of characters to be sent back to remote device/* Create MyServer object that listens on port number 80 (which is default http port) */ESP8266WebServerMyServer(80);/* Access Point's SSID and Password */constchar*SsID="WIoT - Hydroflyer";// SsID should not be more than 15 charsconstchar*Password="12345678";/*EasyTransfer library makes it much easy to send and receive composite data over Serial.Create separate object for sending and receiving.*/EasyTransferETin,ETout;/* 'SEND_DATA_STRUCTURE' MUST BE IDENTICAL ON GATEWAY SIDE (WITH NAME OF 'RECEIVE_DATA_STRUCTURE') */structSEND_DATA_STRUCTURE{byteArguments[Argument_Size];};/* 'RECEIVE_DATA_STRUCTURE' MUST BE IDENTICAL ON GATEWAY SIDE (WITH NAME OF 'SEND_DATA_STRUCTURE') */structRECEIVE_DATA_STRUCTURE{charReplyBuffer_100[SensorBuffer_Size];};SEND_DATA_STRUCTUREOutgoingData;RECEIVE_DATA_STRUCTUREIncomingData;/* Global Counters */uint8_tC1;unsignedlongLastAccessTime;// To reset 'Arguments' if no connection was made in last AutoReset_Timeout milliseconds./* Handles index or root requests */voidHandleRoot(){MyServer.sendHeader("Cache-Control","no-cache, no-store, must-revalidate",false);MyServer.sendHeader("Pragma","no-cache",false);MyServer.sendHeader("Expires","1000",false);MyServer.send(200,"text/html","<html><head><title>Windows IoT - Hydroflyer</title></head><body>Hydrofler is online.<br/>Windows IoT is the heart of the boat.<br/>To maneuver boat, please refer: www.hackster.io/AnuragVasanwala/windows-10-iot-core-hydroflyer");}/* Handles maneuver requests */voidHandleManeuver(){/* Parse arguments and store it to Arguments byte array */for(C1=0;(C1<Argument_Size)&&(C1<MyServer.args());C1++){/* Convert string argument value to equivalent byte */OutgoingData.Arguments[C1]=(byte)(MyServer.arg(C1).toInt());}/* Prepare html headers to instruct remote device to not to cache page */MyServer.sendHeader("Cache-Control","no-cache, no-store, must-revalidate",false);MyServer.sendHeader("Pragma","no-cache",false);MyServer.sendHeader("Expires","0",false);/* Send data to remote device */MyServer.send(200,"text/plain",IncomingData.ReplyBuffer_100);LastAccessTime=millis();}voidsetup(){/* Wait for a one and half second to make ESP stable */delay(1500);/* Configure and start Serial Communication with gateway. SERIAL BAUD RATE MUST BE IDENTICAL GATEWAY, TOO. */Serial.begin(115200);/* Setup ESP as AP with 'SsID' and 'Password'. Please make sure to do not give SSID more than 15 and password length must also be less than 10 char in order to achieve quick response from ESP. */WiFi.mode(WIFI_AP);WiFi.softAP(SsID,Password);/* Handle index or root GET request on function HandleRoot */MyServer.on("/",HandleRoot);/* Handle Maneuver GET request on function HandleManeuver */MyServer.on("/Maneuver",HandleManeuver);/* Start MyServer */MyServer.begin();/* Initialize ReplyBuffer to show initial message */IncomingData.ReplyBuffer_100[0]='B';IncomingData.ReplyBuffer_100[1]='O';IncomingData.ReplyBuffer_100[2]='O';IncomingData.ReplyBuffer_100[3]='T';IncomingData.ReplyBuffer_100[4]='I';IncomingData.ReplyBuffer_100[5]='N';IncomingData.ReplyBuffer_100[6]='G';IncomingData.ReplyBuffer_100[7]='\0';/* Initialize ETin for incoming data while ETout for outgoing data + Received data from gateway will be stored in 'IncomingData' + 'OutgoingData' will holds data to be send to gateway on request */ETin.begin(details(IncomingData),&Serial);ETout.begin(details(OutgoingData),&Serial);}voidloop(){/* Periodically check for request on Web Server */MyServer.handleClient();/* If gateway sends data to ESP, receive it and send back 'Arguments' */if(ETin.receiveData()){/* If no device has been connected for last 'AutoReset_Timeout' time, reset Arguments */if(millis()-LastAccessTime>AutoReset_Timeout){for(C1=0;C1<Argument_Size;C1++){OutgoingData.Arguments[C1]=0;}}/* Send back 'Arguments' to Gateway */ETout.sendData();}}