LCD on a hat

In this project we will be creating a wearable hat that will display text based on information sent to it by your phone. We will be using the Adafruit’s Flora microprocessor board, along with a breakout board with a low-powered LCD on it and a low energy Bluetooth board.

What is a microcontroller, anyway?

A microcontroller is nothing more than a very small, low powered computer on a chip. They are generally small enough to run off no more than the USB power from your laptop, or a few triple-A batteries. They tend to have very little processing power, with clock speeds measuring in the megahertz. Because of their simple instruction set and lower power consumption, they are very useful in applications where something needs be constantly running, whether on wall power or batteries.

Microcontrollers deal with their relative lack of power in several ways. The first is that in general microcontrollers never run an operating system. Code is run directly on the hardware, and only one program at a time is running, giving it complete control over system memory. Because of the need for complete control, microcontroller software is written in C/C++, ensuring that every byte of memory is accounted for, as most microcontrollers only have a few KB of memory. Even though the microcontrollers lack the power of modern day computers or even your phone, because of their durability, versatility, and affordability (around $20 for a whole board), they are frequently used in DIY electronics and art projects.

Most hobbyists don’t use microcontrollers directly. Instead, microcontrollers are generally mounted on printed circuit boards, which make it easy to connect wires by plugging them in or soldering. They also generally have a USB port to allow the chips to be easily reprogrammed from a computer. All of these connections let us connect all sorts of fun devices to our microcontroller, including:

  • switches
  • buttons
  • LEDs
  • keypads
  • sensors (heat, accelerometer, etc)
  • LCD screens
  • And much much more more…

What about Wearables?

Wearables have become much more of a trend among arduino enthusiasts with the advent of the modern commercial wearables. In particular, it has become easier and easier to build wearable gadgets, with companies such as Adafruit selling both sewable conductive thread and programmable LED sequins.

Introducing, the Flora!

The Flora is an arduino compatible microcontroller board specifically designed for use in wearables. The first thing to notice about the flora is that rather then using socket headers, which are great for inserting stiff solid-core wire or jumper wires, it provides fat connection plates spaced wide around the board. These connections aren’t very useful for wires, but are excellent for both alligator clips and conductive thread.

Conductive thread is thread that is generally made of steel, and which can be used to stitch traces between components into clothing. There are multiple design features of the Flora that make it easier to use conductive thread with it. The wide spacing on the plates on the flora make it easy to wrap conductive thread around them and tie it off, while avoiding shorting the connectors together. In addition, there are both 3.3V outputs and grounds interspersed throughout the board, meaning that you don’t have to cross over other threads to get power. This is important because the threads themselves don’t have insulation, so cross-overs are basically difficult to impossible.

You’ll also notice one more subtle feature of the Flora that makes it great to use in wearable products, which is that there are no wires poking out the bottom. Even if you’ve never dealt with microcontrollers, you may have seen other printed circuit boards with pokey bits from soldered on chips sticking out the backside. There are reasons why chips are normally manufactured this way, but with the Flora, Adafruit avoided that to prevent it from snagging on clothing or your skin.

Get the Arduino IDE

The use of microcontrollers really took off with the Arduino, which packaged the programming environment and the board in an inexpensive package. We will be using a different board, but it is still based on the same chip and architecture used by Arduino. This also means we can use the same programming environment as well.

You should download the Arduino IDE at https://www.arduino.cc/en/Main/Software, or you can grab one of our USB keys preloaded with it. Installing the IDE should be as simple as unpacking the zip file in which it is packaged and running the program.

Install the Flora drivers

Before we can write or hello world program for the Flora, we first need drivers to upload code to the board. The newest versions of the Arduino IDE make it super easy to install drivers for new devices. In order to do this, you should find the preferences menu (Under “Arduino” on OS X, and “File” for Windows/Linux). Once in the preferences menu, add https://adafruit.github.io/arduino-board-index/package_adafruit_index.json to Additional Boards Manager URLs. Adding the Adafruit boards source

