LED Helmet

by on September 3, 2013 at 7:18 pm | 0 comments.


Last week I posted the following video

I had a lot of good feedback and, as promised, I said I’d write an article on how I did it. I had to ensure I knew what I was getting into before I went and bought all the components and so I had to start with a prototyping on a breadboard with simple components.

Prototyping

Dot Matrix Prototyping

Dot Matrix Prototyping

I originally tried to power the display by using 8 outputs from the PIC and a PCF8574 to act as 8 switches to ground. However since the PIC could not supply enough current (and I didn’t want to use 8 transistors per display), I decided instead to use the MAX7221.

Using some dot matrix displays I had lying around I built a circuit that involved the MAX7221 chip and my PIC18F4580. The PIC connects to the MAX7221 via the SPI protocol and allows you to control the output of eight columns of eight LEDs.

The MAX7221 was designed to allow eight 7-segment displays to be controlled from a single SPI interface. Since 7-segment displays also have a decimal point, this allowed for eight outputs per digit. I wired it up so that each column would be controlled as each digit and each LED would be controlled as each segment (per the datasheet).

MAX7221 Circuit Diagram

MAX7221 Circuit Diagram

Once I had wired up one of the displays I could connect more MAX7221s and some more dot matrix displays.

Visor Display Prototyping

Visor Display Prototyping

In the image above I wrote a simple script that chooses a random number between 1 and 8 for each column and lights up that many rows, giving the effect of a vu metre once the numbers change quickly enough.

Writing Words

So now that I had a working dot matrix display, I then need to create some words which could scroll across the displays. Since I was sending data to the MAX7221s as 8 columns of data, I needed to make arrays for each letter that would act as each column (assuming every letter used a 5×7 matrix). Once I had created these arrays I then need to do calculate the following and link them all into an equation:

  • Calculate the total number of columns based on how many displays were connected.
  • Calculate how many columns would be needed for the defined string that was going to be displayed.
    • 1 column of empty pixels needed to be added between each letter.
    • Extra columns needed to be added to the start and end of the string so that it would appear from the right and scroll all the way to the left.
    • Several loops then needed to be created for each display.
      • A window would then be created which would scroll along the columns that create the string and be displayed using the MAX7221s.

Confused? So was I, it took a lot of planning and mistakes to finally create a system that worked.

Calculations

Calculations

Below is the code that I used for the scrolling message function, hopefully this makes a bit more sense than my diagrams and explanation.

void scroll_string(char showMessage[50], int scroll){

	//The variables haven’t been included in order to save space
	//This is the number of columns in the message
	messageLength = ((strlen(showMessage)*5)+(strlen(showMessage)-1))-1; 
	//This is the number of columns to be displayed - includes the blanks at the start and end	
	displayLength = messageLength+(displays*8*2); 
	//This is the amount of the message to be displayed at any one time
	windowLength = displays*8;

	for(i=0;i<=displayLength;i++){ //Loop through the entire display set (message+blanks)

		for(k=0;k<windowLength;k++){ //Used to loop through the display window	

			displayColumn = j+k; //This is the column of the message we are currently looking at 
			currentColumn = displayColumn%6; //Current column of current letter: 0 to 5 where 5 is a column of 0x00
			currentLetter = (displayColumn-currentColumn)/6; //Current letter of string: 0 to 2 for 3 letter string
			totalLetters = (messageLength+2)/6;
			j=i-(8*displays); //This is the current column of the message (ignoring blanks)
			//Otherwise return the part of the letter to show
			display = parse_chars(showMessage[currentLetter]);

			if((i+k<windowLength) || (currentLetter>=totalLetters) || (currentColumn==5)){
				send = 0x00;
			}else{
				send = Chars[display][currentColumn],currentDisplay;
			}
			l = k%8;
			currentDisplay = ((k-l)/8)+1;
			max7221_put(l+1,send,currentDisplay);
		}
		//Add a delay so that it scrolls
		delay_ms(scroll);			
	}
}

And after hours of calculations and coding, I finally managed to get a display that worked.

Soldering

So now that I knew it was all possible, I then had the huge task of soldering together sets of 64 LEDs (as many as I could fit onto the visor of the helmet I bought).

My Motorbike Helmet

My Motorbike Helmet

Since LEDs also have a positive and negative leg, there had to be a way of joining rows and columns without the legs touching. To do this I ensured the LEDs were bent in 2 directions (horizontally and vertically) and on two levels.

I used an old package as a jig and began bending the legs of these LEDs

LED Jig

LED Jig

LEDs

LEDs

You can see how the LEDs would fit as a grid and how the anodes and cathodes wouldn’t overlap in the picture below

Once I had enough I could then go about soldering them into columns
LED Column Jig

LED Column Jig

Loads of Columns of LEDs

Loads of Columns of LEDs

I could then finally solder the columns into 8×8 arrays to create each display. As you can see in the image below, I had to use a cup to ensure the LEDs would press into the grid as far as they could.

8x8 Display Jig

8×8 Display Jig

To hold the LEDs in place I had some thin acrylic laser cut into a grid of holes that was then bent by heating with a hot air gun.

LED Display

LED Display

Visor Displays

Visor Displays

You can also see where the wires were soldered on at the ends of each row and column.

This is two of the displays working correctly. Each time a new display was added to the grid and wired up there was a lot of error checking involved to ensure none of the LEDs were short circuiting.

Insides

Once I had the visor sorted I then needed to consider the insides of the helmet. How would I see? How would I know what the visor was displaying? Was there any other information I could add?

I started by soldering up a 4-digit 7-segment display module. This would be controlled by a PIC which would communicate with the visor PIC via an RS232 interface. This was the easier communication method since I could just send 4 digits which would then be displayed on the module. The reason I used a separate microcontroller was because the module needed constant data being sent to it. I didn’t use another MAX7221 as using a PIC allowed me to better customize how the module would work.

4-Digit Module

4-Digit Module

In the picture above you can see a 5 pin header. I ensured every microcontroller could still be accessed and programmed should I want to change my mind about the software later on.

Display Boards Being Soldered

Display Boards Being Soldered

I also decided to add a small LCD module to the inside of the helmet to display information that cannot be represented using just numbers.

The View From Inside

The View From Inside

You can see in the image above that it is close to impossible to see out through the LEDs. However you can see out through gap below the displays and it is possible to tilt your head to see straight without moving to a crazy angle.

Clock Module Inside

Clock Module Inside

Clock Module and LCD Display

Clock Module and LCD Display

I decided to use the clock module to display the current BPM that the helmet is running at and the LCD display to show what the visor was showing:

  • The type: pattern, text, display
  • The settings: VU Metre, Pacman, Stripes etc…

Once I’ve built the controller, the BPM display will be used to show the menu. I couldn’t use the LCD module because it takes too long to refresh which temporarily stops the visor. I could have used another PIC to control the LCD but I didn’t mind the set up as it was.

Inside

Inside

As you can see the inside is very messy and there are three wires leaving the central controller (red, black and purple). This is the power in for the whole helmet and serial in to control it.

What’s Left

At this stage I have several things left to do:

  • Add a battery with charging capabilities
  • Add wireless controls
  • Tidy up the software
  • Tidy the insides of the helmet, most likely with some fabric.

It has taken me about 7 months to get to this stage and so it could be several months more until the whole thing is complete. At which time I’ll post a finalised article including how I designed the wireless controller.