Image of a steam locomotive with the caption Pittsburgh Locomotive Works

(image from Hill, John A. Locomotive engineering: a practical journal of railway motive power and rolling stock. New York: A. Sinclair, J.A. Hill. 1892. Via the Internet Archive)

due at the start of class 4, Monday January 28th

Your work assignment from the Pittsburgh Train Company

The Pittsburgh Train Company (PitTraCo) needs a new light-blinking system, and they think you’re the right person for the job. They use signal lights to communicate with the train engineers, and want to replace the 80 year old system they’ve been using with new electronically controlled hardware.

First, you’ll build a prototype system, just to prove to them that you are able to use a potentiometer to change the rate at which some lights blink:

Warmup/prototype

  • Input: one potentiometer.
  • Output: two LEDs.
  • Behavior: the two LEDs alternate blinking at a steady pace at all times; adjusting the position of the potentiometer changes the rate at which they blink: 🔴🔴

Once you show them that prototype, they’ll definitely be impressed. Then, you’ll need to make it a little better: you’ll have to upgrade it to a system that can change blinking modes, so they can are able to send two different kinds of signals to the train engineers. That is your real assignment:

Assignment

1. Build a light-blinking system matching the below parameters:

  • Input: one potentiometer and one momentary pushbutton
  • Output: two LEDs and serial feedback
  • Behavior: the pushbutton acts as a mode selector, and the potentiometer acts to change the rate of the LEDs blinking

Explanation of behavior: When the pushbutton is not pressed, the hardware behaves exactly as described in the warmup above, including that the potentiometer changes the rate of blinking: 🔴🔴
However, while the pushbutton is pressed, the two LEDs blink both on at the same time, both off at the same time, instead of alternating: 🔴🔴 (The potentiometer can still be used to change the rate of blinking during this time.)

At all times, once per on-blink, there should be serial feedback formatted like this:

Alternating mode. Blinking once per 123ms.
Alternating mode. Blinking once per 456ms.

where the values such as 123ms are the actual blinking rate, as reported in milliseconds. While the mode-changing button is pushed, the serial feedback should instead read:

Unison mode. Blinking once per 234ms.
Unison mode. Blinking once per 567ms.

1a. Bonus (strictly optional, if you have extra time)

“Wow,” the PitTraCo executive says, leaning back in her cushy chair, “that was pretty good. We would love just one more feature, please…”

PitTraCo needs to be able to send an automated emergency signal to their train engineers. At the push of a button (you’ll need a second momentary button), the LEDs should interrupt whatever they’re doing and blink in unison three quick blinks, pause, three quick blinks, pause, three quick blinks, pause, and then return to their regular blinking after.

When the emergency signal button is first pressed, the serial feedback should read:

*****Emergency signal dispatched!*****

and then once the triple signal has been completely transmitted, the serial feedback should read:

-----End emergency signal. Resuming regular service.-----

2. Use Canvas to submit your code

Your file name should be andrewid-hw-3.ino, where andrewid is your own AndrewID. Submit the file to this Canvas assignment. Be sure to add a standard comment block at the top of the code as specified in the course policies page.

Use good code practice: add comments as needed to help explain non-obvious things to any future readers.

3. Hand in a schematic of your system on a piece of blank 8-1/2”×11” paper

Draw neatly; the emphasis is on legibility and clarity, but it need not be precisely rendered. Use standard symbols for all circuit elements. Be sure your name is on the page, of course.


Hints please!

Potentiometer

In class we learned about how to use the analogRead() function to read a potentiometer’s position. To review: we initialize the potentiometer pin by running this line inside the setup:

pinMode(A0, INPUT);

We can later perform an analogRead() of that pin at any time we’d like to find its current value. This could look like this inside the loop:

int potVal; // create a variable with a name that's short for 'potentiometer value'
potVal = analogRead(A0); // perform an analogRead on pin A0 and then save that value into the variable potVal

In the above case, the variable potVal will contain the most recently found value, so we should expect it to change very often.

What you can expect from analogRead()

The way the analogRead() function runs on our Uno R3 hardware, we are guaranteed it will always return a value between 0 and 1,023, inclusive. This number is a linear approximation of the voltage present on the pin you are measuring. To be clear:

voltage present at a pin ÷ 5V = analogRead() of that pin ÷ 1,023

A few values to illustrate the above equation:

volts analogRead() value
0 0
1 205
2.5 512
4.5 921
5 1023

Adding a button

Tactile pushbuttons are available in bin 12, row 4, column 1 in the Physical Computing Lab.

Consult the course tutorial page on buttons and switches to learn how to wire up a tactile pushbutton for this homework assignment. Pay careful attention to:

  • the need for a “pull-down” resistor, and
  • the non-intuitive internal wiring of a tactile pushbutton.

other points

Q: How do I check to see if a button is in a particular position? By running an if test on its latest observed value. For instance, after running code that detects a button’s state and loads it into the value buttonState:

if (buttonState == HIGH){
    // code in between these curly brackets will run only if the button state is "high"
}
else {
    // code in between these curly brackets will run otherwise
}

You can test for equality using the == operator, as shown above1. You can test for greater than by using the > operator, as in: if (pot1Val > 10), and likewise you can test for less than just as you’d expect: if (pot1Val < 10). Finally, there’s a not equal to operator worth knowing about, written !=, used if (pot1Val != 10) (but note that probably isn’t so useful for this assignment).

For a review of if, head over to its Arduino language reference page.

Q: How can I change the rate of blinking? Well, remember how earlier we put a number into our delay() statements, like delay(1000) or delay(20), etc.? Instead of putting a number into the parentheses, you can put a variable in there—and whatever value the variable has, will be the length of the delay in milliseconds.

Q: How can I format the serial feedback with words and numbers in it? Please see this section of the “Code bites” tutorial page to read more about this topic.

Collaboration and help

Just the same as Homework #2: You are welcome to collaborate with your classmates, friends, etc., on this homework assignment. Look up help in any source that you find useful, including the web, reference books, whatever you’d like to use.

However:

  1. You must type out the code you use. That means that while you can copy parts of it from another source, you have to type every single letter yourself! We’re building muscle memory. (If you work with a partner, you can both have identical code, but you must both type it out yourself.)

  2. You must build your own circuit. You can make the same circuit your friend does, but you have to actually use your own hands to make yours.

Questions? Concerns? Email the instructor or TA and ask! We’re here to help.


Footnotes:

  1. Why use == and not simply = to test for equality? This is a moment when we must remember that writing programs in C is different than writing out math equations; the = symbol has a particular meaning, called assignment, which is to take the value on its right and “assign” it to the variable on its left, as in x = 10. While == asks the question “are they equal?” on the other hand = says “now the thing on the left is equal to the thing on the right.” Don’t confuse these!