CSCI 255 — Making gates with an Arduino

A bit about the Arduino

Making sure it can works

There are a few things we must verify before we start this lab.

Getting in the right group

Start up a command-line session and type the following command:
    id
This will list the Linux groups to which you belong. Make sure that you are a member of the group dialout. If you aren’t, get in touch with the instructor.

Making sure the Arduino is recognized

Using the USB cable, connect your Arduino to your workstation. Use should be able to use the USB ports on the monitor. List the devices on the USB bus with the following command:
    lsusb
If you don’t see the Arduino listed, get in touch with the instructor.

Making sure the Arduino device file is present

Type the following command to make sure the Linux has allocated a device file for your Arduino.
    ls -l /dev/ttyACM*
You should a device file name similar to /dev/ttyACMX which is writeable by members of the dialout group. Remember the name!

Having up-to-date software

The Arduino IDE is frequently updated due to the steady release of new Arduino-compatible devices. We need to use a more recent version of Arduino than is distributed with Ubuntu. Type the command:
    /usr/local/bin/arduino &
If it doesn’t work, again get in touch with the instructor. You should be able to lock the latest version of Arduino to your Launcher by dragging /opt/share/applications/arduino.desktop to the Launcher.

An exploration of the Arduino, ATmega328, and C++

In this part of the lab, you are going to turn an LED on and off as you are introduced to many things that will appear later in this course.

Connecting the IDE to the board

Make the following choices in the Arduino IDE to direct the IDE’s attention to your board.

Open Blink tutorial, However, don’t use a breadboard! On the Arduinos we have, pin 13 is already connected to a built-in LED and current-limiting resistor. Also, don’t connect an LED to your Arduino! Cut-and-paste the blink program into a new sketch and run it. You should see the LED blink.

Change the blink rate. Make it blink as fast as you can without it looking like a somewhat dimmed LED.

Blinking the LED with memory

In Chapter 8 of the textbook, you will read about how “special function registers” are used to control I/O in embedded processors. The special function register looks like a memory location to a C program. In this section, you’ll skip the digitalWrite and write directly to the pin.

Printing in the serial monitor

You will use two very important features of the Arduino language in this part of the lab. Take a look at the following references so that you can do the next part of the lab.

Add a call to Serial.begin(9600) in your setup function to initialize the serial port. Now add a statement to print the variable PORTB in binary (using BIN) in your loop function after each call to digitalWrite.

Build and run your program. You will need to do ToolsSerial Monitor to see the output of your program.

Be sure PORTB is being printing within the serial monitor. The output line should look something like the following:
  PORTB=11001100
Read the documentation for Serial.print() until you get this right.

Special function registers of the ATmega328

The variable PORTB is a special memory location within the ATmega328 chip. Writing to this location sets the output of pins 8 to 13 of the Arduino to either 0 (low) or 1 (high). In embedded microcontrollers these pins are called GPIO, general-purpose input/output, pins.

Look at the Arduino page for port manipulation to see how to change PORTB without calling DigialWrite, along with a reason why you might want to do this.

Modify your loop function so that it turns the LED on and off directly, that is, with statements similar to
    PORTB |= Bxxxxxxxx ;
and
    PORTB &= ~Byyyyyyyy ;
Try to figure out the xxxxxxxx and yyyyyyyy on your own. It will be good practice with bit manipulation.

Big hint: Pin 13 corresponds to bit 5 of PORTB. By the way, the rightmost bit is number 0.

C++ implementation of Arduino classes

Serial is an object within the C++ class HardwareSerial and print is a method of HardwareSerial. The HardwareSerial class extends the Stream class, and The Stream class extends the Print class.

Every Computer Science guru must know a little C++. So let’s take a guided tour of some C++ modules. Just be glad we no longer teach CSCI 202 using C++.

First connect to the Arduino GitHub in a new tab and navigate to the directory hardware/arduino/avr/cores/arduino. Take a look at the following files: (I’m serious. You need to know how to use GitHub.)

Next, take a look at how the C code implements GPIO in wiring_digital.c where you will find the C function Digital Write (around line 137). Setting an individual bit is accomplished by use of masking operations inside this if statement:

    if (val == LOW) {
        *out &= ~bit;
    } else {
        *out |= bit;
    }

The * in the above code segment is the C and C++ dereference operator for pointers. You will meet it in Appendix C.

Most likely, the instructor will guide you through this.

Input to the Arduino

Right now, your Arduino has only one output. In this part of the lab, you will also process input.

Start by taking a look at an Arduino lesson, from Adafruit, on Digital inputs. Best to open it in a second browser window.

Building a breadboard

Stop the Arduino IDE and unplug your Arduino.

Get a breadboard (the half-size and even the tiny will work fine) and create a circuit similar to that shown in Adafruit’s digital inputs lesson but include a second LED connected to the Arduino output pin of your choice. (I suggest pin 3.)

You must use a current limiting resistor for each LED, because only pin 13 is connected through a resistor on the Arduino board. You do not need a pullup resistor for your switches, because there is an internal pullup of 20 to 50 kΩ in the ATmega328 chip. This is common for microcontroller chips.

Wire up your breadboard so that in has two input switches and two output LED’s.

Have someone, maybe a fellow classmate, check your wiring.

