Wednesday, June 24, 2015

WiFiChron fix and other WiFis

The peculiar feature of the "May 2015" revision of WiFiChron board is that it was designed to use software serial to communicate with either the XBee or ESP module. The reason is related to debugging. I wanted to be able to send messages to the serial monitor while (software serially) communicating with the serial device. This solution works well for XBee (GPSBee, BTBee), but not for ESP8266, only because the software takes more than the available 2K of RAM in this case (WiFi + software serial).

The immediate fix to use the ESP module is to connect its Rx/Tx lines to Rx/Tx of the processor. The existing connections can be left uncut, since they are not used in the sketch for ESP8266. The wiring should be like in the photo below.


The "permanent" fix would be re-designing the board to use ATmega1284 SMD (DIP-40 would not fit).

Talking about 1284, take a look at Farit's WiseClock4 mod. He used the WiseClock4 board, but completely re-wrote the software, including, it seems, the definition of new fonts. The SD card is now used for storing MIDI files (among others) that can play tunes through the Fluxamasynth shield.


A few of the other hardware and software features are:
  • WiFi access to the internet through WiFly module;
  • accurate time keeping through NTP;
  • display weather forecast read from the web;
  • daily alarms;
  • automatic adjustment of the display brightness with light sensor;
  • user-selectable display color.
The exquisite and elaborate wooden enclosure adds even more character.

And a photo of the internals, with the extra hardware:



Farit also shared the software he wrote, hopefully an inspiration for future mods.

Thursday, June 11, 2015

Prototype 14-segment-display shield

There are many ways (*) to drive the 6-digit 14-segment common cathode display from Seeed Studio.
This time I chose to multiplex two MAX7221, a method described here (but used for driving a bi-color 8x8 LED matrix).


The code is based on LedControl library, which I extended to cover the definition and display of 14-segment characters (digits, upper case letters, and a few specials). Below is a relevant fragment of the code I added:

/*
* Segment names in the 14-segment (plus DP) display:
*
*     -     A
*   |\|/|   F,I,J,K,B
*    - -    G,H
*   |/|\|   E,N,M,L,C
*     -  .  D,P
*/
// my wiring:
//            GFEDCBAx
// 1st byte: B11111111
//
//            NHJIKMLP
// 2nd byte: B11111111

const static byte charTable14Seg[43][2] = {
    {B01111110,B10001000},  // 0
    {B00001100,B00001000},  // 1
    {B10110110,B01000000},  // 2
    {B00011110,B01000000},  // 3
    {B11001100,B01000000},  // 4
    {B11010010,B00000010},  // 5
    {B11111010,B01000000},  // 6
    {B00000010,B00001100},  // 7
    {B11111110,B01000000},  // 8
    {B11011110,B01000000},  // 9
    {B00000000,B01000000},  // :
    {B00000000,B01000000},  // ;
    {B00000000,B01000000},  // <
    {B00000000,B01000000},  // =
    {B00000000,B01000000},  // >
    {B00000000,B01000000},  // ?
    {B00000000,B01000000},  // @
    {B11101110,B01000000},  // A
    {B00011110,B01100100},  // B
    {B01110010,B00000000},  // C
    {B00011110,B00100100},  // D
    {B11110010,B01000000},  // E
    {B11100010,B01000000},  // F
    {B01111010,B01000000},  // G
    {B11101100,B01000000},  // H
    {B00000000,B00100100},  // I
    {B00111100,B00000000},  // J
    {B11100000,B00001010},  // K
    {B01110000,B00000000},  // L
    {B01101100,B00011000},  // M
    {B01101100,B000100L0},  // N
    {B01111110,B00000000},  // 0
    {B11100110,B01000000},  // P
    {B01111110,B00000010},  // Q
    {B11100110,B01000010},  // R
    {B11011010,B01000000},  // S
    {B00000010,B00100100},  // T
    {B01111100,B00000000},  // U
    {B01100000,B10001000},  // V
    {B01101100,B10000010},  // W
    {B00000000,B10011010},  // X
    {B00000000,B00011100},  // Y
    {B00010010,B10001000},  // Z
};
...
void setChar14Seg(byte pos, byte ascii)
{
  if (pos>7)
    return;

  if (ascii>90 || ascii<48)
    return;

  byte index = ascii - 48;
  for(byte seg=0; seg < 8; seg++)
  {
    SetLed(SEG_AG, pos, seg, charTable14Seg[index][0] & 1 << seg);
    SetLed(SEG_GN, pos, seg, charTable14Seg[index][1] & 1 << seg);
  }
}

This method (hardware and software) can be used for up to 8 14/16-segment displays.


(*) Should be the topic of a future post.


Monday, May 18, 2015

Ideas

First off, a new adapter for the WiFiChron or HDSP clock. The 8-LED Neopixel stick from adafruit has the perfect dimensions to fit them. Naturally, the time is displayed in color code. The best definitions for the 10 colors I could come up with are these:

byte color[10][3] =
{
  {0,0,0}      /*black*/,
  {30,9,0}     /*brown*/,
  {100,0,0}    /*red*/,
  {128,60,0}   /*orange*/,
  {110,120,0}  /*yellow*/,
  {0,64,0}     /*green*/,
  {0,0,111}    /*blue*/,
  {64,0,63}    /*violet*/,
  {15,15,15}   /*grey*/,
  {127,127,127}/*white*/
};

