Documentation – 62-362 Fall 2020 https://courses.ideate.cmu.edu/62-362/f2020 Electronic Logics && Creative Practice Tue, 29 Dec 2020 23:10:37 +0000 en-US hourly 1 https://wordpress.org/?v=5.4.15 Barber Shop https://courses.ideate.cmu.edu/62-362/f2020/gates-documentation-john/ Fri, 18 Dec 2020 21:58:56 +0000 https://courses.ideate.cmu.edu/62-362/f2020/?p=10734 I decided to make an automaton music box for this assignment. I never expected it could be so much work. Of all the projects this semester, I think I learned the most doing this one. In the process I accidentally fried 2 arduinos and a good handful of other electronics. While it was frustrating at the time, the other projects were much easier thanks to the knowledge I gained.

My friend Jackson made the 3 songs used after I gave him some small prompts, I was happy to get to include a piece of him in this odd little project.

The initial idea was a barber shop that caught on fire, not sure how well that was reflected but I was happy with the mood of the finished piece.

 

Electronics and Structure:

Some of the fabrication:

Some early sketches and plans:

 

Electronics:

arduino uno, 7408 quad AND gate, 7404 NOT gate, L293D motor driver, DFPlayer mini, 2 hobby gear motors, 1 continuous rotation servo, micro sd card, micro sd card reader/writer, 3 pushbuttons, 2 potentiometers, speakers, neo pixel ring, 4 yellow LEDs, 8 red LEDs, wires, resistor, breadboard, 5v power source

Materials:

wood, cardstock, cereal boxes, sewing pins, paperclips, wire, plastic bags, old clothing/fabric, thread, tissues, electrical tape, gaffer tape, duct tape, staples, boba straw, pebbles, Styrofoam

Tools:

soldering iron and fan, scissors, wire cutters, needle, pliers, precision knife, compass (drawing tool), stapler, pencils/pens, ruler, cutting mat

 

Code:

Everything but music:

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

#include <Adafruit_NeoPixel.h>
#include <Servo.h>

#define PIN            9
#define NUMPIXELS      12

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

bool stage1 = false;
bool stage2 = false;
bool stage3 = false;

bool button1 = false;
bool button2 = false;
bool button3 = false;

bool song1 = false;
bool song2 = false;
bool song3 = false;

int value;
int angle;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

uint32_t red = pixels.Color(250,0,0);

Servo myservo;

void setup() {
  pixels.begin(); //backlight 
  pixels.setBrightness(0); 
  pixels.show();         

  pinMode(5, OUTPUT); //m1
  pinMode(6, OUTPUT); //m2
  myservo.attach(3); //m3
  
  pinMode(7, INPUT); //button1
  pinMode(8, INPUT); //button2
  pinMode(4, INPUT); //button3
  
  pinMode(A0, INPUT); //p1
  pinMode(A1, INPUT); //p2

  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
}

void loop() {

  //part 1
  if (digitalRead(7) == HIGH) {
    analogWrite(5, analogRead(A0)/4);
    button1 = true; 
  } else {
    button1 = false;
  }

  //part 2
  if (digitalRead(8) == HIGH) {
    analogWrite(6, analogRead(A0)/4);
    button2 = true;
  } else {
    button2 = false;
  }

  //part 3
  if (digitalRead(4) == HIGH) {
    //m3
    value = analogRead(A1);
    angle = map(value, 0, 1023, 10, 170); 
    myservo.write(angle); 
    //backlight
    pixels.setBrightness(150);
    pixels.fill(red);
    pixels.show();
    button3 = true;
  } else {
    myservo.write(10);
    pixels.setBrightness(0);
    pixels.show();
    button3 = false;
  }

  //dfmini 
  stage1 = (button1 && !button2);
  stage2 = (button1 && button2 && !button3);
  stage3 = (button1 && button2 && button3);
  
  if (stage1 && !stage2 && !stage3 && !song1) {
    myDFPlayer.play(3);
    song1 = true;
    song2 = false;
    song3 = false;
  } else if (stage2 && !stage3 && !song2){
    myDFPlayer.play(1);
    song2 = true;
    song1 = false;
    song3 = false;
  } else if (stage3 && !song3){
    myDFPlayer.play(2);
    song3 = true;
    song1 = false;
    song2 = false;
  } 
  
  if (!stage1 && !stage2 && !stage3) {
    myDFPlayer.stop();
    song1 = false;
    song2 = false;
    song3 = false;
  }
  
}

 

dfmini controls:

