Uncategorized – Intro to Physical Computing: Student Work Spring 2023 https://courses.ideate.cmu.edu/60-223/s2023/work Intro to Physical Computing: Student Work Wed, 10 May 2023 20:21:22 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.6 Encouragement Box https://courses.ideate.cmu.edu/60-223/s2023/work/encouragement-box/ Wed, 10 May 2023 20:21:22 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=18430 <featured image>

When I can’t get a loved one on the phone, this box plays a song I associate with them, and the LCD displays an activity that I frequently do with them, the advice I think they’d give me in this scenario, or a link to a piece of media we usually watch together.

<moving image>

<overall photo>

<detail photo>

<image showing use of the thing>

 

Process

<old code where I had to comment out delays>

The amount of SRAM on the board was a huge problem. Whenever the Arduino Uno pulls up a file from the SD card, I think it creates a big file buffer, which takes up almost half of the available SRAM. Getting my code to run all the way to the end without being overwritten by the file buffer was a trial and error process, mostly involving constant commenting things out. This also made debugging really difficult, since I didn’t have enough SRAM for a lot of Serial.print statements.

<pivoting to a feather because it has more on board RAM>

I wound up pivoting to an Adafruit Feather board because it had more RAM available, so I could hardcode in more people.

<CAD model screenshot>

I originally wanted to laser cut pieces to make the enclosure, but decided to pivot to a cardboard box due to time constraints.

 

Discussion

I’m pretty happy with how the project turned out. It evolved a lot from my original concept, which functionally worked as a voicemail box which didn’t autodelete messages. The low sound quality and the way only one message could repeat from each person ended up feeling a little creepy instead of comforting, and pivoting to a music clip instead wound up giving me what I was actually looking for. I haven’t actually gotten a chance to use it, but frequently wind up wanting to use it now that I know it exists. Creating the project made me more conscious of all the barriers stopping me from contacting these people (time zones, stressful deadlines on both sides).

I wound up using a cardboard box due to time constraints, but also actually really liked it. Making a box which can open and close seamlessly is pretty difficult, and the long rectangular prism of the cardboard box actually looks a little sleeker than the squat cube I had originally designed. I think I should definitely use more cardboard for prototyping in future. I did learn that the choice of microcontroller has a lot of effect on the final project, since the amount of SRAM on the Arduino significantly impacted the behavior of the final product – I spent a long time adjusting delays to get the feel of the keypad to more accurately replicate the experience of using a telephone, and had to get rid of all that code because of the SRAM constraint.

I think it would be fun to redo this project with an actual telephone. I have one at home and might give it a shot – that would be a fun item just to keep around the house, and a good conversation starter. I also think that the idea of having people be able to record messages would be really fun! I love hosting events with lots of people, and getting a bunch of audio recordings from an event would be a great memento.

People’s primary critique of my project was that it was difficult to remember numbers. One person suggested “having letters instead of the numbers to make it easier to put in someone’s name instead of remembering their number,” but I’m not a huge fan of this idea. I like having a few friends’ numbers memorized, and I have numbers memorized for all of the people hardcoded in currently. A different person suggested “having the numbers be listed on the box itself could help with that” – I like that option a lot better. I think having the numbers on a piece of paper inside the box could be fun, with the current cardboard box, or having numbers posted on the wall next to the place where the telephone sits. 

 

Block Diagram

Schematic 

Code

/* @file dialaphone.pde
|| @version 4.0
|| @author Bhairavi Chandersekhar
|| @contact bhairavi.chand@gmail.com
||
|| @description
|| plays a song corresponding to a specific person when their telephone number is dialed. 
|| #
*/
#include <Keypad.h>
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>

// These are the pins used for the music maker shield
#define SHIELD_RESET  -1      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)

// These are common pins between breakout and shield
#define CARDCS 4     // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};

//R3, R2, C1, R1, C3, R4, C2
byte rowPins[ROWS] = {A0, A2, 2, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A1, 9, 5}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

Adafruit_VS1053_FilePlayer musicPlayer = 
  Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);

String phone_number; 
int digits_entered = 0;

void setup(){
  Serial.begin(9600);
  //Serial.println("setting up!");

// Music player setup
  if (! musicPlayer.begin()) { // initialise the music player
     Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
     while (1);
  }
  Serial.println(F("VS1053 found"));
  if (!SD.begin(CARDCS)) {
    Serial.println(F("SD failed, or not present"));
    while (1);  // don't do anything more
  } 
  /*
  // list files
  Serial.println("should be listing files...");
  printDirectory(SD.open("/"), 0); */
  
  // Set volume for left, right channels.c lower numbers == louder volume!
  musicPlayer.setVolume(30,30);
  //#2 and #3 are the interrupt pins
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int

  phone_number = "";
  digits_entered = 0; 
}
  
void loop(){
  Serial.println("Start typing phone number");

  while (digits_entered < 12) {
    char key = keypad.getKey();
    bool paused = musicPlayer.paused();
    if (key == '*' && !paused) {
      musicPlayer.stopPlaying();
    }
    else if (key) {
      musicPlayer.playFullFile("/beep____.mp3");
      phone_number += key; 
      Serial.print(key);
      digits_entered++; 
    }
    if (digits_entered == 3 || digits_entered == 7) {
      //delay(10);
      phone_number += '-';
      Serial.print('-');
      digits_entered++;
    }
  }
//Serial.println("phone number: ");
//Serial.println(phone_number);
  Serial.print('\n');
  //delay(200);

  if (phone_number == "617-775-4908") {
    Serial.println("CALEB");
    //delay(700);
    musicPlayer.startPlayingFile("/caleb___.mp3");
    //delay(700);
    
    Serial.println("tinyurl.com/care2pet");
    Serial.println("and then some Carmen Sandiego");
  }

  else if (phone_number == "617-669-3380") {
    Serial.println("JOHN");
    //delay(700);
    musicPlayer.startPlayingFile("/john____.mp3");
    
    //delay(700);
    //Serial.println("go watch forged in fire");
    //delay(700);
    //Serial.println("an episode with will willis");
    //delay(700);
    Serial.println("tinyurl.com/surprisedog"); 
    
  }

  else if (phone_number == "603-233-4056") {
    Serial.println("MOM");
    //delay(700);
    musicPlayer.startPlayingFile("/mom_____.mp3");
    
    //delay("700");
    Serial.println("make yourself some ginger tea!");
    //delay("700");
    Serial.println("or maybe with mint?");
  }

  else if (phone_number == "555-555-5555") {
    Serial.println("PATI");
    //delay(700);
    musicPlayer.startPlayingFile("/pati____.mp3");
    //delay("700");
    Serial.println("maybe it's finally time to learn crochet?");
  }

  else if (phone_number == "111-111-1111") {
    Serial.println("Lorde");
    //delay(700);
    musicPlayer.startPlayingFile("/track002.mp3");
  }

  else if (phone_number == "222-222-2222") {
    Serial.println("the Beatles");
    //delay(700);
    musicPlayer.startPlayingFile("/track001.mp3");    
  }  

  else {
    Serial.println("Phone number not found");
  }

  digits_entered = 0; 
  phone_number = "";
}
/*
/// File listing helper
void printDirectory(File dir, int numTabs) {
  Serial.println("should be printing files");
   while(true) {
     
     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       Serial.println("**nomorefiles**");
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');
     }
     Serial.print(entry.name());
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numTabs+1);
     } else {
       // files have sizes, directories do not
       Serial.print("\t\t");
       Serial.println(entry.size(), DEC);
     }
     entry.close();
   }
}  */

 

]]>
Social Shield 2023 https://courses.ideate.cmu.edu/60-223/s2023/work/my-social-shield/ Wed, 15 Mar 2023 12:23:21 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=17948 Description

