Homework 4: Nightlights
due at the start class on Wednesday, Jan. 29th
Assignment: a reasonable nightlight
You’re hired to help build a prototype nightlight. Your bill of materials includes:
- Inputs
- a single-pole double-throw switch (tutorial link)
- a momentary pushbutton (tutorial link)
- a potentiometer
- a photoresistor, a type of light sensor (tutorial link)
- Outputs
- an LED
Serial
monitor feedback
Nightlight operation
When it gets darker in the room (less light falling on the light sensor), the illumination LED should turn on. When it gets brighter in the room, the LED should turn off.
Turning the potentiometer adjusts the “setpoint,” i.e. the threshold at which the illumination LED turns on/off.
Mode switch
The single-pole double-throw switch changes the nightlight into a daylight. That is to say, when that switch is in “daylight” position, the light turns on when it’s bright out, and off when it’s dark out. (The switch can be flipped to “daylight” or “nightlight” mode whenever the user wants.) The potentiometer still adjusts the setpoint just as it did before.
Flashlight button
While the momentary pushbutton is pressed, the LED turns on. (If it was already on, it remains on.) When the button is released, the LED goes back to its regular functioning. This is meant as a flashlight function for a user who, for instance, needs to see something on the nighstand for a moment, but doesn’t want to leave the nightlight on.
Serial
feedback
In order to help understand what calculations the nightlight is making, and how bright the room is, add some Serial
feedback in this format:
room brightness: 320; setpoint: 300; mode: NIGHTLIGHT; flashlight mode: FALSE; LED: OFF room brightness: 290; setpoint: 300; mode: NIGHTLIGHT; flashlight mode: FALSE; LED: ON room brightness: 290; setpoint: 305; mode: DAYLIGHT; flashlight mode: FALSE; LED: OFF room brightness: 290; setpoint: 305; mode: DAYLIGHT; flashlight mode: TRUE; LED: ON
The Serial
feedback should print no more than twice per second.
Deliverables:
- Working nightlight, as described above, ready to present at the start of class
- Working serial feedback, as described above
- Electrical schematic of the circuit you built, with your name and date at the top, to be handed in on an unlined sheet of 8-1/2”×11” paper
- Code submission to this homework’s Canvas assignment
Recommended general approaches for this assignment
Begin by writing pseudocode, i.e. a summary of the basic logic that will underlie the sketch. This is just meant as an organizational step for your own thinking; it should not be included in the final sketch you submit for the assignment. You may wish to diagram out the logic with bubbles and arrows, etc., instead of putting it into words; whatever works for you is fine. Also draw your schematic (or aspects of your schematic) before beginning wiring: using it as a planning document will be very helpful as more and more wires and components start to crowd your breadboard.
When you’re ready, add only one component at a time. Maybe start with only the photosensor (tutorial link), make sure it’s working (the Serial
feedback will help a lot with that), then add the switch, make sure it’s working, etc. At the same time you’re adding a component and confirming that it’s working electrically, you can start to write the relevant parts of the code that interact with that component.
Rather than writing complete code that totally works and covers all cases, begin by writing code that covers only a portion of what you’ll ultimately need—for instance, get the nightlight working before worrying about getting the daylight working, and get both of those working before worrying about the flashlight button. (You don’t need to follow that order of development; it’s just an example.)
Build towards the goal, and stop at ~4 hours (only optionally pushing beyond that time limit). If you complete the assignment, great, and if not, get as far as you can in ~4 hours. We’re at the learning-a-lot-very-quickly stage of the course, which is coincidentally sometimes also the this-is-too-much-at-once stage.
Code formatting notes
Use a standard comment block at the top of the code as specified in the syllabus.
Use single-line comments in your code to explain anything not obvious. These aren’t only notes for other people—they’re notes for you when you look at the code next month and are trying to figure it out!
Example of a good single-line comment:
// switch is in DAYLIGHT position
if (switchState == HIGH){
The above comment is useful and helps the reader quickly scan the code with understanding.
Example of an gratuitous (unnecessary) single-line comment:
// test the position of the switch and load it into the switchState variable
switchState = digitalRead(SWITCHPIN);
This comment is just spelling out the obvious.
Write constant variable names like pin designations (see next section) in ALL_CAPS
and changeable variable names like sensor values in camelCase
.
Pin designations
As we discussed in class, it’s preferred to use variable names, rather than numbers, to refer to input and output pins.
Using the same order as your pin mapping section of the comment block, add a section at the top of your code to give clear ALL_CAPS
constant variable names for all of your inputs and output pins. For instance:
[code above this point not shown]
/*
* Pin mapping:
*
* pin | mode | description
* ------|--------|------------
* A2 input potentiometer for setpoint
* A4 input photoresistor
* 6 output nightlight/daylight LED
*
*/
const int POTPIN = A2;
const int PHOTOPIN = A4;
const int LEDPIN = 6;
[code below this point not shown]
(Note that this sample does not include the total list of inputs and outputs you’ll need to complete this assignment.)
Code structure notes
First, begin by gathering data about the world. In the setup()
, use the pinMode()
commands to tell the Arduino where everything is plugged in, and what things are inputs and what things are outputs. Also, in the setup()
, don’t forget to add the command to begin Serial
communication.
Then, in the loop()
, begin by gathering information like this:
int brightnessVal = analogRead(A0); // the pin the photoresistor is plugged into
int potVal = analogRead(A1); // the pin the potentiometer is plugged into
int switchVal = digitalRead(7); // the pin the switch is plugged into
Now you have to write the instructions that will turn the LED on or off. It’s a simple question that the code needs to run: is the brightness value lower than the potentiometer value? If so, turn on the LED. If not, turn off the LED.
if (brightnessVal < potVal){
// turn on the LED in here
}
This will set you on your way, but there’s things I left out. For instance, I haven’t told you how to add the logic to make it so that the switch reverses the behavior of the LED to make it into a daylight, or how to implement the flashlight button. The exercise is left to the reader!
String formatting
A reminder from the prior homework is that you can build long Serial
strings like so:
Serial.println((String)"This first variable's value is " + varOne + ", and the second one's is " + varTwo);
Another useful thing to know is that there’s a data type called String
which can hold words, etc., which can be put right into the Serial
commands, like so:
String modeName = "DAYLIGHT";
Serial.println("the current mode is: " + modeName);
In this case modeName
is a variable just like any other, and you can change its value any time you’d like.
Remember to use the built-in reference system in the Arduino software if you’re confused about how to use any functions, or do web searches if you’re not getting the answers you’d like.
Bonus: a nightlight with feature bloat
Do this part of the assignment only if you were able to successfully do the “Reasonable Nightlight” first!
- Inputs are same as above, plus:
- an additional momentary pushbutton, referred to below as the “bloat button”
- Outputs are same as above, plus:
- a servomotor tutorial link
The engineers at the nightlight company must have gotten real bored because they started to add features that no reasonable consumer would want. Specifically:
- When in DAYLIGHT mode: while the bloat button is presssed, that activates “robot mode”—the servo motor turns its position to match the rotation of the setpoint potentiometer. (I.e. turning the potentiometer through its ~270º travel makes the servo motor drive through its 180º travel in sync.) While the additional momentary pushbutton is not held, the servo sits at 90º.
- When in NIGHTLIGHT mode: while the bloat button is pressed, the
Serial
monitor output changes from the previous useful diagnostic information. Instead, it helps the user sleep by printing one more Z per line, like so:
Z ZZ ZZZ ZZZZ ZZZZZ ZZZZZZ ZZZZZZZ
It continues printing longer and longer lines of Zs until the bloat button is no longer held. The next time it’s pressed, it begins again with one Z.
Collaboration and help
Limited collaboration with your classmates is permitted. You must build your own circuit and write your own code, but you can talk with other students to get advice and reason through the problem together. You are not permitted to copy somebody else’s code, nor are you permitted to look at someone else’s schematic or breadboard and simply reproduce what you see there. You are permitted to use any internet/book/etc. resource you’d like.
Feedback
points | assignment |
---|---|
2 | inputs wired properly (with pull-down resistors for button/switch) |
1 | outputs wired properly (current-limiting ≥270Ω resistor in series with LED) |
2 | serial feedback formatted properly and working |
4 | code written cleanly, clearly, and with appropriate commenting practice |
6 | device functions to spec |
3 | schematic clear and correct |
2 | bonus (all or none): additional bloat features work to spec |
18 | (plus 2 bonus points available) |