/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
 <https://www.dfrobot.com/index.php?route=product/product&product_id=1121>

 ***************************************************
 This example shows the basic function of library for DFPlayer.

 Created 2016-12-07
 By [Angelo qiao](Angelo.qiao@dfrobot.com)

 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution
 ****************************************************/

/***********Notice and Trouble shooting***************
 1.Connection and Diagram can be found here
 <https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
 2.This code is tested on Arduino Uno, Leonardo, Mega boards.
 ****************************************************/

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

int counter = 1;

void setup()
{
  pinMode(7, INPUT);
  
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
}

void loop()
{
  
  if (digitalRead(7) == HIGH) {
    if (counter == 1) {
      myDFPlayer.play(3);
    } else if (counter == 2) {
      myDFPlayer.play(1);
    } else if (counter == 3) {
      myDFPlayer.play(2);
    } else {
      myDFPlayer.stop();
    }
    counter = counter + 1;
    if (counter == 5) {
      counter = 1;
    }
    delay(200);
  }

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value){
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

 

Useful references:

DFPlayermini

https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299

https://www.instructables.com/Tutorial-of-MP3-TF-16P/

L293d

https://www.tinkercad.com/things/gigwXYoyaDb

Neopixel_ring

https://www.instructables.com/3D-Printed-NeoPixel-Ring-Butterfly-With-Tinkercad/

https://www.tinkercad.com/things/c4nyZ9UpWer

 

Libraries found on Github:

https://github.com/adafruit/Adafruit_NeoPixel

https://github.com/DFRobot/DFRobotDFPlayerMini

 

TinkerCad Circuits I used to troubleshoot:

https://www.tinkercad.com/things/0evKMIHM0Ai-fantabulous-inari/editel?sharecode=NX5CYihf8vkyRuLa-rzRwghpmeox1-OVk11WzY99hrU

https://www.tinkercad.com/things/7uIwm5bLp6N-copy-of-project-1/editel?sharecode=YA4F9Lz2rxujlDz2OgQx0Xv3PKQZNSbunOs2S8PjWWM

]]>
Dance Space https://courses.ideate.cmu.edu/62-362/f2020/gates-dance-space/ Fri, 18 Dec 2020 17:46:36 +0000 https://courses.ideate.cmu.edu/62-362/f2020/?p=10694

Project Statement:
In order to capture and enhance my existing rountine of dancing in my living room, this dance space has been created. It is meant to be used as a place to let go of any stress, it may be added to a daily routine- or not. As you enjoy tea and dance, the space around you reacts to your actions. The idea is to move freely and unpredictably through the living space until the knit yarn pieces are lifted. I plan to complete this project with a final piece of documentation which will be a video of me dancing to music.

How to Use:
In order to turn the light on, the tea kettle must be lifted. in order to make the “worms” move up, three or more buttons one the ground must be pressed. Enjoy the space, move freely, and dance!

 

Process and Issues:

I ran into some issues while constructing the pieces. I didn’t predict well enough, how many things I would need into order to complete the project successfully. I think, for the time we were given I may have created a project that was a bit too big/complex in the manufacturing process. Another issue I ran into was not prdicting how long the clay was going to take to dry. Once dry, it will be spray painted the same shade as the chair.

The electronics/programming portion of the project ran pretty smoothly except for the uploading the program into the arduino. I didn’t have the library I needed for the code to run, so I downloaded the right library for the motor.
Looking back, I am happy with the direction this project has gone. If I were to change anything, it would most likely be the construction of my pulley system. Although it works, it is very fragile and I would have liked it to be more rigid so that there would be no risk in the whole system falling apart. I’m satisfied with the interactivity and tangibility of this project. I feel that I have achieved a very intuitive system as to how to operate the piece. Perhaps I could have have used less fragile floor pieces, however I enjoy how delicate they are- even the possibility of the clay cracking as I step on it.

 

Clay Floor Pieces

 

 

Electronics Setup

 

Planning

]]>
Love && Logic https://courses.ideate.cmu.edu/62-362/f2020/love-logic/ Fri, 09 Oct 2020 21:14:55 +0000 https://courses.ideate.cmu.edu/62-362/f2020/?p=9803 Sorry, but you do not have permission to view this content. ]]> Sorry, but you do not have permission to view this content. ]]> Workaholic’s Clock https://courses.ideate.cmu.edu/62-362/f2020/workaholics-clock/ Fri, 09 Oct 2020 20:58:39 +0000 https://courses.ideate.cmu.edu/62-362/f2020/?p=9721

