Year 10 Transition Activity at Gungahlin College

Welcome to our Year 10 transition day, and more specifically the IT Class we’ve got prepared for you.

One of the subjects we offer here at Gungahlin College is an introductory programming class that teaches you the fundamentals of how to program computers to do what you want them to do. We explore a number of different programming languages over the two years, and we’ll program a range of devices from desktop computers through to smartphones and embedded systems. The programming you do for each is a little bit different, and today we’re going to look at some of the intricacies of embedded systems programming using Arduino.

We’ve issued each pair an ed1 board, the details of which you can find here. It has been developed by National ICT Australian as a teaching tool for a couple of competitions and programs run by the National Computer Science School, and contains a whole heap of input sensors and output components that you can interact with directly. In today’s lesson, we’ll be exploring the:

To get started, you’ll need to open the Arduino IDE – you’ll find it in the Start menu under Arduino. It has been pre-installed for you and contains everything we need to program our boards. You’ll also need to collect a board and USB cable from the teacher.

When you get back to your computer, plug the board into the USB cable and the USB cable into the computer. It should light up and the board will start running the last program that was uploaded onto it. The way embedded systems work is that they store a single program that executes continuously once it has been loaded, so when the power is cycled to the board it simply restarts the program. There is a reset button on the board that also restarts the current program – find it now and press it to start the program again.

Back to the IDE – the first thing you need to do is use the Tools menu to select the:

  • Board -> Ardunio Duemilanovae w/ ATmega328
  • Serial Port -> COMX (where X is the highest number available in the list)

This ensures the computer knows how to communicate with the board, and does so over the right connection.

Now that’s done, we’re ready to start writing our first program. We’re going to start by loading a pre-written program that writes custom characters to the LCD screen – it allows us to draw whatever we want by lighting up the individual pixels on the screen. Delete everything in the Arduino IDE window, then copy and paste the code below into the window.

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(6, 7, 8, 2, 3, 4, 5);

// make some custom characters:
byte heart[8] = {
 0b00000,
 0b01010,
 0b11111,
 0b11111,
 0b11111,
 0b01110,
 0b00100,
 0b00000
};

byte smiley[8] = {
 0b00000,
 0b00000,
 0b01010,
 0b00000,
 0b00000,
 0b10001,
 0b01110,
 0b00000
};

byte frownie[8] = {
 0b00000,
 0b00000,
 0b01010,
 0b00000,
 0b00000,
 0b00000,
 0b01110,
 0b10001
};

byte armsDown[8] = {
 0b00100,
 0b01010,
 0b00100,
 0b00100,
 0b01110,
 0b10101,
 0b00100,
 0b01010
};

byte armsUp[8] = {
 0b00100,
 0b01010,
 0b00100,
 0b10101,
 0b01110,
 0b00100,
 0b00100,
 0b01010
};
void setup() {

 // create the heart character
 lcd.createChar(1, heart);
 // create the smiley character
 lcd.createChar(2, smiley);
 // create the frownie character
 lcd.createChar(3, frownie);
 // create the armsDown character
 lcd.createChar(4, armsDown); 
 // create the armsUp character
 lcd.createChar(5, armsUp); 

 // set up the lcd's number of columns and rows: 
 lcd.begin(16, 2);

 // Print a message to the lcd.
 lcd.print("I "); 
 lcd.write(1);
 lcd.print(" Arduino! ");
 lcd.write(2);

}

void loop() {

 // read the potentiometer on A0:
 int sensorReading = analogRead(A3);

 // map the result to 200 - 1000:
 int delayTime = map(sensorReading, 0, 1023, 200, 1000);

 // set the cursor to the bottom row, 5th position:
 lcd.setCursor(4, 1);

 // draw the little man, arms down:
 lcd.write(4);
 delay(delayTime);
 lcd.setCursor(4, 1);

 // draw him arms up:
 lcd.write(5);
 delay(delayTime); 

}

Assuming you have now completed all of the above steps in the order specified, you should be able to click the Upload button (The little sideways arrow) and you’ll upload the program to the board. You’ll see when the program is uploading because you’ll see a progress bar on the IDE and you’ll see the little Tx/Rx lights (near where the USB cable plugs in) flicker to indicate data is being transferred and received.

When the program is finished, you should see a message on the LCD screen, and a few custom icons like a heart, smiley face and man. That’s what your program does!

But, you can also interact with it. The dial on the bottom left of the board (called the potentiometer) can be turned, and when you turn it you should see the speed with which the little man flap his arms up and down change.

Let’s take a look at the program in more detail:

// include the library code:
#include 

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(6, 7, 8, 2, 3, 4, 5);

The above code block does two things – it includes the library (the pre-written code that defines what the LCD can do) so that we can make use of it to manipulate the LCD screen more easily. Without this library, writing to the LCD can be very difficult to do. Once we’ve included it, we then initialise the LCD panel by connecting the pins on the board up correctly – this makes sure the computer knows which signals to send to which pins that connect the LCD to the rest of the ed1. The code above is only ever run once – and needs to be done first so that we can make use of the LCD throughout the rest of our program.

// make some custom characters:
byte heart[8] = {
 0b00000,
 0b01010,
 0b11111,
 0b11111,
 0b11111,
 0b01110,
 0b00100,
 0b00000
};

byte smiley[8] = {
 0b00000,
 0b00000,
 0b01010,
 0b00000,
 0b00000,
 0b10001,
 0b01110,
 0b00000
};