This is a wearable piece that includes a pair of glasses that can change the opacity of the lens and a little installation that can be attached to clothes and will display text and make sounds when the sensor senses things within its range.

Overview

 The lens is transparent when there is no one within 50 cm;

and the LCD screen displays”Hi. Do not approach” The lens becomes dark when someone is standing within 50 cm;

and the LCD screen displays “!!!STEP BACK!!!”

 

Simulation of you walking up to a person wearing this device

This is a jacket on a hanger. The glasses’ lens will become dark when the distance is within 50cm, just like what happens in the photo above.

 

 

The overall device. (I don’t have anyone with me, so I have to put it on a table and record this. )

 

 

Detail of the device:

The glass frame has an angle and a rail that allows me to slide the lens in simply if I need to change the lens.

Background

This is an assistive device for me.

First, it’s about social distance. I feel that the term “social distance” was used everywhere during the pandemic. During that time, most of us were used to keeping our distance from others. But as we are now in the post-pandemic era, I don’t see a lot of people still maintaining social distance now. However, I still like to keep a certain distance from other humans in social situations. I also sometimes find it difficult to interact with people at a close distance, especially at social events.

The reason is probably that I read a novel called “No Exit” by Jean-Paul Sartre, a French playwright. He proposed a derived philosophical theory called “others are hell.” This sentence doesn’t mean that other people are the devil. It means that everyone is free without others’ intervention. In the book, Sartre describes four people whose souls have fallen into hell. There is no torture or fire as expected, but only a closed chamber that locks the four people so that whatever they do has to be done in the presence of others. The lights are always on, and the knife cannot kill other people. Sartre considered such to be the suffering of hell. My understanding is that in such a situation, the gaze of others can influence my free will, shape my choices and cause me pain, especially when I sometimes make choices against my will under the influence of others. I see other people as people that are “not me.” In this case, the difference between “me” and “others” defines the scope of “self.” So, without others, I would not be the person I am now, but the person I am now is in danger of losing my ability to judge and choose freely because of others.

To put it in perspective of vision, human vision is more than simply looking at things. When I look at the outside world as an individual, the world comes together towards me, hence, I am the center of the world, and I am completely free. This gives rise to a transcendence, meaning that I am subjective, which is also called the  ‘subject self’ by Sartre. But when in groups or in public, all my activities will be branded with the shadow of others, and I will find myself gazed at by others. I then will degenerate under the gaze of others because I take the gaze of others as my own possibility in my activity. This is also an alienation, an objectification, and a deprivation of freedom and transcendence as a subject. Thus the ‘subject me’ becomes the ‘object me,’ and the OTHERS become the subject in my eyes. The “my world”  built up by my perspective collapses, and this is the so-called “other is hell.”

If we reflect this theory into reality, I think people become “objects” when they interact with each other in any form, for example, eye contact or conversation. I don’t want to lose my subjective self in social and public events, so I thought of making this device. Basically, there is an ultrasonic ranger on the installation that can be attached to clothing. This is to sense the distance. When no one is in my social comfort zone (50cm), the lens of the glasses (light valve) is clear, like normal light-colored indoor sunglasses, and the LCD screen will display “Hi. Do not approach”. But when someone steps into my social comfort zone, the lenses of the glasses will darken, basically impossible to see through, and the device that is attached to the clothing will start going on an alarm. The text on the screen will change to a flashing “!!! STEP BACK!!!”. This device is also an artificial social shield for me.

 

Process

Decision 1:

I spent a lot of time thinking and experimenting with two kinds of sounds for a ‘warning sound.’

  1. Use a buzzer. This will create a sound that really sounds like a warning. but people may wonder if there’s anything bad happening.
  2. 2. Use a speaker that plays my own voice saying “Step back.” This fits my ideation more; however, as I tested it with my friends, I got feedback like “I heard Angie’s voice, so I want to come closer.” This totally contradicts my intention. But I found it interesting that sometimes the result will be different from my ideation until I really experiment with my design with people.

I finally decided to use the buzzer because it is small so it can be glued to the back of the screen together with the ultrasonic ranger. Most importantly, it turns out to be less attractive than using my own voice.

 

 

Decision 2:

For the glasses’ frame, I want it to have a futuristic look like the 3D model I made, ideally.

The modeling process took a very long time because this was my first time using Rhino to build a 3D model.

 

I initially wanted to use 3D printing because the nylon material is more suitable for a wearable device since it can bend a little. However, the 3D printer failed my printing several times, and almost 20 hours were wasted.

These are pictures of the first and second time of printing failures.

 

 

So, Cody suggested and helped me a lot to use the laser cutter instead. Since I have never used a laser cutter before, I also spent time learning how to operate the machine and put the parts together.

 

 

 

 

But the dimension of my model is wrong when the software automatically converts the 3D model to the slices. The original dimension of the frame should exactly fit my head. And the failed 3D printing actually fits according to my original dimension. However, the laser-cut pieces turned out to be much bigger than the dimensions I set. This also resulted in I had to hold the glasses during the showcase. The frame on the right is the 3D printing (third failed version), and the one much bigger on the left is the laser cutting version.

 

Discussion

I prefer to call it my work rather than a project. The idea of my creation has always been to do something meaningful. For example, this work combines the philosophical theory of Sartre while curing my fear of social interaction. So in a macro sense, I am satisfied with it.And I like the process of me brainstorming about things.For example, the futuristic glasses reminded me of my other work about bionic robots. So when I was finishing the wiring, I thought of wrapping the wires with soft pipes. This not only solves the problem of messy wiring but also leads me to think about another possibility: what if a bionic robot were to wear the device? Can these wires be plugged directly into its body? Maybe this can be a way to train it to learn and ‘feel’ like a real person, a person that has problems socializing with other people.

However, there are still some regrets about this work, such as the fabrication part. In fact, the final version of laser cutting is not quite what I wanted in mind. And the size of the cut is not the same as the one I measured, so the work is not perfect. But anyway, I think this is a good start, and I am grateful for everyone’s help. I have never used laser cutters and 3D printers before, so I learned a lot of skills from quick learning and operation this time.

I also received a lot of meaningful feedback. One is about the choice of sound that the device would make when people are getting closer. This is also one of the most tangled questions during the process. It is interesting to hear that different people have different suggestions and preferences on sounds choice. Some say that they would be attracted more by the buzzer sound, while some say they definitely will come closer and take a look if it is displaying a sound of me or a robot. I think this is something associated with psychology and sociology. I definitely would dig into related research and see which way may fit my concept better. Another interesting piece of feedback is from one of the faculties. He commented that maybe it would be better to create a device that could make me invisible in public places. But I thought about it for a long time, and I think that this is not the best solution for me. I think my main point is to avoid social interactions that make me uncomfortable, like getting too close, rather than hiding myself completely. When others step into my comfort zone, even if I don’t want to be forced to be an “object, I am physically present in the world, so I have no right to prevent anyone from gazing at me or interacting with me. This is their freedom. All I can do is shield myself and avoid interactions. After all, all I want is to remain my own self when socializing, and perhaps choosing to avoid unnecessary interactions is also a manifestation of the subjective self.

Technical information

Block Diagram:

Schematic Diagram:

 

Code

// My Social Shield
// Angie (Chuyi) Wang
// This code allows you to make a sound with a buzzer, display different texts on an LCD screen and control the transparency of 
// a light valve while the ultra sonic ranger detects the distance.
//For the light valve, one wire goes to the GND and another wire must be connected to analog pin. (I used A0)
// References: https://courses.ideate.cmu.edu/60-223/s2023/tutorials/I2C-lcd
//             https://www.instructables.com/How-to-use-a-Buzzer-Arduino-Tutorial/

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#define trigPin 10
#define echoPin 13

