Week 10 Exploring – Khalifa Alshamsi

Concept:

This project’s concept is to utilize a combination of hardware components (Arduino, ultrasonic sensor, LEDs, and a slide switch) to create an interactive system that responds to physical proximity and manual control.

Setup:

Video:

Code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const int ledPin = 8; // LED connected to digital pin 8
const int trigPin = 12; // Ultrasonic Sensor Trigger pin
const int echoPin = 11; // Ultrasonic Sensor Echo pin
const int ledPin1 = 9; // First LED pin (PWM capable)
const int ledPin2 = 4; // Second LED pin
const int switchPin = 2; // Slide switch pin
bool ledEnabled = false; // State to keep track of LEDs response state
long duration; // Variable to store the time it takes for the echo to return
float distance; // Variable to store the calculated distance
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
pinMode(ledPin1, OUTPUT); // Sets the first LED pin as an Output
pinMode(ledPin2, OUTPUT); // Sets the second LED pin as an Output
pinMode(switchPin, INPUT_PULLUP); // Sets the switchPin as an Input with internal pull-up resistor
Serial.begin(9600); // Start serial communication at 9600 baud
}
void loop() {
// Read the state of the switch
ledEnabled = digitalRead(switchPin) == LOW; // Check if switch is active
// Measure the distance from the ultrasonic sensor
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and return)
Serial.print("Distance: ");
Serial.println(distance);
if (ledEnabled) {
// Pulse the first LED based on distance
int brightness = map(distance, 0, 200, 255, 10);
brightness = constrain(brightness, 10, 255);
analogWrite(ledPin1, brightness);
// Toggle the second LED based on distance threshold
digitalWrite(ledPin2, distance < 30 ? HIGH : LOW);
} else {
// Turn off LEDs when switch is off
analogWrite(ledPin1, 0);
digitalWrite(ledPin2, LOW);
}
delay(100); // Short delay to stabilize loop and reduce sensor noise
}
const int ledPin = 8; // LED connected to digital pin 8 const int trigPin = 12; // Ultrasonic Sensor Trigger pin const int echoPin = 11; // Ultrasonic Sensor Echo pin const int ledPin1 = 9; // First LED pin (PWM capable) const int ledPin2 = 4; // Second LED pin const int switchPin = 2; // Slide switch pin bool ledEnabled = false; // State to keep track of LEDs response state long duration; // Variable to store the time it takes for the echo to return float distance; // Variable to store the calculated distance void setup() { pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin, INPUT); // Sets the echoPin as an Input pinMode(ledPin1, OUTPUT); // Sets the first LED pin as an Output pinMode(ledPin2, OUTPUT); // Sets the second LED pin as an Output pinMode(switchPin, INPUT_PULLUP); // Sets the switchPin as an Input with internal pull-up resistor Serial.begin(9600); // Start serial communication at 9600 baud } void loop() { // Read the state of the switch ledEnabled = digitalRead(switchPin) == LOW; // Check if switch is active // Measure the distance from the ultrasonic sensor digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and return) Serial.print("Distance: "); Serial.println(distance); if (ledEnabled) { // Pulse the first LED based on distance int brightness = map(distance, 0, 200, 255, 10); brightness = constrain(brightness, 10, 255); analogWrite(ledPin1, brightness); // Toggle the second LED based on distance threshold digitalWrite(ledPin2, distance < 30 ? HIGH : LOW); } else { // Turn off LEDs when switch is off analogWrite(ledPin1, 0); digitalWrite(ledPin2, LOW); } delay(100); // Short delay to stabilize loop and reduce sensor noise }
const int ledPin = 8;           // LED connected to digital pin 8
const int trigPin = 12;         // Ultrasonic Sensor Trigger pin
const int echoPin = 11;         // Ultrasonic Sensor Echo pin
const int ledPin1 = 9;          // First LED pin (PWM capable)
const int ledPin2 = 4;          // Second LED pin
const int switchPin = 2;        // Slide switch pin
bool ledEnabled = false;        // State to keep track of LEDs response state

long duration;                  // Variable to store the time it takes for the echo to return
float distance;                 // Variable to store the calculated distance

void setup() {
  pinMode(trigPin, OUTPUT);     // Sets the trigPin as an Output
  pinMode(echoPin, INPUT);      // Sets the echoPin as an Input
  pinMode(ledPin1, OUTPUT);     // Sets the first LED pin as an Output
  pinMode(ledPin2, OUTPUT);     // Sets the second LED pin as an Output
  pinMode(switchPin, INPUT_PULLUP); // Sets the switchPin as an Input with internal pull-up resistor
  Serial.begin(9600);           // Start serial communication at 9600 baud
}

void loop() {
  // Read the state of the switch
  ledEnabled = digitalRead(switchPin) == LOW; // Check if switch is active

  // Measure the distance from the ultrasonic sensor
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and return)
  Serial.print("Distance: ");
  Serial.println(distance);

  if (ledEnabled) {
    // Pulse the first LED based on distance
    int brightness = map(distance, 0, 200, 255, 10);
    brightness = constrain(brightness, 10, 255);
    analogWrite(ledPin1, brightness);

    // Toggle the second LED based on distance threshold
    digitalWrite(ledPin2, distance < 30 ? HIGH : LOW);
  } else {
    // Turn off LEDs when switch is off
    analogWrite(ledPin1, 0);
    digitalWrite(ledPin2, LOW);
  }
  delay(100);  // Short delay to stabilize loop and reduce sensor noise
}

