Homework 3: More asynch learning, and a train light
complete by the start of class on Monday, Feb. 15th (note that this assignment runs for one week)
(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)
1. Round out the asynchronous lectures
There is one last module of asynchronous lectures on the course Canvas site, called “More inputs and outputs.” This comprises about two hours of videos, with interspersed exercises and challenges.
Once you’ve finished the lectures, then you will have achieved quite a bit of technical learning in just two weeks of class! Once you’re proficient at using the basic functions of the Arduino, we can effectively use the tool to our will. And the first thing you’ll do with your newfound skills is build a light-blinking system as specified below.
Submit at least one asynch discussion question
By Monday, 2/15, every student should have submitted at least one question to the asynchronous homework questions board on the course Canvas site. If you’ve already submitted a question (or more than one) this semester, you do not need to submit a new one for this assignment.
Before submitting your question, take a glance at the ones that are already up, and make sure it’s not a duplicate.
If you don’t organically have a question that you’re actually wondering about, then think of a question that you could have, or reasonably expect that a classmate could have, and post that.
2. 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.
A small note on code style: please refer to this section of the Code Bites page for our preferred style for naming pins.
Below are four different bonuses you may wish to attempt if you didn’t spend too long on the technical assignment above. You can get two maximum extra points total for completing any bonus (i.e. completing more than one bonus won’t confer more bonus points), but I’d encourage you to do as many of these as you’d like for your own learning.
1a. An additional button 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.-----
1b. An ultrasonic ranger bonus (strictly optional, if you have extra time)
“I’m sick of my track attendants falling asleep on the job,” says the PitTraCo executive. “I’d love some sort of system to automatically signal a train to stop when another train is approaching.”
“Aha!” you think to yourself. “I can build one of those!”
Build one of those, using the HC-SR04 ultrasonic ranger. The blinking machine should still work as described in part 1 of the assignment, but if something comes within 5cm of the ultrasonic ranger:
- the two lights should turn steady on (not blinking), and
- the serial feedback should read:
*****Automated proximity detector triggered*****
When there’s no longer something within 5cm of the ultrasonic ranger, the system should resume working as it did before.
1c. A sound-producing bonus (strictly optional, if you have extra time)
“We should also think about automating the train horns,” the PitTraCo executive says. “Why rely on people when we could just use machines to do the work?”
Build a system that will make a beep-beep-beep whenever the rate-of-blinking potentiometer is set to any value between 100ms and 150ms.
The beeping should come in groups of three, and when the beeping starts the system should send a Serial signal back to the computer reading:
+++++Beep beep beep!+++++
To build this, you have three choices of noisemaking hardware included in your kit:
- active piezo buzzer (simplest—just power on to beep)
- passive piezo buzzer (a teensy bit harder in software)
- speaker (same software as passive piezo buzzer, but requires one more electronic component to drive)
If you wish to use either piezo buzzer, the wiring will be very simple: a digital output goes straight into the buzzer’s positive leg, and the buzzer’s negative leg connects to ground. No resistor is needed.
If you wish to use the speaker, you’ll need to use a simple transistor circuit to safely and effectively power it; see the transistor tutorial page for implementation information.
To make a tone come out of the passive buzzer or speaker, you’ll need to use the built-in tone()
function; see the relevant Arduino reference page to learn how to use this. (It’s quite straightforward.)
1d. An LCD display–driving bonus (strictly optional, if you have extra time)
“What if our computers break, though?” the PitTraCo executive asks. “This happens all the time. We’re still on Windows 95, so it’s really an issue.”
“Maybe think about moving to Linux…” you mutter under your breath. But out loud you say, “I can add a dedicated display to show the information independently of any computer.” The executive’s face lights up with amazement.
Add a 16×2 LCD character display to your device. It should show the same sort of messages as the computer, but reformatted slightly to match the smaller screen, as shown below.
For alternating mode, display:
alternating mode 123ms per blink
For unison mode, display:
unison mode 456ms per blink
If you’re also adding an emergency stop signal, when it’s triggered, display:
!! Emergency !! !! Emergency !!
followed by
Regular service now resuming.
If you’re also adding the train horn, when it’s triggered, display:
beep beep beep! !beep beep beep
The course tutorial page on LCD displays has useful information to get you started, but note that this tutorial is written for a slightly different piece of hardware (one which has an additional “I²C backpack”). The Arduino reference page for the LiquidCrystal library is very helpful, and this sub-example shows how to wire up the board and includes working sample code.
2. Use Canvas to submit your code and schematic
Submit your .ino
code (downloaded from Tinkercad or written in the Arduino IDE), as well as your schematic and block diagram (in .jpg
format), to this Canvas assignment.
For your code: Be sure to add a standard comment block at the top of the code as specified in the syllabus. Use good names for your variables and good formatting practices. Add comments as needed to help explain non-obvious things to any future readers.
For the schematic and block diagram: use draw.io to put two drawings on the same page: a functional block diagram illustrating all of the elements of the system, as well as a schematic showing your particular implementation. Use standard symbols for all circuit elements. Refer to the course schematic reference page for a description of standards and expectations.
3a. If you’re in person on Monday 2/15: show your working device in class
I’ll go around at the start of class and (with gloves on) try your device out quickly.
3b. If you’re remote on Monday 2/15: submit a video via Canvas
Remote participants should upload a video of their device working to Canvas. It has to be clear and show you making multiple adjustments and trying all the modes, etc., and it should also show serial feedback.
Collaboration and help
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:
-
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.)
-
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 me and ask! I’m here to help.
Grading rubric
points | part |
---|---|
5 | blinking matches spec, and rate/pattern properly affected by potentiometer and button |
2 | serial feedback as per specification: the correct messages at the correct time |
1 | LEDs wired properly: each driven by its own Arduino output, with its own 270Ω current-limiting resistor |
1 | potentiometer wired correctly |
3 | schematic and block diagrams properly formatted and electrically valid |
5 | code written with correct comment block and reasonable formatting throughout |
2 | bonus (blinking and serial messages as per spec, or proxmity detector as per spec) |
17 | total |
Hints please!
Potentiometer
You can 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. Further operators:
- greater than:
if (potVal > 10)
- less than:
if (potVal < 10)
- greater than or equal to:
if (potVal >= 10)
- less than or equal to:
if (potVal <= 10)
- not equal to:
if (potVal != 10)
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?
Here’s an example:
Serial.println((String)"This first variable's value is " + varOne + ", and the second one's is " + varTwo);
The key part here is the (String)
at the beginning of the stuff in the parentheses; that will turn everything in there into text which the Serial.println
command knows how to read. Please see this section of the “Code bites” tutorial page for more on this topic.
Footnotes:
-
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 inx = 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! ↩