#define LIGHTVALVE A0
int brightness = 0;
int fadeAmount = 5; 

const int buzzer = 7; //buzzer to arduino pin 7
long transparency;


// Set the LCD address to 0x27 for a 20 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);


void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  pinMode(buzzer, OUTPUT); // Set buzzer - pin 7 as an output
  pinMode(LIGHTVALVE, brightness);
  lcd.init();
     lcd.begin(10,2);
}

void loop() {
  float duration, distance;
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2);
 
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) * 0.0344;

  int d1 = distance;
  // mapping the distance to brightness
   if(d1 > 90){
     d1 = 90;
   }

  // analogWrite(LIGHTVALVE , brightness);
  brightness = map(d1, 0, 90, 255,0);
  analogWrite(LIGHTVALVE,brightness);

  lcd.clear();

 // delay(100);
  if (distance >= 50 || distance <= 2){
    Serial.print("Distance = ");
    Serial.println("Out of range");
   // Serial.println(distance);
    //panelState = 0;
    brightness = 0;
    // delay(1000);
    //analogWrite(d1 , LIGHTVALVE);

    	// Turn on the blacklight and print a message.
    lcd.backlight();
    lcd.setCursor(4,1);
    lcd.print("HI.");
    lcd.setCursor(4,2);
    lcd.print("DO NOT APPROACH.");
    delay(500);

  }
  else {
    lcd.backlight();
    lcd.setCursor(1, 5);
   // lcd.clear();
    lcd.print(" !!!STEP BACK!!!");
    //print distance to serial
    Serial.print("Distance = ");
    Serial.print(distance);
    Serial.println(" cm");
    delay(200);

    //Buzzer
    tone(buzzer, 1000); // Send 1KHz sound signal...
    delay(500);        // ...for 1 sec
    noTone(buzzer);     // Stop sound...
    delay(200);        // ...for 1sec
    
    //change the transparency
    // analogWrite(LIGHTVALVE , brightness);
    brightness = brightness + fadeAmount;


  }
  
}

 

]]>
Focus Box https://courses.ideate.cmu.edu/60-223/s2023/work/focus-box/ Tue, 14 Mar 2023 22:26:11 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=17764 Part.0 Overview

An assistive device that helps the user to focus on the task at hand rather than his or her phone by mechanically retracting the phone inside.

 

Technical Demostration: 

Orange Tape Acting as Phone to Trick the IR Sensor

 

Overall Photo:

Overall Dimension (8″x8″x8″)

Internal Wiring & Layout

 

Detailed Photos:

Protoboards Connections: Motor Driver & UI Systems

UI – Front

UI – Back

 

In Use:

Timer Counting Down

 

Part.1 Process Images & Review

Using a Ambient Light Sensor Instead of an IR Sensor

In the very beginning, I decided to use an ambient light sensor as the sensor for detecting the phone on the stand. I also thought about using the same laser range finder I used for the project 1. There were some significant issues with the ambient light sensor, however. It was way too sensitive, and the code had to be tweaked everytime the overhead lighting condition was changed. I also should have considered that there would eventually be a roof covering much of the sensor input, making the ambiance differences between phone on and phone off very difficult to distinguish. Instead, Zach recommended an IR sensor, which was much easier to code and more reliable in its data output. Also, its compact size allowed for more versatility.

Dedicated 9V Power Breadboard (Ignore my disgusting hand)

This decision did not necessarily change the outcome of my project, but it was critical in keeping everything safe and secure. Mixing 5V and 9V on the same breadboard is asking for a disater. Therefore, I opted for a dedicated breadboard and, later, a protoboard to hold all the components that required 9V power. This way, I would always have the opportunity to get everything right.

 

Red Buttons

Before knowing these red buttons existed, I planned to use the tiny four-legged push buttons. That would not have made a massive difference in the wiring. However, I was planning to solder the legs, which would have been annoying. These red buttons are big and eye-catching, much more user-friendly than the legged push buttons.

Part.2 Discussion

 

Overall, I am satisfied with the final result of my assistive device, even though I had to make changes to reduce complexity. However, the project was challenging, and I am content that everything worked during the technical demonstration.

One of the comments I received from the final critique that stood out to me was, “I like how it doesn’t completely lock your phone away— there’s definitely less anxiety associated with it and I think i would be pretty likely to use it!” I thought this was quite interesting. I saw the lack of securing your phone inside as a failure since a focus box should take away your access to your phone over the countdown. However, now reflecting on this quote again, it is intriguing to see others’ perspectives, as it seems to encourage the user to use the device more and make it less intimidating.

Though I was pleased with the final results, as I mentioned before, there were places where I had to cut corners and features to reduce the project’s completion timeline and complexity. First, the box was supposed to function as a toaster, in which the phone would be placed on top of the box, and some mechanical motion would retract the phone inside the box, locking it away until the timer ran out or the release was hit. However, the ratio of extension to overall length could have been better on the linear actuator, which means I would have a massive box if I were to implement a vertical operation. Another idea I had to overcome this issue was to design a DC Motor-driven contraption, maybe pulling on a string or rubber band. However, I had yet to learn how to create a system as such in the time frame given. I also did not do an excellent job designing in Rhino. I have done plenty of detailed, beautiful physical models for my architecture studios; nevertheless, this was my first time creating something involving moving parts and wiring. I ran into issues of pieces not fitting, usually due to inaccuracies in measuring component dimensions and assuming things that may not be true.
Besides learning how the components involved in my project worked, as stated previously, I also learned that working to build a shell for the internal wiring logic in Rhino, or any other CAD software, should be taken seriously and with great care and certainty. I should be more detailed in my component sizing documentation. That way, I would have produced a cut with no adjustment later. I also learned that a linear actuator is hard to use, especially when you want it to push an object parallel to the adjacent walls. I was extremely frustrated when it got stuck on a piece of glue and debris and broke the whole box. Besides that, I decided to use as much soldering as possible in this project to reduce the number of times my hands accidentally bumped into stuff and unplugged wires. I also ensured that everything running on 9V power was separated and placed on their dedicated protoboard to avoid catastrophe.

I was thrilled that the project worked thoroughly during the final critique. However, as stated before, there were places where features had to be cut to save time and ground the project within my capabilities. One of the features includes a trap door, which may be manual or controlled, to close when the phone is retracted and open when the phone is out. I also wanted to implement a way where a notification on your phone may prompt the box to reject it via specific sensors, such as a microphone or photoresistor. If given more time or to approach the project again, I will try my best to implement those forgotten ideas.

 

Part.3 Technical Information

 

Block Diagram:

 

 

Schematics:

 

Code:

// Focus Box: 
// Assistive Device for myself, Project 2, Physical Computing

// Description: 
// The code below will retract the linear actuator if the timer 
// starter button is pressed when a phone is detector via an IR 
// sensor. And when in the retracted state, the code will extend
// the linear actuator if the IR sensor no longer detects a phone, 
// or the release button is hit.


// Credits:
// Used example code for millis() from https://courses.ideate.cmu.edu/60-223/s2023/tutorials/code-bites
// Used and edited example code for countdown timer from https://projecthub.arduino.cc/tylerpeppy/86bb3eef-23ec-4873-ad3b-86c7c277142f

#include <Wire.h>
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C screen(0x27, 16, 2);

const int actuatorPinA = 12;      // linear actuator pinA, driven by a motor driver
const int actuatorPinB = 13;      // linear actuator pinB, driven by a motor driver
const int minutePin = A1;         // potentiometer input, adjust the timer
const int buttonPinRelease = 4;   // release
const int buttonPinTimer = 2;     // start timer
const int irPin = A0;             // IR Sensor pin, detects the phone

int prevReleaseState;
int currReleaseState;
int prevTimerState;
int currTimerState;
int countdown_time = 0;
int tempPotInput;