Once that is done go to Tools -> Board -> Boards Manager, and search for “adafruit”. You should see an entry for “Adafruit AVR boards”. Click on it and install it. Adding the Adafruit boards

Once that is done, close and reopen the Arduino IDE, and you’re ready to start hooking things up.

A basic test project

Our very first hello world will be to make the LED light on the Flora flash on and off. In order to do this, we’re going to create a new “sketch” (basically another name for “program”) in the arduino IDE. If there isn’t already a window open to start coding in, just go to file -> new, and then save your sketch as “blinker”. Once that is done, edit the code to look like the following.

   
void setup() {
  // put your setup code here, to run once:
}

//LED is always pin 7 on the Flora
#define LED 7

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("Hello, World!");
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);               // wait for 500 milliseconds
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(500);               // wait for 500 milliseconds
}

As you’ll see, the arduino environment wants us to implement two functions. The first, setup, is run once when the microcontroller boots up. The second, loop, is run continuously. You can think of it a little like having the following C main function:

int main(void) {
    setup();
    while (true) {
        loop();
    }
}

There are a couple of interesting things to note here. The first is that we simply use the number “7” to represent the LED itself. On the Flora, each connection to the chip is given a number, with different numbers representing different pins. In this case, the number 7 doesn’t represent an external connection, but a pin that is hardwired onto the board as going to the LED. If you look closely at the board, some of the conectors are labeled with numbers such as ‘D6’. In general, these numbers correspond to the number that represents the connector in the programming environment.

The next thing to note is that there are some built in classes and commands in our environment that are useful. The first thing we do in our loop is print “Hello, World!”, on the Serial line. This Serial class corresponds to the serial connection back to the computer when the USB connector is plugged in. You can send any bytes you want to over this connection, but here we are simply sending the bytes corresponding to the string “Hello, World!” You can view the Serial output of the board by going to Tools -> Serial Monitor.

The next builtin function is the digitalWrite function. this function outputs either a high voltage (ON/1/true) or a low voltage (OFF/0/false) on a pin. In this case high/low corresponds to whether the on-board LED should be on or not.

The final useful built-in is the delay function. This simply pauses the code execution for the specified number of milliseconds.

Running the code

Now that we understand what the code should do, we should try running it and seeing if it behaves as expected. The first order of business is to plug a micro-USB cable into your Flora. There should be a green LED that turns on. It is also possible that there is a program pre-loaded onto the Flora that causes the red LED to blink. This is normal.

Once the Flora is connected to the computer, we will need to actually perform the code upload. In the Arduino IDE, go to Tools -> Port, and look for the port that mentions the “Adafruit Flora”. It should probably also be the one that makes a reference to ‘USB’ in the name. Once that port is selected, click the Arrow button to upload the code to the Flora. Your computer should compile for a while, and after a pause, the Flora should start running the program.

Setting the right port

Let’s do some color

The Flora doesn’t only have an onboard LED. It also has a full color NeoPixel, which is a collection of LEDs that can display any level of brightness and any color. As you can imagine, you can do much more exciting things with color and brighness than with just an on/off LED. We’re going to do some fading of colors.

The first order of business is to install the relevant library to use the NeoPixel. To do this, simply go to sketch -> Include Library -> Manage Libraries and search for and install the Adafruit NeoPixel library. Once that is done, we’re going to start with porting our blinking code to the NeoPixel.

Getting the NeoPixel library

Type the following code into the arduino IDE, either in a new sketch or in the current one where you wrote the original blinking code.

#include <Adafruit_NeoPixel.h>

// The NeoPixel is on Pin 8 on the Flora
#define PIN 8

// The first parameter represents the number of Neopixels, the second is the pin.
// The third is the format of the data we send it.
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  // put your setup code here, to run once:
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  // put your main code here, to run repeatedly:

  //These color values are in RGB, and can go up to 255, but that's way to bright.
  strip.setPixelColor(0, strip.Color(50, 50, 50));
  strip.show();
  delay(500);               // wait for 500 ms
  strip.setPixelColor(0, strip.Color(0, 0, 0));
  strip.show();
  delay(500);               // wait for 500 ms
}