Reflection:

Reflecting on this project, I’ve realized it was a substantial learning experience and a test of my problem-solving skills. Integrating various components—Arduino, ultrasonic sensor, LEDs, and a slide switch—presented several challenges that enhanced my understanding of electronic systems and their programming. One of the main difficulties encountered was ensuring stable and reliable readings from the ultrasonic sensor. Interferences occasionally led to erratic LED behaviors, requiring adjustments in the placement and coding to filter out spurious signals effectively. Another challenge was debouncing the slide switch to achieve consistent results, underscoring software stability’s importance in hardware projects. Managing multiple outputs based on input from a single sensor also pushed me to think critically about how different components interact within an embedded system. This project bolstered my technical skills and deepened my appreciation for the meticulous detail required in electronic design and the creative potential of combining simple elements to produce complex interactions.

Week 10 | The Knob and The Bob

Throughout the Eid break, I tried to review the concepts that we have gone through so far. My goal for this assignment is not to create fancy circuitry but rather to design something from the back of my mind and understand what it does, how, and why.

I spent quite a time figuring out TinkerCAD, which is a program that really helps me to visualize and simulate my board before physically building it. I found this YouTube playlist that taught the program really well.

Concept

I want to light up two lights with a button and a knob. Because the knob is an analog input, there is a value that can be used there. So, I decided to make one LED blink in a specific amount of time decided by the knob, whereas the other LED is a simple on-off.

Schematic
How it Works

The code is separated for both green and blue LED.

In the code, I made a variable called sensorValue, which reads the signal from the knob. These values are then used to create blinking effect using delay for the blue light.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Read Potentiometer Value
sensorValue = analogRead(A0);
// Turn the LED On
digitalWrite(LED_BUILTIN, HIGH);
// Pause program for <sensorValue> miliseconds
delay(sensorValue); // Wait for sensorValue millisecond(s)
// Turn the LED Off
digitalWrite(LED_BUILTIN, LOW);
// Pause program for <sensorValue> miliseconds
delay(sensorValue); // Wait for sensorValue millisecond(s)
// Read Potentiometer Value sensorValue = analogRead(A0); // Turn the LED On digitalWrite(LED_BUILTIN, HIGH); // Pause program for <sensorValue> miliseconds delay(sensorValue); // Wait for sensorValue millisecond(s) // Turn the LED Off digitalWrite(LED_BUILTIN, LOW); // Pause program for <sensorValue> miliseconds delay(sensorValue); // Wait for sensorValue millisecond(s)
// Read Potentiometer Value
  sensorValue = analogRead(A0);
  // Turn the LED On
  digitalWrite(LED_BUILTIN, HIGH);
  // Pause program for <sensorValue> miliseconds
  delay(sensorValue); // Wait for sensorValue millisecond(s)
  // Turn the LED Off
  digitalWrite(LED_BUILTIN, LOW);
  // Pause program for <sensorValue> miliseconds
  delay(sensorValue); // Wait for sensorValue millisecond(s)
Demo
End Remarks

I am really proud of this whole assignment. It is not perfect, as in the video, the green LED sometimes does not turn off despite the button being pressed.

Nevertheless, while it may seem simple in the beginning, I was very confused by the whole arrangement of things. But, I did my best to actually sit down, take my time, and learn how these components work and interact with each other and reinforce my knowledge on Arduino itself.

Week 10 Reading Response – Khalifa Alshamsi

Tom Igoe’s blog posts offer the developmental and philosophical underpinnings of physical computing. In “Physical Computing’s Greatest Hits (and misses),” Igoe revisits a series of projects that have significantly influenced how physical computing is taught. By analyzing successful and less effective projects, Igoe highlights the iterative nature of learning in this field, which is crucial for students and educators aiming to refine their approach to technology and design.

On the other hand, “Making Interactive Art: Set the Stage, Then Shut Up and Listen” delves into the essence of interactive art. Igoe argues for the importance of minimal intervention by the artist, allowing the audience to engage freely with the artwork. This approach fosters a unique dialogue between the viewer and the piece, enhancing the personal connection and interpretive freedom. This philosophy not only redefines the role of the creator but also elevates the interactive experience, making it a personal journey for each participant.

Reflecting on Tom Igoe’s insights, I’ve learned about physical computing and art’s iterative and interactive nature. The blog posts illustrate the importance of trial, error, and refinement in developing effective educational strategies for technology and design. Moreover, Igoe’s approach to interactive art—emphasizing minimal artist intervention—has shown me how creating environments for audience engagement can transform the reception and meaning of art. These perspectives challenge traditional roles and invite a deeper understanding of how technology can facilitate more personalized and impactful experiences.

Week 10 Reading Response – Shaikha AlKaabi

Physical Computing’s Greatest Hits (and misses)

The article provides a fascinating exploration into the realm of physical computing, revealing a pattern of innovation that breathes new life into established concepts. It’s not merely about crafting something entirely new, it’s about the clever adaptation and imaginative expansion of familiar ideas. 

Starting with Theremin-like instruments and advancing through gloves equipped with sensors, the text underscores the perpetual evolution of interaction between humans and machines. Projects like ‘Hand-as-cursor’ and ‘Multitouch Interfaces’ take this further by translating human gestures into digital reactions, while ‘Tilty stands and tables’ employ physical manipulation to navigate virtual spaces. 