unsigned long quarterTimer = 0;

bool timerCounting;

void setup() {
  Serial.begin(115200);
  Wire.begin();

  // Linear Actuation
  pinMode(actuatorPinA, OUTPUT);
  pinMode(actuatorPinB, OUTPUT);
  pinMode(buttonPinRelease, INPUT_PULLUP);
  pinMode(buttonPinTimer, INPUT_PULLUP);
  pinMode(irPin, INPUT);

  currReleaseState = digitalRead(buttonPinRelease);
  currTimerState = digitalRead(buttonPinTimer);

  digitalWrite(actuatorPinA, HIGH);
  digitalWrite(actuatorPinB, HIGH);

  // Potentiometer
  pinMode(minutePin, INPUT);



  screen.init();
  screen.backlight();
  screen.home();
  screen.setCursor(0, 1);

  // Serial.print(hourInput);
}

void loop() {

  int luxThreshold = 100;
  int second = 0;
  int potInputA = map(analogRead(minutePin), 0, 1023, 1, 61);
  long countdown_time;


  // Serial.println(analogRead(irPin));
  int dist;
  dist = analogRead(irPin);
  Serial.println(dist);

  // timer start

  prevTimerState = currTimerState;
  currTimerState = digitalRead(buttonPinTimer);
  if (prevTimerState == HIGH && currTimerState == LOW) {  // when retracted
    if (dist > luxThreshold) {
      timerCounting = true;
      countdown_time = potInputA * 60;
      screen.clear();
    }
  }

  prevReleaseState = currReleaseState;
  currReleaseState = digitalRead(buttonPinRelease);

  if (prevReleaseState == HIGH && currReleaseState == LOW) {
    Serial.println("release");
  }

  if (timerCounting) {
    // when timer is counting down

    long countdown_minute = countdown_time / 60;

    long countdown_sec = countdown_time % 60;

    screen.setCursor(0, 1);

    // count down every second
    if ((millis() - quarterTimer) >= 1000) {
      Serial.println("1 Second Has Passed");
      countdown_time -= 1;
      Serial.println(countdown_time);
      quarterTimer = millis();
    }

    if (countdown_minute < 10) {
      screen.print("0");
    }
    screen.print(countdown_minute);
    screen.print(":");
    if (countdown_sec < 10) {
      screen.print("0");
    }
    screen.print(countdown_sec);
  } else {
    screen.setCursor(0, 1);
    // adjustable timer display (not counting down)
    tempPotInput = map(analogRead(minutePin), 0, 1023, 1, 61);
    long totalSec = tempPotInput * 60;
    long tempMin = totalSec / 60;
    long tempSec = totalSec % 60;
    if (tempMin < 10) {
      screen.print("0");
    }
    screen.print(tempMin);
    screen.print(":");
    if (tempSec < 10) {
      screen.print("0");
    }
    screen.print(tempSec);
  }

  if ((tempPotInput > 0) && (dist < luxThreshold)) {
    screen.setCursor(0, 0);
    screen.print("Stand By............");
  } else {
    screen.setCursor(0, 0);
    screen.print("Phone Detected....");
  }

  if ((countdown_time > 0)) {  
    // if counter is still going
    if (prevReleaseState == HIGH && currReleaseState == LOW) {  
      // release
      digitalWrite(actuatorPinA, LOW);
      digitalWrite(actuatorPinB, HIGH);
      timerCounting = false;
    } else {
      if (dist > luxThreshold) {  
        // retract
        screen.setCursor(0, 0);
        screen.print("Phone Detected....");
        if (timerCounting) {
          digitalWrite(actuatorPinA, HIGH);
          digitalWrite(actuatorPinB, LOW);
        }
      } else {  
        // the phone will be on top of the sensor
        screen.setCursor(0, 0);
        screen.print("Stand By........");
      }
    }
  } else {  
    // time is up
    digitalWrite(actuatorPinA, LOW);
    digitalWrite(actuatorPinB, HIGH);
    timerCounting = false;
  }
  if (dist < luxThreshold) {
    digitalWrite(actuatorPinA, LOW);
    digitalWrite(actuatorPinB, HIGH);
    timerCounting = false;
  }
}

 

]]>
The Droplet Distracter https://courses.ideate.cmu.edu/60-223/s2023/work/droplet-distracter/ Mon, 13 Mar 2023 23:26:20 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=17779 Take a break from your phone to witness a soothing disco display of water droplets, that are–hold on–falling upwards???

 

They say the longer you don’t touch your phone, the more still the droplets will become…

Close-up of 4 water droplets suspended in the viewing box.

 

 

 

Demo

Concentrate on which direction the droplets are going!

Frontview of the fountain with frame rate of camera matched such that the "backwards flow effect" occurs and droplets (illuminated light blue) look to fall upwards.

GIF of the fountain with frame rate of camera matched such that the “backwards flow effect” occurs.

 

 

 

Full View

Three quarter view of the droplet fountain box. The lights are on inside and there is a phone laying on the sensor below.

The Droplet Distracter with phone resting in the slot.

 

 

 

 

Internals

Back view of the fountain box with back panel hinged open, revealing circuits, tubes, and water containers inside.

Back of fountain with back panel removed to reveal internals.

 

 

Top Water Container with Spout

Two images side by side. Left: Top view of top water container that dribbles the water into the drain. Right: Bottom view of top water container showcasing the spigot that was made by melting a hole in the bottom.

Top water container with spigot made by heating plastic and pushing a spike through.

 

 

 

Bottom Water Container

Two images side by side. Left: Top view of bottom water container that catches the water from the drain. Right: Side view of bottom water container in its correct position in the fountain.

Bottom water container that catches water droplets from ramp. The tube sucks it back up to the top.

 

 

Water Level Sensor (in Lid)

Ultrasonic sensor taped to the lid, designed to be positioned above the top water container so that the Arduino can sense when water needs to be replenished to the top.

Ultrasonic sensor that measures the water level of the top container and tells the pump to send more water if it’s below a certain level.

 

 

Usage

The user places a phone (dry eraser for simulation) in the slot, causing the LEDs to begin strobing, which makes the water droplets “fall up.” Since this video was captured in 60 FPS, which is far slower than the human eye, the illusion does not work in the video. See GIF above  for better illustration.

 

 

 

Process Media

Design Decision #1:

Making the final housing of the fountain black due to lack of visibility with all white background.

Unfinished prototype of fountain made in softer white plastic with masking tape all around it. There is a black strip on the back of the viewing window to contrast against the water droplets.

All-white prototype of fountain.

Slow-mo of water droplets falling with strobe light effect against black duct tape for clarity.

Black strip helps illuminate droplets as they fall.

 

 

Design Decision #2:

Ramp for water collection with space on the left side for wires and tubing to pass through.

Open side view of fountain with internal structure revealed. The ramp that guides water into the bottom water container is the highlighted subject,

Side profile of final physical model.

Two sketches, backside and left side, of the fountain done in red.

Early design for ramp.

3D render of the fountain with backing removed to show internal structure once again.

3D model of ramp design integrated into structure.

 

Other design photos:

 

Removable platform with glued circuits and slacked wires for easy removal/rewiring

Closer look at circuits hidden behind back panel of fountain. The main brains are glued onto a removable platform for ease of removal and insertion.

 

 

 

Hot-glued straw to help guide tube upright in order to fully suck water.

Close-up of a piece of a yellow drinking straw to help guide the tube responsible for bringing water up to the top water container.

 

 

 

Reflective surface to help illuminate display box.

Photograph of the viewing window of the fountain with highly illuminated LEDs and stream of water going down the center.

 

 

 

 

 

 

Discussion

 