The main apparatus…

Description

This device was referred to as the “Workaholic’s Calendar” during development, but this has since been changed to “Workaholic’s Clock” since it really is just a clock that tells you whether or not you can go to work.

In order to be able to go to work, the following criteria must be met:

  1. You must not be sick.
  2. Hunt Library must be open.
  3. If Hunt Library is closed, you must input the correct 5-digit passcode to disarm security.

The device has 3 main inputs and is controlled by an Arduino and a hard-wired logic circuit. The first input is an infrared break-beam sensor, which is there to detect whether or not you have taken the tissue–doing so would indicate that you are sick. You will get fired if you decide to come in anyway. The second input is a real-time clock, which the Arduino polls in order to determine whether or not Hunt Library (my workplace) is open. If it is open, then pressing * on the keypad will tell the Arduino to probe the logic circuit. If Hunt is closed, then the Arduino will probe the logic circuit once a 5-digit code is entered . If the output of that circuit is high (true), then you can go to work because the necessary conditions were met. If the output is low (false), then you get fired, and a certain message will be displayed, along with an accompanying sound depending on the reason for which you were fired.

In the case where Hunt is open, there is no need to enter a code, and the only thing that would cause you to get fired is sickness.

In the case where Hunt is closed, there are a few more possibilities. You must enter a 5-digit code. If the code is incorrect and you are sick, then you reach the “critical failure” output, where you not only infect everyone but also get arrested by “The Crops.” If the code is incorrect, but you aren’t sick, then you are arrested by “The Crops.” If the code is correct, but you are sick, then you infect everyone. In any of these cases, you get fired.

If Hunt is closed, but you enter the correct code to disarm security and you aren’t sick, then you can come in to work (sneakily, you devil).

Here are some shots of the device working under certain circumstances…

When Hunt is open, but you’re sick…

When you enter the correct code to disarm security, but you’re sick…

When you aren’t sick, but you enter the wrong code to disarm security…

When you are sick AND you enter the wrong code to disarm security…

When you aren’t sick and you properly disarm security…

When Hunt is open and you aren’t sick…

Process Images

Here is the hard-wired logic circuit after completion. When I first wired it up, I accidentally pulled the outputs low, rather than the inputs. This picture is from after I remedied that. From right to left, 7408 quad-AND gate, 7432 quad-OR gate, 7404 hex inverter (six NOT gates). All inputs are pulled low using 10k ohm resistors.

Here’s the device after initially wiring up the Arduino. The only components missing are the LCD and keypad. As you can see, the wiring is quite messy, but more alarmingly, the power is all coming from the Arduino. This is not enough to power everything properly and is ultimately what caused the problem shown in the video below… pardon my French…

Here’s the device after I got the keypad and LCD working. This was the final major hurdle in the build process. I actually had to start using pins 0 and 1 on the Arduino for communicating with the DFPlayer Mini so that I would have enough pins that weren’t A4 and A5 (which you can’t use when using I2C devices like the RTC). To get around problems when uploading code to the Arduino, I just unplug pins 0 and 1 and then plug them back in once the Arduino is ready.

And this was the most satisfying part–getting to come in to work with all parts working correctly.

Process Reflection

The hardest part, after all was said and done, was getting everything to look somewhat neat, while still remaining in the realm of breadboards and jumpers. I had originally planned to enclose parts within their own custom-fabricated enclosures to tidy the device up, but due to my own poor time management and the challenging circumstances brought about by the COVID-19 pandemic, obtaining such parts would prove impossible. As a result, breadboards and jumpers ended up being the final aesthetic. Another issue (closely related to the previous one) was that I never managed to separate the break-beam sensor from the breadboard, as I didn’t have a suitable enclosure that would allow me to thread a tissue through it. I still plan on addressing this at some point when things are a little less frantic, but for now, it is what it is.

I ended up learning (or in some cases, re-learning) quite a lot about the limitations of the Arduino Uno platform, mostly relating to the pinout of its microcontroller. For instance, I re-learned that you can’t use pins A4/A5 and SDA/SCL at the same time, as they conflict. I also learned that you CAN use pins 0 and 1, so long as you unplug whatever device is  connected to them whenever you need to upload code to the Arduino, and you don’t use the built-in serial monitor/plotter. Lastly, I learned that quite a few components are picky about how much power they receive and just won’t work right if you don’t give them enough. This ultimately stopped me from using the Elegoo Power Supply Module, as it wouldn’t supply enough power to the DFPlayer Mini given the audio setup I wanted to use. This was the case even when it was plugged into a 12V, 2A DC power supply, which should’ve been more than enough.