‘Tilty Controllers’ demonstrate the significance of object orientation, expanding our perception of how we can control and influence technology. ‘Things You Yell At’ and ‘Meditation Helpers’ show a more personal side, engaging with our voices and physiological states to guide or react in a context-sensitive manner. 

With ‘Fields of Grass’, we see a poetic application of sensor arrays, creating responsive textures that react to human touch. ‘Remote Hugs’ and ‘Dolls and Pets’ showcase the emotional and relational potentials of physical computing, emphasizing companionship and emotional communication. ‘LED Fetishism’ reminds us to push past the allure of visual feedback to discover deeper, more meaningful interactions. 

The text concludes with an ode to ‘Hybrid projects’, which combine different elements for novel experiences, like a flight simulator that mimics bird flight, showing the limitless potential when various facets of physical computing are merged.

Overall, the reading serves as an inspiration and a challenge to think beyond the conventional, urging creators in the field of physical computing to seek out the untapped potential in the interplay of the digital and physical worlds. It’s an invitation to innovate within the spectrum of sensory experiences, enriching our interaction with technology in both profound and playful ways.

Making Interactive Art: Set the Stage, Then Shut Up and Listen

The article on interactive art highlights a unique perspective on creation: the artist’s role is to set up an experience and then let the audience interact with it in their own way. It suggests that interactive art isn’t about dictating experiences but about creating opportunities for the audience to explore and interpret. This idea parallels a conversation where the artist ‘speaks’ through their work and then listens to the audience’s response through their interactions with it. Just as a stage director doesn’t perform but sets the scene for actors, the artist here provides the tools for expression and then steps back, allowing the audience to find personal meaning and contribute to the art’s ongoing narrative.

Week 10 Reading Response / Blinding Lights – Hamdah AlSuwaidi

In synthesizing the insights from TIGOE’s blog posts, “Physical Computing’s Greatest Hits (and misses)” and “Making Interactive Art: Set the Stage, Then Shut Up and Listen,” there emerges a compelling narrative about the nature of human interaction with technology and the role of the creator in guiding this interaction.

The first post examines the myriad ways in which creators harness technology to bridge the gap between art and the human experience. It underscores that the essence of physical computing is not in the machinery itself, but in the potential for human expression and interaction that it affords. TIGOE celebrates the diversity of approaches—from instruments that translate motion into sound to devices that sense and react to our emotions—each offering a unique dialogue between user and machine. This celebration is not just of the end product but of the process and potential for evolution, highlighting that even familiar ideas can be reinvigorated through creative reinterpretation.

The second post, meanwhile, delves into the philosophy behind interactive art. It champions the idea that art is a collaborative exchange and urges creators to step back after setting the scene, allowing the audience to bring their interpretations and experiences into play. This stance challenges the traditional static relationship between art and observer, proposing instead a dynamic interaction where the audience becomes an integral part of the art’s essence.

Both readings converge on the point that in the realm of interactive experiences, whether through physical computing or art, the creator’s role is not to dictate but to facilitate. It’s an invitation to viewers to engage, explore, and co-create, leading to a richer tapestry of experiences. The pieces do not stand as mere displays of technological or artistic prowess but as starting points for a journey that each participant completes in their own unique way.

By bringing together the physical and the interactive, TIGOE illuminates a future of creation that is ever-evolving, deeply personal, and universally accessible. In this future, the boundaries between the creator, the creation, and the consumer are not just blurred but are actively redefined with each interaction, fostering a space where art and technology serve as mediums for communication, learning, and exploration of the human condition. Both readings serve as a manifesto for the modern maker, encouraging a dialogue with technology and audience that is as open-ended as it is profound.

Blinding lights:

After being inspired by The Weeknd’s album ‘After Hours,’ I chose to name my assignment ‘Blinding Lights,’ which reflects the influence of his music had on me.

https://youtube.com/shorts/uRrlVS0TPpw?feature=shared

This Arduino code controls two LEDs (red and blue) based on the light detected by a photoresistor and the position of a potentiometer. The LEDs alternate based on the light level: if it’s dark (light level below 300), they alternate, with the speed of alternation controlled by the potentiometer. If it’s light, both LEDs remain off. The program uses serial output to display the light level detected by the photoresistor.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const int led0 = 3; // Red LED
const int led1 = 5; // Blue LED
const int photoResistor = A1;
const int potentiometer = A0; // Potentiometer connected to analog pin A0
void setup() {
Serial.begin(9600);
pinMode(led0, OUTPUT);
pinMode(led1, OUTPUT);
}
void loop() {
int lightValue = analogRead(photoResistor);
Serial.print("Light Value: ");
Serial.println(lightValue);
// Read the potentiometer value to control the speed of LED alternation.
int potValue = analogRead(potentiometer);
int delayTime = map(potValue, 0, 1023, 50, 1000); // Adjust this range as needed.
if (lightValue < 300) { // Threshold for photoresistor touch
// Alternate LEDs when the photoresistor is touched.
digitalWrite(led0, HIGH);
digitalWrite(led1, LOW);
delay(delayTime); // Delay controlled by potentiometer
digitalWrite(led0, LOW);
digitalWrite(led1, HIGH);
delay(delayTime); // Delay controlled by potentiometer
} else {
// If the photoresistor is not being touched, turn both LEDs off or keep them in a default state.
digitalWrite(led0, LOW);
digitalWrite(led1, LOW);
}
}
const int led0 = 3; // Red LED const int led1 = 5; // Blue LED const int photoResistor = A1; const int potentiometer = A0; // Potentiometer connected to analog pin A0 void setup() { Serial.begin(9600); pinMode(led0, OUTPUT); pinMode(led1, OUTPUT); } void loop() { int lightValue = analogRead(photoResistor); Serial.print("Light Value: "); Serial.println(lightValue); // Read the potentiometer value to control the speed of LED alternation. int potValue = analogRead(potentiometer); int delayTime = map(potValue, 0, 1023, 50, 1000); // Adjust this range as needed. if (lightValue < 300) { // Threshold for photoresistor touch // Alternate LEDs when the photoresistor is touched. digitalWrite(led0, HIGH); digitalWrite(led1, LOW); delay(delayTime); // Delay controlled by potentiometer digitalWrite(led0, LOW); digitalWrite(led1, HIGH); delay(delayTime); // Delay controlled by potentiometer } else { // If the photoresistor is not being touched, turn both LEDs off or keep them in a default state. digitalWrite(led0, LOW); digitalWrite(led1, LOW); } }
const int led0 = 3; // Red LED
const int led1 = 5; // Blue LED
const int photoResistor = A1;
const int potentiometer = A0; // Potentiometer connected to analog pin A0

