Posted on

Open Source Hardware Plant Health Monitor Recipe

Recipe Overview and Assumptions

The MediaTek LinkIt 7688 and LinkIt 7688 Duo is an innovative chipset with a high potential to move the internet of things space forward. Combined with the sensors and boards available from Seeed a maker can make any number of Internet of things devices. This recipe focuses on the necessary hardware and software to make a device to monitor the health of a plant or plants in a small area. It uses light, temperature and moisture sensors to interface with an Arduino chipset. The Arduino chipset then communicates the measurements to a Wifi enable chip. In this recipe the chip acts as a server and locally hosts a website where the measurement data can be viewed from any computer connected to the Local Area Network (LAN).
We make a few assumptions in this recipe. First a basic understanding of the Linux operating system, embedded systems, network protocols, hardware electronics – specifically Analog to Digital conversions and Digital sampling and javascript.You’ll need access to the internet and a computer. We also assume that you’ve read the startup guide for the MediaTek LinkIt 7688 and are able to put the device into Station mode. Lastly I found some very useful information for this recipe from here: https://azure.microsoft.com/en-us/documentation/articles/documentdb-nodejs-application/but there are some key differences in this embedded application and the server side application described in this article. I do recommend reading it and understanding what is going on in this article.
First we review the list of the materials we need. Then we’ll go over the software setup and configuration process. Lastly we’ll cover the hardware configuration and the results of the functional system.

List of materials

Item
Part Description
Quantity
Link
1
MediaTek 7688 Duo
1
TBD
2
RAVPower 7800mAh Portable Charger Power Bank External Battery Pack (or similar)
1
3
Male USB A to Male USB OTG Cable
1
4
SEEED Light Sensor
1
5
SEEED DHT11 Temp and Humidity Sensor
1
6
Small Breadboard
1

Step 1: Program the MediaTek 7688 Duo MT7688

                After connecting in Station mode to you LAN you can connect to the Duo with ssh. Since I am working on a windows machine I’m going to use Putty to connect. These steps are similar for a linux or mac.

Install the necessary software

Node, Express, DocumentDB, Git,  and Screen are the software packages that you’ll need. Install these with Opkg. Connecting to git can be tricky. Here is how I did it from the command line in openWRT:
# Generate your identity key on openwrt
dropbearkey -t rsa -f ~/.ssh/id_rsa
# Convert public key from dropbear binary to openssh text
# Copy and paste output from below to bitbucket account ssh keys
dropbearkey -y -f ~/.ssh/id_rsa | head -n 2 | tail -1
# Change git ssh command
echo "#!/bin/sh" > ~/.gitssh.sh
echo "dbclient -y -i ~/.ssh/id_rsa $*" >> ~/.gitssh.sh
chmod +x ~/.gitssh.sh
echo "export GIT_SSH=$HOME/.gitssh.sh" >> /etc/profile
# Now login again to openwrt
# Now use git (finally)
git clone git@bitbucket.org:vivaplanet/seeedplanthealthsource.git

Option A: Clone the source from git

As a part of this recipe the source code has been made available to you. Now can clone the code from the git hub: git@bitbucket.org:vivaplanet/seeedplanthealthsource.git Once the software is uploaded to the Duo then you can just run:
npm start
and go to the ip address assigned to your Duo by the router at local port 3000
A successful command line output will look something like this:
The output on the website will look something like this:

 

Note that the output is blank because no data has been uploaded
This is a quick approach to get things up and running. But if you want to spin your own code here are some key components you’ll need.

Option B: Upload the necessary code

