Friday, 25 October 2013

BigCrystal and BigCrystalTWI v1.0.0 released

I've made a some of updates to the BigCrystal and BigCrystalTWI Arduino libraries for displaying double height characters on Liquid Crystal Displays.

I've created version 1.0.0 releases for both projects. This is because I have made a breaking change to the BigCrystal library immediately after the 1.0.0 release to support more hardware.

In order to expand the range of hardware under which BigCrystal operates, I've made the library compatible with either the standard LiquidCrystal library or the New LiquidCrystal library. The New LiquidCrystal library replaces the standard LiquidCrystal in your Arduino library folder and supports:
  • Four bit parallel interface
  • Eight bit parallel interface
  • I2C interface using the PCF8574 expander
  • Shift register interface
If you're using LiquidCrystal after version 1.0.0, the way in which a BigCrystal instance is created has changed. Previously, a BigCrystal instance would be instantiated directly with the IO pins, but now a LiquidCrystal instance needs to be created first, and this instance passed to the BigCrystal constructor.

 #include <BigCrystal.h>  
 #include <LiquidCrystal.h>  
   
 // Set up according to your LCD pins  
 LiquidCrystal lcd(22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);  
 BigCrystal bigCrystal(&lcd);  
   

There are other methods of instantiating a LiquidCrystal instance if connecting via I2C or shift register. These are documented in the New LiquidCrystal library and there are examples in the BigCrystal library.

The methods for writing double height characters has not changed. They are:

  • widthBig() for determining the width of a character
  • writeBig() for displaying a double height character
  • printBig() for displaying a double height string
In addition, all BigCrystal delegates all LiquidCrystal methods are delegated through to the underling instance. This means that you can use the BigCrystal instance for all LiquidCrystal methods, such as displaying normal height characters, or displaying the cursor.

There have been no changes to BigCrystalTWI. This library still supports the MCP230008 I2C expander, as this is not supported in the New LiquidCrystal library. If I get my hands on one of these again, I might try to port it to the New LiquidCrystal library and then retire the BigCrystalTWI library.

Sunday, 20 October 2013

Disco Skirt

What child doesn't like lights? When I suggested to my six year old daughter that I could build her a light up skirt for her school disco, she was thrilled. When my wife started telling the other parents of my plans, I had to hurry up and make it.

This post contains the details of how I made the skirt and describes the software used to control it.



The skirt can light up its lights in different ways and also respond to motion and sound. It's easier to show rather than describe, so watch the video.


Credits

The original design for this project is from Becky Stern of Adafruit Industries. She wrote the original Sparkle Skirt tutorial which has clear instructions on how to build a skirt that responds to motion. I followed all of the instructions in that guide to build a basic skirt, and then added a few more components. I won't repeat the build instructions contained in that tutorial, but focus on how mine differs from the original.

I've added a bit more to the design by incorporating a mode switch which changes the skirt functions and by adding a microphone so the skirt can react to sound. I used the Arduino FHT Library to transform sampled sound into frequencies using a Fast Hartley Transform.

In a number of places in the code, I've used Hue, Saturation and Brightness (HSB) to represent LED colours. I used Kasper Kamperman's HSB to RGB function to convert to the RGB values required by the LEDs.

Circuit

The circuit is similar to that described in the Adafruit tutorial and is based around their Flora board. The Flora is an Arduino compatible microcontroller board that is designed for wearable projects. Most notably, it has evenly spaced pads that can be easily sewn to using conductive thread.

The project contains:
The layout of the circuit is shown in the diagram below.


The accelerometer communicates using an I2C interface and is connected to the SCL and SDA pins of the Flora, as well as 3.3V and ground for power.

The microphone, in addition to 3.3V and ground connections has its output connected to Flora pin D10. D10 also doubles as analog input A10, and we read an an analog voltage to on this pin to determine the microphone level.

The LEDs are all connected VBATT, which is the unregulated battery voltage. The Neo Pixels are nominally 5V devices, however they will work at lower voltage levels with reduced brightness. LiPo batteries have a nominal voltage of 3.7V with a maximum of about 4.2V, and drives these LEDs with sufficient brightness. Using For the data connection, the first LED in the chain is connected to D6 of the Flora. From there, the output of the previous LED is connected to the input of the next LED.

