Sunday, June 20, 2010

Major Project - Lilypad Arduino




My major project was a step up from my minor in a sense that it was no longer based on the Duemilanove but instead by using the Lilypad Arduino and putting it into fabric.

Notes about the Lilypad arduino from the arduino.cc site:

Overview

The LilyPad Arduino is a microcontroller board designed for wearables and e-textiles. It can be sewn to fabric and similarly mounted power supplies, sensors and actuators with conductive thread. The board is based on theATmega168V (the low-power version of the ATmega168) or the ATmega328V. The LilyPadArduino was designed and developed by Leah Buechley and SparkFun Electronics.

Summary

Warning: Don't power the LilyPad Arduino with more than 5.5 volts, or plug the power in backwards: you'll kill it.

MicrocontrollerATmega168V or ATmega328V
Operating Voltage2.7-5.5 V
Input Voltage2.7-5.5 V
Digital I/O Pins14 (of which 6 provide PWM output)
Analog Input Pins6
DC Current per I/O Pin40 mA
Flash Memory16 KB (of which 2 KB used by bootloader)
SRAM1 KB
EEPROM512 bytes
Clock Speed8 MHz

Power

The LilyPad Arduino can be powered via the USB connection or with an external power supply.

If an external power supply is used, it should provide between 2.7 and 5.5 volts. This can come either from an AC-to-DC adapter (wall-wart) or battery. Again, don't power the LilyPad Arduino with more than 5.5 volts, or plug the power in backwards: you'll kill it.

Physical Characteristics