void setup() {
  Serial.begin(9600);
  pinMode(led0, OUTPUT);
  pinMode(led1, OUTPUT);
}

void loop() {
  int lightValue = analogRead(photoResistor);
  Serial.print("Light Value: ");
  Serial.println(lightValue);

  // Read the potentiometer value to control the speed of LED alternation.
  int potValue = analogRead(potentiometer);
  int delayTime = map(potValue, 0, 1023, 50, 1000); // Adjust this range as needed.

  if (lightValue < 300) { // Threshold for photoresistor touch
    // Alternate LEDs when the photoresistor is touched.
    digitalWrite(led0, HIGH);
    digitalWrite(led1, LOW);
    delay(delayTime); // Delay controlled by potentiometer

    digitalWrite(led0, LOW);
    digitalWrite(led1, HIGH);
    delay(delayTime); // Delay controlled by potentiometer
  } else {
    // If the photoresistor is not being touched, turn both LEDs off or keep them in a default state.
    digitalWrite(led0, LOW);
    digitalWrite(led1, LOW);
  }
}

 

Afra Binjerais – Week 10 reading response

Physical Computing’s Greatest Hits (and misses)

As I think back on this reading, the idea that creativity in physical computing—or any other creative field—comes from personalizing and reinterpreting existing concepts rather than from creating anything completely new encourages me. The theremin, for example, is a deceptively simple instrument that may develop into a very personal undertaking that expresses the creative and technical sensitivities of its maker in addition to being functional.

Furthermore, the discourse surrounding initiatives such as “Multitouch Interfaces” and “Body-as-cursor” emphasizes the need of human-centered design in physical computing. The way these initiatives connect human-machine interaction is remarkable, since physical gestures are translated into digital answers that are subsequently translated into tactile or visual outputs. The elegance of physical computing lies in its capacity to enhance technology’s intuitiveness and responsiveness to human presence and movements, as demonstrated by this smooth integration.

Making Interactive Art: Set the Stage, Then Shut Up and Listen

I found the emphasis on avoiding from dictating interpretation to be especially compelling while reading about the process of making interactive artworks. The reading  encourages artists to avoid assuming too much control over the meaning of their creations and the appropriate ways in which viewers should respond to them. Rather, artists are urged to see their works as interactive platforms that allow viewers to delve deeper and find meaning on their own. Furthermore, After establishing the interactive environment, the instruction to “shut up” is dramatic because it subverts conventional ideas of artistic power and control. It suggests faith in the audience’s capacity to interact with and participate in the creative process. This informal attitude enhances the viewing experience for the audience while simultaneously giving the artist insights about how viewers engage with the piece—what they do, what they overlook, and how they understand the tools and surroundings that are made available to them.

Physical Computing and Making Interactive Art Reading Response – Redha

Both of this week’s readings led me to consider interactive art’s relationship with previously understood notions of human interaction and the production of art.

The reading on physical computing led me to identify two forms of approaching human-centred interactive design. The first of which is the repurposing and reapplication of interactions that already exist in the ‘real world’. The two examples that caught my eye which fall under this category were the ‘drum gloves’ and ‘video mirrors’. To me, the latter elevates the universal, almost reflex-like desire to look at oneself in the mirror and creates space for a quite direct form of symbolism (i.e “seeing x in yourself”). The former effectively borrows ‘gestural language’ from the ‘real world’ act of tapping one’s hands to make a beat. Again, this is an example of a familiar act being elevated but introduces an element of learning which is not present in video mirrors. I feel that this point introduces a spectrum of effort required by the user to uphold their side of the ‘conversation’ upon which interactive designs must place themselves. In this case, if video mirrors are like conversation with a talkative person, drum gloves aer like trying to connect with an introvert (i.e it is possible, it’ll just take some time).

Conversely, the reading on making interactive art provided me with a new perspective on its place within the larger artistic space. Previously, I would attempt to receive interactive art in the same way that I would receive other forms of contemporary art. The point raised by the reading that the role of an interactive artist is not to present a complete narrative but to best prepare the user to experience the narrative provided an interesting perspective which I have accepted. With this in mind, it is not unfair to double-down on the notion that interactive art is not complete without the input of the user. Rather than present a complete story, the role of the interactive artist is to facilitate a conversation between the art itself and the user which, hopefully, leads to a meaningful interaction at the end.