If you are taking this route then you have git installed and can successfully push to your repository on git hub.
First make sure that the Duo is functioning correctly on your LAN by doing these steps:
1.Assuming you are currently connected via SSH
2.Use the express generator to generate a new application called seeedrecipe.
express seeedrecipe
3.Open your new seeedrecipe directory and install dependencies.
cd seeedrecipe
npm install
4.Run your new application.
npm start
5.You can you view your new application by navigating your browser tohttp://<your LAN IP>:3000.
So let’s pause and reflect. The small device you have plugged into your computer is now hosting a website. That is pretty cool; but things are going to get much cooler before we are done with this recipe.
Now you’ll need to configure the Duo to upload data do a database. You can use the Vivaplanet SeeedRecipes database for free. This is a No SQL document DB database. You might want to try another database like mongo or something and this is also encouraged and possible. First you’ll need a few more modules to interface with documentDB. You can look at your package.json file to view the installed modules required for this node.js application. We still need to install two more packages for this recipe.
1.Install the async module via npm.
npm install async –save
2.Install the documentdb module via npm. This module allows the Duo to use the DocumentDB package.
npm install documentdb –save
3.A quick check of the package.json file of the application should show the additional modules. This file will tell the Duo which packages to download and install when running this recipe. The dependencies should resemble the example below.
Next we set up the DocumentDB service structure. First we need to create a documentDB model. Here are the steps:
1.Create a new directory named modelsIn the seeedrecipe directory.
2.First let’s make some utility functions to interact with the documentDB. In the models directory, create new file named docdbUtils.js. This file will contain some useful, reusable, code that we will use throughout our application.
3.Copy the following code in to docdbUtils.js
var DocumentDBClient = require('documentdb').DocumentClient;
var DocDBUtils = {
    getOrCreateDatabase: function (client, databaseId, callback) {
var querySpec = {
            query: 'SELECT * FROM root r WHERE r.id=@id',
            parameters: [{
                name: '@id',
                value: databaseId
}]
};
        client.queryDatabases(querySpec).toArray(function (err, results) {
if (err) {
                callback(err);
} else {
if (results.length === 0) {
var databaseSpec = {
                        id: databaseId
};
                    client.createDatabase(databaseSpec, function (err, created) {
                        callback(null, created);
});
} else {
                    callback(null, results[0]);
}
}
});
},
    getOrCreateCollection: function (client, databaseLink, collectionId, callback) {
var querySpec = {
            query: 'SELECT * FROM root r WHERE r.id=@id',
            parameters: [{
                name: '@id',
                value: collectionId
}]
};
        client.queryCollections(databaseLink, querySpec).toArray(function (err, results) {
if (err) {
                callback(err);
} else {
if (results.length === 0) {
var collectionSpec = {
                        id: collectionId
};
var requestOptions = {
                        offerType: 'S1'
};
                    client.createCollection(databaseLink, collectionSpec, requestOptions, function (err, created) {
                        callback(null, created);
});
} else {
                    callback(null, results[0]);
                }
}
});
}
};
module.exports = DocDBUtils;
1.Save and close the docdbUtils.js file; tuck it away. You probably won’t need to open it again.
2.Next, in the models directory, create a file named taskDao.js. This file will contain the model for CRUD (CReate, Upload, Delete) in this recipe.
3.At the beginning of the taskDao.js file, add the following code to reference the DocumentDBClient and the docdbUtils.js we created above:
var DocumentDBClient = require('documentdb').DocumentClient;
var docdbUtils = require('./docdbUtils');
4.Next, you will add code to define and export the Task object. This is responsible for initializing our Task object and setting up the Database and Document Collection we will use.
function TaskDao(documentDBClient, databaseId, collectionId) {
this.client = documentDBClient;
this.databaseId = databaseId;
this.collectionId = collectionId;
this.database = null;
this.collection = null;
}
module.exports = TaskDao;
5.Next, add the following code to define additional methods on the Task object, which allow interactions with data stored in DocumentDB.
TaskDao.prototype = {
    init: function (callback) {
        var self = this;
        docdbUtils.getOrCreateDatabase(self.client, self.databaseId, function (err, db) {
            if (err) {
                callback(err);
            } else {
                self.database = db;
                docdbUtils.getOrCreateCollection(self.client, self.database._self, self.collectionId, function (err, coll) {
                    if (err) {
                        callback(err);
                    } else {
                        self.collection = coll;
                    }
                });
            }
        });
    },
    find: function (querySpec, callback) {
        var self = this;
        self.client.queryDocuments(self.collection._self, querySpec).toArray(function (err, results) {
            if (err) {
                callback(err);
            } else {
                callback(null, results);
            }
        });
    },
    addItem: function (item, callback) {
        var self = this;

                 fs.readFile(path.join(__dirname, '/screenlog.0'), 'utf8', function (err, content) {
                          if (err) {
                          return callback(err);
                     }
            else
            {
                console.log('cat returned some content: ' + content);
                var tmp1 = content.split(" ")
                console.log('tmp1 content: ' + tmp1);
                var item = {
                     Address: "$00000",
                     DeviceID: "17564321",
                     Time: Date(),
                     LightValue: tmp1[tmp1.length - 5],
                    TempValue: tmp1[tmp1.length - 3],
                    HumidValue: tmp1[tmp1.length-1]                   
                };
                 self.client.createDocument(self.collection._self, item, function (err, doc) {
                 if (err) {
                    callback(err);
                 } 
                    else 
                    {
                     console.log(new Date(), 'Uploaded: ' + item.Address + ' ' + item.Time + ' ' + item.LightValue + ' ' + item.TempValue + ' ' + item.HumidValue);
                 }
                 });
            }
        });
    },
    updateItem: function (itemId, callback) {
        var self = this;
        self.getItem(itemId, function (err, doc) {
            if (err) {
                callback(err);
            } else {
                doc.completed = true;
                self.client.replaceDocument(doc._self, doc, function (err, replaced) {
                    if (err) {
                        callback(err);
                    } else {
                        callback(null, replaced);
                    }
                });
            }
        });
    },
    getItem: function (itemId, callback) {
        var self = this;
        var querySpec = {
            query: 'SELECT * FROM root r WHERE r.id=@id',
            parameters: [{
                name: '@id',
                value: itemId
            }]
        };
        self.client.queryDocuments(self.collection._self, querySpec).toArray(function (err, results) {
            if (err) {
                callback(err);
            } else {
                callback(null, results[0]);
            }
        });
    }
};
6.Save and close the taskDao.js file.

Create the controller

1.In the routes directory of your project, create a new file named tasklist.js.
2.Add the following code to tasklist.js. This loads the DocumentDBClient and async modules, which are used by tasklist.js. This also defined the TaskList function, which is passed an instance of the Task object we defined earlier:
var DocumentDBClient = require('documentdb').DocumentClient;
var async = require('async');
function TaskList(taskDao) {
this.taskDao = taskDao;
}
module.exports = TaskList;
3.Continue adding to the tasklist.js file by adding the methods used to showTasks, addTask, and completeTasks:
TaskList.prototype = {
    showTasks: function (req, res) {
        var self = this;
        var querySpec = 
        {
            query: 'SELECT d.Address, d.Time, d.LightValue, d.TempValue, d.HumidValue FROM OpenDevices d WHERE d.Address=@SensorType', //d.DeviceSensors[1].SensorType=@SensorType',     
            parameters: [          
                {name: '@SensorType', value: '$00000'}          
            ] 
            /*query: 'SELECT * FROM  OpenDevices r'*/
        };
        self.taskDao.find(querySpec, function (err, items) 
        {
            if (err) 
            {
                callback(err);
            }
            res.render('index', {
                title: 'My Environment Information',
                tasks: items,
                JSONTasks: JSON.stringify(items)
            });
        });
    },
    addTask: function (req, res) {
        var self = this;
        var item;
        var rule = new cron.RecurrenceRule();
        rule.minute = new cron.Range(0, 59, 3);//should update every 3 mins
        // rule.second = 30;
        cron.scheduleJob(rule, function()
        {
            self.taskDao.addItem(item, function (err) {
                if (err) {
                    throw (err);
                }
                res.redirect('/');
            });
        });
    },
    completeTask: function (req, res) {
        var self = this;
        var completedTasks = Object.keys(req.body);
        async.forEach(completedTasks, function taskIterator(completedTask, callback) {
            self.taskDao.updateItem(completedTask, function (err) {
                if (err) {
                    callback(err);
                } else {
                    callback(null);
                }
            });
        }, function goHome(err) {
            if (err) {
                throw err;
            } else {
                res.redirect('/');
            }
        });
    }
};
4.Save and close the tasklist.js file.

Add config.js

1.In your project directory create a new file named config.js.
2.Add the following to config.js. This defines configuration settings and values needed for our application.
var config = {}
var config = {}
config.host = process.env.HOST || "https://vivaplanetdbdev.documents.azure.com:443/";
config.authKey = process.env.AUTH_KEY || "0NdwA+touBPzjWHApBEvEyLGB/WDNEyMRl3t0CtOXS+Qw84EO5jTMGxoLSPdccr2Lf5iC8PedJ165B/+1ZG4vA==";
config.databaseId = "OpenSeeedRecipie-0";
config.collectionId = "OpenDevices";
module.exports = config;
3.In the config.js file, update the values of HOST and AUTH_KEY using the values found in the Keys blade of your DocumentDB account on the Microsoft Azure Preview portal:
4.Save and close the config.js file.

