Sunday, June 20, 2010

Final Code for Major Project

/*this code is for a multiple format clock that can display the current time in decimal, binary, hex, octal and roman numerals.
The hardware needed for this project is an arduino, ds1307 rtc and a 16x2 character lcd.
Code heavily influenced by code found here : http://www.sullivan-county.com/ele/arduino_ds1307.htm
Code written by Perrin McKenzie for IN620, 2010
*/
#include < EEPROM.h >
#include < Wire.h >
#include < LiquidCrystal.h >

byte SW0 = 4;
byte SW1 = 5;
byte SW2 = 6;
byte SW3 = 3;
byte SW4 = 2;

LiquidCrystal lcd(7,8,9,10,11,12);

boolean pm;
boolean miltime;
boolean refresh;

int base; //0=dec,1=binary,2=hex,3=octal
int hrs;
int mins;
byte hexhrs;
byte hexmins;
byte hexsecs;
byte hexday;
byte hexdate;
byte hexmonth;
byte hexyear;

void setup()

{
Wire.begin();
Serial.begin(9600);

pinMode(SW0, INPUT); //time
pinMode(SW1, INPUT); //minutes
pinMode(SW2, INPUT); //hours
pinMode(SW3, INPUT); //24hr/AM:PM
pinMode(SW4, INPUT); //change number base

digitalWrite(SW0, HIGH);
digitalWrite(SW1, HIGH);
digitalWrite(SW2, HIGH);
digitalWrite(SW3, HIGH);
digitalWrite(SW4, HIGH);

lcd.begin(16, 2);

miltime = EEPROM.read(0);
base = EEPROM.read(1); //retrieve settings
}

void loop()
{
retrieve_time();

//convert hex values from rtc into decimal values to make logic easier
hrs = hexhrs/16;
hrs *= 10;
hrs += hexhrs%16;
mins = hexmins/16;
mins *= 10;
mins += hexmins%16;

lcd.setCursor(0, 0);//first line of screen

lcd.clear();

print_time();


lcd.setCursor(0, 1);//second line of screen

print_date();

if (refresh == true){
lcd.clear();
refresh = !refresh;
}//gives a period blank screen after settings have been changed

if (!(digitalRead(SW0))) set_time(); // hold the switch to set time
if (!(digitalRead(SW3))){
miltime = !miltime;//toggle 24hr time
refresh = true;
EEPROM.write(0,miltime);
}
if (!(digitalRead(SW4))){
++ base; //change base time is shown in
if (base > 4) base = 0;
refresh = true;
EEPROM.write(1,base);
}
delay(500);
}


///////////////////////////////////////////////////////////////////////////////////
void retrieve_time(){ //refreshes global variables from the rtc
Wire.beginTransmission(0x68);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
hexsecs = Wire.receive();
hexmins = Wire.receive();
hexhrs = Wire.receive();
hexday = Wire.receive();
hexdate = Wire.receive();
hexmonth = Wire.receive();
hexyear = Wire.receive();
}

void print_time(){ //modify displayed time depending on settings
if (miltime == false){
if (hexhrs >= 19 && hexhrs <= 35){
hrs -= 12;
pm = true;
}
else if (hexhrs == 0){
hrs += 12;
pm = false;
}
else if (hexhrs == 18) pm = true;
else pm = false;
}

switch (base){ //prints out time format in specified base
case 0:{
lcd.print("DEC ");
if (hrs < 10) lcd.print("0");
lcd.print(hrs,DEC);
lcd.print(":");
if (mins < 10) lcd.print("0");
lcd.print(mins,DEC);
}
break;
case 1:{
lcd.print("B ");
if (miltime == true){
if (hrs <= 15) lcd.print("0");
if (hrs <= 7) lcd.print("0");
if (hrs <= 3) lcd.print("0");
if (hrs <= 1) lcd.print("0");
lcd.print(hrs,BIN);
lcd.print(":");
}
else
{
if (hrs <= 7) lcd.print("0");
if (hrs <= 3) lcd.print("0");
if (hrs <= 1) lcd.print("0");
lcd.print(hrs,BIN);
lcd.print(":");
}
if (mins <= 31) lcd.print("0");
if (mins <= 15) lcd.print("0");
if (mins <= 7) lcd.print("0");
if (mins <= 3) lcd.print("0");
if (mins <= 1) lcd.print("0");
lcd.print(mins,BIN);
}
break;
case 2:{
lcd.print("HEX ");
if (hrs < 16 && miltime == true) lcd.print("0");
lcd.print(hrs,HEX);
lcd.print(":");
if (mins < 16) lcd.print("0");
lcd.print(mins,HEX);
}
break;
case 3:
{
lcd.print("OCT ");
if (hrs < 8) lcd.print("0");
lcd.print(hrs,OCT);
lcd.print(":");
if (mins < 8) lcd.print("0");
lcd.print(mins,OCT);
}
break;
case 4:
{
int temp;
lcd.print("Ro ");
if (hrs >= 20) lcd.print("X");
if (hrs >= 10) lcd.print("X");
temp = hrs%10;
switch(temp){
case 0:lcd.print("");
break;
case 1:lcd.print("I");
break;
case 2:lcd.print("II");
break;
case 3:lcd.print("III");
break;
case 4:lcd.print("VI");
break;
case 5:lcd.print("V");
break;
case 6:lcd.print("VI");
break;
case 7:lcd.print("VII");
break;
case 8:lcd.print("VIII");
break;
case 9:lcd.print("IX");
}
lcd.print(":");
temp = mins / 10;
switch(temp){
case 0:lcd.print("");
break;
case 1:lcd.print("X");
break;
case 2:lcd.print("XX");
break;
case 3:lcd.print("XXX");
break;
case 4:lcd.print("XL");
break;
case 5:lcd.print("L");
break;
}
temp = mins%10;
switch(temp){
case 0:lcd.print("");
break;
case 1:lcd.print("I");
break;
case 2:lcd.print("II");
break;
case 3:lcd.print("III");
break;
case 4:lcd.print("VI");
break;
case 5:lcd.print("V");
break;
case 6:lcd.print("VI");
break;
case 7:lcd.print("VII");
break;
case 8:lcd.print("VIII");
break;
case 9:lcd.print("IX");
break;
}
break;
}
}
if (miltime == false){
if (pm == true){
lcd.print(" PM");
}
if (pm == false){
lcd.print(" AM");
}
}
}