You’ll notice that in this case, we have an actual object, on which we can call methods such as setPixelColor and show, rather than simply writing to a number that represented a particular pin. In this case, the NeoPixel library is hiding all of those details away from us. If you run this code you’ll see the NeoPixel blinking. It’s much brighter than the previous LED, to the point where it’s painful to look at. In this case we only use a brightness value of 50 for each color instead of 255.

But of course, just blinking is boring, so lets add some transitions. Add the following before your loop function:

int red = 50; // Set this to 255 for full strength.
int green = 0; 
int blue = 0;
void displayColors() {
  strip.setPixelColor(0, strip.Color(red, green, blue));
  strip.show();
}

This creates global variables to hold the current color, and the displayColors function just displays the color represented by those global variables.

Now, change your loop function to match the following:

void loop() {
  while (red > 0) {
    displayColors();
    red--;
    green++;
    delay(100);
  }
  while (green > 0) {
    displayColors();
    green--;
    blue++;
    delay(100);
  }
  while (blue > 0) {
    displayColors();
    blue--;
    red++;
    delay(100);
  }
}

This updates the colors evert 100ms so that each color fades out to the next one. Now, when you upload the sketch, you should see a light that slowly changes color between red, green, and blue. Take some time and tamper with the pixel color settings in any way you like.

Our other components

For this project we will also be using two other components. The first is a Bluetooth Low Energy module, which is meant to be used in wearables. You’ll notice that it has a similar design profile to the Flora, and in particular, when we get to wiring it, you’ll see that the connection plates match up nicely with the Flora, again avoiding those annoying crossovers.

The other component we will be using is a 1.44 inch low-power LCD screen. This screen was not originally setup for wearable use, so we will be creating metal loops that we can then spread apart to interface with our conductive thread. In addition, we’ve already pre-soldered a header onto the board so that you can stick wires in without having to solder all your wires on.

Loop making

Now it’s time for some actual hardware wiring. As I mentioned earlier, the breakout board for the LCD screen does not have wearable friendly wires for it, so we’re going to have to make some. This will entail stripping solid core wire, bending it into a hoop, and sealing it into a loop using crimping beads. You’ll need 7 wires total, and we have 6 colors of wire, so I recommend picking one that will be your extra.

Step 1: Strip the wire

Use the largest hole on the wire strippers to pull off about an inch of insulation on one end of the wire for the loop, and a quarter inch on the other end to go into the header socket.

Step 2: bend the wire into a loop

Use the pliers to bend the wire into a loop, first bending out, then bending gently in each place along the wire to get a clean loop.

step 3: Add crimping bead and crimp.

Thread the crimping bead onto the other end of the wire and over the end of the loop, then smash it down with your pliers.

Connections to be made (LCD)

Now we get to the actual connections to be made with the LCD. For the finished product we would like to use thread, but that is hard to test on a table since there is nothing stopping the thread from sliding together and shorting the connection. Therefore, we will be using alligator clips for testing, and only sewing into a hat after all the connections are figured out.

First plug all of your wires into the LCD board. You’ll want a red wire to Vin, and a black wire to ground (that’s electronics convention), and wires to SCK, SI, TCS, RST, and DC. Note that red goes to the Vin and black goes to ground. This is wiring convention, but you don’t strictly have to follow it.

Next, disconnect your Flora from power and alligator clip the wires on the board to the following plates on your Flora

Vin -> 3.3V Gnd -> Gnd SCK -> SCL SI -> D10 TCS -> D9 RST -> D6 DC -> D12

When you reconnect your Flora to your laptop, the LCD should be backlit with nothing displayed on it.

Graphics library + example program.

We’ll need to download another library to use the display device. Go to Sketch -> Include Library -> Manage Libraries and search for ‘ST7735’, then add the Adafruit ST7735 library. After that, search again, this time for Adafruit GFX Library and install it as well.