The battery is connected to the Flora's JST battery port and, the switch is connected between D9 and ground.


Construction

The circuit is sewn, rather than soldered together using stainless steel conductive thread. The thread takes the place of wires or copper traces that are used to connect components in a normal circuit. The components are sewn on the inner layer of a skirt with a mesh outer lay providing some light diffusion. Adafrut has a great guide to working with conductive thread which was useful is sewing the circuit together. I highly recommend reading it you're planning to build something similar.

It was the first time I'd attempted sewing and I made quite a few mistakes. I managed to sew to the wrong pads on the LEDs on a number of occasions, so it pays to double and triple check your connections to save having to re-sew them. I spent about 10 hours sewing this together, though I'm sure my skills improved by the end and I could make this much faster if I ever made another one. Using an embroidery hoop really helped keep things stable while sewing to them.

The microphone breakout board is not designed to be incorporated into a wearable design, but I had no problems sewing to the solder pads.

I had a bit of trouble deciding how to attach the switch to the Flora. I wanted a connection that didn't require soldering as I had already sewn the Flora to the skirt at this point and didn't want to bring a hot soldering iron close to the fabric. I ended up crimping a couple of ring terminals to the switch connectors and sewing conductive thread onto the ring. I then stitched the switch in place with non-conductive thread.


Software

My software is based on the Adafruit sparkle skirt software, but has been enhanced to make it easy to add and remove different modes. I've published the source code on GitHub.

The skirt can perform a number of functions and switches between them when the button is pressed. The modes are:

  • Sparkle with movement. This is the original Adafruit code which flashes random pixels when motion is detected via the accelerometer.
  • Colour wheel cycle. The LEDs are mapped to equally spaced angles on a colour wheel. The colour wheel is then "rotated" through the LEDs so that each LED runs through the complete colour wheel in 3.6 seconds.
  • Fade in and twinkle. A random colour is picked and all LEDs fade from black to the colour. Once maximum intensity is reached, LEDs are randomly twinkled and then all LEDs fade to black.
  • Chaser. A random colour is chosen and all LEDs are turned on, one at a time, in sequence.
  • Sync to sound. Sound is sampled through the microphone and a Hartley transform is used break the input into frequency bands. Each frequency band is mapped to a colour and all LEDs are set to the colour corresponding to the frequency band with the highest level.
Some of the more interesting parts of the code are discussed below.

Modes

The code to change modes is shown below.

 void(*modes[]) () = { &sparkleWithMove,  
            &colorWheelCycle,  
            &fadeAndSparkle,  
            &chase,  
            &soundVisualisation };  

The mode array contains function pointers to each of the modes. The functions should be void returning methods that take no arguments. Functions can be added or removed from this array to change the skirt modes.

The variable changeMode should be checked periodically to see if the mode should exit. If this variable is 1, then the interrupt handler has detected a button press and the mode should return to the main loop which will switch to the next mode and clear the changeMode flag. A good place to check is during delays when the code is idle.

The DELAY macro can be used as a drop-in replacement of the delay() function. This splits the large delay into smaller delays and checks the changeMode flag. If a mode change is detected, then the macro will return out of the function.

Sound Visualisation

The sound visualisation code is interesting in its audio sampling. The analogRead() function is quite a slow way to take read a value, so the Analog to Digital Converter (ADC) is set to free-running mode where it continually takes readings. By sampling faster, the range of frequencies that the skirt can respond to is increased. The skirt seems to respond to frequencies of up to about 5kHz, which means, using Nyquist's theorem that we are sampling at around 10kHz. The following code sets the sampling to free-running mode by setting the AVR registers.

  ADCSRA = 0xe5; // set the adc to free running mode  
  ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((13 >> 3) & 0x01) << MUX5);  
  ADMUX = 0x40 | (13 & 0x7); // use adc13  
  DIDR2 = 0x10; // turn off the digital input for adc13
   