Week 10: Analog/Digital – Guess Who’s Murderer (Pi)

Let’s look at what I need to do…

(Post documentation on blog): Get information from at least one analog sensor and at least one digital sensor (switch), and use this information to control at least two LEDs, one in a digital fashion and the other in an analog fashion, in some creative way.

Hmm… so I can do something along the lines of

  • Ultrasonic Sensor (Analog)
  • Switch (is a requirement)
  • 4 LEDs (3 controlled by digitalWrite, and one fade In/Out through analog PWM)

In some creative way?? Hmm, how about we turn the entire project into a detective game, where you have to guess the murderer by pointing at one of the 3 suspects, then Arduino will tell you whether you got it right or wrong.

Guess Who’s Murderer

Hence, my project…

The player step into the shoes of a cunning detective, whose aim is to unravel the identity of the true culprit among the Crimson Enigma, the Emerald Marksman, and the Honey Hitwoman.

Using their hand, the player must point to one of the suspects. An ultrasonic sensor, detects the location of the player’s hand, illuminating the corresponding LED to indicate their suspicion.

To make their guess official, the player presses a pushbutton. If the guess is correct, a green LED softly fades in and out. However, if the player points their accusatory finger at the wrong suspect, the game’s buzzer sounds.

The demo video is below.

Art

All artworks are generated with midjourney… and some photoshop thrown in.

CODE

The code is below. Note that I am implementing a entire thing as a state machine, where the game alternates between the

{ SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS }

states. This makes the code clean. The microcontroller randomly selects the murderer using a random number generation algorithm, which is triggered at the start of each new game loop.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Pin Definitions
const int buttonPin = 12; // Pushbutton pin
const int buzzerPin = 7; // Buzzer pin
const int greenLedPin = 44; // Green LED pin
const int redLedPins[] = {3, 6, 10}; // Red LEDs for murderer selection
const int trigPin = 2; // Ultrasonic sensor trigger pin
const int echoPin = 4; // Ultrasonic sensor echo pin
// Game state definitions
enum GameState { SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS };
GameState currentState;
// Variables for game logic
int murderer = 0;
int guess = -1;
int buttonState = 0;
int lastButtonState = LOW;
unsigned long previousMillis = 0; // for non-blocking delays
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
for (int i = 0; i < 3; i++) {
pinMode(redLedPins[i], OUTPUT);
}
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
randomSeed(analogRead(0));
currentState = SELECT_MURDERER;
}
void loop() {
switch (currentState) {
case SELECT_MURDERER:
selectMurderer();
break;
case GUESS:
manageGuess();
break;
case CORRECT_GUESS:
handleCorrectGuess();
break;
case WRONG_GUESS:
handleWrongGuess();
break;
}
}
void selectMurderer() {
murderer = random(0, 3); // Randomly select a murderer among 3 LEDs
Serial.print("Murderer is: LED ");
Serial.println(murderer);
currentState = GUESS;
}
void manageGuess() {
lightRedLEDsBasedOnDistance();
readButtonState();
if (buttonState == HIGH && lastButtonState == LOW) {
Serial.println("Button Pressed");
checkGuess();
} else if (buttonState == LOW && lastButtonState == HIGH) {
Serial.println("Button Released");
}
lastButtonState = buttonState;
}
void lightRedLEDsBasedOnDistance() {
long distance = measureDistance();
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
for (int i = 0; i < 3; i++) {
digitalWrite(redLedPins[i], LOW);
}
if (distance >= 2 && distance < 6) {
digitalWrite(redLedPins[0], HIGH);
guess = 0;
} else if (distance >= 6 && distance < 9) {
digitalWrite(redLedPins[1], HIGH);
guess = 1;
} else if (distance >= 9 && distance <= 12) {
digitalWrite(redLedPins[2], HIGH);
guess = 2;
}
}
void readButtonState() {
buttonState = digitalRead(buttonPin);
}
void checkGuess() {
if (guess == murderer) {
currentState = CORRECT_GUESS;
} else {
currentState = WRONG_GUESS;
}
}
void handleCorrectGuess() {
fadeGreenLED(); // Handles the fading of the LED over 4 seconds
currentState = SELECT_MURDERER;
}
void handleWrongGuess() {
buzzBuzzer(3); // Buzzes the buzzer 3 times
currentState = SELECT_MURDERER;
}
void fadeGreenLED() {
for (int i = 0; i <= 255; i += 5) {
analogWrite(greenLedPin, i);
delay(30);
}
for (int i = 255; i >= 0; i -= 5) {
analogWrite(greenLedPin, i);
delay(30);
}
}
void buzzBuzzer(int count) {
for (int i = 0; i < count; i++) {
digitalWrite(buzzerPin, HIGH);
delay(300);
digitalWrite(buzzerPin, LOW);
delay(300);
}
}
long measureDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
return duration * 0.034 / 2; // Calculate distance in cm
}
// Pin Definitions const int buttonPin = 12; // Pushbutton pin const int buzzerPin = 7; // Buzzer pin const int greenLedPin = 44; // Green LED pin const int redLedPins[] = {3, 6, 10}; // Red LEDs for murderer selection const int trigPin = 2; // Ultrasonic sensor trigger pin const int echoPin = 4; // Ultrasonic sensor echo pin // Game state definitions enum GameState { SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS }; GameState currentState; // Variables for game logic int murderer = 0; int guess = -1; int buttonState = 0; int lastButtonState = LOW; unsigned long previousMillis = 0; // for non-blocking delays void setup() { Serial.begin(9600); pinMode(buttonPin, INPUT); pinMode(buzzerPin, OUTPUT); pinMode(greenLedPin, OUTPUT); for (int i = 0; i < 3; i++) { pinMode(redLedPins[i], OUTPUT); } pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); randomSeed(analogRead(0)); currentState = SELECT_MURDERER; } void loop() { switch (currentState) { case SELECT_MURDERER: selectMurderer(); break; case GUESS: manageGuess(); break; case CORRECT_GUESS: handleCorrectGuess(); break; case WRONG_GUESS: handleWrongGuess(); break; } } void selectMurderer() { murderer = random(0, 3); // Randomly select a murderer among 3 LEDs Serial.print("Murderer is: LED "); Serial.println(murderer); currentState = GUESS; } void manageGuess() { lightRedLEDsBasedOnDistance(); readButtonState(); if (buttonState == HIGH && lastButtonState == LOW) { Serial.println("Button Pressed"); checkGuess(); } else if (buttonState == LOW && lastButtonState == HIGH) { Serial.println("Button Released"); } lastButtonState = buttonState; } void lightRedLEDsBasedOnDistance() { long distance = measureDistance(); Serial.print("Distance: "); Serial.print(distance); Serial.println(" cm"); for (int i = 0; i < 3; i++) { digitalWrite(redLedPins[i], LOW); } if (distance >= 2 && distance < 6) { digitalWrite(redLedPins[0], HIGH); guess = 0; } else if (distance >= 6 && distance < 9) { digitalWrite(redLedPins[1], HIGH); guess = 1; } else if (distance >= 9 && distance <= 12) { digitalWrite(redLedPins[2], HIGH); guess = 2; } } void readButtonState() { buttonState = digitalRead(buttonPin); } void checkGuess() { if (guess == murderer) { currentState = CORRECT_GUESS; } else { currentState = WRONG_GUESS; } } void handleCorrectGuess() { fadeGreenLED(); // Handles the fading of the LED over 4 seconds currentState = SELECT_MURDERER; } void handleWrongGuess() { buzzBuzzer(3); // Buzzes the buzzer 3 times currentState = SELECT_MURDERER; } void fadeGreenLED() { for (int i = 0; i <= 255; i += 5) { analogWrite(greenLedPin, i); delay(30); } for (int i = 255; i >= 0; i -= 5) { analogWrite(greenLedPin, i); delay(30); } } void buzzBuzzer(int count) { for (int i = 0; i < count; i++) { digitalWrite(buzzerPin, HIGH); delay(300); digitalWrite(buzzerPin, LOW); delay(300); } } long measureDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH); return duration * 0.034 / 2; // Calculate distance in cm }
// Pin Definitions
const int buttonPin = 12;   // Pushbutton pin
const int buzzerPin = 7;    // Buzzer pin
const int greenLedPin = 44; // Green LED pin
const int redLedPins[] = {3, 6, 10}; // Red LEDs for murderer selection
const int trigPin = 2;      // Ultrasonic sensor trigger pin
const int echoPin = 4;      // Ultrasonic sensor echo pin