void print_date(){
switch(hexday){ //day is an integer between 1 and 7 from the rtc. this case selects the day for display with the date
case 1:lcd.print("Mon ");
break;
case 2:lcd.print("Tues ");
break;
case 3:lcd.print("Wends ");
break;
case 4:lcd.print("Thurs ");
break;
case 5:lcd.print("Fri ");
break;
case 6:lcd.print("Sat ");
break;
case 7:lcd.print("Sun ");
break;
}
if (hexdate < 10) lcd.print("0");
lcd.print(hexdate, HEX);
lcd.print("-");
if (hexmonth < 10) lcd.print("0");
lcd.print(hexmonth,HEX);
lcd.print("-");
lcd.print("20");
if (hexyear < 10) lcd.print("0");
lcd.print(hexyear, HEX);
}

void set_time(){ //couldn't work out how to make this refresh the time as you were changing it so results can not be viewed until the button is released
byte hours = hexhrs;
byte minutes = hexmins;


while (!digitalRead(SW0)) // set time switch must be released to exit
{
while (!digitalRead(SW1)) // set minutes
{
minutes++;
if ((minutes & 0x0f) > 9) minutes = minutes + 6;
if (minutes > 0x59) minutes = 0;
delay(500);

}

while (!digitalRead(SW2)) // set hours
{
hours++;
if ((hours & 0x0f) > 9) hours = hours + 6;
if (hours > 0x23) hours = 0;
delay(500);
}

Wire.beginTransmission(0x68);
Wire.send(0);
Wire.send(0x00); //seconds
Wire.send(minutes); //minutes
Wire.send(0x80 | hours); //24hr time | hours
Wire.send(hexday); // Day
Wire.send(hexdate); // Date
Wire.send(hexmonth); // month
Wire.send(hexyear); // Year
Wire.send(0x10);
Wire.endTransmission(); //writing changes to rtc
}
}

Wednesday, June 16, 2010

Code For Major

This is partially finished code. It currently reads the time from the RTC, converts the values from hex into decimal (this makes the logic easier). Those values are then converted to the base value that is selected for display on the screen. The time shown on the screen can also be selected between 24hr time and AM/PM. The time stored on the RTC can also be adjusted using wired buttons by simultaneously holding the time button and pressing the hour or minute buttons (but the changes are not visible until the time button is released).

#include
#include

byte SW0 = 4;
byte SW1 = 5;
byte SW2 = 6;
byte SW3 = 3;
byte SW4 = 2;

LiquidCrystal lcd(7,8,9,10,11,12);

boolean pm = false;
boolean miltime = false;
boolean refresh = false;

int base; //0=dec,1=binary,2=hex,3=octal
int hrs;
int mins;
byte hexhrs;
byte hexmins;
byte hexsecs;
byte hexday;
byte hexdate;
byte hexmonth;
byte hexyear;

void setup()

{
Wire.begin();
Serial.begin(9600);

pinMode(SW0, INPUT); //time
pinMode(SW1, INPUT); //minutes
pinMode(SW2, INPUT); //hours
pinMode(SW3, INPUT); //24hr/AM:PM
pinMode(SW4, INPUT); //change number base

digitalWrite(SW0, HIGH);
digitalWrite(SW1, HIGH);
digitalWrite(SW2, HIGH);
digitalWrite(SW3, HIGH);
digitalWrite(SW4, HIGH);

lcd.begin(16, 2);
}

void loop()
{
retrieve_time();

//convert hex values from rtc into decimal values to make logic easier
hrs = hexhrs/16;
hrs *= 10;
hrs += hexhrs%16;
mins = hexmins/16;
mins *= 10;
mins += hexmins%16;

print_time();

//print_date();
lcd.setCursor(0, 1);


if (refresh == true){
lcd.clear();
refresh = !refresh;
}

if (!(digitalRead(SW0))) set_time(); // hold the switch to set time
if (!(digitalRead(SW3))){
miltime = !miltime;
refresh = true;
}
if (!(digitalRead(SW4))){
++ base;
if (base > 3) base = 0;
refresh = true;
}
delay(1000); //wait a second before next output
}


///////////////////////////////////////////////////////////////////////////////////
void retrieve_time(){
Wire.beginTransmission(0x68);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
hexsecs = Wire.receive();
hexmins = Wire.receive();
hexhrs = Wire.receive();
hexday = Wire.receive();
hexdate = Wire.receive();
hexmonth = Wire.receive();
hexyear = Wire.receive();
}