Modify app.js

1.In the project directory, open the app.js file. This file was created earlier when the Express web application was created.
2.Add the following code to the top of app.js
var DocumentDBClient = require('documentdb').DocumentClient;
var config = require('./config');
var TaskList = require('./routes/tasklist');
var TaskDao = require('./models/taskDao');
3.This code defines the config file to be used, and proceeds to read values out of this file in to some variables we will use soon.
4.Replace the following two lines in app.js file:
app.use('/', routes);
app.use('/users', users);
with the following snippet:
var docDbClient = new DocumentDBClient(config.host, {
    masterKey: config.authKey
});
var taskDao = new TaskDao(docDbClient, config.databaseId, config.collectionId);
var taskList = new TaskList(taskDao);
taskDao.init();
app.get('/', taskList.showTasks.bind(taskList));
app.post('/addtask', taskList.addTask.bind(taskList));
app.post('/completetask', taskList.completeTask.bind(taskList));
5.These lines define a new instance of our TaskDao object, with a new connection to DocumentDB (using the values read from theconfig.js), initialize the task object and then bind form actions to methods on our TaskList controller.
6.Finally, save and close the app.js file, we’re just about done.

Build a user interface

Now let’s turn our attention to building the user interface so a user can actually interact with our application. The Express application we created uses Jade as the view engine. For more information on Jade please refer to http://jade-lang.com/. You may think that you hate Jade. I hated Jade at first…but after working with it for a while I’ve come to appreciate it so now I don’t hate it as much. I wish you a faster journey than mine.
1.The layout.jade file in the views directory is used as a global template for other .jade files. In this step you will modify it to use Twitter Bootstrap, which is a toolkit that makes it easy to design a nice looking website.
2.Open the layout.jade file found in the views folder and replace the contents with the following;
doctype html
html
  head
    title= title
    link(rel='stylesheet', href='//ajax.aspnetcdn.com/ajax/bootstrap/3.3.2/css/bootstrap.min.css')
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    nav.navbar.navbar-inverse.navbar-fixed-top
      div.navbar-header
        a.navbar-brand(href='#') My Tasks
    block content
    script(src='//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.2.min.js')
    script(src='//ajax.aspnetcdn.com/ajax/bootstrap/3.3.2/bootstrap.min.js')
This effectively tells the Jade engine to render some HTML for our application and creates a block called content where we can supply the layout for our content pages. Save and close this layout.jade file.
3.Now open the index.jade file, the view that will be used by our application, and replace the content of the file with the following:
extends layout
block content
  h1 #{title}
  br
  form(action="/", method="post")
    table.table.table-striped.table-bordered
      tr
        td Address
        td Time
        td Light Intensity
        td Humidity
        td Temperature 
      if (typeof tasks === "undefined")
        tr
          td
      else
        each task in tasks
          tr       
            td #{task.Time}
            td #{task.Address}
            td #{task.LightValue}
            td #{task.TempValue}
            td #{task.HumidValue}               
  hr
  form.well(action="/addtask", method="post")
    br
    button.btn(type="submit") Start Uploading Sensor Data
This extends layout, and provides content for the content placeholder we saw in the layout.jade file earlier.
In this layout we created two HTML forms. The first form contains a table for our data and a button that allows us to update items by posting to /completetask method of our controller. The second form contains two input fields and a button that allows us to create a new item by posting to /addtask method of our controller.
This should be all that we need for our application to work.
4.Open the style.css file in publicstylesheets directory and replace the code with the following:
body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
  color: #00B7FF;
}
.well label {
  display: block;
}
.well input {
  margin-bottom: 5px;
}
.btn {
  margin-top: 5px;
  border: outset 1px #C8C8C8;
}
Save and close this style.css file.

Step 2:  Connect the sensors

Now your application is running but you don’t have any sensors plugged in and you haven’t configured the ATMega323 to upload data to the server yet. This is the focus for step two. The two types of sensors used in this recipe are the DHT11 and the Light sensor. Both are found on Seeed. The basic connection scheme will be shown but any sort of sensor can be used. First let’s look at the pinout of the DUO to for a strategy of where we will be connecting the sensors. The pins to connect the sensors to are shown below.
Since the DHT11 sensor had a digital PWM output you’ll want to connect it to one of the digital GIPO sensors. I picked D2. It really doesn’t matter which pin you connect the DHT11 to as long as the same pin is enabled in your software (see Step 3). Here is an image of what the board looks like when the sensors are connected.

Step 3: Program the Arduino Enabled ATMega323 and test

The next step is programming the ATMega323 and testing the output. First plug in and connect to the Arduino board with the Arduino IDE. Make sure to get the latest copy of the Arduino driver from MediaTek.
There is some sample code that drives the DHT11 here: http://www.seeedstudio.com/wiki/Grove_-_Temperature_and_Humidity_Sensor.This code can be modified in the following way to accommodate the DUO’s configuration.
#include <dht11.h>

//
//   FILE:  dht11_test1.pde
// PURPOSE: DHT11 library test sketch for Arduino
//

//Celsius to Fahrenheit conversion
double Fahrenheit(double celsius)
{
        return 1.8 * celsius + 32;
}
int i = 0;
// fast integer version with rounding
//int Celcius2Fahrenheit(int celcius)
//{
//  return (celsius * 18 + 5)/10 + 32;
//}


//Celsius to Kelvin conversion
double Kelvin(double celsius)
{
        return celsius + 273.15;
}

// dewPoint function NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//

double dewPoint(double celsius, double humidity)
{
        // (1) Saturation Vapor Pressure = ESGG(T)
        double RATIO = 373.15 / (273.15 + celsius);
        double RHS = -7.90298 * (RATIO - 1);
        RHS += 5.02808 * log10(RATIO);
        RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ;
        RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
        RHS += log10(1013.246);

        // factor -3 is to adjust units - Vapor Pressure SVP * humidity
        double VP = pow(10, RHS - 3) * humidity;

        // (2) DEWPOINT = F(Vapor Pressure)
        double T = log(VP/0.61078);   // temp var
        return (241.88 * T) / (17.558 - T);
}