The LilyPad Arduino is a circle, approximately 50mm (2") in diameter. The board itself is .8mm (1/32") thick (approximately 3mm (1/8") where electronics are attached).

Washability

Wash at your own risk - we do ;). We recommend washing projects by hand with a mild detergent. Drip dry. Make sure you remove your power supply first!

Connecting the LilyPad Arduino

To program the LilyPad Arduino, you need to connect it to your computer. The SparkFun FTDI Basic Breakout plugs into the 6-pin male header on the newest version of the LilyPad. Use a USB MiniB cable to connect the FTDI basic breakout to your computer. You can also use an FTDI USB-TTL Serial cable.


Setup: Jacket, Lilypad Arduino, LED's, battery holder, push buttons, conductive thread, sewing needle, contre crayon & lots of time.


Firstly, i drew in where everything was going to placed. This was done by making a basic grid and placing on the LEDs and the arduino to make sure everything was lined up correctly.

Then i measured out the distance at each point to help form the arrow direction


After lining up the LEDs in their new positions, i drew lines around them that would show where to sow to connect them all up. The outer line on both sides is the + side of the LEDs, the inside was the -.


Now the Arduino and the power supply needed to be sewn in. This part was very important and the connection between them needed to be very strong. Because of this, both + and - of each of them have had to have a lot of conductive thread sewn through.
Arduino + & - pins

Power supply pins:

NOTE: The overall distance between theses two was not a lot. They required to be quite close too as the conductive thread can be quite resistant over distance.

Now it was onto the tedious task of sewing all of the other components. This was very time consuming as each LED required a lot of thread to be sewn through their connections points and careful attention was needed to monitor where the thread was being placed so that it wasn't too close to other threads for example, when I was sewing the + and - ends of the arrow LEDs, I had to make sure i wasn't crossing them over or sewing so close to the other that they would connect.

Carefully sewing through only the top layer of the fabric so that the wires were not visible from the outside:
This is the inside of the jacket where the LEDs have been sewn in. The threads at one point did cross over so I had to unpick sections of it and re-sew around to keep the connection.


After sewing in all the LEDs i used a simple program to test if their connections were strong enough and to see if they could all light up.

int ledPin = 13; //the arduino's LED
int leftSignal = 9; //left LEDs
int rightSignal = 11; //right LEDs
int signalLow = 10; //the - side of the LEDs are connected here.

void Setup()
{
pinMode(ledPin, OUTPUT);
pinMode(leftSignal, OUTPUT);
pinMode(rightSignal, OUTPUT);
pinMode(signalLow, OUTPUT);
digitalWrite(signalLow, LOW);
}

void Loop()
{
delay(1000); //1 second delay.
digitalWrite(leftSignal, HIGH); //make the left LEDs light up.
delay(1000);
digitalWrite(leftSignal, LOW); //make the left LEDs turn off.
}

To test both sides I just changed the digitalWrite(variableName , state);

After cutting a few bits of thread back that had become "fluffy" and causing the threads to cross, the LEDs did turn on and off successfully!!



Now to make them more than just decoration, the wearer needs to be able to control them. As the idea for the project is that someone biking could be able to use it, it would be unideal to make the LEDs just flash on and off constantly, this would be confusing to other people and be of no real use.
To make the LEDs manipulatable by the user I sewed in a push button into each of the jackets cuffs. This will allow the user to easily press one of the buttons to help indicate the direction they wish to turn.

This is the inside of the jacket showing the one of the buttons connected up.
Once the user is wearing this, they will not be able to see the back of it, so what happens if they push one of the buttons by mistake or without knowing and may have bumped one by mistake?
To help the user to keep track of which button has been pressed, I have also sewn in LEDs on the upper side of the cuffs. This will help to indicate to the wearer which one has been selected.

The inside of the cuff with both the push button and LED sewn in.
Front side that the wearer will see. The placement on the LED is important as it needs to be visible to the wearer but i have made it so that if they use correct road code turning signals (that is to hold out their arm to indicate the direction they intend to go to others), people behind them will also be able to see the LED on their arm.


The front with the LED on:

The final guts of the project:



Heres a small video of the right side of the jackets functionality:
After the button is pushed, the corresponding LEDs flash. Once the LEDs have flashed 10 times, the back LEDs turn off and the wrist LED remains on. This helps to indicate to the user they are no longer flashing.

My idea for this project was based on a tutorial I found by Leah Buechley, Assistant Professor of Media Arts and Sciences at MIT (Massachusetts Institute of Technology).
The tutorial she had was very useful and provided some of the code she had put into the lilypad arduino to give it a very awesome functionality and put my "push button, LEDs flash 10 times" to shame.

The functionality of her code works so that the jacket now has two modes: night and day.
When the jacket is in day mode, the jacket will flash the back arrow LEDs 10 times when that button is pressed and turn off earlier if the button is pushed again before then. This is day mode.
In night mode, the LEDs all flash constantly until one of the buttons is pushed to indicate a turn, then that side will be the only LEDs flashing until the count is up or the button is pushed again. Once either of these are no longer true, all the LEDs will start flashing again. To toggle the jacket mode, both buttons must be pressed at the same time.

Here is the code to allow for this functionality:

int boardLED = 13; 
int leftSignal = 9;
int rightSignal = 11;
int signalLow = 10;
int rightLow = 4;
int leftSwitch = 6;
int rightSwitch = 12;
int leftLED = 5;
int rightLED = 3;
int x, y;
int mode = 0;
int DAY = 0;
int NIGHT = 1;

void setup() // run once, when the sketch starts
{
pinMode(boardLED, OUTPUT);
pinMode(leftSignal, OUTPUT);
pinMode(rightSignal, OUTPUT);
pinMode(signalLow, OUTPUT);
pinMode(rightLow, OUTPUT);
pinMode(leftSwitch, INPUT);
digitalWrite(leftSwitch, HIGH);
pinMode(rightSwitch, INPUT);
digitalWrite(rightSwitch, HIGH);
pinMode(leftLED, OUTPUT);
pinMode(rightLED, OUTPUT);
digitalWrite(boardLED, HIGH);
digitalWrite(signalLow, LOW);
digitalWrite(rightLow, LOW);
}

void loop() // run over and over again
{
checkLeft();
checkRight();
if (mode == NIGHT) night();
else
day();
}

void checkLeft()
{
if (digitalRead(leftSwitch) == LOW)
{
digitalWrite(boardLED, LOW);
while (digitalRead(leftSwitch) == LOW)
{
if (digitalRead(rightSwitch) == LOW)
{
while (digitalRead(rightSwitch) == LOW | digitalRead(leftSwitch) == LOW);
mode = 1-mode;
digitalWrite(boardLED, HIGH); return; }
}
leftTurn();
}
}

void checkRight()
{
if (digitalRead(rightSwitch) == LOW)
{
digitalWrite(boardLED, LOW);
while (digitalRead(rightSwitch) == LOW)
{
if (digitalRead(leftSwitch) == LOW)
{
while (digitalRead(leftSwitch) == LOW | digitalRead(rightSwitch) == LOW);
mode = 1-mode;
digitalWrite(boardLED, HIGH);
return;
}
}
rightTurn();
}
}

void leftTurn()
{
for (x=0;x less than 10;x++)
{
digitalWrite(leftSignal, HIGH);
digitalWrite(leftLED, LOW);
for(y=0;y less than 10;y++)
{
delay(30);
if (digitalRead(leftSwitch) == LOW)
{
while (digitalRead(leftSwitch) == LOW);
digitalWrite(leftSignal, LOW);
digitalWrite(leftLED, LOW);
return;
}
}
digitalWrite(leftSignal, LOW);
digitalWrite(leftLED, HIGH);
for(y=0;y less than 10;y++)
{
delay(30);
if (digitalRead(leftSwitch) == LOW)
{
while (digitalRead(leftSwitch) == LOW);
digitalWrite(leftSignal, LOW);
digitalWrite(leftLED, LOW);
return;
}
}
digitalWrite(leftLED, LOW);
}
}

void rightTurn()
{
for (x=0;x less than 10;x++)
{
digitalWrite(rightSignal, HIGH);
digitalWrite(rightLED, LOW);
for(y=0;y less than 10;y++)
{
delay(30);
if (digitalRead(rightSwitch) == LOW)
{
while (digitalRead(rightSwitch) == LOW);
digitalWrite(rightSignal, LOW);
digitalWrite(rightLED, LOW);
return;
}
}
digitalWrite(rightSignal, LOW);
digitalWrite(rightLED, HIGH);
for(y=0;y less than 10;y++)
{
delay(30);
if (digitalRead(rightSwitch) == LOW)
{
while (digitalRead(rightSwitch) == LOW);
digitalWrite(rightSignal, LOW);
digitalWrite(rightLED, LOW);
return;
}
}
digitalWrite(rightLED, LOW);
}
}

void night()
{
digitalWrite(boardLED, LOW);
digitalWrite(rightSignal, HIGH);
digitalWrite(leftSignal, HIGH);
digitalWrite(leftLED, LOW);
digitalWrite(rightLED, LOW);
delay(100);
digitalWrite(rightSignal, LOW);
digitalWrite(leftSignal, LOW);
digitalWrite(leftLED, HIGH);
digitalWrite(rightLED, HIGH);
delay(100);
digitalWrite(leftLED, LOW);
digitalWrite(rightLED, LOW);
}

void day()
{
digitalWrite(boardLED, HIGH);
delay(1);
digitalWrite(boardLED, LOW);
digitalWrite(leftLED, HIGH);
delay (1);
digitalWrite(leftLED, LOW);
digitalWrite(rightLED, HIGH);
delay(1);
digitalWrite(rightLED, LOW);
delay (5);
}
The following is a video of the jacket with this code uploaded to the lilypad arduino. Pay attention to when the hands move, this is when the buttons are being pushed.


The biggest difficulty with this project was getting the setup right so that the wires did not cross. As I had already done the minor project with this setup using the Duemilanove, I knew exactly what was going to be connected to where but applying it something larger and more complexly shaped than a bread board was a greater difficulty.

Another issue I had with this project was the conductive thread I was using to connect everything together. The sewing part was easy, keeping the thread from going "fluffy" and breaking all the time wasn't.

The thread was more conductive if each section was sewn together without the thread having to be cut and then re connected (it also looked a lot tidier). However because sections of this required a lot of thread to be used at once, I found that it wore out a lot quicker. There are sections of my threading that appear weaker and needed reinforcement because looping through the + and - of the LEDs wore away at it. There are some sections I have gone over with glue to help hold the thread in place and stop it from breaking. This can be seen on the back of the push buttons.

From here I plan to take the jacket to Otago Girls High school (the school i'm helping out for the RoboCup), because their teacher is intending to have an electronics course next term. I think that by showing them this, it will encourage them to take the paper and show them that there is a lot more that they can do with electronics.

After that, it's heading back home to mum.
It was her jacket I "borrowed" after all ;)

Thursday, June 17, 2010

RoboCup Challenge

Thursday 17th June:
As part of the Embedded Systems paper, we were asked to volunteer to help out a local school. Glenn and I were assigned Otago Girls High School.
After several emails and sorting out a time that didn't clash with our timetable, I was able to go along to check out what they're up to and how their development was coming along.
They currently have 3 robots but are considering classing themselves as 2 teams of 4. Two of the robots have been constructed in a humanised form and the other has been constructed as a crocodile. Both teams only wish to enter into the dance competition which means all they will need to do is get a light or colour sensor to detect if the robot is still inside the dance zone, the movement and how they want them to dance is entirely up to them.
At this stage they only started programming when I arrived, they have spent the rest of the term constructing the robots which has sadly left them short on time.
One of the groups did run into some trouble trying to get their light sensor to pick up anything. It was continuously defaulting to a reading of 100%
I might email Sandy and ask her for a copy of the work booklet that we went through with her, that way I can get back up to speed with all the different components and things available through the mindstorms interface.

Sunday, May 30, 2010

Tasks 54 - 60

54) Data logging. Write a small program that reads a real world signal like light or temperature and takes 10 samples over ten seconds. Output your values to the serial screen.