void print_time(){
if (miltime == false){
if (hexhrs != 0 || hexhrs != 18){
pm = false;
if (hrs >= 12) pm = true;

if (hexhrs >= 19 && hexhrs <= 35){
hrs -= 12;
}
else if (hexhrs == 0){
hrs += 12;
pm = false;
}
else
{
pm = true;
}
}
}
lcd.setCursor(0, 0);
switch (base){
case 0:{
lcd.print("DEC ");
if (hrs < 10) lcd.print("0");
lcd.print(hrs,DEC);
lcd.print(":");
if (mins < 10) lcd.print("0");
lcd.print(mins,DEC);
}
break;
case 1:{
lcd.print("B ");
if (miltime == true){
if (hrs <= 15) lcd.print("0");
if (hrs <= 7) lcd.print("0");
if (hrs <= 3) lcd.print("0");
if (hrs <= 1) lcd.print("0");
lcd.print(hrs,BIN);
lcd.print(":");
}
else
{
if (hrs <= 7) lcd.print("0");
if (hrs <= 3) lcd.print("0");
if (hrs <= 1) lcd.print("0");
lcd.print(hrs,BIN);
lcd.print(":");
}
if (mins <= 31) lcd.print("0");
if (mins <= 15) lcd.print("0");
if (mins <= 7) lcd.print("0");
if (mins <= 3) lcd.print("0");
if (mins <= 1) lcd.print("0");
lcd.print(mins,BIN);
}
break;
case 2:{
lcd.print("HEX ");
if (hrs < 16 && miltime == true) lcd.print("0");
lcd.print(hrs,HEX);
lcd.print(":");
if (mins < 16) lcd.print("0");
lcd.print(mins,HEX);
}
break;
case 3:
{
lcd.print("OCT ");
if (hrs < 8) lcd.print("0");
lcd.print(hrs,OCT);
lcd.print(":");
if (mins < 8) lcd.print("0");
lcd.print(mins,OCT);
//lcd.print(":");
//if (secs < 10) lcd.print("0");
//lcd.print(secs,DEC);
}
break;
}
if (miltime == false){
if (pm == true){
lcd.print(" PM");
}
if (pm == false){
lcd.print(" AM");
}
}
}

void print_date(){
if (hexdate < 10) lcd.print("0");
lcd.print(hexdate, HEX);
lcd.print("-");
lcd.print("20");
if (hexmonth < 10) lcd.print("0");
lcd.print(hexmonth,HEX);
lcd.print("-");
if (hexyear < 10) lcd.print("0");
lcd.println(hexyear, HEX);
}

void set_time(){
byte hours = hexhrs;
byte minutes = hexmins;


while (!digitalRead(SW0)) // set time switch must be released to exit
{
while (!digitalRead(SW1)) // set minutes
{
minutes++;
if ((minutes & 0x0f) > 9) minutes = minutes + 6;
if (minutes > 0x59) minutes = 0;
delay(500);

}

while (!digitalRead(SW2)) // set hours
{
hours++;
if ((hours & 0x0f) > 9) hours = hours + 6;
if (hours > 0x23) hours = 0;
delay(500);
}

Wire.beginTransmission(0x68); // activate DS1307
Wire.send(0); // where to begin
Wire.send(0x00); //seconds
Wire.send(minutes); //minutes
Wire.send(0x80 | hours); //hours (24hr time)
Wire.send(0x06); // Day 01-07
Wire.send(0x01); // Date 0-31
Wire.send(0x05); // month 0-12
Wire.send(0x09); // Year 00-99
Wire.send(0x10); // Control 0x10 produces a 1 HZ square wave on pin 7.
Wire.endTransmission();
}
}

Circuit for Major Project

Monday, June 14, 2010

Major Project

My major project has taken inspiration from the Epoch Alarm Clock. My clock will operate the same except for some removed functions (Namely alarm and the ability to display roman characters). I will be able to display time in decimal, Binary, octal and hex. All number systems will be displayed in either 24hr or am/pm format. The clock will also simultaneous display either Unix Epoch Time or Current date depending on what the user sets (Unix time is proving difficult to calculate so may not be included in the final release). This is all displayed on a 16x2 character LCD with time being regulated by a DS1307 RTC. The project will be displayed in an alarm clock using the original buttons (some will have different functions than the ones labeled though) to manipulate the time displayed.

Friday, May 7, 2010

Missed Tasks from the 50

Tasks 15 (not on notices blog?), 29, 48 and 50 are not completed.

Tasks 2, 3, 6

Task 2: Put Blog link into moodle


Task 3: Fill in Details on Moodle Wiki
Moodle Profile

Task 6: Make a sketches folder

Thursday, May 6, 2010

How many Arduino's? (Task 23)


The Arduino Mega is a board that is code compatible with Arduino Duemilanove. It runs an Atmega1280 (instead of a 168 or 328). As a result it has a greater number of digital pins (54 vs 14), PWM pins (14 vs 6) and analog inputs (16 vs 6).

Baud Rate (Task 37)

The highest rate without ending up with trash output is 19200 baud

Arduino Key Works (Task 25, 33)

setup(): This is a loop that only runs once when the arduino is first powered on (or reset). In this loop settings like pinMode() are specified and variables are set/reset.

loop(): This is where the main portion of the program is. This is a constant loop that begins again immediately after finishing.

analogRead(): This is used to pull values from the analogue pins. The pin number goes in the brackets (analogRead(2)). This is mostly done with sensors that can have a wide range of values (usually based off resistance e.g. LDR, Temperature sensor). The value read is always between 0 and 1023 depending on resistance.

Serial.print(): This is to write what ever is in the brackets out to a serial monitor. Variables can simply be typed in i.e. Serial.print(count) but if you wish to write out simple text it must be within quotation marks i.e. Serial.print("Text Here"). Anything in the brackets will be added to the previous line (unless the previous line was written with Serial.println()).

Serial.println(): Same as above except the message sent will end the current line.

pinMode(): This is used to set whether a digital pin is an input or an output (pinMode(13,INPUT) sets pin 13 as a digital input where as pinMode(13,OUTPUT) is the opposite). This is typically only used in setup() but can also be used in the main loop().

digitalRead(): This is used to check a sensor or button on a digital pin. This will either return HIGH or LOW. An example of how digital read is used: state = digitalRead(13).

Arduino Forum Rules (Task 42)

- Be polite
- Do not post false/inaccurate information
- No abusing/harassing/threatening behavior towards others
- Treat everyone with respect

Task 46, 47,49

By separating the code in the previous post into the send/recieve roles you can send pulses between two ardunio boards.