Despite the issues encountered, I’m actually pretty happy not just with the outcome, but also with what I learned about working with dedicated logic ICs and re-learned about working with the Arduino.

Code

Main program:

/*
   Workaholic's Clock (62-362 Project 1)
   Seth Geiser (sgeiser)

   Collaboration: Reference code and the guides I used for setting and accessing the RTC, setting, storing, and reading the passcode and keypad input, as well as outputting to the LCD can be found at these links:
   RTC: https://create.arduino.cc/projecthub/MisterBotBreak/how-to-use-a-real-time-clock-module-ds3231-bc90fe
   Keypad and passcode: https://www.instructables.com/Arduino-password-lock/
   LCD: Used guide from the Elegoo Super Starter Kit UNO R3 Project.

   Pin mapping:

   pin      | mode       | description
   ---------|------------|------------
   SDA/SCL   I2C          Real-time Clock
   0         RX           DFPlayer Mini TX
   1         TX           DFPlayer Mini RX
   2-8       I/O          Keypad
   9         INPUT_PULLUP Read output of main hard-wired logic...
   10        OUTPUT       Send hi/lo to main logic based on RTC
   11        INPUT        Read state of sick sensor for determining cause of firing (in part to determine which sound to play)
   12        LCD          LCD RS
   13        LCD          LCD Enable
   A0        LCD          LCD D4
   A1        LCD          LCD D5
   A2        LCD          LCD D6
   A3        LCD          LCD D7

*/
#include <ds3231.h>
#include <Wire.h>
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

const int passLen = 5;

const int readOutput1 = 9;
const int huntPin = 10;
const int sickPin = 11;

LiquidCrystal lcd(12, 13, A3, A2, A1, A0);

char password[passLen];
char pass[passLen], pass1[passLen];
int i = 0;
char customKey = 0;

bool arrested = false;
bool infected = false;

const byte ROWS = 4; // four rows
const byte COLS = 3; // four columns
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {5, 3, 2, 7};
byte colPins[COLS] = {4, 8, 6};

// initialize a new instance of class Keypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

struct ts t; // Be sure to set the RTC using setRTC.ino

// RX, TX, disconnect when uploading sketch!!!
SoftwareSerial mySoftwareSerial(0, 1);
DFRobotDFPlayerMini myDFPlayer;

void setup() {
  mySoftwareSerial.begin(9600);
  Wire.begin();
  lcd.begin(16, 2);
  DS3231_init(DS3231_INTCN); // Initialize connection to RTC...
  pinMode(huntPin, OUTPUT);
  pinMode(sickPin, INPUT);
  pinMode(readOutput1, INPUT_PULLUP);

  if (!myDFPlayer.begin(mySoftwareSerial)) {
    // Use softwareSerial to communicate with DFPlayer Mini.
    while (true);
  }

  // Set serial communictaion time out 500ms
  myDFPlayer.setTimeOut(500);
  // Set volume value (range 0-30).
  myDFPlayer.volume(15);
  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);

  lcd.print("CMU IDeATe");
  lcd.setCursor(0, 1);
  delay(1000);
  lcd.print("BOOTING DEVICE");
  delay(2000);
  lcd.clear();
  DS3231_get(&t); // Probe RTC
  if (t.hour >= 19 || t.hour <= 8) {
    digitalWrite(huntPin, HIGH); // Hunt is closed, Q3=T
    lcd.setCursor(0, 0);
    lcd.print("Hunt is closed.");
    lcd.setCursor(0, 1);
    lcd.print("Code: ");
    for (int j = 0; j < passLen; j++) {
      pass[j] = EEPROM.read(j); // Read password from built-in EEPROM
    }
  }
  else {
    digitalWrite(huntPin, LOW); // Hunt is open, Q3=F
    lcd.setCursor(0, 0);
    lcd.print("Welcome to Hunt.");
    lcd.setCursor(0, 1);
    lcd.print("Press '*'");
  }
}