// Game state definitions
enum GameState { SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS };
GameState currentState;

// Variables for game logic
int murderer = 0;
int guess = -1;
int buttonState = 0;
int lastButtonState = LOW;
unsigned long previousMillis = 0; // for non-blocking delays

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(greenLedPin, OUTPUT);
  for (int i = 0; i < 3; i++) {
    pinMode(redLedPins[i], OUTPUT);
  }
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  randomSeed(analogRead(0));
  currentState = SELECT_MURDERER;
}

void loop() {
  switch (currentState) {
    case SELECT_MURDERER:
      selectMurderer();
      break;
    case GUESS:
      manageGuess();
      break;
    case CORRECT_GUESS:
      handleCorrectGuess();
      break;
    case WRONG_GUESS:
      handleWrongGuess();
      break;
  }
}

void selectMurderer() {
  murderer = random(0, 3); // Randomly select a murderer among 3 LEDs
  Serial.print("Murderer is: LED ");
  Serial.println(murderer);
  currentState = GUESS;
}

void manageGuess() {
  lightRedLEDsBasedOnDistance();
  readButtonState();
  if (buttonState == HIGH && lastButtonState == LOW) {
    Serial.println("Button Pressed");
    checkGuess();
  } else if (buttonState == LOW && lastButtonState == HIGH) {
    Serial.println("Button Released");
  }
  lastButtonState = buttonState;
}

void lightRedLEDsBasedOnDistance() {
  long distance = measureDistance();
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
  for (int i = 0; i < 3; i++) {
    digitalWrite(redLedPins[i], LOW);
  }
  if (distance >= 2 && distance < 6) {
    digitalWrite(redLedPins[0], HIGH);
    guess = 0;
  } else if (distance >= 6 && distance < 9) {
    digitalWrite(redLedPins[1], HIGH);
    guess = 1;
  } else if (distance >= 9 && distance <= 12) {
    digitalWrite(redLedPins[2], HIGH);
    guess = 2;
  }
}

void readButtonState() {
  buttonState = digitalRead(buttonPin);
}

void checkGuess() {
  if (guess == murderer) {
    currentState = CORRECT_GUESS;
  } else {
    currentState = WRONG_GUESS;
  }
}