Sender Code:
void setup(){
pinMode(13,OUTPUT);
}

void loop(){
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
}

This code will pulse the IR transmitter between on and off with a ~500ms pause at each state;

Receiver Code:
int reading;

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

void loop(){
reading = digitalRead(13);
if (reading == HIGH){
Serial.println("High");
}
else
{
Serial.println("Low");
}
}

The receiver will either print High or Low depending on what the other board sent.

Task 49:

Sender Code:
int count = 0;

void setup(){
pinMode(13,OUTPUT);
}

void loop(){
for (int i = 0; i < 1001; i ++){
digitalWrite(13,HIGH);
delay(1);
digitalWrite(13,LOW);
delay(1);
}
}

Receiver Code:
int count = 0;

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

void loop(){
for (int i = 0; i < 1001; i ++){
reading = digitalRead(13);
if (reading == HIGH){
Serial.println("High");
count = count + 1;
}
else
{
Serial.println("Low");
}
}
Serial.print(count);
Serial.println(" of 1000 recieved");
}

Infrared Send/Recieve (Task 45)

I set this up to run on a single arduino board (pin 13 being an input and 12 being output) but the code can easily be adapted so that one board can act as a sender and another as a receiver.

int infra;
int count = 0;

void setup(){
pinMode(13,INPUT);
pinMode(12,OUTPUT);
Serial.begin(9600);
}

void loop(){
for (int i = 0; i < 21; i ++){
digitalWrite(12,HIGH);
infra = digitalRead(13);
delay(500);

if (infra == HIGH){
count = count + 1;
Serial.println(count);
}
else{
Serial.print(count);
Serial.println(" Blocked");
digitalWrite(12,LOW);
}
}
Serial.println("Finished");
delay(1000);
}

Class Presentation (Task 44)

Gave a presentation to the class on Shift Registers (namely the 74HC164)

Project Sites (Task 43)

Instructables

Instructables is prob the best site I have found as the creator of the projects have a run down of how they created their project as well as source code etc.

Make:

This site has a lot of project but some are thin on details on how they are done but they also have a few tutorials.

Hack A Day

This site has a number of projects from various sources (including the two above at times) and for various electronic and software platforms.

Practical Arduino

This site is similar to Hack A Day in that thet list projects from other sites except this site is purely arduino projects.

Register for YABB forum (Task 41)

Serial IP Library (Task 40)

Serial IP Library allows communication with an arduino via a network connection without a network shield. This is quite good as it could possibly reduce the cost of the projects that require a network connection.

Thursday, April 29, 2010

Minor Project

Minor project will be a hex stop watch. This will accurately keep time and display the time since a button press in hex.

Monday, April 5, 2010

Possible Minor Project

While at home I found an old gamepad I used as a kid. It connects via gameport. As of Windows Vista, gameport is no longer supported so I would like to "port" it to USB. With the use of an Atmel Mega8 (and most likely others) it is possible to create a USB HID device. This link describes a schematic and code of how to create a USB HID device.

Upon viewing this site using a board called a Teensy (which is basically an Arduino with a USB stack rather than operating over RS232) it would be alot easier to implement a solution using this.

This project is using the same hardware as the first but the code (and number of inputs) is closer to what I would like to implement.

Wednesday, March 17, 2010

Read LDR after Button Press (Task 38,39)

This code waits for a button to be pressed, then reads a value from an LDR and out puts it over serial.
Code:
int reading;
int push;

void setup() {
Serial.begin(9600);
pinMode(2,INPUT);
count = 0;
}

void loop() {
push = digitalRead(2);
if(push == HIGH){
delay(500); //This avoids multiple values being read per push
reading = analogRead(0);
Serial.println(reading);
}
}
Layout:


You can customize the output to make it look better and provide a count to track readings:
int reading;
int push;
int count;

void setup() {
Serial.begin(9600);
pinMode(2,INPUT);
count = 0;
}

void loop() {
push = digitalRead(2);
if(push == HIGH){
count ++;
delay(500);
reading = analogRead(0);
Serial.print("Reading ");
Serial.print(count);
Serial.print(" is ");
Serial.println(reading);
}
}

Random Number Generators (Tasks 34,35,36)

The following program writes a list of 100 random numbers on serial output
Code:
int value;
int count;
void setup(){
Serial.begin(9600);
delay(3000); //This delay allows for the serial monitor to be opened before the first number is generated
for (count = 0; count < 100; count++){
value = random(0,10);
Serial.println(value);
}
}
void loop(){
}

To give a more readable output we can alter the for loop:
for (count = 1; count < 101; count++){
value = random(0,11);
Serial.print(count);
Serial.print(". ");
Serial.println(value);
}

To generate averages from the above code it need to be altered slightly. On each cycle of the for loop it adds the randomized number to a total and then divides the total by 100. Code:
int value;
int count;
int total;

void setup(){
Serial.begin(9600);
randomSeed(analogRead(0));
delay(3000);
for (count = 1; count < 101; count++){
value = random(0,11);
total = total + value;
Serial.print(count);
Serial.print(". ");
Serial.println(value);
}
total = total / 100;
Serial.print("The average is ");
Serial.println(total);
}

void loop(){
}

Push Button, Digital Read (Tasks 30,31,32)

The below code uses digitalread() to check the state of a button and turn an LED on pin 13 on when pressed and off when not pressed.

int state = 0;
void setup(){
pinMode(13,OUTPUT);
pinMode(2,INPUT);
}
void loop(){
state = digitalRead(2); //Writes either HIGH or LOW to the state variable
if (state == HIGH){
digitalWrite(13,HIGH);
}
else{
digitalWrite(13,0);
}
}

Schematic:


To cause the program to do the opposite (have the LED on and turn off when the button is pressed) simply alter the if statement. Two alternatives are:
if (state != HIGH) or if (state == LOW)

