Note: these blue boxes are instructions to you to make the documentation, and should not be included in your final submission!
1b. A photo that is a good overall view of the project. This image should be one of the "well-shot" images described below, or a cropped subset of one of them.
Front view of the binary adder, without power on, and all the counting switches in the off position.
(Above is a reasonable sample caption. This picture could be a bit brighter, but it's clear and shows the project effectively.)
Remember to include alt text for visually disabled readers! The above image has alt text added properly, though it's not visible in most browsers.
1c. A brief explanation of the project. This should be short and sweet.
This project helps me to learn how to add binary numbers up. Each of the vertical toggle switches represents one of the powers of two, so the rightmost switch is the ones, the next one over is the twos, the next over is the fours, and so on. The horizontal switch at the bottom changes the board back and forth between decimal and hexadecimal representation of the sum.
1d. At least four good still images of the final project. If it's possible for you to take higher-quality image, like using a DSLR (here's the class DSLR photography guide) that's fine; but camera phone pictures are ok, too if they're carefully shot and good quality. Images:
Overall photo for proportion and scale (at least 1)
Detail photo of any part that you'd like to highlight (up to 3)
Images showing the thing being used (up to 3)
All of the components are screwed into the back of the main board with wood screws. The wires are plugged into the Arduino, a small power rail for all the grounds, and they're soldered onto the back of the 7-segment display for security.
(The above caption is pretty good. Image note: this photo is taken from the same place as the one above it, but it's got the focal plane on the chips behind rather than the wires in front. It also has useful alt text.)
1e. Moving image (one or more), a .gif, .mp4, or .mov file. Your movie can be as short as a second or two if that's all that needed to show the interactivity of your device, but should go longer as is necessary. It can feature voice narration if you like, but does not need to.
Upload instructions: Do not merely link to an outside hosting service like YouTube and do not embed a YouTube or other video service frame into your page. Rather, the videos are inserted by uploading a video file to this Google Drive folder and then under the Insert tab on the right, selecting "Drive," then clicking on the Shared drive called "60-223 f25." By keeping video files in that Shared drive, we ensure that this documentation page will remain intact for the long term.
If the movie is not audibly narrated, a caption should describe the action of the movie so that a blind person would still be able to understand what is happening.
(Note that videos don't have captions or alt-text options on Google Sites, so you just need to write your own text boxes below them.)
In this video, I show operation of the machine in decimal mode, flipping different switches on to make different sums. When all switches are off, the sum is 0; when the rightmost switch is on, the sum is 1, and then when that switch is off but the next one over is on, the sum is 2; when only the third switch over is on, the sum is 4; and so on.
Working on debugging, the stitch count was increasing without button presses. Turns out something was up with the Arduino Pro Micro and I switched to an Arduino Feather.
Got all the components in place, just needed to work on my code! I was happy about switching to the feather since I could use a rechargeable lithium battery.
Received the mini rotary encoder and could swap out the large one I was using as a place holder.
< After everything was up and running, I worked on soldering everything together! A lot of miniaturizing had to happen, and organization of the components in a way that made sense to put on a wearable.
< Unhoused project I presented in the final critique. I attached an elastic fabric band a bit haphazardly, but I was glad to have something put together.
Address all of the prompts below. It is best to address all of these topics in a natural piece of prose. However, if you prefer, you may write four disjoint paragraphs, each of which is addressing a prompt. (The first way is better.) In total, this section should be ~300–500 words.
A reminder that as outlined in the course syllabus, you are strictly prohibited from using any generative AI service or writing assistant in your reflection/discussion.
Response to comments gathered during the in-class crit. Quote (verbatim) from *at least* two written critiques that you received (positive, negative, or otherwise) from the in-class crit, and respond to them. (You may agree or disagree—in either case, explain your position.) You can access the written critique feedback by going to the class's Shared Drive and opening "11/5/25 Project 2 Final Critique feedback".
Self critique pertaining to the project. Are you happy with how the project came out? Did it satisfy your own goals? This *should not* simply be a recital of your process, but rather a meaningful reflection.
What you learned about your own abilities and/or limitations through the process of working on this project. These could be technical in nature (i.e. "I found that coding this particular behavior was surprisingly difficult"), or not (i.e. "I enjoyed making cardboard forms very much, and I think it will be a useful prototyping medium for me in the future"). What would you do differently next time? What would your advice to your past self be? Did you get hung up at a particular point in progress, or fail to see an easy workaround to a problem? Did you find a creative spark you didn't anticipate? Etc.?
Next steps. Do you expect to build another iteration of this project? If so, describe what you're planning to do. If not, describe what you *would* do if you were to build another iteration, based on the experience you had with this first one.
4. Technical information
4a. Include **schematic and block diagrams**, drawn in https://draw.ioref.org, and exported from that software as .png images.
The block diagram should legibly show all inputs, computational steps, and outputs of your project. The schematic should be done so that a competent person, reading your drawing and with the appropriate parts, could recreate the electrical system of the project. For both schematics and block diagrams, follow all of the standards described on the course schematics guidance page.
/*
Project 2: Stitch Counter
60-223 Intro to Physical Computing
Indie Lee
This code is written for an electronic stitch counter, designed to help me
keep track of my stitches while knitting and crocheting. In these kinds of
projects, I often count in large increments to make counting how many stitches
I have in one row a lot faster, but I also often lose count! This project both
keeps track of my stitch count and enables me to count my stitches in
customizable increments.
This code was written by me, with support from component libraries, Joseph,
and ChatGPT.
Pin mapping:
Arduino pin | role | description
-------------------------------------
0 INT rotary encoder
1 INT rotary encoder
2 I2C OLED
3 I2C OLED
11 input rotary encoder button
12 input push button
13 input switch
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Encoder.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
const int SWITCHPIN = 13,
BUTTONPIN = 12,
ROTARYPIN = 11;
int screenstate = 0;
int stitchCount = 0;
int countInc = 1;
int buttonVal, switchVal, rotaryVal;
int lastButtonVal, lastRotaryVal;
unsigned long pressTime = 0;
const unsigned long holdTime = 1000;
Encoder myEnc(0, 1);
long oldPosition = 0;
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
pinMode(BUTTONPIN, INPUT_PULLUP);
pinMode(SWITCHPIN, INPUT_PULLUP);
pinMode(ROTARYPIN, INPUT_PULLUP);
lastButtonVal = digitalRead(BUTTONPIN);
lastRotaryVal = digitalRead(ROTARYPIN);
//OLED screen setup
Serial.begin(9600);
// Wait for display
delay(500);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
; // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
homescreen();
}
void loop() {
buttonVal = digitalRead(BUTTONPIN);
switchVal = digitalRead(SWITCHPIN);
rotaryVal = digitalRead(ROTARYPIN);
if (switchVal == LOW) {
display.ssd1306_command(SSD1306_DISPLAYON);
//turning the rotary encoder
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
newPosition = (newPosition / 2);
}
//SCREENSTATE 0
if (screenstate == 0) homescreen();
//turning the rotary encoder to toggle screen
if (newPosition != oldPosition && screenstate == 0) {
togglehomescreen();
oldPosition = newPosition;
}
//pressing the button to count stitches in screenstate 0 and 1
if (buttonVal == LOW && lastButtonVal == HIGH && (screenstate == 0 || screenstate == 1)) {
delay(50);
pressTime = millis(); //button is pressed, start the timer
lastButtonVal = buttonVal;
}
if (buttonVal == LOW && ((millis() - pressTime) >= holdTime)) {
stitchCount = 0;
}
if (buttonVal == HIGH && lastButtonVal == LOW && ((millis() - pressTime) < holdTime)) {
stitchCount += countInc;
}
//SCREENSTATE 1
if (screenstate == 1) togglehomescreen();
//turning the rotary encoder to toggle screen
if (newPosition != oldPosition && screenstate == 1) {
homescreen();
oldPosition = newPosition;
}
//pressing the rotary encoder button to switch screens
if (rotaryVal == LOW && lastRotaryVal == HIGH && screenstate == 1) {
delay(50);
setcountscreen();
lastRotaryVal = rotaryVal;
}
//SCREENSTATE 2
if (screenstate == 2) setcountscreen();
//twisting rotary encoder to increase count increment
if (newPosition > oldPosition && screenstate == 2) countInc++;
if (newPosition < oldPosition && screenstate == 2) countInc--;
if (countInc < 1) countInc = 1;
//pressing rotary encoder button to switch screens
if (rotaryVal == LOW && lastRotaryVal == HIGH && screenstate == 2) {
delay(50);
countscreen();
lastRotaryVal = rotaryVal;
}
//SCREENSTATE 3
if (screenstate == 3) countscreen();
//twisting the rotary encoder to toggle screens
if (newPosition != oldPosition && screenstate == 3) {
togglesetcountscreen();
oldPosition = newPosition;
}
//SCREENSTATE 4
if (screenstate == 4) togglesetcountscreen();
//twisting the rotary encoder to toggle screens
if (newPosition != oldPosition && screenstate == 4) {
setcountscreen();
oldPosition = newPosition;
}
//pressing rotary encoder button to switch screens
if (rotaryVal == LOW && lastRotaryVal == HIGH && screenstate == 4) {
screenstate = 0;
lastRotaryVal = rotaryVal;
}
//reset variables
lastButtonVal = buttonVal;
lastRotaryVal = rotaryVal;
oldPosition = newPosition;
} else {
display.ssd1306_command(SSD1306_DISPLAYOFF);
//reset variables
lastButtonVal = buttonVal;
lastRotaryVal = rotaryVal;
screenstate = 0;
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
}
}
}
void homescreen() {
screenstate = 0;
display.clearDisplay(); //clear display buffer
display.setTextSize(4); //4x scale text
display.setCursor(0, 10);
display.setTextColor(SSD1306_WHITE);
display.println(stitchCount);
display.setTextSize(1);
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); //draw inverse text
display.setCursor(0, 45);
display.println(F("stitch counter!!"));
display.setCursor(0, 56);
display.setTextColor(SSD1306_WHITE);
display.println(F("set count increment"));
display.display(); //display
}
void togglehomescreen() {
screenstate = 1;
display.clearDisplay();
display.setTextSize(4);
display.setCursor(0, 10);
display.setTextColor(SSD1306_WHITE);
display.println(stitchCount);
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 45);
display.println(F("stitch counter!!"));
display.setCursor(0, 56);
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.println(F("set count increment"));
display.display();
}
void setcountscreen() {
screenstate = 2;
display.clearDisplay();
display.setTextSize(4);
display.setCursor(0, 10);
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.println(countInc);
display.setTextSize(1);
display.setCursor(0, 56);
display.setTextColor(SSD1306_WHITE);
display.println(F("< back"));
display.display();
}
void countscreen() {
screenstate = 3;
display.clearDisplay();
display.setTextSize(4);
display.setCursor(0, 10);
display.setTextColor(SSD1306_WHITE);
display.println(countInc);
display.setTextSize(1);
display.setCursor(0, 56);
display.setTextColor(SSD1306_WHITE);
display.println(F("< back"));
display.display();
}
void togglesetcountscreen() {
screenstate = 4;
display.clearDisplay();
display.setTextSize(4);
display.setCursor(0, 10);
display.setTextColor(SSD1306_WHITE);
display.println(countInc);
display.setTextSize(1);
display.setCursor(0, 56);
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.println(F("< back"));
display.display();
}