void handleCorrectGuess() {
  fadeGreenLED();  // Handles the fading of the LED over 4 seconds
  currentState = SELECT_MURDERER;
}

void handleWrongGuess() {
  buzzBuzzer(3);   // Buzzes the buzzer 3 times
  currentState = SELECT_MURDERER;
}

void fadeGreenLED() {
  for (int i = 0; i <= 255; i += 5) {
    analogWrite(greenLedPin, i);
    delay(30);
  }
  for (int i = 255; i >= 0; i -= 5) {
    analogWrite(greenLedPin, i);
    delay(30);
  }
}

void buzzBuzzer(int count) {
  for (int i = 0; i < count; i++) {
    digitalWrite(buzzerPin, HIGH);
    delay(300);
    digitalWrite(buzzerPin, LOW);
    delay(300);
  }
}

long measureDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH);
  return duration * 0.034 / 2;  // Calculate distance in cm
}

Week 10 Reading Response – Jihad Jammal

Jihad Jammal

Intro to IM

Professor Aaron Sherwood

Reading Reflection Week 10

April. 15, 2024

 

 

Re-evaluating Creativity

 

Tom Igoe’s perspectives on physical computing and interactive art present a compelling reevaluation of how creativity is often framed, particularly the expectation of producing entirely novel works. He argues persuasively for the value of revisiting and reinterpreting existing themes, thus challenging the traditional pursuit of absolute novelty in both art and technology. This approach strikes me as both practical and liberating, suggesting that innovation can flow from iteration—a continuous dialogue with established ideas—rather than emerging ex nihilo. This notion that revisiting familiar concepts can be a rich soil for personal expression and originality really resonates with me, encouraging a more inclusive and sustainable model of creative practice.

 

Building on Igoe’s redefined approach to creativity, his analogy of interactive art to a stage set for audience participation further deepens the dialogue about the creator-audience relationship. This model, which advocates for minimal intervention by the artist after the artwork’s initial presentation, challenges traditional notions of artistic control and opens up new possibilities for viewer engagement. Personally, I find this perspective transformative; it shifts the completion of an artwork’s meaning to the realm of audience interaction, thereby changing how art is consumed and interpreted. This democratization not only makes art more accessible but also enhances its depth by welcoming a multitude of interpretations.

 

Citations:

www.tigoe.com. (n.d.). Physical Computing’s Greatest Hits (and misses) – hello. [online] Available at: https://www.tigoe.com/blog/category/physicalcomputing/176/.

 

Anon, (n.d.). Making Interactive Art: Set the Stage, Then Shut Up and Listen – hello. [online] Available at: https://www.tigoe.com/blog/category/physicalcomputing/405/.

Week 10: Digital/Analog Input and Output – Guessing Game

Concept & Inspiration

For this assignment, my aim was to create a simple gamified experience that engaged the user. I used to play this intuition game with my sister where she would think of a random number and I would try to “read” her mind and guess what that number was. With context clues of how “warm” or “cold” my guess was, I would eventually be able to get to the correct answer. My circuit is effectively a realization of this in hardware form.

Implementation

The circuit is composed of one RGB LED, three LEDs, a potentiometer, and a momentary switch. The game starts with the user pressing on the momentary switch (the digital sensor), upon which the Arduino program initializes a random number to be guessed. Upon activating the circuit, the RGB LED lights up in a pink color, indicating that the game is underway. The user then has to guess the number by using the potentiometer (the analog sensor) to find the correct value. The blue LED is lit if the current guess is far away from the correct number. The red LED lights up if the user is within a close range of the answer (±100 in my implementation). Once the number is guessed, the green LED lights up and the game is won. If the game is won, the RGB LED light show starts to celebrate the win, with different colors illuminating in succession. The user can turn off all the LEDs and restart the game using the momentary switch.

Code Snippets

The function