void loop() {
  customKey = customKeypad.getKey(); // Read keypad...
  if (digitalRead(sickPin)) {
    infected = true;
  }
  else if (!digitalRead(sickPin)) {
    infected = false;
  }
  if (t.hour >= 19 || t.hour <= 8) { // Hunt closed...
    if (customKey) {
      password[i++] = customKey;
      lcd.print(customKey);
    }
    if (i == passLen) {
      i = 0;
      delay(200);
      for (int j = 0; j < passLen; j++)
        pass[j] = EEPROM.read(j);
      if (!strncmp(password, pass, passLen)) {
        i = 0;
        lcd.setCursor(0, 0);
        lcd.print("Passkey Accepted,");
        lcd.setCursor(0, 1);
        lcd.print("Welcome 2 IDeATe");
        delay(3000);
        digitalWrite(huntPin, LOW); // Open Hunt Library, disarm security...
        submit();
      }
      else {
        i = 0;
        lcd.clear();
        lcd.print("Access Denied...");
        delay(3000);
        arrested = true;
        submit();
      }
    }
  }
  else if (customKey == '*') {
    submit();
  }
}

void submit() {
  lcd.clear();
  if (digitalRead(readOutput1)) {
    // Logic is outputting LOW into a NOT-gate. Since the pin is being pulled up, pin 9 is connected to the output of the NOT-gate...
    lcd.setCursor(0, 0);
    lcd.print("You're fired!");
    lcd.setCursor(0, 1);
    if (arrested && infected) {
      lcd.print("Busted AND sick.");
      myDFPlayer.play(2); // 0002_get_out.mp3
    }
    else if (infected) {
      lcd.print("You're sick.");
      myDFPlayer.play(4); // 0004_bruh.mp3
    }
    else if (arrested) {
      lcd.print("Busted!");
      myDFPlayer.play(1); // 0001_crops.mp3
    }
  }
  else { // Logic is outputting HIGH into a NOT-gate...
    lcd.setCursor(0, 0);
    lcd.print("You can come to");
    lcd.setCursor(0, 1);
    lcd.print("work today!");
    myDFPlayer.play(3); // 0003_scatman_world.mp3
  }
}

Set real-time clock:

#include <Wire.h>
#include <ds3231.h>
 
struct ts t; 
 
void setup() {
  Serial.begin(9600);
  Wire.begin();
  DS3231_init(DS3231_INTCN);
  /*----------------------------------------------------------------------------
  In order to synchronise your clock module, insert timetable values below !
 ----------------------------------------------------------------------------*/
  t.hour=12; 
  t.min=7;
  t.sec=0;
  t.mday=9;
  t.mon=10;
  t.year=2020;
 
  DS3231_set(t);
}
 
void loop() {
  DS3231_get(&t);
  Serial.print("Date : ");
  Serial.print(t.mday);
  Serial.print("/");
  Serial.print(t.mon);
  Serial.print("/");
  Serial.print(t.year);
  Serial.print("\t Hour : ");
  Serial.print(t.hour);
  Serial.print(":");
  Serial.print(t.min);
  Serial.print(".");
  Serial.println(t.sec);
 
  delay(1000);
}

Initialize EEPROM with default password of “12345”:

#include<EEPROM.h>

void setup() {
  // Passcode will be 5 digits long
  for (int j=0;j<5;j++) {
    EEPROM.write(j, j+49);
  }
}

void loop() {

}

Test password storage + retrieval and optionally change password stored in EEPROM:

/*
    +------------------------------------------------------------------------+
    |                                                                        |
    |               ARDUINO LOCK SYSTEM FIRMWARE v1.1.0                      |
    |                       BY: DIY MECHANICS                                |
    |    --------------------------------------------------------------      |
    |  written_by: suhail  project:HOME AUTOMATION:-passcode lock sytem v1.1 |
    |  facebook.com/suhail jr.                      twitter.com/suhail jr.   |
    |             visit more @ www.diymechanics.wordpress.com                |
    +------------------------------------------------------------------------+
*/

///////////////////////////////////////////////////////////////////////////////

#include <Keypad.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>

//////////////////////////////////////////////////////////////////////////////

LiquidCrystal lcd(12, 13, A3, A2, A1, A0);
const int passLen = 5;
char password[passLen];
char pass[passLen], pass1[passLen];
int i = 0;
char customKey = 0;

//////////////////////////////////////////////////////////////////////////////

const byte ROWS = 4; // four rows
const byte COLS = 3; // four columns
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

///////////////////////////////////////////////////////////////////////////////

byte rowPins[ROWS] = {5,3,2,7}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {4,8,6}; // connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

////////////////////////////////////////////////////////////////////////////////////