One comment I was taken aback by was Cody Soska saying, “I seriously can’t find any criticism for this project. The fabrication is especially impressive, given that you’ve never used a laser cutter before.” This is overwhelmingly high praise given Cody’s expertise in fabrication, which surprised me given that the thing I struggled with the most was putting these damn pieces of plastic together. The step that I had thought would be the simplest was actually the most challenging. I had thought fingerjointing the panels would make for an easy puzzle that would snap and hold together via friction, however ambiguous orienting made for falsely matched pieces and a nasty thing called gravity chose to make pieces fall as soon as they were being conjoined. This part of the process was certainly the most frustrating aspect of the build. I also read a written piece of criticism saying, “Maybe think about changing the art color or allowing variable LED colors to add more customization.” Varying the colors was a feature that I unfortunately did not have time to implement, but I totally agree. In my opinion, the lights are the selling factor of this project that really draw the user in, so I acknowledge that it is a feature that could have upscaled this build by quite a bit.

Overall, I am quite happy about my final build. I dedicated way more time than I had initially planned to this project, though each extra minute was out of love. I had a vision to make a sleek, jet black box that put on a light show when you put your phone away, and I can confidently say I made just that. Ever since I was a kid, I was obsessed with this water droplet illusion and I’ve always wanted to see it done in person. Therefore I’m extra proud that the first time seeing it live is by building it myself. I knew this project was going to be pretty ambitious given my vision of the end-product and obsessive perfectionism (amidst my other deadlines/exams) but it was all so worth it. I’m happy to be finally dusting off my hands with an amazing end-product.

I learned many technical things through this build. Here are a few: I learned that laser cutting is relatively easy, however construction is not. I learned how to split a 12V power supply into 5V, which made for a sleek finish at the end (just one plug to power the whole thing!). I also learned how to solder pretty well, which made for more compact and sturdy wiring. I also learned that working with water and electronics is probably the most annoying combination in the world. One thing I would have done differently is make it easier to fill/dispose the water, perhaps by simply making the back panel a hinged door instead of a solid back. Regardless, safe to say I’ll be taking a break with pumps for a long time. On this topic, I’d advise my past self to pick a different project with similar aspects but without the water. See https://wondermachines.com/.

If I made another droplet machine, I’d make it wayy bigger! Maybe one day I could get commissioned by the university to make one in Gates that falls beside the Helix, though this time it would have another dimension of user interaction to it. Imagine streams of water falling around the Helix and when you go to touch it, a laser beam that flows through just that one stream begins strobing. It would make for a trippy effect, just the droplets inside the outline of your hand moving up as all other droplets move down.

 

 

Diagrams and Schematics

 

Block diagram of the entire project.

 

 

Electrical schematic of the entire project.

 

 

 

Code

 

// Droplet Distracter
// Author: Cameron
// Date: 3/15/23
// This code is responsible for reading whether the user has placed his/her
// phone in the slot, triggering the light show, and maintaining the water level.
//
//                   ---------------------------
//                   |   PIN        |  LABEL   |
//                   ---------------------------
//                   | TRIGGER_PIN  |    12    |
//                   | ECHO_PIN     |    11    |
//                   | PUMPPIN1     |    3     |
//                   | PUMPPIN2     |    4     |
//                   | INFRAPIN     |    A0    |
//                   | ledStrip pin |    10    |
//                   ---------------------------


#include <NewPing.h>
#define TRIGGER_PIN  12 
#define ECHO_PIN     11 
#define MAX_DISTANCE 200
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

const int PUMPPIN1 = 4;
const int PUMPPIN2 = 3;

#include <PololuLedStrip.h>
PololuLedStrip<10> ledStrip;
#define LED_COUNT 34
rgb_color on[LED_COUNT];
rgb_color off[LED_COUNT];
rgb_color on_boring[LED_COUNT];
int R = 69;
int G = 222;
int B = 110;
int factor = 5;

const int INFRAPIN = A0;


// set up for peristaltic pump
void pump_setup(){
  pinMode(PUMPPIN1, OUTPUT);
  pinMode(PUMPPIN2, OUTPUT);
}

// set up for infrared sensor
void infra_setup(){
pinMode(INFRAPIN, INPUT);
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  // establish on
  for (uint16_t i = 0; i < LED_COUNT; i++)
  {
    on[i] = rgb_color(R, G, B);
    on_boring[i] = rgb_color(R/factor, G/factor, B/factor);
    off[i] = rgb_color(0, 0, 0);
  }

  pump_setup();
  infra_setup();

}

// debugging: moves all water from one container
// to another
// void loop(){
//   bool fill_top = false;

//   int water_lvl = sonar.ping_cm();
//   Serial.print("Water Level: ");
//   Serial.println(water_lvl);

//   // (we turned CW)
//   if(fill_top){
//     digitalWrite(PUMPPIN1, HIGH);
//   }
//   // (we turned C'CW)
//   if (!fill_top){
//     digitalWrite(PUMPPIN2, HIGH);
//   }
// }

// pumps in water level so that there
// is at most 2 cm of distance between
// USR and water level
void maintain_water_lvl(){
  int water_lvl = sonar.ping_cm();
  Serial.print("\n\n\n\n\n\n");
  Serial.print("Water Level: ");
  Serial.println(water_lvl);
  if(water_lvl > 2){
    digitalWrite(PUMPPIN1, HIGH);
  }
  else{
    digitalWrite(PUMPPIN1, LOW);
  }
}

// light setting when phone not in slot
void boring(){
  ledStrip.write(on_boring, LED_COUNT);
}

// light setting when phone is in slot
void light_show(){
  ledStrip.write(on, LED_COUNT);
  delay(3);
  ledStrip.write(off, LED_COUNT);
  delay(10.5);
}

// main loop
void loop() {
  maintain_water_lvl();
  int read = analogRead(INFRAPIN);
  Serial.print("INFRA: ");
  Serial.println(read);
  
  if(read > 80){
    light_show();
  }
  else{
    boring();
  }

}

 

 

]]>
My Day Duffle https://courses.ideate.cmu.edu/60-223/s2023/work/my-day-duffle/ Wed, 08 Mar 2023 03:50:20 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=17552 This is a redefined bag, personalized to cater to my schedule requirements. 

Video of it working:

This is a video of the bag in practice. According to my schedule for Thursday, pockets one, two and, three are lit up ad only when all the three pockets are filled with the required things the LED strips turn off, indicating that my bag is packed and I am ready to go for the day.

Product photos:

Overall photo for proportion and scale

Side view of the bag

Detail photos:

Housing details: Image showing LED strip placed in the center on top of every pocket. The LCD screen in popping out from the middle as well to display RTC. This image also focuses on the detail of how the base of the pocket is fabricated with an open box using plywood where the IR break beam sensors are screwed to the side to detect an object intervention. The box has holes on the backside for the wires to follow a path from one pocket to the next till the last pocket to connect to the Arduino.

A close-up of how it looks inside. The LCD screen is stitched to the bag from inside and the open box is placed at the bottom of the pocket with wires pushed to the side so that there is clear space for interaction.

Usage photos:

According to the day’s schedule the bag has certain pocket LED strip lights on indicating that the specific items are missing and the pockets need to be filled, to make my bag ready for the day.

As all the pockets are filled the red indication light turns of implementing I am ready for the day

The bag is conditioned to work from 6:00 am to 8:00 am which is my regular time to arrange my bag for the day. So that during the day if I take out stuff from my bag the LED strip doesn’t glow back as the purpose of the bag is not to indicate whether the pocket is full or empty but rather to make the morning routine simpler and more efficient for me.

Process images and review:

This is my initial ideation of the project where I thought of the bag as a smart bag where the detection of the object was decided through pressure sensor. Through the initial making of the project I realized that the pressure sensor will not be very consistent and reliable as it is very small and sensitive. As the bag is soft the pressure sensor could actually get activate by any surface of the bag. This was a very initial exploration but I feel it had a big change in my idea as I had a lot of add-ons which I initially didn’t think of.