Note that the analog 10 pin to which the microphone is connected needs to be converted to the correct ADC number "under the hood". This can be found be referring to the Flora pinout diagram. We also disable the digital input on the analog input as recommended by Open Music Labs.

We take the required number of samples from the ADC pin. while we are taking samples, TIMER0 is disabled to reduce sampling jitter. We then check the ADCSRA register to check whether it's ready for a sample to be taken. Once the data is ready, we restart the ADC and get the high and low bits of the sample. We covert the 10 bit value to a signed number, as required for the transform, and then scale it up to a 16 bit value.

   TIMSK0 = 0; // turn off timer0 for lower jitter  
   for (int i = 0 ; i < FHT_N ; i++) {
    while(!(ADCSRA & 0x10)); // wait for adc to be ready  
    ADCSRA = 0xf5; // restart adc  
    byte m = ADCL; // fetch adc data  
    byte j = ADCH;  
    int k = (j << 8) | m; // form into an int  
    k -= 0x0200; // form into a signed int  
    k <<= 6; // form into a 16b signed int  
    fht_input[i] = k; // put real data into bins  
   }  
   TIMSK0 = 1; // turn on timer0 so we can use millis() again  
   

After sampling, we perform a Fast Hartley Transform to covert the signal into frequencies. I set up the conversion to give 8 frequency bins, each covering an octave. This needs to be set up at the beginning of the sketch, before the FHT.h library is included.

 // FHT configuration for sound visualisation  
 #define OCTAVE 1  // Group buckets into octaves  
 #define OCT_NORM 0 // Don't normalise octave intensities by number of bins

We use the FHT functions to process the sample data. As we are using octave outputs, we have 8 outputs to process. We check to see which octave has the highest intensity and set all LEDs to the colour that corresponds to the octave.

   fht_window();  
   fht_reorder();  
   fht_run();  
   fht_mag_octave();  
     
   int index = 0;    
   int mx = fht_oct_out[0];  
   for (int i = 1; i < 8; i++) {  
    if (fht_oct_out[i] > mx) {  
     index = i;  
     mx = fht_oct_out[i];  
    }  
   }  
     
   int r = fhtColors[index][0];  
   int g = fhtColors[index][1];  
   int b = fhtColors[index][2];  
     
   for (int i = 0; i < numPixels; i++) {  
    strip.setPixelColor(i, r, g, b);  
   }  
     
   strip.show();  
   

Further Work

There are a couple of things that I'd like to improve with this project. Firstly, there's always room for more or improved modes, especially when responding to sound. Trying some sort of beat detection is an obvious next step.

Whilst I like the mode switch, I think I'l like to try a capacitive touch sensor instead of a hard plastic button. I could then set to a touch sensor breakout with some conductive fabric to create a soft button.

Sunday, 13 October 2013

Displaying large text on LCD displays

EDIT: The constructor has changed since v1.0.0 of the BigCrystal library. See my subsequent post for details.

I have been playing around with a 20x4 character LCD display on an Arduino and discovered that it's possible to use custom characters to display large text. I wasn't that happy with the code that I saw, so I decided to write a library to make large characters easy to use.

This approach works by using the custom character functionality on Hitachi HD44780 compatible displays. There are eight characters that can be programmed to display any combination of pixels on a 5x7 matrix. Characters in adjacent positions can "tile" together these special characters to make double height characters.

Code Development

The original code on which the library is based was initially posted on a thread in the Arduino forums, and further documented in an instructable. Michael Pilcher created the original fonts and code, and this was further refined by "Mark S" that encoded the font data in arrays stored in the Arduino's program memory. These guys did all of the hard work, I've just repackaged it all to make it a bit easier.

I've enhanced the code in a number of ways. Firstly, I've changed the storage of fonts to save about 60 bytes of program memory. I did this by creating separate arrays based on character width to reduce the "placeholder" entries in the original array for characters wider than the standard three characters.

I've also added some symbols that were not present in the original code. I've added parentheses, colon, quotation marks, semicolon, plus, minus and a few others. I've also made characters slimmer than the standard three character width for symbols where it makes sense. For example: the colon, semicolon, comma and full stop are one character wide, whilst parentheses and the minus sign are two characters wide.

