The Raspberry Pi Foundation just announced that they are partnering with Farnell and RS Components to manufacture and distribute their much anticipated 'Raspberry Pi' computer.
This is a sensible move. Else the charity would have to built up an Amazon style logistics operation from scratch -- a huge distraction from their mission to provide affordable and hackable computers for teaching, experimentation and kids to play with. I just managed to get my order in to Farnell. It wasn't easy. Their system was creaking under the load! (at 06:00 in the morning!)
A quick summary of what a Raspberry Pi has to offer: it's an electronics board about the size of a credit card (no casing is provided right now). At its heart is an ARM based Broadcom BCM2835 with integrated CPU, GPU and RAM clocked at 700MHz (and a pretty beefy GPU by all accounts!), 256MB RAM, HDMI video output, SD card for storage, 2 x USB for peripherals and external storage, 1 x 100Mbps ethernet port, 3.5mm jack for audio. And for hardware hackers, a general purpose IO port (with hardware support for UART, SPI, I2C etc).
Cost? Well it's supposed to be about $35. I got mine for €31.87 + VAT (ie about €35) from Farnell. But that includes shipping: so it's a fair price. (BTW: here is a direct link to the Raspberry Pi Model B at Farnell).
I look forward to my Pi in the coming days!
Update (1 Mar 2012): Just got an email from Farnell. Despite pushing in my order 13 minutes after the announcement I still didn't make the first batch of 10,000 units. ETA for my Pi: end April 2012 ☹
Wednesday, February 29, 2012
Monday, February 13, 2012
Getting started with the PIC24FJ64GB002 and PIC32MX110F016B
Microchip's new MPLABX development environment (free download) came out of beta a few weeks ago and the PICkit3 programmer/debugger was on special offer. So I figured this was as good a time as any to pick up a PICkit3 and to get a 'hello world' program running on the PIC24FJ64GB002 and PIC32MX110F016B samples I had in my parts drawer. Both are available in 28 pin DIP packages. (Can't beat DIPs and breadboards for quick prototyping!)
Programming the 8 bit PIC range such as 12F and 16F series with the PICkit2 programmer is simple: just connect the five ICSP pins MCLR, Vdd, GND, PGD, PGC from the programmer to the corresponding pins on the chip. Nothing else is needed. The chip can then be probed and programmed. I prefer to use the command line tool. For example to verify that a chip was present:
pk2cmd -P
and then I'd upload myprogram.hex firmware with something like
pk2cmd -P -Fmyprogram.hex -M -R
and apply power at 3.3V for testing (internal oscillator must be configured if there is no external crystal):
pk2cmd -P -T -A3.3
The PIC24FJ64GB002 and PIC32MX110F016B chips are not as straight forward. My naive attempt at treating them like the 8 bit PICs didn't work. I noticed searching Microchip's forums that others were have difficulty also. Like most problems relating to programming MCUs the answer is in the datasheet. You either need to read it cover-to-cover or fumble around and experiment. I'm still not sure which approach gets you there faster, but the latter is more fun :-)
There are a few important differences when compared to the older 12F and 16F series. These chips use a dual power supply. The CPU core runs at a lower voltage (usually 2.2V) and the on-chip peripherals run off a higher voltage (usually 3.3V). The core power can be configured to be supplied from an on-chip source or externally. The on-chip supply is selected by grounding the DISVREG pin and connecting Vcap to ground via a 10µF capacitor [Reference PIC24FJ64GB004 family datasheet, section 2 "Guidelines for getting started with 16-bit microcontrollers"].
Another important difference: the chip must be powered up, even for probing and programming. This is not necessary for the 8 bit PICs that I've been using. This one threw me for a bit: MPLABX with PICkit3 kept telling me no target was connected. Finally I twigged that I should have power applied:
right-click on the project and select 'Properties', select PICkit3, select the Power category from the pull down menu, select the desired voltage (usually something close to 3.3V) and check "Power target circuit from PICkit3" checkbox.
So to summarize the setup for both chips (electrically identical, just different names/functions on some pins).
PIC24FJ64GB002
|
PIC32MX110F016B
|
Finally the configuration bits must be set just right if you want the PICkit3 in-circuit debugger to work. The syntax used to defining the configuration bits seem seems to vary from compiler to compiler. For the PIC24FJ64GB002 this is what worked for me using the Microchip C30 C compiler version 3.30c:
_CONFIG1(JTAGEN_OFF
& GCP_OFF
& GWRP_OFF
& ICS_PGx2 // NB: set to correct channel
& FWDTEN_OFF
& WINDIS_OFF
& FWPSA_PR32
& WDTPS_PS8192);
_CONFIG2(IESO_OFF
& FNOSC_FRCPLL
& OSCIOFNC_ON
& POSCMOD_NONE
& PLL96MHZ_ON
& PLLDIV_DIV2
& FCKSM_CSDCMD
& IOL1WAY_OFF);
_CONFIG3(WPFP_WPFP0
& SOSCSEL_IO
& WUTSEL_FST
& WPDIS_WPDIS
& WPCFG_WPCFGDIS
& WPEND_WPENDMEM);
_CONFIG4(DSWDTPS_DSWDTPS3
& DSWDTOSC_LPRC
& RTCOSC_LPRC
& DSBOREN_OFF
& DSWDTEN_OFF);
The configuration bits I found that worked for the PIC32MX110F016B (Microchip C32, v2.02) are:
#pragma config FPLLODIV = DIV_1 #pragma config FPLLMUL = MUL_20 #pragma config FPLLIDIV = DIV_2 #pragma config FWDTEN = OFF #pragma config FPBDIV = DIV_1 #pragma config WDTPS = PS1 #pragma config FCKSM = CSECME #pragma config OSCIOFNC = OFF #pragma config POSCMOD = HS #pragma config IESO = ON #pragma config FSOSCEN = OFF #pragma config FNOSC = PRIPLL #pragma config CP = OFF #pragma config BWP = OFF #pragma config PWP = OFF #pragma config ICESEL = ICS_PGx2 // NB: set to correct channel #pragma config DEBUG = OFF
Note that both of these chips have several programming ports. Any can be used for programming. However for debugging you must specify which port is being used in the configuration bits.
Saturday, January 28, 2012
Interfacing Sensirion temperature / humidity sensors to the XBee using 'bit-banging' technique
This article documents an technique to interfacing digital sensors such as the Sensirion SHT21 to an XBee Series 2 radio module running ZigBee end device firmware without using any additional hardware components. The same technique should apply to similar digital sensors.
Digi provide several protocol options including DigiMesh (their own proprietary protocol) and ZigBee. For interoperability with other vendors equipment and security I use ZigBee. Each protocol family has several firmware options which can be loaded on the module: usually Coordinator, Router and End Device. For battery powered applications the End Device firmware must be used to achieve reasonable battery life. In this mode the module spends most of its time asleep using less than 1µA current. Periodically it will wake (briefly consuming 15 - 40mA), query its parent router to see if there are any waiting packets. If there are none it will go back to sleep. In this mode a set of AAA batteries can last a year or more.
Analog sensors can be coupled to XBee IO lines in ADC mode (10 bits resolution ranging from 0 - 1.2V) and read remotely using Digi's remote sampling API. However analog sensors will probably require signal conditioning circuitry (op amps, filters etc) to make the best use of the ADC voltage range. This conditioning circuitry is likely to require individual calibration to achieve good results.
The headache of analog design can be conveniently side-stepped by using a sensor with a digital IO interface. Sensirion produce a range of temperature / humidity sensors with an impressive resolution (14 bit temperature, 12 bit humidity) and accuracy (less than ±0.3°C for some versions). These sensors talk I2C protocol (or a variant of I2C). But there is a catch: the XBee firmware from Digi does not directly support I2C.
A common solution is to use a low cost MCU as a bridge between the sensor and the XBee's UART. The MCU waits for a command from the network (via the XBee's UART), queries the sensor and relays the result back to the UART for transmission on the ZigBee network. By monitoring the XBee's SLEEP pin the MCU can also spend most of its time in a low power sleep, waking only when the XBee wakes.
There is an alternative... a common solution in a situation where there is no direct hardware support for a serial protocol: "bit banging". Each of the XBee's IO lines can be set high, low or in high impedance (input) state by remote control: everything needed to realize the I2C and SPI protocols. But there is a catch: unlike a MCU bit banging its own IO lines which can happen at clock speeds exceeding 100kHz, remotely bit banging XBee IO lines is a very slow process. Fortunately the Sensirion sensor datasheets do not place any lower bound on the protocol clock speed. So a clocking speed of just 1Hz will work just as well as 100kHz... it's just going to take a while to complete a query.
This is what the test setup looks like. A SHT75 sensor is at the bottom of the photo. A XBee board (the Grove XBee Carrier board from SeeedStudio) with DIO1 and DIO2 connected to the SHT75 clock and data pins respectively. The 3.3V power supply from the board powers the sensor.
Implemenation details:
The details of how to communicate with an XBee module are beyond the scope of this article. A good introduction to the topic is the book Building Wireless Sensor Networks from O’Reilly.
It’s important to note that the I2C protocol requires pull-up resistors on the clock and data lines. Fortunately the XBee has configurable 30k internal pull-up resistors for digital inputs which are configured with the ATPR command. They are enabled by default.
A sensor query begins by first issuing a remote ATIR command to the XBee to initiate frequent IO sampling. I found 100ms sampling period gave good results. ATIR must be followed by ATAC (commit) for the change to take effect. The sampling will keep the (normally sleeping) XBee awake. Also each time a sample packet is transmitted the acknowledgement will let the XBee know if there are incoming packets waiting for it. So it helps keep packet latency relatively low. Samples packets comprise the high/low state of any digital input pins and the ADC value of any pins configured as ADC.
Before proceeding to the next step wait until the first sample arrives. This may take several seconds depending on where the XBee is in its sleep cycle. When it starts to transmit samples you know it is awake and will stay awake.
Now issue ATD commands to set the clock and data lines into the necessary state. For example, ATD13 sets DIO1 into input (or high impedance) state, ATD14 sets DIO1 into a output low (0V) and ATD15 sets DIO1 into output high (3.3V). Any ATD command will need to be followed by an ATAC before the change will take effect.
To read a data line during the read phase of an I2C conversation, wait for a IO sample to arrive after the low-to-high transition of the clock.
Finally when the I2C conversation is complete set ATIR=0 to stop automatic sampling, followed by ATAC. On reception the XBee should go back to sleep.
I found that a short delay (about 100ms) between each AT command was required for acceptable results.
This is an oscilloscope trace of a temperature query of a SHT75 sensor. The SHT7x and SHT1x range use a protocol similar to, but not compatible with I2C. Note the time base is 3.7 seconds per division! The clock is in green, the data in yellow. The blue trace is connected to a third pin which was used for debugging (to help separate out parts of the conversation). Here it is set high while writing out the command (0x03, read temperature) .
The SHT21 and SHT25 are more recent temperature / humidity sensors from Sensirion. These sensors use standard I2C protocol. This trace is a I2C read temperature query to a SHT21 sensor:
Some results:
This is a chart of a few hours of data from a SHT21 and SHT75 connected to an XBee using this technique. For comparison a third wireless sensor, a Digi XS-Z16-CB2R sensor is included. All three sensors were enclosed in an insulated polystyrene box to ensure that all sensors were reading the same temperature and humidity. I've also included the supply voltage (a handy feature of the XBee modules).
One slightly disappointing result is that there are quite a few failed queries (compare the number of CB2R samples in blue to those in red and green). It seems that with my current implementation of this bit banging technique the success rate is about 66%. I believe this can be significantly improved with some changes to the implementation.
Conclusion:
Bit banging serial IO protocols such as I2C, SPI with the XBee IO lines under remote control is feasible. A battery powered sensor unit can be constructed with nothing more than a XBee, a digital sensor (and some means to physically link the sensor to the XBee), a battery holder and suitable housing. No other components are required.
However there are some down sides: it takes a long time to make a measurement (10 - 30 seconds). During this period the XBee is awake (consuming 15 - 30mA). This is not a problem if AA or AAA cells are used and the measurements are infrequent (eg once per hour). As currently implemented, reliability is far from perfect (2 out of 3 queries succeed) however I believe this can be improved with some tweaks to the implementation. Also over 100 ZigBee packets are required to complete one measurement: this could be a problem on a congested network.
Code:
Unfortunately the test setup is too complex to package up a simple self contained ZIP file to implement this technique. However here is the source code of the main Java class file which implements the necessary XBee AT commands.
/**
* Implement temperature and humidity queries to a SHT71 and SHT75 sensor by bit banging
* XBee IO lines.
*
* @author Joe Desbonnet, jdesbonnet@gmail.com
*
*/
public class SHT7x {
public static final int CMD_TEMPERATURE_READ = 0x03;
public static final int CMD_HUMIDITY_READ = 0x05;
private XBeeSeries2 xbee;
private int clockPin;
private int dataPin;
// delay=100, sampleRate=250 does not work
// delay=150, sampleRate=250 does not work (reliably)
// delay=200, sampleRate=250 works
// delay=180, sampleRate=50 works
// delay=180, sampleRate=100 works
// delay between sending each packet to the NIC for transmission
private int delay = 180;
// ms between each sample
private int sampleRate = 100;
/**
*
* @param xbee XBee proxy object
* @param clockPin XBee pin used to implement SCK (0 = DIO0, 1 = DIO1 etc)
* @param dataPin XBee pin used to implement SDA (0 = DIO0 .. etc)
*/
public SHT7x(XBeeSeries2 xbee, int clockPin, int dataPin) {
this.xbee = xbee;
this.clockPin = clockPin;
this.dataPin = dataPin;
}
/**
* Implement short delay. Usually used to space ZigBee packets apart.
*/
private void delay() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void clockHigh() throws IOException {
byte[] param = new byte[1];
param[0] = XBeeSeries2.HIGH;
xbee.atCommand("D" + clockPin, param);
xbee.atCommand("AC");
delay();
}
private void clockLow() throws IOException {
byte[] param = new byte[1];
param[0] = XBeeSeries2.LOW;
xbee.atCommand("D" + clockPin, param);
xbee.atCommand("AC");
delay();
}
private void dataHigh() throws IOException {
byte[] param = new byte[1];
// Data high is achieved by high impedance state (HIGH_Z) ie digital
// input mode
param[0] = XBeeSeries2.HIGH_Z;
xbee.atCommand("D" + dataPin, param);
xbee.atCommand("AC");
delay();
}
private void dataLow() throws IOException {
byte[] param = new byte[1];
param[0] = XBeeSeries2.LOW;
xbee.atCommand("D" + dataPin, param);
xbee.atCommand("AC");
delay();
}
/**
* Reset communications with sensor. Required if the previous query did not complete.
*
* @param xbee
*/
public void resetComms() throws IOException {
int i;
dataHigh();
// Pulse clock 9+ times while data high
for (i = 0; i < 10; i++) {
clockHigh();
clockLow();
}
}
/**
* Start sequence.
*
* @throws IOException
*
*/
private void startSequence() throws IOException {
clockHigh();
dataLow();
clockLow();
clockHigh();
dataHigh();
clockLow();
}
/**
* A command is 8 bits (MSB first) followed reading an ack bit from the device.
* In this implementation I ignore the result of the ack bit (but there
* still must be a 9th clock pulse). Bits are written by setting the
* data pin to either 0V (logic 0) or high impedance (logic 1). The data is
* read by the sensor during a low to high transition of the clock signal.
*
* @param command
* @throws IOException
*/
private void sendCommand (int command) throws IOException {
int i;
boolean lastBit = true;
boolean currentBit = false;
// MSB first
for (i = 0; i < 8; i++) {
currentBit = ((command & 0x80) != 0);
// Only change data pin if there is a change. This reduces the number
// of ZigBee packets transmitted.
if (currentBit != lastBit) {
if (currentBit) {
dataHigh();
} else {
dataLow();
}
lastBit = currentBit;
}
// Pulse clock
clockHigh();
clockLow();
command <<= 1;
}
// If data currenly low bring to high_z/input mode
if (currentBit == false) {
dataHigh();
}
// I don't bother to read the ACK bit, but the clock
// must still be pulsed for it.
clockHigh();
// don't bother sampling data pin -- will assume all ok
clockLow();
}
/**
* Reference datasheet §4.3.
* @return Temperature in °C
* @throws IOException
*/
public float readTemperature() throws IOException {
int v = makeReading(CMD_TEMPERATURE_READ);
return -39.7f + 0.01f * (float) v;
}
/**
* Reference datasheet §4.1.
*
* @return Humidity as RH%
* @throws IOException
*/
public float readHumidity() throws IOException {
int v = makeReading(CMD_HUMIDITY_READ);
return (float)(-2.0468 + 0.0367*(double)v - 1.5955e-6*(double)v*(double)v);
}
/**
* Reset comms, send start sequence, command and read 16 bits of data.
*
* @param what One of SHT7x.CMD_TEMPERATURE_READ or SHT7x.CMD_HUMIDITY_READ
* @return
* @throws IOException
*/
private int makeReading (int what) throws IOException {
int i;
//
// Configure XBee to send frequent IO samples. This has two important functions.
// First it keeps the XBee end device awake. Also an end device transmitting a
// packet (which must go via its parent) has the side effect of polling the
// parent for any incoming packets. So frequent transmission also means low
// latency in receiving packets.
byte[] params2 = new byte[2];
params2[0] = (byte) (sampleRate >> 8);
params2[1] = (byte) (sampleRate & 0xff);
xbee.atCommand("IR", params2);
xbee.atCommand("AC");
// Now wait for the first sample to arrive before proceeding. At this point we'll
// know the end device awake.
long t0 = System.currentTimeMillis();
while (xbee.getLastIOSampleTime() < t0) {
delay();
}
// XBee End Device should now be awake and responsive
// The last query may not have completed leaving the communications in an undefined
// state. Reset communications to a known state.
resetComms();
delay();
delay();
// Start sequence ref §3.2.
startSequence();
delay();
delay();
// Send 8 bit command (and read ack bit)
sendCommand(what);
// Wait for measurement to complete. We could poll the DATA line. It will be pulled
// low by the sensor when the reading is complete. However the overhead of doing
// this makes it not worth the effort.
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
// ignore
}
//
// Read 16 bits
//
int v = 0, sample;
for (i = 0; i < 16; i++) {
v <<= 1;
clockHigh();
// wait for IO sample
t0 = System.currentTimeMillis();
while (xbee.getLastIOSampleTime() < t0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
}
// sample = xbee.getIOSample();
sample = xbee.getLastIOSample();
if ((sample & 0x04) != 0) {
v |= 1;
}
clockLow();
// write ack bit
if (i == 7 || i == 15) {
// write ack bit (0)
dataLow();
clockHigh();
clockLow();
dataHigh();
}
}
//
// Return end device to normal sleep pattern by disabling sampling (ie by
// setting sample period to 0).
//
params2 = new byte[2];
params2[0] = 0;
params2[1] = 0;
xbee.atCommand("IR", params2);
xbee.atCommand("AC");
return v;
}
}
Thursday, December 15, 2011
LED killed the fairy light
I noticed something while visiting my local hardware store today: they had no incandescent fairy lights this year. None at all. All LED. It's sad to see such an old technology die.
The "fairy light" is 129 years old this year. Its etymology comes from the Gilbert and Sullivan operetta Iolanthe which opened on 25 November 1882. The story is about fairies and someone had the bright idea of festooning some of the principle fairies with miniature light bulbs powered by a small battery. Apparently it caused quite a sensation and the term "fairy light" came into common use ever since.
The "fairy light" is 129 years old this year. Its etymology comes from the Gilbert and Sullivan operetta Iolanthe which opened on 25 November 1882. The story is about fairies and someone had the bright idea of festooning some of the principle fairies with miniature light bulbs powered by a small battery. Apparently it caused quite a sensation and the term "fairy light" came into common use ever since.
Installing Cadsoft Eagle 6 on Ubuntu 10.4
Update (19 Dec 2014): Just reviewing old blog posts. This article is now way out of date. Please ignore.
Update (5 Mar 2012): I've just been informed that libpng-1.4.8 has been replaced by libpng-1.4.9 and removed from ftp.simplesystems.org. I'll update the script in the next few days. In the mean time, please edit the script to change the version of libpng.
The recently released Eagle 6 from Cadsoft has a dependency on libpng 1.4, libjpeg 8, libcrypt 1.0, libssl 1.0. My Ubuntu 10.4 distribution has older versions of these libraries which Eagle 6 does not like.
There are a few posts on how to fix this, eg this one. However it relies on some helpful person's pre-built binaries. While I'm sure it's perfectly good, I'm just a little too paranoid to copy and execute code from an unknown source. So I set about downloading and building these libraries from source. I've written up the procedure as a bash script in case someone as paranoid as myself would like to do the same.
This script will build these libraries from source, and copy them to a directory specifically for use with Eagle.
This is the procedure:
Update (5 Mar 2012): I've just been informed that libpng-1.4.8 has been replaced by libpng-1.4.9 and removed from ftp.simplesystems.org. I'll update the script in the next few days. In the mean time, please edit the script to change the version of libpng.
The recently released Eagle 6 from Cadsoft has a dependency on libpng 1.4, libjpeg 8, libcrypt 1.0, libssl 1.0. My Ubuntu 10.4 distribution has older versions of these libraries which Eagle 6 does not like.
There are a few posts on how to fix this, eg this one. However it relies on some helpful person's pre-built binaries. While I'm sure it's perfectly good, I'm just a little too paranoid to copy and execute code from an unknown source. So I set about downloading and building these libraries from source. I've written up the procedure as a bash script in case someone as paranoid as myself would like to do the same.
This script will build these libraries from source, and copy them to a directory specifically for use with Eagle.
This is the procedure:
- First create an empty directory. Copy this script into it. Next open the script with an editor.
- Set EAGLE_DEPS_DIR to a location where you want the libraries to be copied to after building (eg /home/joe/libeagle in my case)
- I recommend that you verify the download locations of the library sources before you run this script. This is security best practice: it's generally not a good idea to download and execute code from an untrusted source. Once you are happy with the download URLs, then set I_HAVE_VERIFIED_DOWNLOAD_LOCATIONS=true
- Save and run the script. If it's your first time running it, it will download the sources. Subsequent runs wont waste bandwidth if they are already there. Building the libraries will take a few minutes.
-
Verify the contents of the directory defined in EAGLE_DEPS_DIR. It should
have the following files:
- libcrypto.so.1.0.0
- libjpeg.so.8.3.0
- libpng14.so.14.8.0
- libssl.so.1.0.0
- libjpeg.so.8 -> /home/joe/libeagle/libjpeg.so.8.3.0
- libpng14.so.14 -> /home/joe/libeagle/libpng14.so.14.8.0
- Before running the Eagle installer or the Eagle software set environment variable LD_LIBRARY_PATH to include this directory (eg export LD_LIBRARY_PATH=/home/joe/libeagle )
Enjoy!
Update (30 Jan 2012): I received some improvements to the script from Leandro (wisleca@gmail.com). Revision 2 is here.
Update (30 Jan 2012): I received some improvements to the script from Leandro (wisleca@gmail.com). Revision 2 is here.
Tuesday, December 13, 2011
Time tagging data streams using a short bash script
I've often had to write Arduino sketches and small PIC programs to read data from sensors for transmission to a PC over the serial link. This is mostly for testing and evaluating sensors in the lab – so I don't want to waste any more time than I have to writing software.
A common requirement is to have each sensor record time tagged. However implementing a real time clock on a Arduino, PIC etc can be a lot of hassle. It makes more sense to tag the record on the PC as it comes in.
Here is a short bash shell script that runs on a Linux PC which reads data from an input stream (usually the serial port) line by line and prefixes each line with the unix epoch time (seconds since 1 Jan 1970):
A common requirement is to have each sensor record time tagged. However implementing a real time clock on a Arduino, PIC etc can be a lot of hassle. It makes more sense to tag the record on the PC as it comes in.
Here is a short bash shell script that runs on a Linux PC which reads data from an input stream (usually the serial port) line by line and prefixes each line with the unix epoch time (seconds since 1 Jan 1970):
#!/bin/bash
while read line ; do
echo `date +%s` $line
done
So, for example, right now I have an Arduino sketch polling a SHT75 temperature humidity sensor. The Arduino is writing a record (about 1 every second) with the current temperature and humidity. The data looks like this:
19.70 49.22 19.70 49.38 19.68 49.38 19.66 49.22
This is coming in on /dev/ttyUSB2 in this case. The above script is in file timetag.sh. On the PC I do:
cat /dev/ttyUSB2 | bash timetag.sh > sensor.log
sensor.log looks like this:
1323808719 19.70 49.22 1323808720 19.70 49.38 1323808721 19.68 49.38 1323808723 19.66 49.22
The data can now be plotted with the insanely useful gnuplot utility like this:
$ gnuplot set title "Temperature and Relative Humidity from SHT75 sensor"
set grid set xlabel "Time" set ylabel "Temperature (C) / Relative Humidity (%)" set xdata time # X axis is time set timefmt "%s" # Input file time format is unix epoc time set format x "%R" # Display time in 24 hour notation on the X axis plot 'sensor.log' using 1:2 title 'T', 'sensor.log' using 1:3 title 'RH'If you don't like the unix time notation, you can use alternative notations. See the manual page for the unix date command to get alternative time formats. You'll need to match the date format with the gnuplot 'set timefmt' command (help timefmt inside gnuplot will display available formats). For plots spanning more than one day you'll need to adjust time labeling with 'set format x' command (help set format time_specifier will provide information on this).
Sunday, December 11, 2011
Quick and dandy BusPirate breadboard connector
I have found that the probe kit that I had ordered from SeeedStudio with my BusPirate last year wasn't as useful as I had hoped. The quality of the the probe connectors wasn't great and having 10 probes in a bunch when all you need is 4 can be cumbersome. I can't complain – the probe kit was only $5.
I needed to check out a I2C temperature/humidity sensor with the BusPirate on a breadboard. So hacked this connector comprising a short length of 10 wire ribbon cable, a 5x2IDE IDC connector to mate with the BusPirate IO header at one end and an IC socket at the other end.
The IC socket can then be plugged into the breadboard. I don't expect this connector to last forever, but it's certainly neater and easier to use than the probe kit.
I needed to check out a I2C temperature/humidity sensor with the BusPirate on a breadboard. So hacked this connector comprising a short length of 10 wire ribbon cable, a 5x2
The IC socket can then be plugged into the breadboard. I don't expect this connector to last forever, but it's certainly neater and easier to use than the probe kit.
Friday, November 25, 2011
A water drop microscope with a smart phone camera
Which got me thinking: what if I put a drop of water onto the camera window: would the camera become a microcope?
And indeed it does. The quality isn't great, but you can certainly see things that are not visible with the naked eye.
The trick is to ensure that the drop is small enough so that the entire surface is curved. A large drop will have a mostly flat surface and will not act as a lens. Objects will come into focus at a very short distance from the water drop lens – about 5mm.
Using the front facing camera on some of the newer camera models (eg the Galaxy Nexus) has the benefit that you can easily illuminate the subject while viewing the display. The normal camera can be trickier to get good photos because the camera blocks the light needed for a good exposure. The flash doesn't work very well because the subject is so close to the lens. If the subject matter is semi-transparent (eg a leaf) you can try back lighting it. When finished dry and clean the camera window with a soft cloth.
Here are some photos I took (some with the Galaxy Nexus, some with Galaxy Tab).
![]() |
| A microscopic photo of a HTC Magic LCD display through the water drop. |
![]() |
| Holly leaf back lit with a desk lamp. |
![]() |
| The pins of a TQFP IC package. The width of the pin is 0.22mm. |
![]() |
| A holly leaf back lit by a desk lamp. |
![]() |
| Finger tip. |
![]() |
| Leaf, back lit by a desk lamp. Cropped and some sharpening applied. |
![]() |
| PCB vias. |
If you have any suggestions on how to improve the quality of the images or would like to share some of your microscope images, please leave a comment at the end of this post. More photos from this online album.
Updates:
27 Nov 2011: It occurred to me that oil has a higher refractive index than water (1.47 for vegetable oil vs 1.33 for water) which might result in better magnification. I'll try it at some point, but it will certainly be messier to clean up.
Monday, November 14, 2011
Roaming bandwidth in Spain with the Samsung Galaxy Tab
There seems no end in sight to the roaming ripoff in Europe. While the situation is improving slowly it's still ridiculous.
At the moment I'm on holiday in the Canary Islands (part of Spain). Before travelling I checked with my operator (Vodafone IE) re data roaming packages. The best they could do is €12 per day for 50MB after which €1 is charged per additional MB (down from €5/MB a few years ago!). I need about 100MB per day so that's €12 for the first 50MB and €50 for the next 50MB: a total of €62 per day, or €620 for a 10 day trip! Added to this is the complication that between myself and the wife we have 6 WiFi devices (2 x laptops, 2 x smartphones, a Kindle and an Android tablet). Our hotel WiFi is locked to a single device, is expensive, slow (128kbps?!), and is only accessible in certain areas (not our rooms).
I found a nice solution. I purchased a pay-as-you-go SIM from a local Vodafone shop (a €9 once off charge and you'll need photo ID to make that purchase). I then applied a data top-up to that SIM: €15 for 1GB lasting one week or €20 for 1GB lasting up to a month. I inserted the SIM into my Samsung Galaxy Tab 10.1v and started the portable hotspot mode (under Settings -> Wireless & networking -> Tethering and portable hotspot -> Portable WiFi Hotspot). Bingo: a portable WiFi hotspot good for up to 5 devices.
The Galaxy Tab's battery life is sufficient that I can carry the tablet in my day bag and have enough power to keep all our devices continuously connected no matter where we were. The Galaxy Tab has security disabled by default: I'd strongly recommend enabling security to prevent others nearby gaining unauthorized access to precious bandwidth (the mobile network here is good... it won't take long to download a full 1GB).
There are still a few problems (which I'm sure there are good solutions out there): Android 3.0 (Honeycomb) installed on the Galaxy Tab 10.1v (aka GT-P7100) seems to have no ability to report current or historical bandwidth use. I believe this has been addressed in Android 4.0 which I eagerly look forward to. Also I haven't figured out how to get remaining data credit on my SIM. And finally Windows 7: in the first few minutes after connecting it seems to go through megabytes per minute: presumably software updaters phoning home, Facebook, GMail brower windows fetching updates etc. It seems to settle down to a reasonable rate after a minute when about 5MB is consumed.
At the moment I'm on holiday in the Canary Islands (part of Spain). Before travelling I checked with my operator (Vodafone IE) re data roaming packages. The best they could do is €12 per day for 50MB after which €1 is charged per additional MB (down from €5/MB a few years ago!). I need about 100MB per day so that's €12 for the first 50MB and €50 for the next 50MB: a total of €62 per day, or €620 for a 10 day trip! Added to this is the complication that between myself and the wife we have 6 WiFi devices (2 x laptops, 2 x smartphones, a Kindle and an Android tablet). Our hotel WiFi is locked to a single device, is expensive, slow (128kbps?!), and is only accessible in certain areas (not our rooms).
I found a nice solution. I purchased a pay-as-you-go SIM from a local Vodafone shop (a €9 once off charge and you'll need photo ID to make that purchase). I then applied a data top-up to that SIM: €15 for 1GB lasting one week or €20 for 1GB lasting up to a month. I inserted the SIM into my Samsung Galaxy Tab 10.1v and started the portable hotspot mode (under Settings -> Wireless & networking -> Tethering and portable hotspot -> Portable WiFi Hotspot). Bingo: a portable WiFi hotspot good for up to 5 devices.
The Galaxy Tab's battery life is sufficient that I can carry the tablet in my day bag and have enough power to keep all our devices continuously connected no matter where we were. The Galaxy Tab has security disabled by default: I'd strongly recommend enabling security to prevent others nearby gaining unauthorized access to precious bandwidth (the mobile network here is good... it won't take long to download a full 1GB).
There are still a few problems (which I'm sure there are good solutions out there): Android 3.0 (Honeycomb) installed on the Galaxy Tab 10.1v (aka GT-P7100) seems to have no ability to report current or historical bandwidth use. I believe this has been addressed in Android 4.0 which I eagerly look forward to. Also I haven't figured out how to get remaining data credit on my SIM. And finally Windows 7: in the first few minutes after connecting it seems to go through megabytes per minute: presumably software updaters phoning home, Facebook, GMail brower windows fetching updates etc. It seems to settle down to a reasonable rate after a minute when about 5MB is consumed.
Monday, October 31, 2011
Weather radar animation
Here is a short weather radar animation I made of a 24 hour period last week (24 October 2011) when the east coast of Ireland (Dublin city in particular) was deluged with an exceptionally heavy rain storm.
I made this video clip starting with a directory of individual radar images in PNG format and then used the mencoder tool (part of mplayer) to generate a MP4 video clip from the frames.
Note that I've set the frames per second to 5 (fps=5). The usual 24 frames per second is too fast.
Images from Met Éireann (the Irish Meteorology service).
I made this video clip starting with a directory of individual radar images in PNG format and then used the mencoder tool (part of mplayer) to generate a MP4 video clip from the frames.
mencoder mf://*.png -mf fps=5:type=png -ovc lavc -lavcopts vcodec=mpeg4 -o video.mp4
Note that I've set the frames per second to 5 (fps=5). The usual 24 frames per second is too fast.
Images from Met Éireann (the Irish Meteorology service).
Subscribe to:
Posts (Atom)



.jpg)






.png)
.png)
