void(* resetFunc) (void) = 0;
void setup() {
  lcd.begin(16, 2);
  lcd.print("STARK-TECHNOLOGY");
  lcd.setCursor(0, 1);
  delay(4000);
  lcd.print("BOOTING DEVICE");
  delay(1000);
  lcd.clear();
  lcd.print("KEYPAD-LOCKED");
  lcd.clear();
  lcd.print(" Passcode Please:");
  lcd.setCursor(0, 1);
  for (int j = 0; j < passLen; j++) {
    pass[j] = EEPROM.read(j);
  }

  ////////////////////////////////////////////////////////////////////////////////////

}
void loop()
{
  customKey = customKeypad.getKey();
  if (customKey == '#') {
    change();
  }
  if (customKey == '*') {
    resetFunc();
  }
  if (customKey) {
    password[i++] = customKey;
    lcd.print(customKey);
  }

  if (i == passLen) {
    i = 0;
    delay(200);
    for (int j = 0; j < passLen; j++) {
      pass[j] = EEPROM.read(j);
    }
    if (!(strncmp(password, pass, passLen))) {
      i = 0;
      lcd.clear();
      lcd.print("Passkey Accepted");
      lcd.setCursor(0, 1);
      lcd.print("#-Change");
      lcd.print("*-Lock");
    }
    else {
      lcd.clear();
      lcd.print("Access Denied...");
      lcd.clear();
      lcd.print("restarting...");
      delay(5000);
      i = 0;
      resetFunc();
    }
  }
}

////////////////////////////////////////////////////////////////////////////////////

void change() {
  int j = 0;
  lcd.clear();
  lcd.print("Current Passcode:");
  lcd.setCursor(0, 1);
  while (j < passLen) {
    char key = customKeypad.getKey();
    if (key) {
      pass1[j++] = key;
      lcd.print(key);
    }
    key = 0;
  }
  delay(500);

  if ((strncmp(pass1, pass, passLen))) {
    lcd.clear();
    lcd.print("Wrong Passkey...");
    lcd.setCursor(1, 1);
    lcd.print("DENIED");
    delay(2000);
    customKey = 0;
    resetFunc();
  }
  else {
    j = 0;
    lcd.clear();
    lcd.print("New Passcode:");
    lcd.setCursor(0, 1);
    while (j < passLen) {
      char key = customKeypad.getKey();
      if (key) {
        pass[j] = key;
        lcd.print(key);
        EEPROM.write(j, key);
        j++;
      }
    }
    lcd.print("  Done......");
    delay(1000);
    resetFunc();
  }
}

 

]]>
University Pandemic Personal Planning Device (UPPPD) https://courses.ideate.cmu.edu/62-362/f2020/upppd-final-documentation/ Fri, 09 Oct 2020 20:24:59 +0000 https://courses.ideate.cmu.edu/62-362/f2020/?p=9751 Sorry, but you do not have permission to view this content. ]]> Sorry, but you do not have permission to view this content. ]]> Warp Field https://courses.ideate.cmu.edu/62-362/f2020/process-blog-warp-field/ Wed, 30 Sep 2020 18:58:16 +0000 https://courses.ideate.cmu.edu/62-362/f2020/?p=9708 Final Documentation: 10-9-20

By William Lamkin

Warp Field

(Name changed from the prototype title Cut. )