Too add serial output referring to the LED and button state this is the new code:

int state = 0;
boolean change = HIGH;
void setup(){
pinMode(13,OUTPUT);
pinMode(2,INPUT);
Serial.begin(9600);
}
void loop(){
state = digitalRead(2);
if (state != HIGH){
digitalWrite(13,1);
if (change == HIGH){
Serial.println("LED On, Button Not Pressed");
change = !change;
}
}
else{
digitalWrite(13,0);
if (change == LOW){
Serial.println("LED Off, Button Pressed");
change = !change;
}
}
}

Friday, March 12, 2010

LED Project

This project takes a serial input of a single hex digit and displays it on a 7 segment display. The display is driven by only 2 data pins by the use of a shift register.

Fritzing Diagram:


Code:
int clock = 13;
int data = 12;
int input;

byte value[] = {B01111110,B00010010,B10111100,B10110110,B11010010,B11100110,B11101110,B00110010,B11111110,B11110110,B11111010,B11001110,B10001100,B10011110,B11101100,B11101000,B00000000}; //This is the byte patterns for the shift register stored in an array.

void setup()
{
pinMode(clock, OUTPUT);
pinMode(data , OUTPUT);
Serial.begin(9600);
}

void loop()
{
int i = Serial.read();
switch (i){ //This case statement takes the ASCII value read from serial and translates it to its corresponding index value in the array
case 48:{ input = 0;}
break;
case 49:{ input = 1;}
break;
case 50:{ input = 2;}
break;
case 51:{ input = 3;}
break;
case 52:{ input = 4;}
break;
case 53:{ input = 5;}
break;
case 54:{ input = 6;}
break;
case 55:{ input = 7;}
break;
case 56:{ input = 8;}
break;
case 57:{ input = 9;}
break;
case 65:{ input = 10;} //Values beyond 9 are letters A-F (65-70) and a-f(97-102)
break;
case 66:{ input = 11;}
break;
case 67:{ input = 12;}
break;
case 68:{ input = 13;}
break;
case 69:{ input = 14;}
break;
case 70:{ input = 15;}
break;
case 97:{ input = 10;}
break;
case 98:{ input = 11;}
break;
case 99:{ input = 12;}
break;
case 100:{ input = 13;}
break;
case 101:{ input = 14;}
break;
case 102:{ input = 15;}
break;
default: {input = 16;} //If no value is input this value will be chosen
}
if (input == 16){ //this loop flashes the centre bar of the display when no value has been read
shiftOut(data, clock, LSBFIRST, B10000000);
delay(1000);
shiftOut(data, clock, LSBFIRST, value[input]);
delay(1000);
}
else
{ //if a value has been read, it will display it on the display for 2 seconds then clear the display for 1
shiftOut(data, clock, LSBFIRST, value[input]);
delay(2000); //with no delay all segments stay on
shiftOut(data, clock, LSBFIRST, value[16]);
delay(1000);
}
}

Sunday, March 7, 2010

LED Project (Due Friday 12 March)

My project will consist of a 7 segment display run from a 74HC164 shift register. The 7 segment display will be able to display any hex character (0-9,a-f) input via serial from a computer. Code updates and pictures/videos to follow.

Thursday, March 4, 2010

Shift Registers

Lots of projects on sites like Make and Instructables make use of shift registers but what are they exactly? The most basic way to explain what they do is to say that they expand the number of digital pins available to use (with some downsides). A more complex way to explain them is to call them a cascade of flip-flops. What this means is that with only 2 data pins, you can control 8 (or more with different chips) digital outputs (but not inputs). A common chip used with Arduinos are 74HC164 (I got mine from Jaycar for $3.50 74HC164 8-bit Serial in/out Shift Register IC) and here is a project that gives a basic run down of the chip and some simple projects to use them in http://www.instructables.com/id/The-74HC164-Shift-Register-and-your-Arduino/. The below code is adapted from project two from the instructables link to emulate a program I wrote earlier ("snake" around a 7 segment display):

#define data 2
#define clock 3

byte zero = B11100000;
byte one = B01110000;
byte two = B10110000;
byte three = B10011000;
byte four = B10001100;
byte five = B00001110;
byte six = B10000110;
byte seven = B11000010;//these are variables that specify which pins should be turned on

void setup()
{
pinMode(clock, OUTPUT);
pinMode(data , OUTPUT);

void loop()
{
shiftOut(data, clock, LSBFIRST, zero);
delay(100);
shiftOut(data, clock, LSBFIRST, one);
delay(100);
shiftOut(data, clock, LSBFIRST, two);
delay(100);
shiftOut(data, clock, LSBFIRST, three);
delay(100);
shiftOut(data, clock, LSBFIRST, four);
delay(100);
shiftOut(data, clock, LSBFIRST, five);
delay(100);
shiftOut(data, clock, LSBFIRST, six);
delay(100);
shiftOut(data, clock, LSBFIRST, seven);
delay(100);
}

shiftOut is a specialised command for shift registers. the first two values specify the data pin (the pin which sends a high/low pattern) and the clock pin (this breaks up the individual values in one variable by cycling high/low to specify the end of a value). LSBFIRST is short for Last Significant Bit First and is used to specify in which order the byte pattern is loaded and then the byte pattern for the shift register to use (B11110000 for example will turn pins 1,2,3 and 4 on high from the shift register and 5,6,7 and 8 on low).

Analog Input (LDR) with Digital Output (7 Segment Display) (Task 27)

Addition to the program we wrote that read a value of an LDR and the output it to serial. This program takes that reading, divides it by 10 then outputs the value onto a 7 segment display. The board layout is that same as in the post titled "Combining Some New Concepts" :

int reading;
void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
Serial.begin(9600);
}