The clock code is trivial, especially because it's using the great Neopixel library. Below is the most important function:

void displayTime()
{
  byte digit1 = hour/10;
  byte digit2 = hour%10;
  
  strip.setPixelColor(0, strip.Color(color[digit1][0], color[digit1][1], color[digit1][2]));
  strip.setPixelColor(1, strip.Color(color[digit2][0], color[digit2][1], color[digit2][2]));

  digit1 = minute/10;
  digit2 = minute%10;

  strip.setPixelColor(3, strip.Color(color[digit1][0], color[digit1][1], color[digit1][2]));
  strip.setPixelColor(4, strip.Color(color[digit2][0], color[digit2][1], color[digit2][2]));

  digit1 = second/10;
  digit2 = second%10;
  
  strip.setPixelColor(6, strip.Color(color[digit1][0], color[digit1][1], color[digit1][2]));
  strip.setPixelColor(7, strip.Color(color[digit2][0], color[digit2][1], color[digit2][2]));
    
  strip.show();
}

The video I took of the clock in action is, for the lack of a better word, of too little value :), mainly because my camera doesn't seem to distinguish the colors as well as my eyes.

Even though this photo sucks, I added it only as proof :)


The time is shown as "HH MM SS", with spaces between hours, minutes and seconds. 0 is represented by an unlit (off) pixel. It is easy to get used to the colors, with help from the changing seconds.

Note that the 595 shift register on the board is not used (could even be removed, or not mounted at all).

Secondly, here is how one can save $20 on WiFiChron with GPS: use the $12 ublox instead of the $32 GPSBee. Some minimal wiring is required though, to connect 3 lines (5V, Gnd and Rx) to the module. Luckily, the GPS module has the right dimensions to fit in the spot for XBee (without the 2 headers mounted, nor the 74HC125, which is not needed in this case anyway).


If you really want everything to fit in the Serpac A20 box, you need to replace the original antenna with a smaller one (but working just fine), as shown in the next photo.


Thirdly, Craig (thanks very much!) published on thingiverse the plans for a 3D-printed enclosure he designed for Wise Clock 4:



Saturday, April 4, 2015

"Home-made", Wise Clock-based, Alpha Clock Five

I saw Justin's recent post on Alpha Clock Five and I just couldn't resist not to try it myself too. Since I didn't have that clock, I thought of improvising one by making a 5-character display that would plug into my Wise Clock 4 board. The idea was easy, the implementation not so. After many hours of hand-wiring, this is how it looks like.


The displays are 1" single digit alphanumeric (common anode) from sparkfun, now retired. They came with non-functional dots, probably the reason they were less than $2 each.
The spacing between the individual displays is forced by the protoboard.


The 2 boards are connected through the pairs of 2x8 headers. All pins used by Alpha Clock 5 to drive the displays are wired to the unused header on the Wise Clock 4 board.


Not to mention  that the software compilation and upload worked without any glitch (after downloading the very nice DS1307RTC library)

The only regret is that this clock lacks seconds. One extra display would have added lots of extra value, but probably lacked the cool factor (the "6-letter clock" requires a lot more memory to store all 6-letter words than the approx 50k required by the 5-letter-word collection).

You should try this at home :)

Sunday, March 29, 2015

Modding WiFiChron with GPS or Bluetooth

The latest revision of WiFiChron has an XBee socket (beside the ESP8266 8-pin socket), which allows the addition of a few individual features:
  1. GPS-based time synchronization, by using the GPSBee;
  2. displaying messages sent from a Bluetooth device, by using the BTBee/BLEBee;
  3. displaying data acquired from an XBee/ZigBee network of sensors (not implemented yet);


Things did not go smoothly, without some drama though. Naively (I always seem to forget that there is a difference between theory and practice), I designed the XBee/ESP to connect to the serial port, with the expectation that once the development (including testing with debug statements to the serial monitor) is done, I will just plug in the serial module (either XBee of ESP8266) and things will work properly. Well, I had to re-consider this approach once again. Luckily, I had two pins left available (D7 and D17), which I could use for software serial. I re-wired those to the XBee/ESP and used the hardware serial for console communication. Until the next board revision, anyone wanting to follow will need to re-route a couple of traces manually, as shown in the photos below (cuts are red-circled).


A few details on my implementation of the GPS time sync (so that one doesn't need to look at the code to figure it out):
  • user can set a timezone (stored in eeprom, default is -1); there is no (easy) way to determine if the timezone was set or not, since -1 (eeprom byte being 255) is a valid value;
  • estimate the timezone from the longitude, assuming that a every 15 degrees is an hour difference;
  • a difference between GPS estimated timezone and the user-set timezone of more than 2 hours would mean that the time is way off and the user did not set the timezone; in this case, blink the display; a difference of 2 hours or less would be acceptable (for many reasons, including summer-time, or variations from the "15-degrees-longitude-per-hour" approximation);
  • in any case, the minutes and seconds are set from the GPS data;
  • date and day are not set/synchronized at all (currently);
  • the GPS sync is scheduled to happen every 10 hours (and also after a reset);
  • a successful sync is indicated by an up arrow at the end of the scrolling date (e.g. March 29, 2015 ^).
I will publish the code as soon as I have a chance to polish it (and also test it with BTBee).

As you can see in the photo below, the GPS antenna fits well in the case. It also works well: the GPS has good reception inside the house, 5 meters from the closest window.