// delta max = 0.6544 wrt dewPoint()
// 6.9 x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
        double a = 17.271;
        double b = 237.7;
        double temp = (a * celsius) / (b + celsius) + log(humidity*0.01);
        double Td = (b * temp) / (a - temp);
        return Td;
}


#include <dht11.h>

dht11 DHT11;

#define DHT11PIN 4
#define LIGHTPIN 3
int tempPIN = 10;
int humidPIN = 12;

void setup()
{
  Serial.begin(115200);
  Serial.println("DHT11 TEST PROGRAM ");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT11LIB_VERSION);
  Serial.println();

  Serial1.begin(57600); // open internal serial connection to MT7688
   // make our digital pin an output
//  pinMode(tempPIN, OUTPUT);
//  pinMode(humidPIN, OUTPUT);

}
float lightVal = 0;
float maxLightVal = 0;

void loop()
{
  char buffer [50];
  Serial1.println("n");

  int chk = DHT11.read(DHT11PIN);

 // Serial.print("Read sensor: ");
  switch (chk)
  {
    case DHTLIB_OK:
               Serial1.println("OK");
               break;
    case DHTLIB_ERROR_CHECKSUM:
               Serial1.println("Checksum error");
               break;
    case DHTLIB_ERROR_TIMEOUT:
               Serial1.println("Time out error");
               break;
    default:
               Serial1.println("Unknown error");
               break;
  }

  float humidVal = (float)DHT11.humidity;
  float tempVal = (float)DHT11.temperature;
  int lightValIn = analogRead(0);
  if(lightVal > maxLightVal)//self calibrating
  {
    maxLightVal = lightVal;
  }

  lightVal = map(lightValIn, 0, 1023, 0 ,255);
  float lightPct = ((float)lightVal/maxLightVal)*100;
   Serial1.print("Light (%):  ");  Serial1.print(lightPct);
  Serial1.print("Humidity (%): ");  Serial1.print((float)DHT11.humidity, 2);
  Serial1.print("Temperature (F): ");  Serial1.print(Fahrenheit(DHT11.temperature), 2);
  delay(120000); //every two mins.
}
//
// END OF FILE

Step 4: Put it all together

This is not totally helpful though. Once you verify the sensors are working with this method you’ll need to access the same data via the internal serial port. The way to do this is to log back in using putty. Then use screen to connect to dev/ttyUSB1.
screen /dev/ttyUSB1 57600
You’ll then see the output of the sensor on the screen. There are a couple of strategies from this point. The simplest is to write the output to a log file and then read it in using the node application discussed in step 1. The way to do this is by pressing Ctrl-a H. Then move to the command line by pressing Ctrl-a c. Then type
npm start
Then go to your webpage and click the “Begin sending data” Button. Wait a few minutes and refresh. You’ll soon have some measurements appear nicely on your node js webserver.

Step 5: Monitor your plant’s health

At this point you’ll need to acquire some information about what type of environment your plant likes to live in and track it.  You can make a nice graphic as shown below:
Happy growing J.

 

Posted on

Hummingbird tutorial II: Visual C# .NetMf 4.2 and Zigbee series 2

Overview

1.   Connect to VivaPlanet

This next step is a bit more complex and requires some C# and visual studio with the Gagetter software from GHI Installed.  This will take some time…persist it will be worth it in the end…There are a lot of great tutorials out there on how to get this installed on your machine so I won’t go into that here. I spent some time getting all the right references so I’ve taken a screen shot of all the references I’m using in this script.This is a two part post. This post covers the initial libaries, setup and some of the XBee packet handling.

Figure 1: References to be used in Visual Studio

Now we’ll start the teardown of the code.  I’m going to put my commentary in order of how it appears within the code. So to really understand what’s going on you’ll need to read through it at least twice. I’m taking a XBee packet and writing it’s ADC values to a file. Then I’m reading this packet from the file to the serial output. I’m doing this every 5 seconds. There are several of debug points in this script and I’ve left them in. You can literally use this code and get some real time data analytics from your sensor system. You can even send pictures. But this is more complex and may be in a different project all together.

2.   Getting the right headers.

First we need to make sure we have all the system essential headers. This will be a multi-threaded application so we need System.Threading and we’ll have a serial port output so we’ll also need the System.Io libraries.