Warp Field is an interactive experience for one person and a modular synthesizer, through the medium of a pair of scissors and a sheet of paper. Designed as an act of exploration, the performer sits with the paper in a private space and cuts the paper at their own pace, exploring the effects their choices make on the sounds created by the synthesizer. The performer knows that they must begin the experience by cutting from one end of the paper to the other, but is free to cut however they want in the spaces in between.
The way sounds reacts might not exactly be clear at first, but the more the performer cuts, the more they learn. Instead of a blank piece of paper, the sheet is decorated with stars and galaxies, likening the cut of the scissors to a spacecraft gaining knowledge from exploring the vast unknown. This is the meaning of the title Warp Field. Different areas trigger different changes in sound when cut, sometimes permanently. In this way, all actions made truly do matter. And because the paper is being destroyed in the process, these choices matter even more.
As an artist, I’ve always sought out ways of finding interaction that asks more of the person on the other side of the experience. Video games, for example, are successful at this, creating investment through the user’s own explorations and decisions. Instead of a passive experience, the relationship between art and audience is turned into an active one. Without someone to interact with it, the art wouldn’t exist. My goal with this, as with some other past works, is to find a way to take the this kind of relationship and applying it to music, blurring the lines between performer, audience, and composer.
Process Images
An early draft of what the sheet could have looked like. The Pen drawn paths were eventually abandoned for more free exploration.
Originally, the plan was for the signal to be transmitted through the body like so. However, this proved to not be feasible as the body introduced too much resistance.
An idea of what the setup would be like. This ended up being fairly accurate. Stereo panning ended up not being used so the speakers were kept to one side in the final product.
One key decision point was in me realizing I could use my synthesizer to generate sounds in real time, as opposed to sound files like I had originally planned.
As shown in this draft image, the geometry of the circuit paths in the original idea was much more important. This also required the use of much more alligator clips going into the sheet. The final product ended up only having one power source.
Process Reflection
The easiest part of the process was probably working on the sound design at the end. That is my field of expertise – so it was easy for me to create the sounds and decide how to control that with the device I made. The hardest was definitely the circuitry aspect. I had no prior experience using logic chips, and things like Pull down resistors were confusing for me and took me many hours to figure out how to get all of logic chips working. I am definitely glad I did learn how to get them to work and build a complex circuit out of it! I definitely want to continue exploring circuitry and using the Arduino especially because I am starting to see the potential it can give me.
I think another challenge was in creating a good idea for the project itself! I spent so much energy on the original idea that I had a very strong idea of what the final project would end up looking like and how it would function. Obviously there were some changes along the way, but I hope I can continue to think up interesting ideas for the remaining projects.
Logic Diagram
Electronic Schematic
Arduino Code
/*  Warp Field
 *  William Lamkin
 *  
 *  This code takes inputs from the external Logic Gates and sends
 *  predetermined voltage values out of the 4 outputs of the
 *  Adafruit MCP4728 Quad DAC. These voltage signals are then
 *  sent into a Eurorack synthesizer to control sounds.

*/

#include <Adafruit_MCP4728.h>
#include <Wire.h>

//assign pin names
const int pinA = 9;
const int pinB = 2;
const int pinC = 3;
const int pinD = 4;
const int pinE = 5;
const int pinF = 6;
const int pinG = 7;
const int pinH = 8;

//defining variables for the values of pins 
int A = 0;
int B = 0;
int C = 0;
int D = 0;
int E = 0;
int F = 0;
int G = 0;
int H = 0;

Adafruit_MCP4728 mcp;

void setup() {

  //activating pins
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  pinMode(pinC, INPUT);
  pinMode(pinD, INPUT);
  pinMode(pinE, INPUT);
  pinMode(pinF, INPUT);
  pinMode(pinG, INPUT);
  pinMode(pinH, INPUT);

  
  // checks for I2C connection to the MCP4728 (code from Adafruit)
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MCP4728 test!");

  // Try to initialize!
  if (!mcp.begin()) {
    Serial.println("Failed to find MCP4728 chip");
    while (1) {
      delay(10);
    }  

  }

  //default values for the outputs
  mcp.setChannelValue(MCP4728_CHANNEL_A, 0);
  mcp.setChannelValue(MCP4728_CHANNEL_B, 0);
  mcp.setChannelValue(MCP4728_CHANNEL_C, 0);
  mcp.setChannelValue(MCP4728_CHANNEL_D, 0);

}

void loop() {

  //update pin state variables
  A = digitalRead(pinA);
  B = digitalRead(pinB);
  C = digitalRead(pinC);
  D = digitalRead(pinD);
  E = digitalRead(pinE);
  F = digitalRead(pinF);
  G = digitalRead(pinG);
  H = digitalRead(pinH);
  
  
  // Had to mirror the logic of the gates in here since only one
  // value can be sent to an output at a time

  // Channel B controlled the lowpass filter cutoff on the drone
  if (A == HIGH) {
    if (H == HIGH) {
      mcp.setChannelValue(MCP4728_CHANNEL_B, 0);
    }
    if (H == LOW) {
       if (B == LOW) {
            mcp.setChannelValue(MCP4728_CHANNEL_B, 1024);
          }
       else if (B == HIGH) { 
          if (C == LOW) {
            mcp.setChannelValue(MCP4728_CHANNEL_B, 2048);
          }
          else if (C == HIGH) {
            mcp.setChannelValue(MCP4728_CHANNEL_B, 4095);
          }
       }
    }          
  }


  // Channel C controlled the amount of resonance on that filter
  if (D == HIGH) {
    if (F == HIGH) {
      mcp.setChannelValue(MCP4728_CHANNEL_C, 4095);
    }
    else if (F == LOW) {
      mcp.setChannelValue(MCP4728_CHANNEL_C, 2048);
    }
    
  }
 
  // Channel D controlled the volume of the random pitch granular
  if (E == HIGH) {
    if (H == HIGH) {
      mcp.setChannelValue(MCP4728_CHANNEL_D, 0);
    }
    else if (H == LOW) {
      if (F == LOW) {
        mcp.setChannelValue(MCP4728_CHANNEL_D, 2048);
      }
      else if (F == HIGH) {
        mcp.setChannelValue(MCP4728_CHANNEL_D, 4095);
      }
    } 
  }

  // Channel A checks if the scissors are touching the circuit
  if (G == HIGH) {
    mcp.setChannelValue(MCP4728_CHANNEL_A, 4095);
    
  }
  else if (G == LOW) {
    mcp.setChannelValue(MCP4728_CHANNEL_A, 0);
    
  }

  
}

 