byte frownie[8] = {
 0b00000,
 0b00000,
 0b01010,
 0b00000,
 0b00000,
 0b00000,
 0b01110,
 0b10001
};

byte armsDown[8] = {
 0b00100,
 0b01010,
 0b00100,
 0b00100,
 0b01110,
 0b10101,
 0b00100,
 0b01010
};

byte armsUp[8] = {
 0b00100,
 0b01010,
 0b00100,
 0b10101,
 0b01110,
 0b00100,
 0b00100,
 0b01010
};

The code above creates all of our custom characters using arrays of bytes – groups of single bits of information that can take on the values of 1 and 0. Here, a value of 1 indicates that the display should show a black dot, and a value of 0 means the display should leave that pixel clear.

You’ll notice that all of the bytes in the arrays are made up of 5 bits, and that each array has 8 bytes in it. This means that each character is made up of 40 individual pixels in a box that is 5 wide by 8 high. If you look closely, you’ll see how the patterns of 1s and 0s create the shapes we’re after – the heart is probably the easiest one to see, but the other shapes are also visible now that you know what you’re looking for.

We create the custom characters at the top of the program so that they can be used everywhere we want them to be used.

void setup() {
...
}

The setup() function is run as soon as the board is turned on, and is only run once. We can put any code we want to inside the curly braces (where the … is above) and that code will be run in that order as soon as the board has power. Let’s see what we do inside our setup() function:

 // create the heart character
 lcd.createChar(1, heart);
 // create the smiley character
 lcd.createChar(2, smiley);
 // create the frownie character
 lcd.createChar(3, frownie);
 // create the armsDown character
 lcd.createChar(4, armsDown); 
 // create the armsUp character
 lcd.createChar(5, armsUp); 

First, we create the characters by assigning each of our patterns to a single integer value (a number). You’ll see that the lcd.createChar() function requires 2 parameters – the first is the number you want to use to represent that character, and the second is the character itself (so in our case, 1 will be for the heart we created earlier). We assign all 5 of our characters to a number.

 // set up the lcd's number of columns and rows: 
 lcd.begin(16, 2);

This code tells the program that the LCD has 16 columns and 2 rows.

 // Print a message to the lcd.
 lcd.print("I "); 
 lcd.write(1);
 lcd.print(" Arduino! ");
 lcd.write(2);

Using the lcd.print() command, we can write text to the LCD. The print command understands how to display each of the standard symbols on the keyboard (letters, numbers etc), so we can specify any words or phrases we might want directly to print(). Notice how we use quotes (“) around the words? That’s so the program knows we want to print those actual characters to the screen.

You’ll see that we then use the lcd.write() function, and that corresponds to our heart on the display. By specifying a number inside the brackets of the write() function, it tells the lcd to draw the custom character we set up earlier to be assigned to our number 1. Notice also that we don’t use quotes this time – the value 1 will be substituted instead of the array of bytes we made earlier.

You can mix write() and print() statements together to print a combination of custom and regular characters to the screen. It will print them in order from left to right.

void loop() {
...
}

In addition to our setup() function, we also need a loop() function to be written. The loop() function runs as soon as the setup() function finishes, but unlike the setup() function, the loop() function repeats forever, so when it it finishes it starts itself again.

Let’s see what happens in the loop function:

 // read the potentiometer on A0:
 int sensorReading = analogRead(A3);

 // map the result to 200 - 1000:
 int delayTime = map(sensorReading, 0, 1023, 200, 1000);

The first two lines of code read from the potentiometer (it is on pin A3) and map the result of the reading from a number between 0 and 1023 to a number between 200 and 1000. What this means is that when you turn the potentiometer to a zero value, the program sets the delayTime to a value of 200 (instead of 0), and when the potentiometer is at 1023 it sets delayTime to 1000. This makes it easy for us to convert one range of numbers to a more useful one. The computer automatically works out what values the numbers between 0 and 1023 take on by breaking the range up into equal parts.

 // set the cursor to the bottom row, 5th position:
 lcd.setCursor(4, 1);

 // draw the little man, arms down:
 lcd.write(4);
 delay(delayTime);
 lcd.setCursor(4, 1);

 // draw him arms up:
 lcd.write(5);
 delay(delayTime); 

}

By writing the above code into the loop() function, the program will repeatedly perform the following code:

  1. It will set the cursor to the fifth position on the second row (we count the first row/column as number 0, so the second is 1, third is 2 and so on…)
  2. It will then draw the armsDown character (character number 4)
  3. It will then wait for the delayTime worked out by the potentiometer (i.e. it will do nothing for between 200 and 1000 milliseconds)
  4. It will then set the cursor back to the fifth position on the second row, and…
  5. Overwrite the armsDown character with the armsUp character (5)
  6. Then wait for another 200-1000 milliseconds

Since the reading is taken each time that block of code starts, every time the loop gets run a different value can be read from the potentiometer, which is what allows you to alter the time that it takes for the man to wave his arms up and down.

So, thats what our code does – cool, huh? Now its your turn to do something of your own using the bit of knowledge we’ve given you today. Here are some tasks you can try for yourself, and don’t forget, ask for help if you need it:

  1. Write your own message to the LCD screen, and try centring your top and bottom rows;
  2. Make up your own set of custom characters, and write them to different locations around the board;
  3. Use the potentiometer to change between different custom characters/numbers on the screen;
  4. See if you can make the potentiometer move a character across/around the screen; and
  5. If you finish the above, ask what other activities you might be able to do.

Leave a Reply