Most importantly, I've created two libraries to make large characters easy to use in your sketches. They are BigCrystal, for LCDs hooked up directly to an Arduino and BigCrystalTWI for LCDs that are connected using a Two Wire Interface (i.e. I2C). These libraries extend the standard Arduino LiquidCrystal library and the LiquidTWI library respectively.

Usage

As the BigCrystal libraries extended existing libraries, and add three methods:

  • writeBig to write a single large character;
  • printBig to print a string of large characters; and
  • widthBig to determine the width of a single character
A simple example using the BigCrystal library is shown below:

 #include <BigCrystal.h>  
 #include <LiquidCrystal.h>
  
 // Set up according to your LCD pins  
 BigCrystal lcd(22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);  

 void setup() {  
  lcd.begin(20, 4);  
  lcd.printBig("10:22", 0, 0);  
 }  

 void loop() {  
 }  

The same example, using the BigCrystalTWI is:

 #include <Wire.h>  
 #include <LiquidTWI.h>  
 #include <BigCrystalTWI.h>  

 // Set up according to your LCD pins  
 BigCrystalTWI lcd(0);  

 void setup() {  
  lcd.begin(20, 4);  
  lcd.printBig("10:22", 0, 0);  
 }  

 void loop() {  
 }  


Further Work

I've had to duplicate much of the code between the two libraries. I had considered splitting out the common functions into a separate library, but this would mean that users would have to import two libraries into their Arduino IDE instead of one, so I went for ease of use. The libraries are pretty small and I'll just have to be conscientious and make changes to both libraries when I'm fixing bugs or adding features.

There is a non-standard LiquidCrystal library from Adafruit that can use SPI communication. To use SPI, the default LiquidCrystal library needs to be replaced with this non-standard version. I haven't adapted Adafruit's library for large characters.

Testing

I have done my testing on the the BigCrystal library, however, I no longer have access to an I2C backpack and so haven't tested the BigCrystalTWI library. Everything compiles and I'm confident that it will work. I'd appreciate it if somebody with compatible hardware can try it out and report back.

Saturday, 5 October 2013

Storing Arduino Ethernet Configuration in EEPROM

One of the interesting things about using Ethernet with the Arduino is that you need to set up the hardware address manually. This address (known as the MAC address) is a six byte number that uniquely identifies a device on a network. Usually, network adapters have a hardware assigned MAC which can't be changed, but on the Arduino, it has to be set in software.

Setting the MAC in the software becomes a problem if you want to upload a sketch to multiple Arduinos on the same network. You need to remember to tailor each sketch so that each device has a unique MAC address. Forgetting to do this, or incorrectly duplicating a MAC can cause issues, such as not being able to connect to one or more Arduinos.

One common solution is to store the MAC address in the Arduino's EEPROM, an area of memory that survives after the Arduino has been reset. There are a number of libraries and tutorials around that do this, such as the ones from z900collector, Mitchnicegear and blackcatm. I found that they didn't go far enough, as I also wanted to store the IP configuration in EEPROM as well as the MAC.

Storing both MAC and IP configuration means that the network configuration is independent of the loaded sketch. After initial setup, each Arduino will have its network configuration tied to the hardware, rather than the software. Subsequently, any number of ethernet enabled sketches can be loaded, and as long as they all use the NetEEPROM library, the MAC address and network configuration will remain the same for each sketch on the same hardware.

I've written the NetEEPROM library that stores to EEPROM:
  • a MAC address; and
  • whether DHCP or manual IP configuration is used; and
  • if manual IP configuration is used, the IP address, DNS server address, gateway address and subnet mask.
In addition, there are functions and examples to set the MAC address and network configuration for both DHCP and manual IP configurations.

Initialising the Ethernet adapter to use the stored configuration is simple, it's just requires one line in the setup() function:

NetEeprom.begin();

If there is no network configuration stored in EEPROM and NetEeprom.begin() is called, then the network adapter is set up with a random MAC address and will use DHCP for IP configuration. The randomised configuration is saved to EEPROM so that the same MAC will be used the next time.