Group Check-In 2: 9-30-20

By William Lamkin

Made significant progress from Monday in that I discovered how logic chips function! Got an AND gate to function with the scissors, showing its ability to be conductive, and also how that could successfully route through the human body. Video below:

Video of conductive scissors working with logic chip

I am still waiting on my Adafruit Quad DAC to come in, from which I could complete my circuit and be able to control my synthesizer, since it would allow my Arduino to send out a full range of voltages.

 

Process Blog Check-In 9-28-20

 

By William Lamkin

In reflecting on how to utilize ambient sound that adaptively changes, I’ve decided to use a modular synthesizer to generate sounds. I had toyed around with the idea of using an mp3 playing device that would work with an Arduino, but I realized that the technology involved with those wasn’t as fully interactive as I would like it to be. My goals for this project are for the actions of the user to have a significant effect on the sound.

I will be using logic chips for all of connections, and these will be connected to the board to be cut via a alligator clips, and the output signals of these logic chips will then be sent into the inputs of the Arduino. The Arduino will send out voltages through an Adafruit Quad DAC which I have ordered and I will be able to connect to the synthesizer via these audio jack parts. In the link is a demo of the kinds of sounds that can be made and changed.

Ambient Sound Demo

Here is a diagram of what I want the setup to be like! I do want it to be a dark and isolated experience so the user can focus on what they are doing. For documentation purposes, I will be recording a video of myself at home working on this.

Here is an example logic problem for how a parameter of music could be changed.

 

In Process Critique: 9-23-20

 

By William Lamkin

 

Draft version of Cut, made using cardstock and conductive tape to create circuits. In essence, all circuits start ON (1), except one involving the scissors,  and breaking them (0) triggers a reaction in ambient sound created from the experience interactively.

The side which starts the experience is labeled at the top “START”, and will be cut using specially created scissors to interact with it. Breaking the start circuit will begin the the output of music. Cutting along the dashed lines, at forks in the path, the player will be given prompts to choose a direction to go down cutting. Certain circuits are cut (turned off) to trigger an effect. Others are created through the act of cutting itself, because the scissors also have conductive tape on them that connects the blade of the scissors to the hand. The body is then used as a connection in itself to the other end of circuit. Therefore, circuits are actively created throughout the piece. Eventually the other end of the sheet is breached (labeled “END”) and this stops music playback.

Connections on scissors labeled below.

Multiple logic operations will be used through combinations of the different circuits. Here is one example of how one could work.

Group Check-In 1: 9-16-20
By William Lamkin
Cut is an experiment in creating an interactive work with permanent consequences exacted on the piece by the audience member. Intended for use by one person in a private space, a piece of cardstock has printed on it a branching pathway for the participant to cut along using scissors, along with pieces of texts that instruct which pathways to cut down. Attached to the surface at various points along this branching surface are pieces of a conductive material (such as aluminum foil or conductive tape). These are connected to a logic chip or an Arduino, allowing for these connections to be turned off when bisected by scissors. The participant will have to choose where they cut carefully, and as they cut, these severed connections have lasting changes on an ambient piece of music in the background, made either through Analog circuitry or an mp3 sampler chip like DFPlayer Mini. This musical part is what ties this more to my musical side – I love interactive music and as for what led me to this, I’ve always found destructive art fascinating. There’s more stakes for the participant. Choice is important and I want to illustrate that in this piece!
Bill of materials:
  • Cardstock/Cardboard (already have)
  • Aluminum Foil (already have)
  • Glue/Tape (already have
  • Scissors (already have this)
  • Logic chip(s) (part of take home kit)
  • Possibly Arduino/alligator clips (already have this)
  • small loudspeaker (already have)

 

 

]]>