Here we compare 3 different clocks against NTP over a period of 30 days using the Blaze Stone Time API.
Author: c0psn
Numerical Variance Among Processors and Operating Systems
Here we evaluate the results of the Polynomial Fit API for Windows (7), Linux (Ubuntu 14.04) and Raspbian.
Open Source Hardware Plant Health Monitor Recipe
Recipe Overview and Assumptions
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
Install the necessary software
# 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
npm start
Option B: Upload the necessary code
express seeedrecipe
cd seeedrecipe
npm install
npm start
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;
var DocumentDBClient = require('documentdb').DocumentClient;
var docdbUtils = require('./docdbUtils');
function TaskDao(documentDBClient, databaseId, collectionId) {
this.client = documentDBClient;
this.databaseId = databaseId;
this.collectionId = collectionId;
this.database = null;
this.collection = null;
}
module.exports = TaskDao;
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]);
}
});
}
};
Create the controller
var DocumentDBClient = require('documentdb').DocumentClient;
var async = require('async');
function TaskList(taskDao) {
this.taskDao = taskDao;
}
module.exports = TaskList;
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('/');
}
});
}
};
Add config.js
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;
Modify app.js
var DocumentDBClient = require('documentdb').DocumentClient;
var config = require('./config');
var TaskList = require('./routes/tasklist');
var TaskDao = require('./models/taskDao');
app.use('/', routes);
app.use('/users', users);
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));
Build a user interface
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')
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
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;
}
Step 2: Connect the sensors
Step 3: Program the Arduino Enabled ATMega323 and test
#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
screen /dev/ttyUSB1 57600
npm start
Step 5: Monitor your plant’s health
Hummingbird tutorial II: Visual C# .NetMf 4.2 and Zigbee series 2
Overview
1. Connect to VivaPlanet
2. Getting the right headers.
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/
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.
Step 1: Building the sensor node
Figure 2: Functional example of 2 XBees sending ADC data from a BJT Oscillator to a coordinator node.
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.
Step 3: Connect to VivaPlanet
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/
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, represents the radius of a circle, is its diameter, is its circumference, is the length of an arc of the circle, and is the angle which the arc subtends at the centre of the circle. The distances and are expressed in the same units.
- which is the same as (This equation is a definition of (pi).)
- If the arc is a semicircle, then
- If is in radians then (This is a definition of the radian.)
- If is in degrees, then which is the same as
- If is in grads (100 grads, or grades, or gradians are one right-angle), then which is the same as
- If is in turns (one turn is a complete rotation, or 360°, or 400 grads, or radians), then
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 |
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***
Digital Phase Frequency Detector
Figure 3: Some initial boards wired completed. Wiring and soldering and wiring and soldering…
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:
Figure 3: Some initial boards wired completed. Wiring and soldering and wiring and soldering…
I will update this blog post and my blog at the big idea as I make progress.
HARDWARE ENCRYPTION
Some inspirational poetry
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.