Showing posts with label DIGITAL. Show all posts
Showing posts with label DIGITAL. Show all posts

Moving Message Display On LCD

Friday, 28 June 2013
Moving Message Display On LCD
PROJECT IS DONE BY Mr SANI THEO

Moving-message displays are ideal to get your message (advertisements, greetings, etc) across in an eye-catching way. You can make an LCD show a brief moving message by interfacing it to a microcontroller.

Here’s an AVR-based moving-message display that uses a 16×2 LCD display incorporating HD44780. The 16×2 LCD can display 16 characters per line and there are two such lines.

Circuit description
Fig. 1 shows the circuit for AVR ATmega16-based moving-message display on an LCD. It consists of an ATmega16 microcontroller, a 16×2 LCD, an SPI6 connector and a power supply section.
 

Fig. 1: Circuit for AVR microcontroller-based moving-message display on the LCD
To derive the power supply for the circuit, 230V AC mains is stepped down by a 9V, 250mA secondary transformer, rectified by bridge rectifier module BR1A and filtered by capacitor C1. The voltage is regulated by a 7805 regulator. LED1 glows to indicate the presence of power in the circuit. The regulated 5V DC powers the entire circuit including SPI6 connector.

Port-C pins PC4 through PC7 of the microcontroller (IC2) are connected to data lines D4 through D7 of the LCD. The LCD control lines—read/write (R/W), register-select (RS) and enable (E)—are connected to PD6, PC2 and PC3 of IC2, respectively.

Why AVR microcontroller? AVR is faster and more powerful than 8051 microcontroller, yet reasonably cheaper and in-circuit programmable. Most AVR development software are free as these are Open Source. Moreover, discussions and tutorials on the AVR family of processors are available on the Internet.

ATmega16 is a high-performance, low-power 8-bit AVR microcontroller. It has 16 kB of in-system self-programmable flash, 1 kB of internal SRAM, 512 bytes of EEPROM, 32×8 general-purpose working registers and JTAG Interface (which supports programming of flash, EEPROM, fuse and lock bits).

Some of the on-chip peripheral features are:
1. Two 8-bit timers/counters with separate pre-scaler and compare modes
2. One 16-bit timer/counter with separate pre-scaler, comparator and capture modes
3. Four pulse-width-modulation channels
4. 8-channel, 10-bit analogue-to-digital converter
5. Byte-oriented two-wire serial interface
6. Programmable serial USART
7. Master/slave serial peripheral interface
8. Programmable watchdog timer with separate on-chip oscillator

LCD display module
The project uses a Hitachi HD44780-controlled LCD module. The HD44780 controller requires three control lines and four or eight input/output (I/O) lines for the data bus. The user may choose to operate the LCD with a 4-bit or 8-bit data bus. If a 4-bit data bus is used, the LCD will require a total of seven data lines—three lines for sending control signals to the LCD and four lines for the data bus. If an 8-bit data bus is used, the LCD will require a total of eleven data lines—three control lines and eight lines for the data bus.

The enable control line is used to tell the LCD that the microconroller is sending the data to it. To send data to the LCD, first make sure that the enable line is low (0). When other control lines are completely ready, make enable pin high and wait for the LCD to be ready. This time is mentioned in the datasheet and varies from LCD to LCD. To stop sending the data, bring the enable control low (0) again. Fig. 2 shows the timing diagram of LCD control lines for 4-bit data during write operation.

When the register-select line is low (0), the data is treated as a command or special instruction (such as clear screen and position cursor). When register-select is high (1), the text data being sent is displayed on the screen. For example, to display letter ‘L’ on the screen, register-select is set to high.

When the read/write control line is low, the information on the data bus is written to the LCD. When read/write is high, the program effectively queries (or reads) the LCD. This control command can be implemented using ‘C’ programming language.

For 4-bit interface data, only four bus lines (D4 through D7) are used for data transfer. Bus lines D0 through D3 are disabled. The data transfer between HD44780 and the microcontroller completes after the 4-bit data is transferred twice.