int photoCellPin = 0;
int photoCellReading;

int i;


void setup(void)
{
Serial.begin(9600);

photoCellReading = analogRead(photoCellPin);


for(i=0;i less than 10;i++)
{
Serial.print("analog reading = ");
Serial.print(photoCellReading);


if (photoCellReading less than 10)
{Serial.println(" - Dark");}
else
if (photoCellReading less than 200)
{Serial.println(" - Dim");}
else
if (photoCellReading less than 500)
{Serial.println(" - Light");}
else
if (photoCellReading less than 800)
{Serial.println(" - Bright");}
else
{Serial.println(" - Very Bright");}

Serial.println(i);
delay(1000);

}
}

void loop(void)
{
}



55) Same but this time store your values in an array called mySamples[] and output the array on completion of the tenth sample.

int photoCellPin = 0;
int photoCellReading;

int i;
int x;

int mySamples[10];

void setup(void)
{
Serial.begin(9600);

for(i=0; i less than 10; i++)
{

photoCellReading = analogRead(photoCellPin);

Serial.print("analog reading = ");
Serial.print(photoCellReading);

if (photoCellReading less than 10)
{Serial.println(" - Very Dark");}
else
if (photoCellReading less than 100)
{Serial.println(" - Dark");}
else
if (photoCellReading less than 200)
{Serial.println(" - Dim");}
else
if (photoCellReading less than 500)
{Serial.println(" - Light");}
else
if (photoCellReading less than 600)
{Serial.println(" - Lighter");}
else
if (photoCellReading less than 800)
{Serial.println(" - Bright");}
else
{Serial.println(" - Very Bright");}

delay(1000);

mySamples[i] = photoCellReading;
}

for(x=0;x less than 10;x++)
{
Serial.println(mySamples[x]);
}

}