void loop() {
reading = analogRead(0);
reading = reading/100;
digitalWrite(13,0);
digitalWrite(12,0);
digitalWrite(11,0);
digitalWrite(10,0);
digitalWrite(9,0);
digitalWrite(8,0);
digitalWrite(7,0); //resets all LEDs on segment
Serial.println(reading); //output value to serial for debugging and checking values
switch (reading) {
case 1:{
digitalWrite(10,1);
digitalWrite(7,1);}
break;
case 2:{
digitalWrite(13,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(9,1);
digitalWrite(8,1);}
break;
case 3:{
digitalWrite(13,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 4:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(10,1);
digitalWrite(7,1);}
break;
case 5:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 6:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(9,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 7:{
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(7,1);}
break;
case 8:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(9,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 9:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 0:{
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(9,1);
digitalWrite(8,1);
digitalWrite(7,1);} // if a value is above 999 or below 99 then the display will show 0
}
delay(500);
}

Tuesday, March 2, 2010

PWM RGB LED Part 2

This code is built of code from the previous post but works slightly different (namely it uses arrays and for loops rather than explicitly defining pins and value changes) and has a new feature: fading of each colour to both extremes and then back again:

boolean go = HIGH;
int pins [3] = {11,10,9};
int colours [3] = {0,0,0};
boolean dir [3] = {HIGH,HIGH,HIGH};

void setup() {
randomSeed(analogRead(5));
Serial.begin(9600);
}

void loop() {
if (go == HIGH){
go = !go;
for (int i = 0; i < 3; i ++){
colours[i] = random(1,255);
} //sets up initial values for cycling
}

for (int i = 0; i < 3; i ++){
if (dir[i] == HIGH){
colours[i] += 5;
if (colours[i] >= 250){ //if this value exceeds 255 then that colour will turn off resulting in a flash when it drops below 255 again
dir[i] = LOW;
}
}
else
{
colours[i] -= 5;
if (colours[i] <= 5){
dir[i] = HIGH;
}
}
analogWrite(pins[i],colours[i]);
}
delay(30);
}

EDIT

Did some playing around with the above code and now in the beginning loop when first assigning values it will also randomize the beginning direction of the colour value as well as randomizing the incrementing value.

First Attempt at Using Pulse Width Modulation

Bored (again) and wanted to play around with the RGB LED from the kit. After a bit of research and reading up on PWM with the Arduino I wrote this little program:

boolean go = HIGH;
int red;
int green;
int blue;

void setup() {
randomSeed(analogRead(5));
Serial.begin(9600);
}

void loop() {
if (go == HIGH){
go = !go;
red = random(1,255);
blue = random(1,255);
green = random(1,255);
analogWrite(11,blue);
analogWrite(10,green);
analogWrite(9,red);
Serial.print("red =");
Serial.println(red);
Serial.print("blue =");
Serial.println(blue);
Serial.print("green =");
Serial.println(green);
}
}

Basically the Arduino will generate three random numbers and use those values on the PWM pins to display a random colour with the RGB LED. These values are also sent via serial back to the PC to view. I wrote the program to only run once so to generate a new colour the reset button must be used. I was happy with how the program ran but disappointed with the physical output as the colours do not "blend" well enough.

Monday, March 1, 2010

Dark LDR, Turn on LED (Task 28)

Sinple program that reads the light levels from the LDR and will turn an LED if it is dark and off if it is light:

int reading;

void setup() {
pinMode(13,OUTPUT);
Serial.begin(9600);
}

void loop() {
reading = analogRead(0);
if (reading < 200) {digitalWrite(13,1);}
else
{digitalWrite(13,0);}
}

Catch Up on Missed Tasks (Tasks 4, 5)

I've been treating this as a sort of code dump so I'm going to catch up on some of my "wordy" tasks in this post.

4)Check out all the sites related to the list in the embedded notices blog.
Write a sentence about what each one does. You don't have to be very familiar with each one.

Arduino Environment: This is the compiler used for writing and uploading code to Arduinos. It also has a built in serial monitor for receiving feedback from the Arduinos.

Processing environment: This is an open source programming language that uses visual aids to teach people how to program.

GNU gcc: The GCC is the GNU Compiler Colelction. It is a set of compilers for C, C++, Fortran, Pascal, Java and Ada as well as others. Since these come under the GNU license they are all free and open source.

WikiEducator: A wiki specially for teachers and students that can be used for sharing resources.

Moodle: A free open source e-learning platform that is similar to BlackBoard.

Chip8: This is a specialized programming language and virtual machine for running old school 8 bit games.

Fritzing: A program that is similar to Crocodile Clips. It is used to document breadboard circuits and design PCB layouts. This software is free and open source.

Open Office: More free and open source software. The open office suite is a Microsoft Office replacement.

PeerWise: A website that can be used as a revision tool. Students can ask questions and receive answers as well as view other questions and answers asked by other students.

5) Find 4 more Arduino LED related videos in Youtube, BlipTV etc. Put a link and a two-sentence review about each one in your blog. Be prepared to talk about one or more of them.

Team Fortress 2 Kill Counter

The arduino is constantly monitoring for serial communication to display output from a separate program running on the computer. Once it receives the value via serial it displays it in binary on the LEDs.

LED matrix for an Umbrella

The umbrella has 80 LEDs that are all individually addressable. Its not running purely off an arduino but has a secondary microcontroller to allow the use of so many LEDs

POV Ceiling Fan

From the site instructables (http://www.instructables.com/id/Ceiling-Fan-LED-Display/). Each blade of the fan had a row of LEDs on them that flash on or off depending on what image is being displayed. The LEDs are controlled via shift registers.

Overclocked, Liquid Cooled Arduino

Still technically an LED project as the sketch flashes a single LED on and off.

Combining some new concepts

Working with some ideas i had yesterday with the 7 segment display and the LDRs. I wrote this small program this morning that runs a pattern across the display (this pattern is stored in an array) and the speed at which the pattern is run through is decided by an LDR:

int pattern[8] = {10,11,12,13,7,8,9,13};
int pri;
int sec;
int tri;
int rate;

void setup(){
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
pinMode(11,OUTPUT);
pinMode(10,OUTPUT);
pinMode(9,OUTPUT);
pinMode(8,OUTPUT);
pinMode(7,OUTPUT);
Serial.begin(9600);
}

void loop(){
for (int i = 0; i < 8; i++){
digitalWrite(pattern[pri],0);
digitalWrite(pattern[sec],0);
digitalWrite(pattern[tri],0);
tri = sec;
sec = pri;
pri = i;
digitalWrite(pattern[pri],1);
digitalWrite(pattern[sec],1);
digitalWrite(pattern[tri],1);
rate = analogRead(0);
delay(rate);
}
}

The bread board is set out identical to dice part 2 except the button is replaced with an LDR.

Sunday, February 28, 2010

Dice Part 2

I tracked down a 7 segment LED display so that I could display "real" numbers for each number. Code and Fritzing screen shot follows:

int roll;
int push;

void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
Serial.begin(9600);
}

void loop()
{
push = analogRead(0);
//delay(1000);
if (push > 100)
{
roll = random(1,7);
//generates random number for roll
digitalWrite(13,0);
digitalWrite(12,0);
digitalWrite(11,0);
digitalWrite(10,0);
digitalWrite(9,0);
digitalWrite(8,0);
digitalWrite(7,0);
//resets all segments to off
delay(1000);
Serial.println(roll);
switch (roll) {
case 1:{
digitalWrite(10,1);
digitalWrite(7,1);}
break;
case 2:{
digitalWrite(13,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(9,1);
digitalWrite(8,1);}
break;
case 3:{
digitalWrite(13,1);
digitalWrite(11,1);
digitalWrite(10,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 4:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(10,1);
digitalWrite(7,1);}
break;
case 5:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(8,1);
digitalWrite(7,1);}
break;
case 6:{
digitalWrite(13,1);
digitalWrite(12,1);
digitalWrite(11,1);
digitalWrite(9,1);
digitalWrite(8,1);
digitalWrite(7,1);}
}
}
}

Overlapping wires makes it difficult to see whats going on.

EDIT
The sequence of numbers is not random between runs. To fix this randomSeed(analogRead(5)) is added to void setup().

Binary Dice

Editing my previous code and adding a button (which is modified from the LDR project) I made a simple die program that will randomly select a number between 1 and 6 and output the value in binary:

int onePin = 13;
int twoPin = 12;
int fourPin = 11;
int roll;
int push;

void setup() {
pinMode(onePin, OUTPUT);
pinMode(twoPin, OUTPUT);
pinMode(fourPin, OUTPUT);
Serial.begin(9600);
}

void loop()
{
push = analogRead(0);
//delay(1000);
if (push > 100)
{
roll = random(1,7);
//generates random number for roll
delay(1000);
switch (roll) {
case 1:{
digitalWrite(onePin,1);
digitalWrite(twoPin,0);
digitalWrite(fourPin,0);}
break;
case 2:{
digitalWrite(onePin,0);
digitalWrite(twoPin,1);
digitalWrite(fourPin,0);}
break;
case 3:{
digitalWrite(onePin,1);
digitalWrite(twoPin,1);
digitalWrite(fourPin,0);}
break;
case 4:{
digitalWrite(onePin,0);
digitalWrite(twoPin,0);
digitalWrite(fourPin,1);}
break;
case 5:{
digitalWrite(onePin,1);
digitalWrite(twoPin,0);
digitalWrite(fourPin,1);}
break;
case 6:{
digitalWrite(onePin,0);
digitalWrite(twoPin,1);
digitalWrite(fourPin,1);}
}
}
}

Again readability has suffered due to blogger not liking indentation.

Binary Counter

Was bored in the Project room the other day and wrote this simple program that can count from 0 to 15 in binary using 4 LEDs on pins 13,12,11 and 10:

int onePin = 13;
int twoPin = 12;
int fourPin = 11;
int eightPin = 10;
int del =1000;
int one = 0;
int two = 0;
int four = 0;
int eight = 0;

void setup() {
pinMode(onePin, OUTPUT);
pinMode(twoPin, OUTPUT);
pinMode(fourPin, OUTPUT);
pinMode(eightPin, OUTPUT);
}

void loop()
{
if (one == 1)
{
one = 0;
if (two == 1)
{
two = 0;
if (four == 1)
{
four = 0;
if (eight == 1)
{
eight = 0;
}
else
{
eight = 1;
}
}
else
{
four = 1;
}
}
else
{
two = 1;
}
}
else
{
one = 1;
}
if (one == 1) { digitalWrite(onePin, HIGH); } else { digitalWrite(onePin, LOW); }
if (two == 1) { digitalWrite(twoPin, HIGH); } else { digitalWrite(twoPin, LOW); }
if (four == 1) { digitalWrite(fourPin, HIGH); } else { digitalWrite(fourPin, LOW); }
if (eight == 1) { digitalWrite(eightPin, HIGH); } else { digitalWrite(eightPin,LOW); }
delay(del);
}



The code is written with nested if statements. A way to re-write this code so it would look a lot cleaner and easier to read is to use a case statement (it doesn't help that blogger doesn't carry over my code indentation either).

Analogue Inputs giving Serial Outputs (Tasks 24, 26)

http://www.ladyada.net/learn/sensors/cds.html
This site is a great resource for info on LDRs and the following program is taken from this site.

The code is starting to gain some more practical purposes. With this code (and circuit diagram) you can read the resistance of an LDR (Light De pendant Resistor) and output a value. We use the analogue pins along the bottom edge of the board to read a value between 0 and 1024 from the LDR. That value can then be used to determine the light levels in the room:

int reading;

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

void loop() {
reading = analogRead(0);

Serial.print("Analog reading = ");
Serial.print(reading);

if (reading < 10) {Serial.println (" - Dark");}
else if (reading < 200) {Serial.println (" - Dim");}
else if (reading < 500) {Serial.println (" - Light");}
else if (reading < 800) {Serial.println (" - Bright");}
else {Serial.println (" - Very Bright");}
delay(1000);
}


(this image was copied directly from Peter's Blog http://embeddednotices.blogspot.com/)

In the well lit room D207, the highest value I was able to cause was 724, and the lowest was 34.

Blinking with Serial Output (Tasks 21, 22)

This piece of code will flash an LED on, output a message that can be read by a serial monitor, then turn it off:

void setup(){
Serial.begin(9600);
pinMode(13, OUTPUT);
}

void loop() {
Serial.println("RED");
digitalWrite(13,1);
delay(1000);
digitalWrite(13,0);
delay(1000);
}

This can be made more complex by adding another LED and give corresponding output to match:

void setup(){
Serial.begin(9600);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}

void loop() {
Serial.println("RED");
digitalWrite(13,1);
delay(1000);
digitalWrite(13,0);
Serial.println("BLUE");
digitalWrite(12,1);
delay(1000);
digitalWrite(12,0);
}

Ascending then Descending Flash Rate (Task 19, 20)

This code has two separate loops that are entered depending on the value of a boolean:

int rate = 100;
boolean up = true;

void setup() {
pinMode(13, OUTPUT);
}

void loop()
{
if (up == true){
digitalWrite(13,1);
delay(rate);
digitalWrite(13,0);
delay(rate);
if (rate == 1000){
up = false;
}
else{
rate = rate + 100;
}
}
else
{
digitalWrite(13,1);
delay(rate);
digitalWrite(13,0);
delay(rate);
if (rate == 0){
up = true;
}
else{
rate = rate - 100;
}
}
}

This code starts with an if ... else loop. The first if checks if the up variable is true, if so it enters the ascending loop (if false it enters the descending loop). It then flashes with it's current rate (starts at 100ms) then increments the value by 100 until it reaches 1000. At that point the boolean value is switched to false and it enters the second loop. The LED then flashed with the current rate (1000 when entering the loop) and then decrements the value by 100 until it reaches 100 and switches the boolean again to start from the beginning.

This code can be altered so that the rate of flashing moves in 10ms increments down to 10ms instead of 100ms

int rate = 10;
boolean up = true;

void setup() {
pinMode(13, OUTPUT);
}

void loop()
{
if (up == true){
digitalWrite(13,1);
delay(rate);
digitalWrite(13,0);
delay(rate);
if (rate == 1000){
up = false;
}
else{
rate = rate + 10;
}
}
else
{
digitalWrite(13,1);
delay(rate);
digitalWrite(13,0);
delay(rate);
if (rate == 0){
up = true;
}
else{
rate = rate - 10;
}
}
}

Blinking using a for loop (Tasks 17,18)

The following code uses a for loop to blink the LED on pin 13 5 times after blinking one on pin 12:

void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}

void loop()
{
digitalWrite(12, 1);
delay(500);
digitalWrite(12,0);
delay(500);
for (int i=0; i < 5; i++){
digitalWrite(13,1);
delay(500);
digitalWrite(13,0);
delay(500);
}
}

The number of times that the second LED flashes can be changed simply by changing the for statement for example: for (int i=0; i < 23; i++) will flash 23 times rather than 5

Alternating Blinking (Tasks 11, 12, 13, 14, 16)

Basic program that will alternate between two LEDs flashing with no delay between On/Off

void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}

void loop()
{
digitalWrite(13, 1);
digitalWrite(12, 0);
delay(500);
digitalWrite(13, 0);
digitalWrite(12, 1);
delay(500);
}

You can alter the flashing pattern by changing the delay. For example:

void loop()
{
digitalWrite(13, 1);
digitalWrite(12, 0);
delay(250);
digitalWrite(13, 0);
digitalWrite(12, 1);
delay(1000);
}

This code will cause the LED on pin 13 to flash for a short period, then the LED on pin 12 to flash for a longer period of time. You could also cause the opposite by swapping the delay values.

This code is similar to the first program except there is a delay between each LED being turned on:
void loop()
{
digitalWrite(13, 1);
delay(500);
digitalWrite(12, 0);
delay(500);
digitalWrite(13, 0);
delay(500);
digitalWrite(12, 1);
delay(500);
}

This is yet another flashing pattern where one led flashes twice then the other once then repeat:
{
digitalWrite(13, 1);
delay(500);
digitalWrite(13, 0);
delay(500);
digitalWrite(13, 1);
delay(500);
digitalWrite(13, 0);
delay(500);
digitalWrite(12, 1);
delay(500);
digitalWrite(13, 0);
delay(500);
}

Thursday, February 25, 2010

Blink (First Arduino Program) (Tasks 7,8,9,10)

Here is my version of blink:
void setup() {
pinMode(13,OUTPUT);
}

void loop()
{
digitalWrite(13, 1);
delay(500);
digitalWrite(13, 0);
delay(500);
}

It works off pin 13. Turns the LED on, waits ~500ms and turns the LED off, waits ~500ms again and then restarts the loop.

An easy way to vary this program would be to increase or decrease the speed of the blink. An example of code that would cause a long delay between short blinks would look like this

digitalWrite(13, 1);
delay(250);
digitalWrite(13, 0);
delay(1000);

This would turn the LED on for ~250ms and then turn it off for ~1 second. You could also do the opposite with this code

digitalWrite(13, 1);
delay(1000);
digitalWrite(13, 0);
delay(250);

By changing both the delays to 10ms, the LED appears to constantly stay on and not blink, at 20ms it appears to “flicker” and at 40ms it begins to flash.