Fig. 2: Timing diagram of LCD control lines for 4-bit data during write operation

Controlling a standard numeric LCD is not that difficult. To display text on the LCD, correct library files for the LCD are needed. Many LCD libraries are available on the Internet, which are used in various applications. You may get confused which library is suitable for your application.

Libraries for LCDs found in AVRLIB library occupy unnecessary program memory space. To solve the problem, you can write your own library for LCD control.

Software program
This project demonstrates sending the text to the LCD controller and scrolling it across the LCD. For the project, AVR Studio 4 and WINAVR software need to be installed in your PC. Three program codes are used here—movm.c, lcd2.c and lcd2.h. The movm.c contains the text message to be scrolled on the LCD. lcd2.c and lcd2.h are the library files. The programming technique given here may not be the best as it uses a simple logic, but it works pretty fine.

The LCD library for 4-line or 4-bit mode operation is used here. Each pin connected to the LCD can be defined separately in the lcd2.h code. The LCD and AVR port configurations in the C code along with comments are given below:

#define LCD_RS_PORT LCD_PORT
LCD port for RS line
#define LCD_RS_PIN 2              
PORTC bit 2 for RS line
#define LCD_RW_PORT PORTD   
Port for RW line
#define LCD_RW_PIN  6            
PORTD bit 6 for RW line
#define LCD_E_PORT LCD_PORT 
LCD port for enable line
#define LCD_E_PIN 3                
PORTC bit 3 for enable line

Enable control line. The E control line is used to tell the LCD that the  instruction for sending the data on the data bus is ready to be executed. E must always be manipulated when communicating with the LCD. That is, before interacting with the LCD, E line is always made low. The following instructions toggle enable pin to initiate write operation:

/* toggle enable pin to initiate 
write * / 
static void toggle_e(void)  
{   
 lcd_e_high(); 
 lcd_e_delay();
 lcd_e_low(); 
}   

The complete subroutine of this code can be found in lcd2.c.

The E line must be left high for the time required by the LCD to get ready for receiving the data; it’s normally about 250 nanoseconds (check the datasheet for exact duration).

Busy status of the LCD. It takes some time for each instruction to be executed by the LCD. The delay varies depending on the frequency of the crystal attached to the oscillator input of the HD44780 as well as the instruction being executed.

While it is possible to write the code that waits for a specific amount of time to allow the LCD to execute instructions, this method of waiting is not very flexible. If the crystal frequency is changed, the software needs to be modified. Additionally, if the LCD itself is changed, the program might not work even if the new LCD is HD44780-compatible. The code needs to be modified accordingly.

The delay or waiting instruction can be implemented easily in C language.

In C programing, the delay is called using the delay( ) function. For instance, delay(16000) command gives a delay of 16 milliseconds.

Initialising the LCD. Before using the LCD, it must be initialised and configured. This is accomplished by sending a number of initialisation instructions to the LCD.

In WINAVR GCC programming given here, the first instruction defines the crystal frequency used in the circuit. This is followed by a standard header file for AVR device-specific I/O definitions and header file for incorporating program space string utilities. The initialisation steps in movm.c file are as follows:

#define F_CPU 16000000 
#include
#include
#include
#include “lcd2.h” 
#define RATE 250

Clearing the display. When the LCD is first initialised, the screen should automatically be cleared by the HD44780 controller. This helps to clear the screen of any unwanted text. Clearing the screen also ensures that the text being displayed on the LCD is the one intended for display. An LCD command exists in ‘Assembly’ to accomplish this function of clearing the screen. Not surprisingly, the AVR GCC function is flexible and easy to implement.

Refer the code given below:
lcd_init(LCD_DISP_ON);     
lcd_clrscr();                    

Here the first line is for LCD initialisation (turn on the LCD) with cursor ‘off.’ The second line clears the display routine to clear the LCD screen.

Writing text to the LCD. To write text to the LCD, the desired text is put in the memory using the char string[ ] function as follows:

char string[] PROGMEM=”WECOME TO
ELECTRONICS FOR YOU – NEW DELHI”;

The program makes this text scroll on the first line and then the second line of the LCD. The speed of scrolling the text on the LCD screen is defined by “# define RATE 250” in the beginning of the movm.c code. To start with, first the LCD screen is cleared and then the location of the first character to appear on the screen is defined. Getting the text from the program memory and then scrolling it on the LCD screen continuously is achieved using the following code:

while(j<=(len-1)) 
    {   
        lcd_clrscr(); 
        lcd_gotoxy(0,0);

        for(k=0,i=j;(k<16) && ( pgm_ 
        read_byte(&string[i])!=’\0’ 
        );k++,i++)  
        { 
          lcd_putc(pgm_read_ 
          byte(&string[i])); 
        }  

        WaitMs(RATE); 
        j++; 
    }  

Compiling and programming. Compiling the movm.c to generate the movm.hex code is simple. Open AVR Studio4 from the desktop and select new project from ‘Project’ menu option. Select AVR GCC option and enter the project name. Next, select ‘AVR Simulator’ and click ‘Ok’ button.

First, copy the three codes (movm.c, lcd2.c and lcd2.h) to your computer. Import the movm.c and lcd2.c files into ‘Source Files’ option on the left side of the screen. Next, import the lcd2.h file into ‘Header Files’ option. Select the device as ATmega16 and tick the box against ‘Create Hex’ option in the project configuration window. Now click ‘Rebuild All’ option in ‘Build’ menu. If the code is compiled without error, the movm.hex code is generated automatically under ‘Default’ folder of the project folder.

To burn the hex code into ATmega16, any standard programmer supporting ATmega16 device can be used. There are four different AVR programming modes:
1. In-system programming (ISP)
2. High-voltage programming
3. Joint test action group (JTAG) programming
4. Program and debug interface programming

Here two options for burning the hex code in standard ISP mode are explained. Some AVR tools that support ISP programming include STK600, STK500, AVRISP mkII, JTAGICE mkII and AVR Dragon. There are also many other AVR programming tools available in the market.

PonyProg2000 software. This software along with programmer circuit is available from www.lancos.com/prog.html website. After installing PonyProg2000, select the device family as AVR Micro and device type as ATmega16. Now in ‘Setup’ menu, select ‘SI Prog’ I/O option for serial programmer and COM port from ‘Interface Setup’ option. In ‘Security and Configuration Bits’ option, configure the bits as shown in Fig. 3. Next, open the device file (hex code) and click ‘Write All’ option to burn the chip.

Frontline TopView software. This software along with programmer board is available from www.frontline-electronics.com website. After installing the software, select COM port from ‘Settings’ menu. In ‘Device’ menu, select the device as ATmega16. Burn the hex code into the chip by clicking ‘Program’ option. Note that the microcontroller uses a 16MHz externally generated clock. Program the fuse bits in the software by selecting upper and lower bytes as follows:

Fuse low byte = EF
Fuse high byte = C9 
If the fuse bits are not configured properly, the text will scroll slowly or text scrolling may not function properly even if the scrolling rate in the code is changed. The SPI6 connector allows you to program the AVR using SPI adaptor in ISP mode.


Fig. 3: Screenshot of configuration and security bits option


Fig. 4: An actual-size, single-side PCB for the moving-message display on an LCD using AVR microcontroller

Click here to view/download a
n actual-size, single-side PCB for the moving-message display on an LCD using AVR microcontroller.


Fig. 5: Component layout for the PCB

Click here to view/download component layout for the PCB.

Construction and testing
An actual-size, single-side PCB for the moving-message display using AVR is shown in Fig. 4 and its component layout in Fig. 5. Before mounting the AVR onto the PCB, ensure proper power supply to the circuit. Program the AVR as mentioned above, insert it into the PCB and power-‘on’ the circuit. The text will scroll from right to left in the first line and then in the second line of the LCD, repeatedly. If there is any problem in the display, press reset switch S1 momentarily. If there is no message display at all, vary the contrast-control preset (VR1) until the text is visible on the LCD.
Read more ...

3D scanner

Friday, 28 June 2013
3D scanner
Prototype.
Simple but works well.
Digital camera with video recording function (resolution: 640x480, 30 frames/sec).
Laser pointer with special ending for linear beam (ending from laser level).
Phonograph as a rotational drive. Modified with low speed motor and Arduino.
Board and measuring tape.


How it works?
Digital camera placed in phonograph axes of rotational record laser light on objects surfaces (it works better in the darkness). Distortion of laser line corresponding to objects deformation derive from location of laser source. Very important is constant rotational speed and precise measurment (calibration).

Based on scheme and calibration value (a,b and c) we can calculate coordinates of every scanned point.


Software.
I wrote special python script for converting video direct to point cloud in Blendera 2.49b. Script require Python Image Library (PIL-1.1.7.win32-py2.6). PIL require conversion from *.mov to *.gif format (but *.gif works with only 256 colors).
Helpful documents: PIL handbook, Blender 2.49b API.


Results.
Blender screens of room scan:







Scan parameters:
  360 degrees scan,
  video recording time: 82 sec,
  'video to point cloud' conversion time: 115 sec,
  number of generated points: 72 000.
Sample point cloud file: Room.blend.

Sample face scan:

Scan with auto faces generating script:

Mesh after a little processing:




What next?
This construction is better for scan large object. There are some problems with scan in light places and with shining surfaces. It is also interesting a choise of video filter (sometimes it is better to work with red laser on green channel than with red).
Now I am serching for best 'points to surface' algorithm (generating triangle or quad mesh).
See open source MeshLab'a.
Read more ...

Citi Bike Helmet

Sunday, 23 June 2013

Citi Bike Helmet

 

Overview 

Improve your visibility with style! Mod up this bike helmet with LED strip, a FLORA GPS, and find your way to the nearest Citi Bike station with ease. We used a Carrera foldable helmet, which has grooves between the protection, perfect for NeoPixel strip.

Before you begin this project, we recommend reading the following guides:
Do not affix electronics to the outer smooth surface of your bike helmet! Helmets are designed to be smooth for your safety.
This project was created in collaboration with Tyler Cooper & Justin Cooper, with major video help from Risa Rose and JM Imbrescia.

Tools & Supplies 

For this project, gather up:

Any entry level 'all-in-one' soldering iron that you might find at your local hardware store should work. As with most things in life, you get what you pay for.
Upgrading to a higher end soldering iron setup, like the Hakko FX-888 that we stock in our store, will make soldering fun and easy.

Do not use a "ColdHeat" soldering iron
! They are not suitable for delicate electronics work and can damage the Flora (see here).

Click here to buy our entry level adjustable 30W 110V soldering iron.

Click here to upgrade to a Genuine Hakko FX-888 adjustable temperature soldering iron.

Learn how to solder with tons of tutorials!

You will want rosin core, 60/40 solder. Good solder is a good thing. Bad solder leads to bridging and cold solder joints which can be tough to find.

Click here to buy a spool of leaded solder (recommended for beginners).

Click here to buy a spool of lead-free solder.

You will need a good quality basic multimeter that can measure voltage and continuity.

Click here to buy a basic multimeter.

Click here to buy a top of the line multimeter.

Click here to buy a pocket multimeter.

Don't forget to learn how to use your multimeter too!

Don't forget your wire strippers, pliers, and flush snips!

Wiring Diagram 

Repeat the process above with the GPS module, connecting corresponding TX/RX pads to FLORA (remember that TX goes to RX and RX goes to TX).

Sugru insulates the back of the GPS module from the LSM303 and FLORA main board, and also provides a semipermanent sticky situation. The silicone is not quite an adhesive, though it will remain affixed unless you choose to carefully peel it off.

The lithium polymer battery slides behind the elastic of the head brace. We sewed a small fabric pouch around the battery, which in turn was stitched to the elastic. 

Build Circuit 


Wrap a long piece of NeoPixel strip throughout the grooves in the Carrera "foldable" helmet. Start at one back edge, shifting the strip so that four LEDs are visible to the rider along the front brim.

Cut the strip to length at the opposite back edge and tack the LED strip to the nylon webbing in the grooves of the helmet with a needle and clear thread. We didn't affix to every piece of webbing, just in enough spots to secure the LED strip.
Do not affix electronics to the outer smooth surface of your bike helmet! Helmets are designed to be smooth for your safety.

Using a needle and more clear thread, affix the FLORA main board to the back head brace of the helmet through two unused pins (we used the 3.3v pad next to the USB port and the GND pad next to the JST connector).

Strip and tin three wires, then solder them to the input side of the LED strip.

Cut to length, strip and solder these wires to VBATT, D6, and GND, referring to the wiring diagram on the previous page if necessary.

Solder small flexible wires to the LSM303 accelerometer/compass module, then apply a small piece of Sugru to cover the back of the module. Stick it in the middle of the FLORA main board, making sure not to cover the on/off switch or reset button. We are making a circuit sandwich!

Solder the wires to 3.3v, SCL, SDA, and GND on FLORA, referring again to the wiring diagram.

Program it

Created by Becky Stern
The Citi Bike Helmet code takes the FLORA to the limit. The code is used to drive LEDs, the FLORA GPS module, and the FLORA compass/accelerometer module. It looks at a long list of all Citi bike sharing stations in NYC (over 300!) and determines which coordinate is closest to you. It then uses the GPS module, and the compass module to navigate you there. Click the button below to download the code.
Download the Citi Bike Helmet Arduino Sketch
This code example requires the following Arduino libraries:
Adafruit GPS library which can be downloaded from https://github.com/adafruit/Adafruit-GPS-Library
Adafruit NeoPixel library which can be downloaded from https://github.com/adafruit/Adafruit_NeoPixel
Pololu LSM303 library which can be downloaded from https://github.com/pololu/LSM303
Learn how to install libraries here.
Right near the top of the sketch, you are going to see a long list of GPS coordinates that look like this:


float lat_lon[LAT_LON_SIZE][2] PROGMEM = {
{40.767272, -73.993928},
{40.719115, -74.006666},
{40.711174, -74.000165},
These coordinates were copied and pasted using a bit of node.js (learn more here). This also means that if you live in a city other than NYC that has a bike sharing program, you can use our code to get your own list of coordinates. If you live in NYC, all of the current bike share stations are loaded into the sketch.
The next piece of important code is this:


Adafruit_NeoPixel strip = Adafruit_NeoPixel(45, 6, NEO_GRB + NEO_KHZ800);
int FarRight = 9;
int CenterRight = 10;
int CenterLeft = 34;
int FarLeft = 35;
int HeadsUp[] = {35, 34, 10, 9};
int RightStrip[] = {8, 7, 6, 5, 4, 3, 2, 1, 0};
int RightCenterStrip[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
int LeftCenterStrip[] = {33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23};
int LeftStrip[] = {36, 37, 38, 39, 40, 41, 42, 43, 44};
int counter = 0;
This is where we set up which LEDs on our helmet are used. This will likely need to be updated to fit your own bike helmet project. Learn more about how the FLORA NeoPixels work here.

In the setup function, you will find a section that deals with calibrating the FLORA compass module.


// Calibration values. Use the Calibrate example program to get the values for
// your compass.
compass.m_min.x = -581; compass.m_min.y = -731; compass.m_min.z = -1097;
compass.m_max.x = +615; compass.m_max.y = +470; compass.m_max.z = 505;
Included with the Pololu LSM303 library is a little sketch that will get you these values. Run the sketch and view the serial monitor. Then tilt your helmet/sensor in every possible direction. When done, dump the values in the serial monitor into the above bit of code (replacing our values).

Thats about all you need to know to get started. Upload the code to your FLORA, and you are ready to hit the road.
To test out your animations inside, try the following code that reacts to just the compass:


#include <Adafruit_NeoPixel.h>
#include <LSM303.h>
// Test code for Adafruit Flora GPS modules
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Flora GPS module
// ------> http://adafruit.com/products/1059
// Pick one up today at the Adafruit electronics shop
// and help support open source hardware & software! -ada

Adafruit_NeoPixel strip = Adafruit_NeoPixel(45, 6, NEO_GRB + NEO_KHZ800);
int FarRight = 9;
int CenterRight = 10;
int CenterLeft = 34;
int FarLeft = 35;
int HeadsUp[] = {35, 34, 10, 9};
int RightStrip[] = {46, 8, 7, 6, 5, 4, 3, 2, 1, 0, 46};
int RightCenterStrip[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
int LeftCenterStrip[] = {33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23};
int LeftStrip[] = {46, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46};
int counter = 256*5;

#include <Wire.h>
#include <LSM303.h>

LSM303 compass;

void setup() {
Serial.begin(9600);
Wire.begin();
compass.init();
compass.enableDefault();

strip.begin();
strip.show(); // Initialize all pixels to 'off'

// Calibration values. Use the Calibrate example program to get the values for
// your compass. M min X: -561 Y: -679 Z: -558 M max X: 232 Y: 109 Z: 224
compass.m_min.x = -561; compass.m_min.y = -679; compass.m_min.z = -558;
compass.m_max.x = 232; compass.m_max.y = 109; compass.m_max.z = 224;
}

void loop() {
compass.read();
int heading = compass.heading((LSM303::vector){0,-1,0});

//Use this part of the code to determine which way you need to go.
if ((heading > 348.75)||(heading < 11.25)) {
Serial.println(" N");
//Serial.println("Forward");
GoForward(strip.Color(0, 51, 20), strip.Color(255, 255, 0), 200);

}

if ((heading >= 11.25)&&(heading < 33.75)) {
Serial.println("NNE");
//Serial.println("Go Left");
GoForward(strip.Color(0, 51, 10), strip.Color(255, 255, 0), 200);
}

if ((heading >= 33.75)&&(heading < 56.25)) {
Serial.println(" NE");
//Serial.println("Go Left");
TurnLeft(strip.Color(11, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 56.25)&&(heading < 78.75)) {
Serial.println("ENE");
//Serial.println("Go Left");
TurnLeft(strip.Color(39, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 78.75)&&(heading < 101.25)) {
Serial.println(" E");
//Serial.println("Go Left");
TurnLeft(strip.Color(74, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 101.25)&&(heading < 123.75)) {
Serial.println("ESE");
//Serial.println("Go Left");
TurnLeft(strip.Color(74, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 123.75)&&(heading < 146.25)) {
Serial.println(" SE");
//Serial.println("Go Left");
TurnLeft(strip.Color(79, 61, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 146.25)&&(heading < 168.75)) {
Serial.println("SSE");
//Serial.println("Go Left");
TurnAround(strip.Color(79, 61, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 168.75)&&(heading < 191.25)) {
Serial.println(" S");
//Serial.println("Turn Around");
TurnAround(strip.Color(79, 32, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 191.25)&&(heading < 213.75)) {
Serial.println("SSW");
//Serial.println("Go Right");
TurnAround(strip.Color(79, 61, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 213.75)&&(heading < 236.25)) {
Serial.println(" SW");
//Serial.println("Go Right");
TurnRight(strip.Color(79, 61, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 236.25)&&(heading < 258.75)) {
Serial.println("WSW");
//Serial.println("Go Right");
TurnRight(strip.Color(74, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 258.75)&&(heading < 281.25)) {
Serial.println(" W");
//Serial.println("Go Right");
TurnRight(strip.Color(74, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 281.25)&&(heading < 303.75)) {
Serial.println("WNW");
//Serial.println("Go Right");
TurnRight(strip.Color(39, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 303.75)&&(heading < 326.25)) {
Serial.println(" NW");
//Serial.println("Go Right");
TurnRight(strip.Color(11, 79, 0), strip.Color(255, 255, 0), 200);
}

if ((heading >= 326.25)&&(heading < 348.75)) {
Serial.println("NWN");
//Serial.println("Go Right");
GoForward(strip.Color(0, 51, 10), strip.Color(255, 255, 0), 200);
}
}

void TurnLeft (uint32_t c, uint32_t stripe, uint8_t wait) {
strip.setPixelColor(CenterRight, 0);
strip.setPixelColor(CenterLeft, 0);
strip.setPixelColor(FarLeft, c);
strip.show();
for(uint16_t i=0; i<11; i++) {
strip.setPixelColor(LeftCenterStrip[i], strip.Color(0, 0, 0));
strip.setPixelColor(LeftStrip[i], strip.Color(0, 0, 0));
strip.show();
delay(30);
}
//delay(wait);
strip.setPixelColor(FarLeft, 0);
strip.show();
colorWipe(stripe, 30);
//delay(wait);
}

void TurnRight (uint32_t c, uint32_t stripe, uint8_t wait) {
strip.setPixelColor(CenterRight, 0);
strip.setPixelColor(CenterLeft, 0);
strip.setPixelColor(FarRight, c);
strip.show();
for(uint16_t i=0; i<11; i++) {
strip.setPixelColor(RightCenterStrip[i], strip.Color(0, 0, 0));
strip.setPixelColor(RightStrip[i], strip.Color(0, 0, 0));
strip.show();
delay(30);
}
//delay(wait);
strip.setPixelColor(FarRight, 0);
strip.show();
colorWipe(stripe, 30);
//delay(wait);
}

void TurnAround (uint32_t c, uint32_t stripe, uint8_t wait) {
strip.setPixelColor(CenterRight, c);
strip.setPixelColor(CenterLeft, c);
strip.show();
for(uint16_t i=0; i<11; i++) {
strip.setPixelColor(LeftCenterStrip[i], strip.Color(0, 0, 0));
strip.setPixelColor(RightCenterStrip[i], strip.Color(0, 0, 0));
strip.show();
delay(30);
}
//delay(wait);
strip.setPixelColor(CenterRight, 0);
strip.setPixelColor(CenterLeft, 0);
strip.show();
colorWipe(stripe, 30);
//delay(wait);

}

void GoForward (uint32_t c, uint32_t stripe, uint8_t wait) {
strip.setPixelColor(CenterRight, c);
strip.setPixelColor(CenterLeft, c);
strip.show();
for(uint16_t i=0; i<11; i++) {
strip.setPixelColor(LeftCenterStrip[i], strip.Color(0, 0, 0));
strip.setPixelColor(RightCenterStrip[i], strip.Color(0, 0, 0));
strip.show();
delay(30);
}
colorWipe(stripe, 30);
//delay(wait);
}

// Slightly different, this makes the rainbow equally distributed throughout
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<11; i++) {
strip.setPixelColor(LeftCenterStrip[i], strip.Color(255, 255/i^16, 255/i^16));
strip.setPixelColor(RightCenterStrip[i], strip.Color(255, 255/i^16, 255/i^16));
strip.setPixelColor(RightStrip[i], strip.Color(255, 255/i^16, 255/i^16));
strip.setPixelColor(LeftStrip[i], strip.Color(255, 255/i^16, 255/i^16));
strip.show();
delay(wait);
}
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}

Wear it!

Created by Becky Stern

The sample code uses the LEDs at the right and left edge of the helmet's brim to signal you to turn, and uses the two LEDs in the center of your forehead to tell you "go forward" (solid blue) or "turn around" (blinking red). Customize to your own navigation style!


Oh hey! You weren't thinking of wearing this helmet in the rain, were you? The circuit isn't waterproof! We recommend removing the battery if you have to wear it in the rain, then waiting until it's completely dry before reconnecting.

   


Repeat the process above with the GPS module, connecting corresponding TX/RX pads to FLORA (remember that TX goes to RX and RX goes to TX).

Sugru insulates the back of the GPS module from the LSM303 and FLORA main board, and also provides a semipermanent sticky situation. The silicone is not quite an adhesive, though it will remain affixed unless you choose to carefully peel it off.

The lithium polymer battery slides behind the elastic of the head brace. We sewed a small fabric pouch around the battery, which in turn was stitched

Optional: Generating Coordinates

Created by Becky Stern
You may need to re-generate the coordinates for the bike stations from time to time, and this page will show you how to do that.

Another reason you may want to re-generate coordinates is so you can use the bike share system in your city with the helmet! It isn't limited to the NYC Citi Bike system.

The below code will parse the wonderful citybik.es api:


var request = require('request');
var BIKE_SHARE_URL = 'http://api.citybik.es/citibikenyc.json';
request(BIKE_SHARE_URL, function (error, response, body) {
if (!error && response.statusCode == 200) {
var comma = ",";
var locations = JSON.parse(body);
locations.forEach(function(l, i) {
if (i === locations.length-1)
comma = "";

console.log(" {" + (l.lat / 1000000).toFixed(6) + ", " + (l.lng / 1000000).toFixed(6) + "}" + comma);
});

console.log(locations.length);
}
});
Let's not get too far ahead of ourselves though. First, we need to install the dependencies to run that code.

To start with, you'll need node.js. It's a really easy install. Navigate to http://nodejs.org, and follow the installation instructions for your operating system (Windows, Linux, and OS X are supported).

Next, create a folder somewhere (mine is titled 'cityparser'). Then, create a file in that folder titled parser.js and copy and paste the above snippet of code into that file, and save it.

Now, open your favorite command line utility (Terminal.app, cmd.exe, etc) and navigate into the 'cityparser' folder.

Now, we need to install the one dependency that is required for the parser to run. Execute the following from within the cityparser folder:


npm install request
Now that you have request installed, you can (finally!) run the parser to generate the locations for your particular city bike share program.

Execute the following command to run the parser:


node parser.js
Great! It should have output a bunch of coordinates with a count at the end of it.

For example, these are the last few of my output:


{40.715348, -73.960241},
{40.741472, -73.983209},
{40.736502, -73.978094},
{40.744449, -73.983035},
{40.702550, -73.989402},
{40.698920, -73.973329},
{40.716887, -73.963198},
{40.734160, -73.980242},
{40.725500, -74.004451},
{40.705311, -73.971000},
{40.765909, -73.976341}
311
If your output is similar to the above, you'll now want to choose the correct BIKE_SHARE_URL for your city (NYC pre-loaded).

Open the citybik.es api page, and scroll down to the section titled "System" and "JSON". Choose your location from the dropdown, and then replace it in the parser.js file variable "BIKE_SHARE_URL" and re-run the program.

Ok, now to set up your sketch. The last number in the results is the count of locations in that bike share. Take that number and place it in the sketch for the size of the array:


#define LAT_LON_SIZE 311
Then, copy and paste all of the locations (not the number), and replace the existing locations in the Bike Helmet Sketch. It should look something like this:


float lat_lon[LAT_LON_SIZE][2] PROGMEM = {
{40.767272, -73.993928},
{40.719115, -74.006666},
{40.711174, -74.000165},
{40.683826, -73.976323},
{40.702550, -73.989402},
{40.698920, -73.973329},
{40.716887, -73.963198},
{40.734160, -73.980242},
{40.725500, -74.004451},
{40.705311, -73.971000},
{40.765909, -73.976341}
};
Now, compile your sketch, upload it, and start biking!








Read more ...