I opted for a step-by-step process for my project. This was my first step to explore the IR Break beam sensor (the sensor I chose to work with instead of the pressure sensor) by experimenting with the basic obstacle detecting method and using a LED for indication.

During the process, since I was including one set of sensor in each pocket of the bag I coded all four sensors individually and then combined the code for all. The step where I had to condition the system to work according to my schedule was a little confusing for me as there where so many conditions I needed to keep in mind, so through making flow charts and diagrammatic references I managed to code it all.

Since, I didn’t have the bag for the first week, I targeted myself to complete the electrical part which was finishing the coding for the whole system in relation to the RTC. This image shows my prototype model for the four sensors as four pockets working with respective LEDs in relation to the RTC following my schedule.

The next step was to measure each bag pocket and fabricate the base where the sensors will be installed and so that each pocket has support to avoid any bag fabric intervention. I measured the bases of each pocket and sensor sizes using calipers for accuracy. It was difficult to reach till the bottom of the bag and so since the bag was flexible I folded the pockets outward to measure the size, however I felt it didn’t give me exact dimensions and I had to sort of eyeball ay some points at the stitches didn’t align entirely.

Also, it was my first time working with plywood and I think it was a little challenging as in the very first place I made the boxes to align at the edges instead of making finger joints for the corner as that challenged me to be extra careful with the craft.

This image shows my process of making each base, gluing the edges using the tite bond wood glue and clamping the edges for half an hour. This made the whole process very slow as it was very time consuming. The other challenge was that I had to be very careful aligning the edges as I had to make sure I clamped them at exact 90 degrees.

After fabricating the boxes I placed each box in the pockets respectively however the screws available where only 20 mm which increased the size and thus there was no margin to fit the box in and thus I had to cut the extra screw using the hacksaw. To avoid the friction I also oiled the hacksaw, it was a new discovery for me.

After placing all the boxes and doing the wiring in the bag, it became very messy as it was very chaotic than I had thought and made it very difficult for me to keep a track. The wiring was majorly wiring and groung however there were sensor wires and LED strip data pins that had to be connected. During this porcess I also had to be very careful that the wires are long enough to reach to the end of the bag. With a few wires my estimation was wrong and I actually had to solder couple of wires in the bag which was very hard.

The fabrication was personally more difficult than coding the system for me. After making the device there was some wiring issue that I came across and wasn’t able to figure out which sadly crashed my device and the sensors stopped working. However to make the system work and convey my idea I tried to do a quick fix by making a prototype using the proximity sensor.

I added proximity sensors for prototyping and coded the system to work according to analog reading. The system worked as expected and was successfully running.

Discussion:

One critique I received during the in-class critique was about the limited time frame during which the project operates. The commenter felt that the restriction to operate only between 6:00 am to 8:00 am was a really sensitive consideration. In response, I feel that the project was designed to fit my personal schedule and needs, but I acknowledged that it may not be ideal for everyone. Another critique I received was about the use of IR break beam sensors. The commenter was unfamiliar with this type of sensor and questioned its reliability. They also suggested an E textiles class which could help me with the skills to incorporate my sensors into the bag so that I can get rid of the extra box like base that I had to create for the sensors. I feel how the sensors work and the advantages of using them in this project, such as their ability to detect object presence accurately and their low power consumption is beneficial. I also noted that there are other types of sensors that could be used in a similar project like pressure sensor, and that the choice of sensor depends on the specific design of the bag, like the pocket sizes and bag type(soft or stiff). I am pleased with the project’s overall outcome. It succeeded in helping me create a strategy that makes sure I have everything I need in my bag before leaving for the day. The usage of the IR break beam sensors, which have shown to be dependable and accurate, has particularly impressed me. I gained a lot of coding and technological knowledge while working on this project. The code for the RTC and LCD screen was simple, however initially I had trouble configuring the IR break beam sensors. Yet with perseverance and investigation, I was able to get beyond the difficulties and make them work. While I find them to be both tough and satisfying, I would like to keep working on projects that involve more condition-based applications in the future. Even though I am pleased with the project’s current state, I would like to keep tweaking and enhancing it. One potential improvement would be if creating the same bag I would think more about the wire connection and how I can improve the fabrication design so that I can avoid the wire chaos and have a more organized layout, which would also help in the sensors having any random intervention, making them more efficient. I would also like to explore other types of sensors that could be used in conjunction with the IR break beam sensors to provide more comprehensive information about the contents of the bag. Ultimately, my goal is to create a smart bag that can help users stay organized and prepared for the day ahead.

Technical Information:

Block diagram of the device showing inputs and outputs of the system

Electrical schematic of and how each component is attached to Arduino

Code:

// My Day Duffle
// By: Juhi Kedia

// The following code is intended to indicate whether the bag is ready for the day or not
// according to my schedule. There is a RTC running in the code which tracks the day, date and time.
// It can also be manually adjusted for testing. The LCD screen is coded to display the information
// provided from the RTC so that the clock is visible to the user. There are 4 IR break beam sensors
// attached to 4 inputs which detect whether the object is present or not. There is an emitter and
// a receiver in the IR break beam sensor so if the object is present the receiver doesn't receive light
// which indicates the LEDs attached to the sensor to either turn on or off accordingly. This thus indicates
// whether stuff in bag is present or not. This is conditioned to work between 6:00 am to 8:00 am
// so that the LEDs don't turn on and off during the day as it can become very distracting to carry a bag like that.
// The code has different conditions for each sensor and LED strip respectively according to the day of the week
// in this case for me according to my schedule.

// Pin Mapping:
//     Arduino Pin  /  Role  /   Description
//       2            Input    Pocket 1 sensor
//       3            Input    Pocket 2 sensor
//       4            Input    Pocket 3 sensor
//       5            Input    Pocket 4 sensor
//       7            Output   Pocket 1 LED strip
//       8            Output   Pocket 2 LED strip
//       9            Output   Pocket 3 LED strip
//       10           Output   Pocket 4 LED strip

// Reading the IR break beam sensor and turning on a LED code inspiration from:
// https://www.sensingthecity.com/using-ir-breakbeam-senors-to-detect-the-fullness-of-a-trash-bin-and-change-rgb-color-accordingly/

// Understanding how the RTC needs to be coded and how the information from the RTC
// can be displayed on the LCD screen code inspiration from:
// https://www.youtube.com/watch?v=aJcncPB0GHg


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <PololuLedStrip.h>

// setup PololuLedStrip and set each strip to a pin number
PololuLedStrip<7> ledStrip1;
PololuLedStrip<8> ledStrip2;
PololuLedStrip<9> ledStrip3;
PololuLedStrip<10> ledStrip4;

#define LED_COUNT 5

RTC_DS3231 rtc;

#define SENSORPIN1 2
#define SENSORPIN2 3
#define SENSORPIN3 4
#define SENSORPIN4 5

int sensorState1 = 0, lastState1 = 0;
int sensorState2 = 0, lastState2 = 0;
int sensorState3 = 0, lastState3 = 0;
int sensorState4 = 0, lastState4 = 0;

rgb_color on[LED_COUNT];
rgb_color off[LED_COUNT];


char daysOfTheWeek[7][4] = {
  "Sun",
  "Mon",
  "Tue",
  "Wed",
  "Thu",
  "Fri",
  "Sat"
};

int Day;
int Month;
int Year;
int Secs;
int Minutes;
int Hours;

String dofweek;  //days of week
String myDate;
String myTime;
String dow;

LiquidCrystal_I2C screen(0x27, 16, 2);