using System;
using System.Collections;
using System.Threading;
using System.Text;
using System.Security.Cryptography ;
using System.IO; //for series 2
using System.IO.Ports;
Next we’ll need to add some Microsoft libraries to support the hardware. The most important are Microsoft.SPOT and SPOT.hardware. The rest don’t need to be there yet. There will be functionality in the future for these libraries so I chose to leave them.
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.IO;
Lastly the API’s need to be added. This includes GHI’s libraries, some xbee libraries and the netmf toolbox library. I spent a lot of time finding these libraries so please use them!
using GHIElectronics.Gadgeteer;
using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.OpenSource;
using Gadgeteer.Modules.GHIElectronics;
using GHI.OSHW.Hardware;
using NETMF.OpenSource.XBee.Api;
using NETMF.OpenSource.XBee.Api.Common;
using Toolbox.NETMF;
using NETMF.OpenSource.XBee.Api.Zigbee;
using NETMF.OpenSource.XBee.Util;
The main program namespace I call VivaPlanetEmbedded. This namespace handles all of the datarouting on the embedded system. Right now it has Xbee functionality and serial out functionality. In the future we’ll add some Ethernet and camera functionality as well.
namespace VivaPlanetEmbedded
{
The first class is a manager class of sorts. It takes a packet listener and makes it publicly available to other classes. This was really a key learning for me to add this class. It works very well and makes the code stable.
    public classIOSampleDecodedEventArgs : EventArgs
    {
        public string DecodedPacket { get; set; }
        publicIOSampleDecodedEventArgs(string myString)
        {
            this.DecodedPacket = myString;
        }
    }
The IOSampleListener class handles the incoming Xbee packets. I am using two XBees in my system but I’m sure it can take more.  Let’s walk through this class.
public class IoSampleListener : IPacketListener
    {
        public bool Finished { get { return false; } }
        public XBeeResponse[] Packets;
        UsbSerial usbSerial = new UsbSerial(1);
        static bool flash = true;
        public event EventHandler IOSampleDecoded;
Here we initialize the variables for the class. I have a ‘finished’ flag to make sure that I know when the packets are done.  The UsbSerial variable is for debug. It doesn’t have to be here but it sure helps. We need an public event handler and a packet variable to put the packets somewhere. Keep in mind most of these datatypes come from the XBee API at Github. There is some documentation there but some of this I had to learn myself and ask others.
        public void ReportPacket(string packet)
        {
            EventHandler handler =IOSampleDecoded;
            if (handler != null)
            {
                handler(this, new IOSampleDecodedEventArgs(packet));               
            }
        }
This method passes the received string to the even handler to do something with it. The string is formatted as an xbee packet which makes it really nice. I don’t have to do any fancy parsing.
        public voidProcessPacket(XBeeResponse packet)
        {
            if (packet is IoSampleResponse)
            {
                IoSampleResponse myPackets =ProcessIoSample(packet as IoSampleResponse);
            }
        }
        public IoSampleResponse ProcessIoSample(IoSampleResponse packet)
        {
            DateTime time = new DateTime(2007, 06, 21, 00, 00, 00);
            Utility.SetLocalTime(time);
            try
            {
                for (int ii = 0; ii < 5; ii++)
                {  
               //String format: Address HasData DataId SensorType TimeValue
                    string s = “^” + packet.SourceAddress.Address.ToString() + “^” + “true” + “^” + “0” + “^” + ii.ToString() + “^” + time.TimeOfDay.ToString() + “^” + packet.Analog[ii].ToString() + rn;
                    ReportPacket(s);           
                }
            }
            catch (Exception e) //Catch any exceptions
            {
                Debug.Print(e.ToString()); //print the error to the debug ouput
            }
            return packet;
        }
This method is the meat-and-potatoes of the Xbee portion. We format the string and the ‘report’ the packet to the ReportPacket Class. This enables other classes within this namespace to access the Xbee data.
        private void DebugPrint(string str)
        {
            flash = !flash;
            Debug.Print(str + rn);
            try
            {
                usbSerial.SerialLine.Write(str + rn);
            }
            catch (Exception e)
            {
                Debug.Print(“USB Not enabled” + rn);
                Debug.Print(e.ToString() + rn);
            }
        }
        This method is just a debug script. It is very helpful.
        public XBeeResponse[] GetPackets(int timeout)
        {
            throw newNotImplementedException();
        }
    }
Below we can see the main portion of the .NetMF class. First it is important to note there is a lot of autogenerated code in .Netmf. So this class is only a partial class. The other portion of it is hidden.
    public partial class Program
    {
        public const string DeviceSerialNumer = “17564321”;
        private string _root; //volume
        bool flash = true;
        bool newPackets = false;
        //set up the Xbee                    
        const string serialPortName = “COM1”;
        const Cpu.Pin resetPin = GHI.Hardware.FEZCerb.Pin.PB0;
        const Cpu.Pin sleepPin = GHI.Hardware.FEZCerb.Pin.PC13;
        XBee xBee = new XBee(serialPortName, resetPin, sleepPin) { DebugPrintEnabled = true };       
There are some more variables declared here up front. The most important part here is setting up the Xbee. This code affects the onboard Xbee on the FEZCerbuino Bee. It enables the reset and sleep functions as well as the serial functions.  I have a lot of comments in this next portion that describe what the code is doing so I’m going to rely on them until the next method.
        // This method is run when the mainboard is powered up or reset.  
        void ProgramStarted()
        {
            Debug.Print(“Viva Planet!”);
            try //both usbSerial.Configure and usbSerial.Open()have different exceptions but it is rare that they will triggered in this specific code
            {
                //mount the SD card
                GHI.OSHW.Hardware.StorageDev.MountSD();
                //configure the usbSerial port
                usbSerial.Configure(9600, GT.Interfaces.Serial.SerialParity.None, GT.Interfaces.Serial.SerialStopBits.One, 8);
                //if the port is not open then open it
                if (!usbSerial.SerialLine.IsOpen)
                {
                    usbSerial.SerialLine.Open();
                    DebugPrint(“opened the serial port”);
                }
                if (VolumeInfo.GetVolumes()[0].IsFormatted)//check to make sure the SD card is formatted
                {
                    _root = VolumeInfo.GetVolumes()[0].RootDirectory;
                    DebugPrint(“SD Card is formatted: “ + _root);
                }
                else
                {
                    DebugPrint(“SD Card is not formatted”); //print the error to the debug output
                }             
            }
            catch (Exception e) //Catch any exceptions
            {
                DebugPrint(e.ToString()); //print the error to the debug output
            }
           
            //Gets the command data from the intertubes. This is interrupt driven.            usbSerial.SerialLine.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(SerialLine_DataReceived);
            //Implement the interface member
            IoSampleListener sample = new IoSampleListener();  //created 1x only
            sample.IOSampleDecoded +=sample_IOSampleDecoded;  //every time the event is raised (report packet)
            //add the listener
            xBee.Api.AddPacketListener(sample);
            // initialize the loop timer and send a file to the server
            GT.Timer timer = new GT.Timer(5000);
            //set the interrupt
            timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
            timer.Start(); 
        }
        //this method is an event handler that decodes the packet within this class
        private voidsample_IOSampleDecoded(object sender, EventArgs e)
        {
            IOSampleDecodedEventArgs eventargs = (IOSampleDecodedEventArgs)e;
            string packet = eventargs.DecodedPacket;
            writeToFile(packet); //write the packet to file
            newPackets = true;
        }
        private void writeToFile(string packet)
        {           
            //initialize variables
            string fileName = Path.Combine(_root, “file.txt”);
            Stream stream;
            try
            {
                //write it to file
                if (File.Exists(fileName))
                {
                    stream =File.OpenWrite(fileName);
                    stream.Position = stream.Length;
                }
                else
                {
                    stream =File.Create(fileName);
                }
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine(packet);
                    DebugPrint(“wrote:  “ + packet);
                }
                stream.Dispose();
            }
            catch (Exception e)
            {
                DebugPrint(e.ToString());
            }
        }

This is the timer event handler. It fires at the designated time and allows the code to run in an endless loop on the embedded device. It is better than using a while loop for a lot of different reasons.