By the end of this class you should know how to wire up an LED and button switch without looking at any reference.

Loading the initial program

Restart the Arduino IDE and cut-and-paste the program from the digital inputs lesson into a sketch.

Test the program.

Improving the program

Meaningful variable names

Change the names of the variables to something more suggestive than buttonApin and ledPin. I suggest you use leftSwitch, rightSwitch, leftLight and rightLight to hold the pin numbers. However, be like a real C programmer, and declare the pin variables with the const modifier. (Google for it.)

Modify your program so that the left switch turns the left LED on and off, and right switch turns the right LED on and off,

Meaningful function names

Think a little about how your program reacts to the switches and LED’s. What value is read when then switch is pressed: HIGH or LOW? What value is written to turn on the LED: HIGH or LOW? It can be confusing to remember if the “output” of the switch was 0 or 1 when it was pressed. Let’s write two functions to help us out here.

Keep in mind that in C/C++, 0 is false and non-zero is true.

These two functions are very short, probably just a single ifelse statement. (You should be able to write the function headers all by yourself with no references. Don’t interview for a job before you can do this.)

Aim for a loop that looks like this.

void loop() 
{
  boolean leftPressed = switchRead(leftButton) ;
  boolean rightPressed = switchRead(rightButton) ;
  ledWrite(leftLED, leftPressed) ;
  ledWrite(rightLED, rightPressed) ;
}

By the way, boolean is really just another way of saying int in C. There really isn’t a boolean type. Change the boolean to int to prove you are a true or, at least old-fashioned, C programmer.

Again, test your program to verify this change.

The combinational gates

Modify your program so that the left LED displays the NAND of the two inputs and the right LED display the NOR. Do this without any ifelse statements in the loop(). Just use C’s logical operators and two simple statements.

If you can’t remember NAND and NOR try out this JavaScript page.

The SR latch

Now create an SR latch with your Arduino. Assume your switches are S and R and your LED’s are Q and Q'. You may assume that no one ever presses both S and R at the same time. If they do, your latch is allowed to self destruct.

You may want to add an extra variable to your program that records the present value of the flip-flop, but this really isn’t necessary.

Show off your latch.

If you can’t remember the SR try out this JavaScript page.

The D latch

The D flip-flop has one data input and one clock, or enable, input. The D flip-flop “reads” and remembers its data input only when the clock is 1. While the clock is 0, changes in the data input or ignored. The initial state of the flip-flop should be 0 for the D.

Create a D latch with an Arduino program. This one might just be a little easier than the SR latch. Remember, the initial value of the D flip-flop should be 0.

If you can’t remember the D latch, try out this JavaScript page.

The D positively edged flip-flop

The D flip-flop has one data input and one clock input. The D flip-flop “reads” and remembers its data input only when the clock has changed from 0 to 1. This means you’ll have to write your Arduino to look for changes in the clock button. You will need a value to store the “old” clock.

Create a D flip-flop with an Arduino program. This time the solution is a little harder. Your program must remember the old value of the clock so to determine when the clock has changed from 0 to 1.

If you can’t remember the D flip-flop try out this JavaScript page.

The T flip-flop

The T flip-flip has two inputs, a trigger, T, and a clock. The flip-flop will toggle its output on the positive edge of the clock if T is 1. The initial state of the flip-flop should be 0 for the T. Go ahead and try out the T’s JavaScript page.

Create a T flip-flop Arduino program.

Test your program by pressing the clock button about once a second while the T button is held down. Sometimes it may not change.

Switch (de)bounce

Generally when you press a switch it will bounce on and off a few times. The bounces are very quick. You won’t see them when turning on a desk lamp. However, computers are so fast that the Arduino may “think” you are really pressing that switch several times a second. Take a look at some nice screenshots illustrating switch bounce from the Switch Bounce and How to Deal with It article at All About Circuits

You can fix switch bounce mechanically by using mercury in the switch, but too much mercury can make you mad. You could also use a low pass filter, but that requires a capacitor and a resistor and clearly costs more.

Alternatively, you can add a call to delay() to your program to make it wait for the bounces to subside.

Try to debounce the switch using delay. You have to call delay whenever the switch changes, even if it is changing from 1 to 0.

You may need to experiment to find the best value for the argument to delay.

The problem with delay

Avoid delay in embedded systems. When your Arduino sketch is executing delay() it does nothing else. That means it may miss other important events.

Once you start using delay(), it becomes hard to break the habit. The designers of Processing tried to remove delay() between versions 1 and 2 of Processing, but the delay() addicts demanded its return. It is back in Processing, but is no longer mentioned in the Processing reference page. By the way, JavaScript does not have a delay operator, but jQuery does.

Also never use Arduino interrupts to debounce a switch. That is simply silly.

Using timers to avoid using delay

Fortunately there are many on-line tutorials on how to use timers to debounce a switch. Read the Debounce tutorial on the Arduino web site to see how this is done. Better your, take a look at the Arduino tutorial on avoiding delay() for more information.

Debounce your switch with timers. You may need to tune the debounce “delay” to get your program to working smoothly.

Don’t leave so soon!

If you have completed all these tasks, connect to Autodesk Circuits and see if you can make one of those nice diagrams for your breadboarded circuit.