Next we’re going to develop from an example: Go to File-> Examples, and select the ‘graphicstest’ example under ‘Adafruit ST7735 library’. Once you load it, you should immediately save. The arduino IDE will then prompt you to pick a new save location so that you can make the example your own.

Getting the graphicstest example

Slight modifications

The pins we’re planning on using don’t match up with the sample programs’ pins, so we’re going to need to modfy them. Change the define statements at the top of the file to match the following

// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS     9
#define TFT_RST    6  // you can also connect this to the Arduino reset
                      // in which case, set this #define pin to 0!
#define TFT_DC     12

We’re also going to be using software SPI instead of hardware SPI, so we’ll need to comment the uncommented line under “Option 1”, and uncomment the line under Option 2. In addition, we’ll want to modify the define directives to match up with the pins you have chosen. All-in-all, it should look like this:

// Option 1 (recommended): must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 3   // set these to be whatever pins you like!
#define TFT_MOSI 10   // set these to be whatever pins you like!
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

Now, try uploaded the script. If all went well, you should see some patterns and some text. Things will be fairly slow because we’re using software SPI instead of hardware API, but the whole set of graphics shouldn’t take more than a couple minutes to run.

Connections to be made (BLE device)

Luckily our bluetooth device is made to work perfectly with the RX/TX ports on the Flora. Simply wire Gnd to Gnd, 3.3V to 3.3V, and RX to TX and vice versa (because one device transmits on a port while the other recieves on it.

Bluetooth libraries + program

These libraries can also be installed using the library manager. Simply look for Adafruit BluefruitLE nRF51 library and install it. We will again be basing our code off of an example, but in this case it will be based off of the Adafruit BlueFruitLE nRF51 -> bleuart_datamode example.

When you load up this example you’ll notice that there are a couple files. Much of the configuration for the board lives in BlueFruitConfig.h. The main two items you’ll want to change are to change the value of BLUEFRUIT_UART_MODE_PIN to -1 since we don’t use it at all (you’ll note that we didn’t wire up the mode plate on the bluetooth chip), and to also remove the ifdef around #define BLUEFRUIT_HWSERIAL_NAME Serial1. The other pin settings should be correct if you wired the module using the instructions above.

Once those changes are done, you should be able to upload the sketch to the Flora. Unfortunately, Bluetooth libraries aren’t very useful without someone to bluetooth with.

Bluefruit app

The easiest way to interface with the Bluetooth LE device is to use the Adafruit Bluefruit app. It is available for iOS and android, and it’s fairly small, so download it from your App store of choice now.

Once the app is downloaded, open it and connect to the ‘Adafruit Flora BLE’ device. Your device name should have a unique number next to it and should be the strongest signal, so make sure you always connect to that one so there is no crosstalk between bluetooth devices. When you connect, you should pick the “UART” connection mode.

Once you have done that, you should also open the Serial Monitor (Tools -> Serial Monitor). You should see a message about “Switching to DATA mode!” If you see that, then you can start typing in the text field in your phone, and the characters you type should show up in the Serial Monitor on your computer.

Display text sent from Adafruit App

Now that we know both of our components work individually, we’re going to do the real programming for this project, which is combining our individual code lego peices into a more powerful whole.

We’re going to interleave the chunks of each of our previous sketches, and remove some of the pointless demo cruft that existed in them previously. Either open a new sketch in the Arduino IDE or blank out an existing one. This is going to be fun.

First we need to combine all the header imports so we know that we have all the functions and variables we need. Grab the headers from both the graphics and the bluetooth demo applications and put them at the top of your sketch. You should get something like the following:

#include <Arduino.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_)
  #include <SoftwareSerial.h>
#endif
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"

Next we have the initialization for the graphics display:

// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS     10
#define TFT_RST    9  // you can also connect this to the Arduino reset
                      // in which case, set this #define pin to 0!
#define TFT_DC     3

// Option 1 (recommended): must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 12   // set these to be whatever pins you like!
#define TFT_MOSI 6   // set these to be whatever pins you like!
Adafruit_ST7735 tft = 
    Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

And initialization for the bluetooth:

// COMMON SETTINGS
// ----------------------------------------------------------------------
// These settings are used in both SW UART, HW UART and SPI mode
// ----------------------------------------------------------------------
#define BUFSIZE                        128   // Size of the read buffer
#define VERBOSE_MODE                   true  // Enables debug output

#define BLUEFRUIT_HWSERIAL_NAME      Serial1
#define BLUEFRUIT_UART_MODE_PIN        -1    // Set to -1 if unused
/* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */
Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN);