void loop(void)
{}



56) Same as 55 but this time store your values into eeprom then output from there after 5 second delay.


57) Same as 56 but this time write a separate function to find the smallest value and out put that at the end of the sampling with a suitable message.


58) Same as 57 but this time write two functions average() and biggest(). The average function outputs the mean of the values as a floating point number and the other function, biggest(), will output the greatest value that you have sampled.


--Next tasks are to do with longer term data logging over a day or longer.


59) Create an experiment that will log a real-world variable like light or temperature over 24 hours or more. Store your logged values in eeprom and display your values in a useful way. Write up your experiment with photos and movies in your blog.


60) Make a presentation to the class with at least three slides on one of the function blocks of the mega328. This is a diagram in the blog with the heading "the main parts of the mega 328".

//not enough time left in the semester - asked to flag as it will be included in the test.

Sunday, May 23, 2010

Minor Project



My minor project is the basic layout that my major will have. It consists of two push buttons, each with their own corresponding set of LED's that "flash" when the button is pressed. This will eventually be migrated to the Lilypad Arduino so that it can sewn onto the back of a jacket to represent indicators.

At this stage I have only just received the Lilypad Arduino so will not be using it for the minor.

The major projects code will have a much stronger structure. The code for this is very basic but it represents how the major project will function.

