Monday, February 17, 2014

"Method and apparatus" for mass-synchronizing clocks

Most of my clocks (e.g. this Nixie clock, this other Nixie clock, BookClock, and obviously Wise Clock 4) have on-board Bluetooth, intended mainly for setting up the time, without the need for buttons (the lousy holes I would drill may negatively impact the aesthetics).
To set up the time, simply send the command TIME=hh:mm:ss, where "hh", "mm", "ss" are the hours, the minutes and the seconds, respectively.

Setting up multiple clocks is a tedious process: pair your Android tablet with one at a time, then (from BlueTerm) send the command that includes the correct time. Then repeat for each clock.

What if you could broadcast the TIME=... command? And that command to include the most accurate time, acquired from GPS? This is what this post is about. Now you have the "method".

Next, to the "apparatus". It consists essentially of 3 parts: GPS receiver, microcontroller and Bluetooth master module. Putting them together is trivial, since both GPS receiver and Bluetooth module communicate through serial ports.


I used an old (now discontinued at the major online stores, but still available on ebay) Fastrax UP-501 GPS module I already had laying around. But any GPS receiver should work as well, including the Adafruit Ultimate GPS Breakout.

The "Bluetooth master module" is a re-programmed HC-05 (see the datasheet) as master, with CMODE=1 (for broadcasting).

The sketch, presented below, uses SoftwareSerial library to communicate with the GPS module (Rx on D3, Tx on D4) and TinyGPS library to extract the time from the NMEA sentence. The BTBee module is connected to the hardware serial port (D0, D1).


#include "TinyGPS.h"
#include "SoftwareSerial.h"
SoftwareSerial GPSSerial(4, 3);

// GPS Fatrax UP501, connected as follows:
// - power pin to 3.3V
// - ground pin to ground
// - VBAT pin to 3.3V if no battery is used
// - TX pin to D4
// - RX pin to D3 through a voltage divider (2 resistors, 10k + 4k7)

#define _DEBUG_  true

// commands  for GPS module;
#define PMTK_SET_NMEA_UPDATE_1HZ  "$PMTK220,1000*1F"
#define PMTK_SET_NMEA_UPDATE_5HZ  "$PMTK220,200*2C"
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"

// turn on only the second sentence (GPRMC)
#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on ALL THE DATA
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"

// MTK command datasheet at http://www.hhhh.org/wiml/proj/nmeaxor.html

TinyGPS gps;

void setup()  
{
  // default baud rate for BTBee (on hardware serial);
  Serial.begin(9600);

  // default baud rate for UT501 (on software serial);
  GPSSerial.begin(9600);
  
  // turn on all the available data (for 9600 baud you'll want 1Hz rate);
  GPSSerial.println(PMTK_SET_NMEA_OUTPUT_ALLDATA);
  
  // set update rate to 1Hz
  GPSSerial.println(PMTK_SET_NMEA_UPDATE_1HZ);

#ifdef _DEBUG_
  Serial.println("ready for reading GPS...");
#endif
}

void loop()
{
  acquireTimeFromGPS();
  delay(5000);
}

void acquireTimeFromGPS()
{
  unsigned long age;
  int Year;
  byte Month, Day, Hour, Minute, Second, Hundredths;

  if (feedgps())
  {
#ifdef _DEBUG_
    Serial.println("GPS feed acquired...");
#endif
    gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, &Hundredths, &age);
    char buf[20] = {0};
    sprintf(buf, "TIME=%02d:%02d:%02d", Hour, Minute, Second+1);
    Serial.println(buf);
  }
}

bool feedgps()
{
  while (GPSSerial.available())
  {
    char c = GPSSerial.read();
#ifdef _DEBUG_
    Serial.print(c);
#endif

    if (gps.encode(c))
      return true;
  }
  return false;
}

As protoboard I used the XBee Shield from seeedstudio because it had a socket for my BTBee (plus 3V3 regulator) and also ample space for processor and GPS. (It could even fit in a Altoids tin if  the GPS receiver is soldered directly to the board, without headers.)

Future improvements should include a couple of status LEDs, one to show that the data was being acquired from GPS, another to indicate that the "TIME" command was successfully built and broadcast. Similarly but more expensively, a small OLED screen could be used to display the activity.
On the software side, the time, which comes as UTC in the NMEA sentence, should be adjusted to the current time zone, probably based on the longitude.

Saturday, February 8, 2014

Altoids Geiger counter

My "Remixed Geiger counter" board fits almost perfectly, by chance, in the "classic" Altoids box, with room left for the SI-29 GM tube, the 1100mAh LiPo battery and the 0.96" OLED display.


The ATmega328 processor runs at 8MHz with the internal oscillator, a better choice (than the 16MHz of Arduino 2009) for the LiPo voltage of approx 3.7V.  The display I used is compatible with the monochrome 128x64 OLED display from Adafruit.
It is powered at 3V3, requiring a voltage regulator (78L33, TO-92), placed where the the trim-pot (for adjusting LCD contract) was supposed to be (top-right corner of the board).

The sketch uses Adafruit_SSD1306 library, with the wiring to the display as defined below:

#define OLED_DC 8
#define OLED_CS 7
#define OLED_CLK 4
#define OLED_MOSI 3
#define OLED_RESET 5

Note that the same D3-D8 are used for connecting to the LCD 1602 display in the "regular" DIYGeigerKit.
Also note that I did not install the "click" LED nor the buzzer, relying instead on the OLED display to indicate the radiation level.

Since the lid needs to be open anyway in order to see the screen, I thought it does not make sense to drill 2 holes in the box for the USB miniB connector (used for charging the battery) and the on/off switch. (As well, this sounds like a believable excuse for being lazy.)


If I were to improve on it, I would replace the right-angle toggle switch with a straight-up one (easier to operate), then add a button or two for user inputs (configuration parameters, menu navigation etc). The "click" buzzer and the LED could be made "digital", wired to controller's outputs. Adding a Bluetooth module would be also useful (if it works at all from inside the closed box, I need to try it). Ideally, I would also add RTC, GPS and SD card, for logging purposes. And then it would become a smaller and cheaper version of Safecast bGeigieNano :)