setColor
setColor controls the color of the RGB LED in an analog fashion. This function is called when the game is started using the switch to set the color of the RGB LED to pink, and when the game is won, transitioning the RGB LED from having a static color to a dynamic light show (implementation below). The principle of blinking without delay is used to ensure the RGB LED seamlessly transitions from one color to the next and that the user is able to turn off all the lights without lags using the momentary switch.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
void setColor(int redValue, int greenValue, int blueValue) {
analogWrite(redRGBPin, redValue);
analogWrite(greenRGBPin, greenValue);
analogWrite(blueRGBPin, blueValue);
}
void setColor(int redValue, int greenValue, int blueValue) { analogWrite(redRGBPin, redValue); analogWrite(greenRGBPin, greenValue); analogWrite(blueRGBPin, blueValue); }
void setColor(int redValue, int greenValue, int blueValue) {
  analogWrite(redRGBPin, redValue);
  analogWrite(greenRGBPin, greenValue);
  analogWrite(blueRGBPin, blueValue);
}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if (won && gameState){
if (millis()>timer){
timer = millis()+interval;
i = (i+1)%5;
}
if (i == 0){
setColor(255, 0, 0); // red
}
else if (i==1){
setColor(0, 255, 0); // green
}
else if (i==2){
setColor(0, 0, 255); // blue
}
else if (i==3){
setColor(255, 255, 255); // white
}
else if (i==4){
setColor(170, 0, 255); // purple
}
}
if (won && gameState){ if (millis()>timer){ timer = millis()+interval; i = (i+1)%5; } if (i == 0){ setColor(255, 0, 0); // red } else if (i==1){ setColor(0, 255, 0); // green } else if (i==2){ setColor(0, 0, 255); // blue } else if (i==3){ setColor(255, 255, 255); // white } else if (i==4){ setColor(170, 0, 255); // purple } }
if (won && gameState){
  if (millis()>timer){
    timer = millis()+interval;
    i = (i+1)%5; 
  }
  if (i == 0){
    setColor(255, 0, 0); // red
  }
  else if (i==1){
    setColor(0, 255, 0); // green
  }
  else if (i==2){
    setColor(0, 0, 255); // blue
  }
  else if (i==3){
    setColor(255, 255, 255); // white
  }
  else if (i==4){
    setColor(170, 0, 255); // purple
  }
}

The game logic occurs inside the

loop
loop function, where the potentiometer value is read and compared against the number to be guessed. The potentiometer controls which LED lights up based on its value’s distance from the correct number (blue if the guess is far away from the correct answer, red if the guess is close, and green if it is correct).

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if (gameState && !won){
setColor(227,50,121); // pink
if (abs(pentSensorVal - randNum) == 0){ // if number is guessed correctly
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
digitalWrite(redPin, LOW);
won = true;
}
else if (abs(pentSensorVal - randNum) < 100){ // getting warmer
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
digitalWrite(redPin, HIGH);
}
else{ // you are way off
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, HIGH);
digitalWrite(redPin, LOW);
}
}
if (gameState && !won){ setColor(227,50,121); // pink if (abs(pentSensorVal - randNum) == 0){ // if number is guessed correctly digitalWrite(greenPin, HIGH); digitalWrite(bluePin, LOW); digitalWrite(redPin, LOW); won = true; } else if (abs(pentSensorVal - randNum) < 100){ // getting warmer digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW); digitalWrite(redPin, HIGH); } else{ // you are way off digitalWrite(greenPin, LOW); digitalWrite(bluePin, HIGH); digitalWrite(redPin, LOW); } }
if (gameState && !won){
    setColor(227,50,121); // pink     
    if (abs(pentSensorVal - randNum) == 0){ // if number is guessed correctly
      digitalWrite(greenPin, HIGH); 
      digitalWrite(bluePin, LOW);
      digitalWrite(redPin, LOW);
      won = true; 
    }
    else if (abs(pentSensorVal - randNum) < 100){ // getting warmer 
      digitalWrite(greenPin, LOW); 
      digitalWrite(bluePin, LOW);
      digitalWrite(redPin, HIGH);
    }
    else{ // you are way off
      digitalWrite(greenPin, LOW); 
      digitalWrite(bluePin, HIGH);
      digitalWrite(redPin, LOW);
    }
  }
Circuit Schematic

Here’s the schematic of the wiring of the hardware components:

Demo

Reflections and Extensions

After last week’s reading, I wanted to focus more on the creative idea than the technical complexity of the hardware components. It proved to be quite challenging to think of building something creative with the input sensors and output devices that we have been using in class. I spent a lot of time ideating and the implementation portion was not as time-consuming, especially since I made sure to diagram the schematic and outline the software logic prior to wiring the circuit and connecting the Arduino. One thing that I should have anticipated, however, is how easy the game would be due to the limited directionality of the potentiometer. If you know that your guess is not correct by dialing the potentiometer all the way to the left, for example, the answer must be found by dialing it all the way to the right. To make the game a little harder, I made the trivial modification of adding a second potentiometer. The guess is considered correct if the sum of the potentiometer readings is within 50 of the number to be guessed. I increased the “warm” range from ±100 to ±500 as it was getting extremely difficult to play the game.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sum = pentSensorVal1 + pentSensorVal2;
if (abs(sum - randNum) < 50){
digitalWrite(greenPin, HIGH);
digitalWrite(bluePin, LOW);
digitalWrite(redPin, LOW);
won = true;
}
else if (abs(sum - randNum) < 500){
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, LOW);
digitalWrite(redPin, HIGH);
}
else{
digitalWrite(greenPin, LOW);
digitalWrite(bluePin, HIGH);
digitalWrite(redPin, LOW);
}
sum = pentSensorVal1 + pentSensorVal2; if (abs(sum - randNum) < 50){ digitalWrite(greenPin, HIGH); digitalWrite(bluePin, LOW); digitalWrite(redPin, LOW); won = true; } else if (abs(sum - randNum) < 500){ digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW); digitalWrite(redPin, HIGH); } else{ digitalWrite(greenPin, LOW); digitalWrite(bluePin, HIGH); digitalWrite(redPin, LOW); }
sum = pentSensorVal1 + pentSensorVal2; 
if (abs(sum - randNum) < 50){
  digitalWrite(greenPin, HIGH); 
  digitalWrite(bluePin, LOW);
  digitalWrite(redPin, LOW);
  won = true; 
}
else if (abs(sum - randNum) < 500){
  digitalWrite(greenPin, LOW); 
  digitalWrite(bluePin, LOW);
  digitalWrite(redPin, HIGH);
}
else{
  digitalWrite(greenPin, LOW); 
  digitalWrite(bluePin, HIGH);
  digitalWrite(redPin, LOW);
}

Admittedly, adding a second analog sensor introduced complexity that came at the expense of interpretability. It becomes harder to strategize one’s guesses, partly due to the nature of the potentiometer values being hard to track.  Perhaps using a display, like an LCD, to reveal the current potentiometer values would be helpful.