And we have a setup function for the BlueFruit to be called from the main setup function. This is basically copied and pasted from the setup method of the Adafruit Bluetooth example:

// A small helper
void error(const __FlashStringHelper*err) {
  Serial.println(err);
  while (1);
}

void setupBluefruit(void)
{
  while (!Serial);  // required for Flora & Micro
  delay(500);

  Serial.println(F("Adafruit Bluefruit Command <-> Data Mode Example"));
  Serial.println(F("------------------------------------------------"));

  /* Initialise the module */
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  Serial.println( F("OK!") );

  /* Disable command echo from Bluefruit */
  ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  /* Print Bluefruit information */
  ble.info();

  ble.verbose(false);  // debug info is a little annoying after this point!

  /* Wait for connection */
  while (! ble.isConnected()) {
      delay(500);
  }

  Serial.println(F("******************************"));

  // Set module to DATA mode
  Serial.println( F("Switching to DATA mode!") );
  ble.setMode(BLUEFRUIT_MODE_DATA);

  Serial.println(F("******************************"));
}

And now we add the setup code from the graphics example. In this case, however, we can leave out a lot of the extra code that renders cool patterns, since we don’t need them. We’ll leave in the code that renders Lorem ipsum though, so we know when everything has initialized.

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void setupScreen(void) {
  Serial.begin(115200);
  Serial.print("Hello! ST7735 TFT Test");

  // Use this initializer (uncomment) if you're using a 1.44" TFT
  tft.initR(INITR_144GREENTAB);   // initialize a ST7735S chip, black tab

  Serial.println("Initialized");

  uint16_t time = millis();
  tft.fillScreen(ST7735_GREEN);
  time = millis() - time;

  // large block of text
  tft.fillScreen(ST7735_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST7735_WHITE);
}

Finally we get to the meat of the program, which is printing on the screen. This setup routine will set our screen to have a black background and white text. The loop routine will simply loop checking for data over blootooth, and if it sees it, will print it on the screen.

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  Serial.begin(9600);
  Serial.print("Hello! ST7735 TFT Test\n");  
  setupScreen();
  setupBluefruit();
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextWrap(true);
}
 
// the loop routine runs over and over again forever:
void loop() {
    // Check for user input
  char n, data[BUFSIZE+1];
  int index = 0;
  // Echo received data
  while ( ble.available() )
  {
    data[index] = ble.read();
    index++;
  }
  data[index] = '\0';
  tft.print(data);
}

Other expansion options

Congratulations! You’ve completed all the coding and prototyping for this project. There are lots of ways to expand this project. You can use any of the data that the Adafruit app passes along to display on your screen, or you can fork the Adafruit app on github and modify it to send phone sensor data, API results, or anything else along.

Sewing to the hat

Now that you have a working electrical circuit, you can turn it into a wearable. The next goal is to emulate that circuit with conductive thread. In order to do this, you’ll need to place the screen on the front of the hat, and the flora positioned on the side of the hat. Then, for each wire from the original prototype, thread the wire through the wire hoop we created earlier, and stitch over to the corresponding plate on the Flora. Next, wrap the thread at least three times around both the hoop and the plate, and then tie it off and cut off any remaining loose thread.

After you stitch each thread, test the circuitry by running your program. That way you’ll know which thread, if any, is problematic. Once all the thread is stitched and all the boards are attached, you can use a battery pack to power the devices for portability.

Congratulations on your hack! if you want more ideas, Adafruit has tons of good example projects as well as documentation for how to implement them. Just go to https://learn.adafruit.com/ to learn more about different wearable and other microcontroller products.