void setup() {
  screen.init();
  screen.backlight();
  Serial.begin(9600);
  screen.begin(16, 2);
  delay(3000);

  // initialize the sensor pin as an input:
  pinMode(SENSORPIN1, INPUT);
  pinMode(SENSORPIN2, INPUT);
  pinMode(SENSORPIN3, INPUT);
  pinMode(SENSORPIN4, INPUT);

  digitalWrite(SENSORPIN1, HIGH);  // turn on the pullup
  digitalWrite(SENSORPIN2, HIGH);  // turn on the pullup
  digitalWrite(SENSORPIN3, HIGH);  // turn on the pullup
  digitalWrite(SENSORPIN4, HIGH);  // turn on the pullup

  Serial.begin(9600);

  for (int i = 0; i < LED_COUNT; i++) {
    // on is red
    on[i] = rgb_color(255, 0, 0);
  }
  for (int i = 0; i < LED_COUNT; i++) {
    // off is clear/nothing
    off[i] = rgb_color(0, 0, 0);
  }

  if (!rtc.begin()) {
    Serial.println(" RTC Module not Present");
    while (1)
      ;
  }
  if (rtc.lostPower()) {
    Serial.println("RTC power failure, reset the time!");
    // automatically sets the RTC to the date & time on PC this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // rtc.adjust(DateTime(2023, 2, 20, 3, 0, 0));
  } else {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // adjusts the rtc manually for demo
    // rtc.adjust(DateTime(2023, 2, 23, 6, 0, 0));
  }
}


void loop() {
  // read the state of the sensors:
  sensorState1 = digitalRead(SENSORPIN1);
  sensorState2 = digitalRead(SENSORPIN2);
  sensorState3 = digitalRead(SENSORPIN3);
  sensorState4 = digitalRead(SENSORPIN4);
  // Serial.println(sensorState1);

  DateTime now = rtc.now();
  screen.clear();
  Day = now.day();
  Month = now.month();
  Year = now.year();
  Secs = now.second();
  Hours = now.hour();
  Minutes = now.minute();
  dofweek = daysOfTheWeek[now.dayOfTheWeek()];

  myDate = myDate + dofweek + " " + Day + "/" + Month + "/" + Year;
  myTime = myTime + Hours + ":" + Minutes + ":" + Secs;

  // send to serial monitor
  Serial.println(dofweek);
  Serial.println(myDate);
  Serial.println(myTime);

  //print on lcd
  screen.setCursor(0, 0);
  screen.print(myDate);
  screen.setCursor(0, 1);
  screen.print(myTime);
  myDate = "";
  myTime = "";
  delay(1000);

  // check if the sensor beam is broken
  // if it is, the sensorState is LOW:
  // turn LED off:
  // Red (turn the red LED off):

  if (now.hour() >= 6 && now.hour() < 8) {
    if (dofweek == "Mon") {
      if ((sensorState1 == LOW) && (sensorState4 == LOW)) {
        ledStrip1.write(off, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);

      } else {
        // On (LED on):
        ledStrip1.write(on, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(on, LED_COUNT);
      }
    }

    if (dofweek == "Tue") {
      if ((sensorState1 == LOW) && (sensorState2 == LOW)) {

        ledStrip1.write(off, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);


      } else {
        // On (LED on):
        ledStrip1.write(off, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(on, LED_COUNT);
        ledStrip4.write(on, LED_COUNT);
        // Serial.println("sensorState1");
      }
    }


    if (dofweek == "Wed") {
      if ((sensorState1 == LOW) && (sensorState3 == LOW) && (sensorState4 == LOW)) {
        ledStrip1.write(off, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);

      } else {
        // On (LED on):
        ledStrip1.write(on, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(on, LED_COUNT);
        ledStrip4.write(on, LED_COUNT);
      }
    }

    if (dofweek == "Thu") {
      if ((sensorState1 == LOW) && (sensorState2 == LOW) && (sensorState3 == LOW)) {
        ledStrip1.write(off, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);

      } else {
        // On (LED on):
        ledStrip1.write(on, LED_COUNT);
        ledStrip2.write(on, LED_COUNT);
        ledStrip3.write(on, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);
      }
    }

    if (dofweek == "Fri") {
      if ((sensorState1 == LOW) && (sensorState2 == LOW)) {
        ledStrip1.write(off, LED_COUNT);
        ledStrip2.write(off, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);

      } else {
        // On (LED on):
        ledStrip1.write(on, LED_COUNT);
        ledStrip2.write(on, LED_COUNT);
        ledStrip3.write(off, LED_COUNT);
        ledStrip4.write(off, LED_COUNT);
      }
    }
  } else {
    ledStrip1.write(off, LED_COUNT);
    ledStrip2.write(off, LED_COUNT);
    ledStrip3.write(off, LED_COUNT);
    ledStrip4.write(off, LED_COUNT);
  }


  // if (sensorState && !lastState) {
  //   Serial.println("Unbroken");
  // }
  // if (!sensorState && lastState) {
  //   Serial.println("Broken");
  // }
  // lastState = sensorState;
}

 

]]>
Double Transducer – Temperature to Fan Speed. https://courses.ideate.cmu.edu/60-223/s2023/work/project-1-double-transducer-temperature-to-fan-speed/ Tue, 14 Feb 2023 22:19:37 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=17171 Angie Wang, Stanley Ip, Michelle Liu

Top view of Stanley’s Double Transducer. Thermistor (left), fan (right)

Top view of Michelle’s Double Transducer. Fan (left), thermistor (right).

Top view of Angie’s Double Transducer. Thermistor(Middle-left, labeled as “INPUT”), Fan(Top-right, labeled as “OUTPUT”)

Adafruit color sensor secured directly above color wheel, which is spun by a stepper motor.

Another angle of the Adafruit color sensor secured above the color wheel and overview of some of the wiring we did to connect the steps.

Close up of the fan and LED setup.

 

Final Working Model:

Stanley

Michelle

Narrative Description:

The thermistor picks up on the temperature being emitted, and based on how high or low the temperature is, the Arduino Uno will determine how much to rotate a stepper motor. A color wheel is attached to the stepper motor, and an RGB sensor will detect the hue rotated in front of it. This hue then determines the wind speed.

 

Process:

A hand holding the adafruit sensor next to a color wheel, propped up on a stepper motor.

Testing the Adafruit sensor and stepper motor to make sure these middle step components work reliably. – Stanley

 

Getting the color sensor to pick up hue from the color wheel. As the color wheel spins, the hue value is recorded and is represented by the graph on screen. – Stanley

 

Getting the fan to respond to hue. A higher hue value (blues, purples) corresponds to higher fan speed, and lower hue values (red) corresponds to lower fan speed. – Michelle

 

Putting it all together (stepper motor, color wheel, fan) – Michelle

 

Discussion:

From the beginning of the project, we didn’t expect that our direction of going from a temperature input, to color, and fan speed would be technically challenging to execute. In particular, there were a few external things we had to learn, from learning how to use a MOSFET to control fan speed, to using a driver for the stepper motor, etc. We worked through this by taking the time to understand each component individually first – their capabilities, how the hardware itself works, how to speak to it through code, etc. and that helped us get a holistic idea of how we can get each component to communicate with each other.

Needless to say, there was a lot of debugging in our process. With so many new components and systems, it was difficult to pinpoint exactly which part was going wrong – whether it was the software, weak connections, or just a single wire plugged incorrectly. Oftentimes, we would mess with the code and wiring a lot just to find that the breadboard was faulty. Towards the end, we learned to use software workarounds for hardware problems. For example, with the RGB sensor, it was difficult to figure out a way to physically set the stepper motor such that the low temperature corresponds to the red part (low hue value) of the color wheel. Instead, we wrote a function to rotate and calibrate the color wheel, so that a lower temperature always corresponds to red, and a higher temperature always corresponds to purple. 

In the end, we are glad that we followed through with the idea, using these different dimensions (temperature, hue, fan speed) in a novel yet cohesive way, and it was definitely a very productive experience in learning how to work with hardware and software simultaneously and creatively. 

 

Block Diagram & Schematic:

 

 

Code:

/*
* TEMPERATURE > COLOR > FAN SPEED DOUBLE TRANSDUCER
* Michelle Liu, Stanley Ip, Angie Wang
* 
* The thermistor picks up on the temperature being emitted, and based on how high or 
* low the temperature is, the Arduino Uno will determine how much to rotate a stepper motor.
* A color wheel is attached to the stepper motor, and an RGB sensor will detect the hue
* rotated in front of it. This hue then determines the fan speed.
* 
* Pin Map:
variable name | mode | pin | description
-----------------------------------------------
FAN_PIN | output | 10 | controls fan speed
STEP_PIN | output | 2 | stepper motor: sets stepper position
DIR_PIN | output | 3 | stepper motor: sets stepper direction
THERMO_PIN | output | A0 | thermistor: reads in resistance from the thermistor
* 
* Credits:
* RGB sensor code referenced from the Adafruit TCS34725 breakout library example
* code: https://learn.adafruit.com/adafruit-color-sensors/arduino-code
* 
* Algorithm for converting RGB values to hue values referenced from
* https://www.geeksforgeeks.org/program-change-rgb-color-model-hsv-color-model/
* 
* Stepper motor code referenced from the course website:
* https://courses.ideate.cmu.edu/60-223/s2023/tutorials/stepper
* 
* LCD display code referenced from the course website: 
* https://courses.ideate.cmu.edu/60-223/s2023/tutorials/I2C-lcd
*/


#include <Wire.h>
#include "Adafruit_TCS34725.h" // ADAFruit TCS34725 driver for ADAFruit TCS34725 RGB Color Sensor by Adafruit
#include <AccelStepper.h> // AccelStepper stepper motor driver by Mike McCauley
#include <LiquidCrystal_I2C.h> // LiquidCrystal I2C LCD display driver by Frank de Brabander

LiquidCrystal_I2C screen(0x27, 16, 2);

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);