        private void timer_Tick(GT.Timer timer)
        {
               DebugPrint(“tick”);
               if (newPackets)
               {
                   //populate the device struct with the measurements
                   DeviceReport device = readPacketData();
                   //Send the data
                   NotifyServiceQueue(device, null);
                   newPackets = false;
               }
               else
               {
                   DebugPrint(“no new packets”);
               }
        }
 Stay tuned for the next update. We’ll finish going over the code and show some working output.

Posted on

Hummingbird tutorial I: The Hardware

Overview

Hummingbird is a hardware scheme designed to interface with a free data-analysis engine: VivaPlanet (http://www.vivaplanet.io/) . Hummingbird will send information about the health of it’s environment to the VivaPlanet data-analysis engine to allow the user to predict and better understand the health of the environment of Hummingbird.  Anyone can use an ethernet, GPRS or WiFi enabled Internet of Things or wearable device to interface with the VivaPlanet data analysis engine. These are the instructions on how to build a simple serial interface to this engine.

There are three major parts to this project. There is the free VivaPlanet data-analysis engine, the coordinator node and the sensor node. The senor node(s) send information to the coordinator node. The coordinator node manages inputs from various sensor nodes and sends this data periodically to VivaPlanet. The user can then go look at the big data analytics on their free VivaPlanet website.

We choose GHI (https://www.ghielectronics.com/) and Seeed (https://www.seeedstudio.com/) to purchase a lot of the hardware. GHI uses .NETMF capable hardware which is great. I’m using .NetMF 4.2 for this project.This means I can write embedded code in C# and have it cross-compile in Visual Studio 2012 and run on the GHI hardware. This is really great because I get all of the power and flexibility of C# when coding. There is some overhead in this on the hardware side but for a light weight application like this it is a really great way to quickly prototype.


Figure 1: This is an overview of how Hummingbird could be used to send information to VivaPlanet.

Step 1: Building the sensor node

A functional test can be easily constructed with 2 XBees and a BJT Oscillator (more details on how to do this are here: http://meca-labs.blogspot.com/2014/05/fun-with-xbe…) The sensor node is the easiest node to assemble it is shown in Figure 2 below. We hacked into a solar powered light and added a moisture sensor to the bottom. Then we ran a wire up to the top and stored the XBee (series 2) and power system. The XBee has 4 ADC converters and we used one of these to poll the moisture sensor and send the information to the coordinator node. We just used XTCU to program the sensor node.

 Figure 2: Functional example of 2 XBees sending ADC data from a BJT Oscillator to a coordinator node.

Figure 3: Sensor node deconstructed 
Figure 4: Sensor node in action

Step 2: The coordinator node

The coordinator node is also the same solar power set but it consists of a GHI CerbuinoBee an XBee (series 2) and some sort of way to connect to the internet. We’ve demonstrated this project with a GHI GPRS module, shown in figure 5, and a USB-Serial Module. Using the Serial interface in C# is really simple and that’s what we’ll focus on here. Getting the GPRS working is tricky and is another project in itself.

 Figure 5: Coordinator node with a SIM900 GPRS Module.

Step 3: Connect to VivaPlanet
Connecting to VivaPlanet is easy and mostly a software based task.

I’ll post the code in github and link it here. But for now there is a tutorial: https://blazestonetechnologies.com/2015/07/06/hummingbird-tutorial-ii-visual-c-netmf-4-2-and-zigbee-series-2/

Posted on

A Time Project

I’ve decided to build a set of clocks to keep time on all 8 of the planets (I’m not going to keep time on Pluto because it is too erratic. Additionally I’d have to track all of the Dwarf Planets not just Pluto if I did this and I don’t want make such a large effort). I started thinking about this and I realized that there are several different types of  ‘time’ one can consider. The first type of time is the most common we can consider how long it takes one of the planets to move based on where we are on earth. This is done by saying Mars takes so many earth days to go around the sun. But another way of thinking about this is if you were actually on Mars. Then the time on Earth would not be very useful. You would need your own time base. Since we are used to a 24 hour period that tells us about when the sun will come up and when the sun will set something like this would be the most useful for telling time on other planets. So one Earth second would indicate the Earth has rotated by a fixed number degrees while one Mars second would indicate that Mars has rotated by another fixed amount. The third way of telling time is less intuitive than the first; it is called Gravitational time dilation.

In the context I am using this in means that a person ages differently on different planets due to the space-time fabric bending differently on that planet.  We typically measure our age in years on Earth. This increments every time the earth completes a revolution around the sun. Gravitational time dilation implies that the actual rate we age in the time it takes the earth to rotate the sun will be different depending on where we are at in the universe.  I haven’t found much published research other than what is shown here and in the references. This third set will be a tough egg to crack; I will attempt it after I build the second type of clock. One can now imagine a 2 column by 8 row clock. The first column would show the time on each planet at the 0 degree point; similar to the time at the prime meridian on our planet. The second column would show how old you are given the space-time distortion on that planet. In this project I’m not going to address the first case. I will address the second and third cases because they are more interesting. Also because I couldn’t find any information in this area so I thought I would work through it here. I cool result of all this would also be a set of probes sent to each planet in our solar system. The probe would simply report back the time on that planet. It would need to be an atomic clock of some sort so that we could measure the relative differences in space time between our planet and the other planets.

I’m going to address the second case first. This is the case where we do a 24 hour time base transform for each planet. I need to first understand how long one earth second is compared to a second on any other planets in our solar system. The rotational velocity for each planet is the major piece of information. I built a table for this. The table has links to NASA’s planet home page and Wikipedia’s home page since NASA doesn’t have the rotational velocity information immediately available.

Planet Equatorial rotation velocity (m/s)
Mercury 3.026
Venus 1.81
Earth 465.1
Mars 241.17
Jupiter 12600
Saturn 9870
Uranus 2590
Neptune 2680

What this really says is how far the planet spins in 1 earth second. One of many assumptions I will make here is that each planet is a circle at it’s equator. This means that one of normalizing factors I can use is the amount of degrees a planet moves. This amount can then be used for the transform to find one second on a given planet. For this measurement I’ll need the mean radius. Here I look at the minimum radius so there is some error introduced. Since there is a range I can make this more accurate in the future my making an average or another similar model of the radius to estimate the second. The big picture here is a unit’s game with the goal to find the frequency in Hertz for a given planets revolution.

Planet Mean Radius (min)
Mercury 2438700
Venus 6050800
Earth 6371000
Mars 3389300
Jupiter 6990500
Saturn 5822600
Uranus 2460300
Neptune 2535500

Now I need to understand how many degrees and radians the earth turns in one second. Since this was a simple calculation I made a table for it as well

On Earth Metric
Degrees in a circle 360
Day/Degree 0.002777777778
Hours/Degree 0.06666666667
Minute/Degree 4
Seconds/Degree 240
Degrees in a second 0.004166666667
Radians in a second 0.00007272205217

Now there is a formula to find out the arc length is for the each planet with a given radius. The Wikipedia article gives the best description of this calculation:

Arcs of circles

Arc lengths are denoted by s, since the Latin word for length (or size) is spatium.
In the following lines, r represents the radius of a circled is its diameterC is its circumferences is the length of an arc of the circle, and thetais the angle which the arc subtends at the centre of the circle. The distances r, d, C, and s are expressed in the same units.
    • C=2pi r, which is the same as C=pi d. (This equation is a definition of pi (pi).)
    • If the arc is a semicircle, then s=pi r.
    • If theta is in radians then s =rtheta. (This is a definition of the radian.)
    • If theta is in degrees, then s=frac{pi r theta}{180}, which is the same as s=frac{C theta}{360}.
    • If theta is in grads (100 grads, or grades, or gradians are one right-angle), then s=frac{pi r theta}{200}, which is the same as s=frac{C theta}{400}.
    • If theta is in turns (one turn is a complete rotation, or 360°, or 400 grads, or 2pi radians), then s=C theta.
Based on these calculations I can get the distance each planet travels in it’s unique second:
Planet Distance (m) Traveled in 1 earth second
Mercury 177.3472686
Venus 440.0265932
Earth 463.3121944
Mars 246.4768514
Jupiter 508.3635057
Saturn 423.4314209
Neptune 178.9180649
Uranus 184.3867633
Lastly I need to divide the rotational velocity in earth seconds by the rotational velocity in each planet’s seconds.  This will give me 1/s or the frequency each planet rotates at:

Planet (m/Es)/m = 1/Ps = fmin
Mecury 0.01706256896
Venus 0.004113387754
Earth 1.003858749
Mars 0.9784691691
Jupiter 24.7854141
Saturn 23.30955973
Neptune 14.97892346
Uranus 14.04656145

How do I know that these values are correct? I can check it because I know the answer to Earth’s time should be 1 second. It is, but it is not a perfect second. Something else I notice is that Venus is really odd. There is something seriously wrong with that planet. It is so close to earth in size but it spins so slowly. I wonder if something crashed into it and messed up its rotation or something…?

Here is a visual representation of of the orbit of each planet’s orbit in relation to the other planets.

I could go two directions here. I could build my clock or I could calculate the gravitational time dilation for each planet. I think I’ll do the schematic for the clock. Then I’ll work on the gravitational time dilation for each planet.

I have completed a block diagram of what the system will look like. This is shown below.

The diagram above shows 3 basic stages to this clock. The first part is the a 10MHz time base. This is driven by an low cost crystal oscillator. The oscillator drives the 8 output buffer. Each line from the buffer goes to into the next stage. The next stage is the counter or the brains of this system. The micro-controller drives some flip-flops which control when the seven-segment LED is incremented. The last stage is the seven-segment driver. This driver will control 6 separate seven segment LEDs each set will be seconds, minutes and hours.

The schematic above shows a cross section of one of the full signal paths of this clock. Each black box represents one block in the block diagram above. Each block will be on a separate printed circuit board.  I’m still working on laying these out. I got this schematic design from here: allaboutcircuits.com It is a really great website with a lot of useful information.  

The image above shows a block diagram of the three  main parts of the clock. I wanted to reduce the risk of spending a lot of money and getting a bad board. So I made a small board with some key concepts and risky parts on it. In this case it is the seven segment display. I am also going to look at the workmanship of this vendor and see how they do. The boards will be here in about 4 weeks so I’ll update some more then.

The first board is the buffer board. This board holds the oscillator and fan-out buffer for the rest of the frequencies for the time base on the rest of the planets. The image below shows a four layer board but I’m going to redo it so that is is two layers and not four layers to save money.

 The second board sets the specific frequency of the signal driving the clock logic. This board also has set switches and LEDs indicating when the signal is high and low. This is a 4 layer board.

This last board is a third of the full time. It will represent the seconds clock portion of the clock. I am actually fabricating this board to make sure it actually  works. This is a two layer board.

 This board will simply increment each time the signal through it toggles.  I might hook an accelerometer and xbee up to it and wirelessly do something interesting 🙂


***I will update this post as I make progress***

Posted on

Digital Phase Frequency Detector

I have all the hardware I need to complete this project. I’ll be uploading a few pictures and videos in the next few days of this working. I’ve decided to close the loop with the Arduino Uno. The Arduino will receive the output of the phase-frequency detector and change the input. I needed to do this for a few reasons. The time required to assemble and debug the entire phase-locked loop would have taken longer than I would of had. Second the Arduino adds a really interesting component to this project. Since the phase-frequency detector is a very robust you can do things like lock two XBees together and double your sensor bandwidth for 3D imaging.  Or you can use it to drive two wheels forward and keep them moving at the same speed with two electric motors. 
Also the demo kit that NXP sent is awesome for a lot of reasons. It allows easy prototyping of typically difficult to work with surface mount components. The kit shows how small the SMT components are. The additional resistors and capacitors for proper functionality are also included in the dev kit.  I hope NXP would consider selling it would be great to use in electrical designs that would eventually be miniaturized. 
First let’s take a look at a single demo board. There are a few observations about this board I’ll make before I move onto the design.
b2ap3_thumbnail_hardwareSize.png
Figure 1: Single Demo Board (Back)
As you can see in this demo board there are some added resistors and capacitors. This will help to limit the current through the device. In my original schematic I neglected these but it is clear they are needed. Second I wanted to point out the dime to the left of the board in Figure 1. If you compare Franklin D. Roosevelt’s ear to the size of the 74AUP2G57GM his ear is slightly larger! This is a very small chip; ideal for the Internet of Things and wearables.
So I was sent 5 of these boards. I can imagine they are ESD sensitive. I found some ESD Foam and used that to lay out all the boards. The boards for the phase frequency detector are shown below as well as their alignment as it shows in the schematic.
b2ap3_thumbnail_Step2.png
Figure 2a: The initial layout of the boards.
b2ap3_thumbnail_PhaseLockedLoopImg_20150602-211553_1.png
Figure 2b:  The schematic we are wiring to.
The next step to wire these boards as they are represented in the schematic. This was a multi-day process. I went through one board at a time and wired them per the schematic. Some of this progress is shown in Figure 3 below.
b2ap3_thumbnail_Step4.png
Figure 3: Some initial boards wired completed. Wiring and soldering and wiring and soldering…
So after spending time wiring and soldering and then soldering and wiring even more the entire phase frequency detector is assembled and ready to detect some frequency and phase differences! The entire device is shown below in figure 4. 
b2ap3_thumbnail_step5.png
Figure 4: the entire phase frequency detector
This concludes my post on assembling the phase frequency detector. In the next post we’ll plug it in and turn it on, look at some code and watch some flashing LEDs.
Posted on

A Phase Locked Loop Project

NXP is hosting a design competition called The Big Idea. I’ve decided to enter into this competition to go through the process of building a digital phase locked loop. I’m not going to have it be really fast; I will be happy if it works. Since I have never directly built a phase locked loop this should be a bit of a learning experience. The parts of the pll that I will be designing are the phase-frequency detector, the charge-pump, the low pass filter, the voltage controlled oscillator and the frequency divider. I’ll be documenting these sections in this blog post.

Frequency Phase Detector:

Day 2: the Phase-Frequency Detector
I’ve done a logic schematic for the phase-frequency detector for my phase lock loop. This is the part in the phase lock loop that determines what frequency the voltage controlled oscillator is set at. The schematic is an optimized version of two D-Flip Flops and some other logic. If I had the NXP part in the MultiSIM Blue library I would be able to use a single part number for each one of these logic gates.
Frequency Divider
Day 3: The Frequency Divider
One of the blocks in the phase locked loop is the frequency divider. I’ve designed a divide by 2 frequency divider out of a D-flip flop with feedback. I could use the 74AUP2G57GM in this design if it existed in the MultiSIM Blue library. However it does not. I’ve asked when they plan to have this part available and I haven’t received a reply. I’ll post the theory on my own personal blog when I’m done.
I have all the hardware I need to complete this project. I’ll be uploading a few pictures and videos in the next few days of this working. I’ve decided to close the loop with the Arduino Uno. The Arduino will receive the output of the phase-frequency detector and change the input. I needed to do this for a few reasons. The time required to assemble and debug the entire phase-locked loop would have taken longer than I would of had. Second the Arduino adds a really interesting component to this project. Since the phase-frequency detector is a very robust you can do things like lock two XBees together and double your sensor bandwidth for 3D imaging.  Or you can use it to drive two wheels forward and keep them moving at the same speed with two electric motors.
Also the demo kit that NXP sent is awesome for a lot of reasons. It allows easy prototyping of typically difficult to work with surface mount components. The kit shows how small the SMT components are. The additional resistors and capacitors for proper functionality are also included in the dev kit.  I hope NXP would consider selling it would be great to use in electrical designs that would eventually be miniaturized.
First let’s take a look at a single demo board. There are a few observations about this board I’ll make before I move onto the design.
b2ap3_thumbnail_hardwareSize.png
Figure 1: Single Demo Board (Back)
As you can see in this demo board there are some added resistors and capacitors. This will help to limit the current through the device. In my original schematic I neglected these but it is clear they are needed. Second I wanted to point out the dime to the left of the board in Figure 1. If you compare Franklin D. Roosevelt’s ear to the size of the 74AUP2G57GM his ear is slightly larger! This is a very small chip; ideal for the Internet of Things and wearables.
So I was sent 5 of these boards. I can imagine they are ESD sensitive. I found some ESD Foam and used that to lay out all the boards. The boards for the phase frequency detector are shown below as well as their alignment as it shows in the schematic.
b2ap3_thumbnail_Step2.png
Figure 2a: The initial layout of the boards.
b2ap3_thumbnail_PhaseLockedLoopImg_20150602-211553_1.png
Figure 2b:  The schematic we are wiring to.
The next step to wire these boards as they are represented in the schematic. This was a multi-day process. I went through one board at a time and wired them per the schematic. Some of this progress is shown in Figure 3 below.
b2ap3_thumbnail_Step4.png
Figure 3: Some initial boards wired completed. Wiring and soldering and wiring and soldering…
So after spending time wiring and soldering and then soldering and wiring even more the entire phase frequency detector is assembled and ready to detect some frequency and phase differences! The entire device is shown below in figure 4.
b2ap3_thumbnail_step5.png
Figure 4: the entire phase frequency detector
This concludes my post on assembling the phase frequency detector. In the next post we’ll plug it in and turn it on, look at some code and watch some flashing LEDs.

I will update this blog post and my blog at the big idea as I make progress.

Posted on

HARDWARE ENCRYPTION

This idea fully exploits the configurable logic aspect of the 74aup2g57gm. This idea work similarly to AES encryption. Each configurable logic device would be act as a tumbler preceding the logic device before it. The opens and shorts would determine the resulting logic which would result in an unique code for that message. To further encrypt a GPS Time sync could be added to allow for a more obscure message. To decrypt the device would simply need to be inverted…so a message could be uniquely encoded using a basic ASCII binary representation. The hardware device would be the key for the message. so something like this could be realized. There’s probably a patent lurking somewhere within this one…. 🙂
USB -> NXP Encryption -> Computer
Posted on

Some inspirational poetry

Do not go gentle into that good night

Dylan Thomas1914 – 1953

Do not go gentle into that good night,
Old age should burn and rave at close of day;
Rage, rage against the dying of the light.

Though wise men at their end know dark is right,
Because their words had forked no lightning they
Do not go gentle into that good night.

Good men, the last wave by, crying how bright
Their frail deeds might have danced in a green bay,
Rage, rage against the dying of the light.

Wild men who caught and sang the sun in flight,
And learn, too late, they grieved it on its way,
Do not go gentle into that good night.

Grave men, near death, who see with blinding sight
Blind eyes could blaze like meteors and be gay,
Rage, rage against the dying of the light.

And you, my father, there on the sad height,
Curse, bless, me now with your fierce tears, I pray.
Do not go gentle into that good night.
Rage, rage against the dying of the light.