Code:

const int leftButton = 7;
const int rightButton = 8;

const int leftLED = 11;
const int rightLED = 12;

boolean leftBool;
boolean rightBool;

int x;

int buttonStateL = 0; // variable for reading the pushbutton status
int buttonStateR = 0;


void setup() {
// initialize the LED pin as an output:
pinMode(leftLED, OUTPUT);
pinMode(rightLED, OUTPUT);

// initialize the pushbutton pin as an input:

pinMode(rightButton, INPUT);
pinMode(leftButton, INPUT);

leftBool = false;
rightBool = false;
}

void loop(){
// read the state of the pushbutton value:

//right
buttonStateR = digitalRead(rightButton);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonStateR == HIGH) {
rightBool = true;
}

if (rightBool == true)
{
// turn LED on:
for (x=0;x less than 10;x++)
{
digitalWrite(rightLED, HIGH);
delay(500);
digitalWrite(rightLED, LOW);
delay(500);
}
rightBool = false;
}



//left buttonStateL
buttonStateL = digitalRead(leftButton);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonStateL == HIGH)
{
leftBool = true;
}

if (leftBool == true)
{
// turn LED on:
for (x=0;x less than 10;x++)
{
digitalWrite(leftLED, HIGH);
delay(500);
digitalWrite(leftLED, LOW);
delay(500);
}
leftBool = false;

}
}



Fritzing Diagram:
Note: from first attempt.



Photos:


Video:

Thursday, May 6, 2010

Tasks 51 - 53

51) Check out the eeprom read program at http://arduino.cc/en/Reference/EEPROMRead
Get it running and put a screen dump into your blog. They may be all $FFs or all $00's at first.

Note: EEPROM.write(address, value);
#include EEPROM.h

int a = 0;
int value;

void setup()
{
Serial.begin(9600);
}

void loop()
{
value = EEPROM.read(a);

Serial.print(a);
Serial.print("\t");
Serial.print(value);
Serial.println();

a = a + 1;

if (a == 512)
a = 0;

delay(500);
}


My first attempt printed this out to the serial monitor:


However after I ran the eeprom write program and went back to try the read program again it printed out this instead:
This was because it had reset the values through the for loop.

52) Now run the similar eeprom write program to send $23 to address 01 and $2A to address 02. Add a eeprom dump, all 512 bytes, function to your program based on the eeprom read program above so you can see that your bytes have been changed.

//Notes:
EEPROM.write(address, value);
#include EEPROM.h

void setup()
{
//for (int i = 0; i less than 512; i++)
// EEPROM.write(i, i);

instead of the above for loop:
EEPROM.write(01, 23);
EEPROM.write(02, 24);

This will write the values 23 and 24 to the address of 01 and 02.

}

void loop()
{
}



53) Fill the total eeprom with $AB's all 1024 bytes. Read eeprom space back onto your screen and do a screen capture picture for your blog.

Tasks 45 - 50

45)Explore the way your infrared transmitter sends pulses to the receiver. Set up a little demonstration to be marked in class. You may share this project with another person but both members have to know what's going on. Transmission from one Arduino to another is especially excellent.