// WIRING
const int FAN_PIN = 3;
const int STEP_PIN = 8;
const int DIR_PIN = 9;
const int THERMO_PIN = A0;
const int FAN_START_SPEED = 0;

AccelStepper myMotor(1, STEP_PIN, DIR_PIN);

int pos = 800; // variable to store motor position instruction
int fanSpeed = 0;
int dispDelay = 0;

void setup(void) {
  screen.init();
  Serial.begin(9600);

// LCD DISPLAY SETUP

  screen.backlight();
  screen.home();

// RGB SENSOR SETUP

  if (tcs.begin()) {
    Serial.println("Found sensor");
  } else {
    Serial.println("No TCS34725 found ... check your connections");
    while (1);
  }

// STEPPER MOTOR SETUP

  myMotor.setMaxSpeed(1000); // measured in steps per second
  myMotor.setAcceleration(500); // measured in steps per second squared

  initializeMotorPos();

  pinMode(FAN_PIN, OUTPUT);
  pinMode(THERMO_PIN, INPUT);
  analogWrite(FAN_PIN, FAN_START_SPEED);

}

// HUE ALGORITHM
// Algorithm from https://www.geeksforgeeks.org/program-change-rgb-color-model-hsv-color-model/
// Range: 0 (red) - 360 (violet)
double calculateHue(uint16_t r, uint16_t g, uint16_t b) {
  double rDepth = r / 65535.0;
  double gDepth = g / 65535.0;
  double bDepth = b / 65535.0;

  double rgbMax = max(max(gDepth, bDepth), rDepth); // maximum of r, g, b
  double rgbMin = min(min(gDepth, bDepth), rDepth); // minimum of r, g, b

  double rgbDiff = rgbMax - rgbMin; // diff of cmax and cmin.

  if (rgbDiff == 0) {
    return 0.0;
  } else if (rgbMax == rDepth) {
    return fmod(60.0 * ((gDepth - bDepth) / rgbDiff) + 360.0, 360);
  }
  else if (rgbMax == gDepth) {
    return fmod(60 * ((bDepth - rDepth) / rgbDiff) + 120, 360);
  } else {
    return fmod(60 * ((rDepth - gDepth) / rgbDiff) + 240, 360);
  }
}

// Reads RGB sensor data without introducing a delay like the built-in function does
void getRawData_noDelay(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c)
{
  *c = tcs.read16(TCS34725_CDATAL);
  *r = tcs.read16(TCS34725_RDATAL);
  *g = tcs.read16(TCS34725_GDATAL);
  *b = tcs.read16(TCS34725_BDATAL);
}

// initialize motor pos to approximately red
void initializeMotorPos() {
  uint16_t r, g, b, c, colorTemp, lux;

  getRawData_noDelay(&r, &g, &b, &c);
  int hue = (int)calculateHue(r, g, b);

// rotate the stepper motor by 1 degree until the hue reaches a value close to red
  while (hue > 15) {
    getRawData_noDelay(&r, &g, &b, &c);
    hue = (int)calculateHue(r, g, b);
    myMotor.move(1);
    myMotor.run();
  }
  Serial.print("RED FOUND: ");
  Serial.println(myMotor.currentPosition());
  myMotor.setCurrentPosition(0);
}

// debugging helper function for printing values with their labels
void p(String label, int val) {
  Serial.print(label + ": "); Serial.print(val, DEC); Serial.print(" ");
  Serial.println(" ");
}

void displayVal(String c, int i) {
  screen.print(c);
  screen.print(":");
  screen.print(i < 10 ? "0" : "");
  screen.print(i < 10 ? "0" : "");
  screen.print(i);
}

/*
   i = input, iMax = input upper range
   m = middle-step actuator value, mMax = middle-step actuator value upper range
   s = middle-step sensor value, mMax = middle-step sensor value upper range
   o = output, oMax = middle-step actuator value upper range
*/
// helper function for displaying values on the LCD screen
void displayLCD(int i, int iMax, int m, int mMax, int s, int sMax, int o, int oMax) {
  int iNorm = map(i, 0, iMax, 0, 99);
  int mNorm = map(m, 0, mMax, 0, 99);
  int sNorm = map(s, 0, sMax, 0, 99);
  int oNorm = map(o, 0, oMax, 0, 99);

  displayVal("i", iNorm);
  screen.print("  ");

  displayVal("  m", mNorm);

  screen.setCursor(1, 6);

  displayVal("s", sNorm);
  screen.print("  ");

  displayVal("  o", oNorm);

   screen.print("      ");

  if (dispDelay > 100) {
    dispDelay = 0;
    screen.clear();
  }
}

void loop() {
  int thermoVal = analogRead(THERMO_PIN);

  pos = map(thermoVal, 450, 600, 0, 200);

  myMotor.moveTo(-pos); // and tell the motor to go there
  myMotor.run(); // call this function as often as possible

  uint16_t r, g, b, c, colorTemp, lux;

  getRawData_noDelay(&r, &g, &b, &c);
  int hue = (int)calculateHue(r, g, b);

  fanSpeed = map(hue, 0, 360, FAN_START_SPEED, 255);

  analogWrite(FAN_PIN, fanSpeed);

  displayLCD(thermoVal, 1023, pos, 400, hue, 360, fanSpeed, 255);

  dispDelay += 1;
}

 

 

]]>
Protected: Double Transducer: Varying Light Valve Transparency https://courses.ideate.cmu.edu/60-223/s2023/work/dunns-double-transducer/ Mon, 13 Feb 2023 02:43:59 +0000 https://courses.ideate.cmu.edu/60-223/s2023/work/?p=17115

This content is password protected. To view it please enter your password below:

]]>