I've released the NetEEPROM library on github and entered it into the public domain in the hope that someone will find it useful.


Wednesday, 25 September 2013

Web Controlled Garage Door


A few months ago, I decided to learn a bit more about electronics and I stared to do this by looking at the Arduino platform. There are a lot of learning resources, and as a programmer in my day job, the transition to programming on the Arduino platform was quite easy.

The first practical project that I put together was a web interface to control my garage door. I did this so that I wouldn't have to carry a garage door opener when riding my bike. As I always have my phone on me, it's one less thing to carry.

Garage door motor



I opened up the garage door opener and after some poking around with a multimeter, found two pins that had a potential difference of 35V which when shorted together activated the motor. Those were pins 1 and 3 on the header, highlighted in the photo below.



Relay

I needed a relay to connect the pins on the garage door motor when I wanted to open or close the garage door on the Arduino. I picked up a TRR1A05D00 relay and wrote the initial code to make the door open. I later found out that I needed to put a diode across the input of the relay to suppress voltage spikes when turning the relay off. I got myself a few 1N4004s and put one across the relay.

Sensors

One problem with the initial circuit was that I could only toggle the garage door motor with the relay. If the door was closed, I could open it and if the door was open, I could close it. However, I couldn't tell whether the door was open or closed.

I tried out some A3144 Hall Effect Sensors. These detect a nearby magnetic field and by using a couple of them with some rare earth magnets attached to the door, I was able to detect the door position.

These sensors require three connections, ground, power and output. The output pin goes low when there is a magnetic field detected, and remans high if no field is detected.

Status Indicators

The sensors worked well, but during testing, I thought that it would be nice to have a status indicator so that I could easily tell whether the sensors were sensing the magnets. I had just bough a bunch of RGB LEDs which were perfect. I could use a different colour for the door open, closed and in-between.

Putting it All Together

I decided on the EtherTen from Freetronics. This board combines an Arduino Uno with an Ethernet shield, allowing me to hook up the board to my local network. I used the ProtoShield Short as the prototype board to connect my components. It works well with the EtherTen as it is (as the name implies) shorter than standard Arduino shields, leaving enough room for the Ethernet connector.

We can make out a number of things from the photo below.



Firstly, the relay is connected to D2 of the relay, which is also connected to the negative end of the flyback diode. I put connected header pins to the relay output so I could attach the wires to go to the garage door motor.

Secondly, pins D5, D6 and D7 are connected through resistors to the red, green and blue leads of the LED. I used 150Ω for the red and 100Ω for green and blue to limit the current to 20mA per output.

Thirdly, I soldered on a couple of three three pin headers to connect to the hall effect sensors which were mounted near the garage door.

The EtherTen is cable tied in place around a conduit running on the ceiling of my garage. It could be neater, but this seems to do the trick for now. In the photo below, the LED is blue, indicating that the door is in the open position.



The sensors are just taped in place on the garage door frame. You can see one of the magnets on the door next to the lower sensor.



Finally, a photo of everything together. In it, you can see the EtherTen, and a wireless router attached to the ceiling. Also note the Ethernet over power adapter that connects back to the home network. You can also see the cabling; the green and white cables for the garage door motor and the ribbon cable for the sensors.



Software

The Arduino sketch is available on github and is is released into the public domain. Apart from the standard Arduino libraries, the sketch requires the Webduino library which handles the web serving.

The server responds to both HTTP GETs and POSTs to control the URL. In both cases, a parameter of named "action" needs to be set to either "open" or "close" to operate the door.

The page has a touch icon, served from the /icon.png path. This icon is used for iPhones when the link is saved to the home screen. I have tried using different images for both the favicon and the iOS icon, however, I've run into issues uploading to code the Arduino and compiler problems when the encoded image data gets larger than about 1.1kb.

The software I'm running on my Arduino is slightly different to what I've posted on github. I can't release the graphics for my icons, I drew up a simple favion an iOS icon for the released code.

I also read my network configuration from the Arduino's EEPROM, using a library that I wrote. For the released code, I've gone back to configuring the network settings in the code. I'll talk about that library in a future post.