Had done this - just completely forgot to upload the photo and describe it.

For this task I decided to use the blink program. This would light up the sending IR led so to make a connection, the receiver would have to be in line with it. Because we cannot see infrared light, I added an LED which was set up to light up when there was a connection between the 2 IR's.
The transmitting IR is placed at pin 13 and ground, with the concave side facing the breadboard.
There are also 2 wires connected at ground and 3v pins on the power side of the arduino board. The 3v is set inline with the IR receiver and ground with the LED, the IR and LED are placed so that they link up.
When run with the blink sketch, the LED on the breadboard will light up. If something interrupts the signal, the LED goes off.

//insert photo here..


46) Get a plan to send a signal from one Arduino to another. Set one up to receive and one to transmit. Connect the input pin of the receiver to an output pin of the transmitter. Get the receiver to note on the serial screen what it's reading. Get the transmitter to send a slow square wave that can be received and displayed in real human time.


Plan: One arduino has the blink sketch running which also has TxPin = 2 (transmitter), as an output to the other arduino. When the ledPin is HIGH the TxPin is HIGH also. This is then connected to the other arduinos RxPin = 2 (reciever) and the grounds of both arduinos are connected. The recieving arduino is either expecting something or nothing (0 or 1). If the RxPin is equal to 1, it means the led on the other arduino is HIGH so the recieving arduinos led is set to HIGH and outputs a H to the serial monitor.


Transmitter:

int ledPin = 13;
int TxPin = 2;

void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(TxPin, OUTPUT);
}

void loop()
{
digitalWrite(TxPin, HIGH);
digitalWrite(ledPin, HIGH);
delay(1000);

digitalWrite(TxPin, LOW);
digitalWrite(ledPin, LOW);
delay(1000);
}


Reciever:

int RxPin = 2;
int ledPin = 13;

void setup()
{
pinMode(RxPin, INPUT);
Serial.begin(9600);
}

void loop()
{
if (digitalRead(RxPin)==1)
{
Serial.println("H");
digitalWrite(ledPin,HIGH);
}
else
{
digitalWrite(ledPin,LOW);
Serial.println("L");
}
}


47) Same as 46 but this time reverse roles of sender and receiver.

..cut, paste, done :)

48) Same as 46 but get the receiving Arduino to send the level, 1 or 0, that it's getting back to the other Arduino. So it's just receiving and sending a copy back for checking. Get both Arduinos to display what they are getting. A one second on/off will work ok.

This time I tryed getting both the arduinos to send and receive at the same time. This was my code:

int RxPin = 2;
int TxPin = 3;
int ledPin = 13;

void setup()
{
pinMode(RxPin, INPUT);
pinMode(TxPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
//sending
digitalWrite(TxPin, HIGH);
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(TxPin, LOW);
digitalWrite(ledPin, LOW);
delay(1000);
//receiving
if (digitalRead(RxPin)==1)
{
Serial.println("H");
digitalWrite(ledPin,HIGH);
}
else
{
digitalWrite(ledPin,LOW);
Serial.println("L");
}
}

This was on both arduinos (Rx and Tx pin numbers swapped), but it didnt seem to work properly, one would only output low and the other only high so im not sure if this was working correctly.



49) Get one Arduino to send a given series of pulses, say about a 100, about 1ms long, to the other. Get the receiver to count the number of pulses it gets and display this number on the serial screen.

//in the setup so it doesnt loop once its done.

while (count less than 100)
{
digitalWrite(TxPin, HIGH);
digitalWrite(ledPin, HIGH); // set the LED on
delay(500); // wait for a second
digitalWrite(TxPin, LOW);
digitalWrite(ledPin, LOW); // set the LED off
delay(500);
count++;
}


50) How fast can you send a thousand 1/0 pulses and still count them accurately.
I reduced the delay times on both the sender and receiver but it still printed out, not all at once though.

Sunday, April 18, 2010

Week 8: Interrupts

Lab 1: External Interrupts.

TBC