Assignment Four

The pomodoro technique

Password: MakingThingsInteractive

This was a bit of a tricky project for me. I had several idea’s that seemed to bypass either the Arduino or p5.js completely. So, after my board kicked the bucket at 3 in the morning, I went back to the drawing board. Lately, I’ve been struggling with task management in terms of mustering up the courage to even begin. I was researching memory and multitasking for another class, when I stumbled upon something called The Pomodoro Technique. This is a technique that uses a timer to break down tasks into intervals of 25 minutes. The idea is to focus on something for 25 minutes straight, take a short break, then tackle another 25 minutes.

Using an RFID reader and tags, I sought to physicalize the interaction of changing tasks to intentionally bring awareness to the switch. These tags are labeled with my current class schedule, plus a personal passion project. You can scan in the task you want to focus on and a full screen time will take over the browser window. When 25 minutes have passed, the user will be notified by LED light. In addition, a small accomplishment dot is added to the task. You can collect up to three right now, however if you switch tasks in the middle of another, you will not get a dot.

Arduino Code:
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 newReader(SS_PIN, RST_PIN); // Create MFRC522 instance.
String id = "";

//--------NEOPIXEL SETUP --------
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
static const int PIN = 8;
static const int NUMPIXELS = 1;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

//--------INCOMING CASE STATE--------
int caseState;

//--------OUTGOING CASE STATE--------
static const int neutralState = 0;
static const int thesisState = 1;
static const int rmeState = 2;
static const int mtiState = 3;
static const int cdfState = 4;
static const int personalState = 5;
int sendState = neutralState;

//--------TIME--------
unsigned long lastSampleTime = 0;
unsigned long sampleInterval = 300000; // in ms 5 minutes

void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
newReader.PCD_Init(); // Init MFRC522 card
Serial.println("Scan PICC to see UID and type...");
pixels.begin();
}

void loop() {
unsigned long now = millis();
pixelOff();

if (Serial.available() > 0) {
caseState = Serial.read();
}

getID();

if (lastSampleTime + sampleInterval < now) {
lastSampleTime = now;
if (caseState == 6) {
pixelBlink();
} else {
pixelOff();
}
}
}

void pixelBlink() {
pixels.setPixelColor(0, pixels.Color(138, 70, 215));
pixels.show(); // This sends the updated pixel color to the hardware.
delay(500);
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show(); // This sends the updated pixel color to the hardware.
delay(500);
}

void pixelOff() {
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void getID() {
// Getting ready for Reading PICCs
if ( ! newReader.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
return 0;
}
if ( ! newReader.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
return 0;
}

// Serial.print("Card UID:");

for (byte i = 0; i < newReader.uid.size; i++) {
// Create a RFID Hexdecimal String
id += String(newReader.uid.uidByte[i], HEX);
// Serial.print(newReader.uid.uidByte[i] < 0x10 ? " 0" : " ");

}
// Convert to Uppercase
id.toUpperCase();

// If it is this card, do something
if (id == "B0A167A") {
sendState = thesisState;
// Serial.println("Card One: Thesis");
// Serial.print("State: ");
// Serial.println(sendState);
}
if (id == "B0DECE7A") {
sendState = rmeState;
// Serial.println("Card Two: Responsive Mobile Environments");
// Serial.print("State: ");
// Serial.println(sendState);
}
if (id == "702E89C") {
sendState = mtiState;
// Serial.println("Card Three: Making Things Interactive");
// Serial.print("State: ");
// Serial.println(sendState);
}
if (id == "3078E49B") {
sendState = cdfState;
// Serial.println("Card Four: Communication Design Fundamentals");
// Serial.print("State: ");
// Serial.println(sendState);
}
if (id == "50611A9C") {
sendState = personalState;
// Serial.println("Card Five: Personal Projects");
// Serial.print("State: ");
// Serial.println(sendState);
}
Serial.write (sendState);

// Reset Id
id = "";
// Serial.println();
newReader.PICC_HaltA();
newReader.PCD_StopCrypto1();
}
p5.js Code:
//---Serial---
var serial;
var portName = '/dev/cu.usbmodem1411';
//---Incoming Case State---
var caseState;
//---Outgoing Case State---
var accomplishState;

//---Color---
var c;
var thesisColor;
var rmeColor;
var mtiColor;
var cdfColor;
var personalColor;

//---Canvas---
var xLen = 1000;
var yLen = 700;

//---Squares & Grid---
let squares = [];
let bubbles0 = [];
let bubbles1 = [];
let bubbles2 = [];
let bubbles3 = [];
let bubbles4 = [];

//---Time---
var time = 1500;
var timer0 = time;
var timer1 = time;
var timer2 = time;
var timer3 = time;
var timer4 = time;

//---Counter---
var count0 = 0;
var count1 = 0;
var count2 = 0;
var count3 = 0;
var count4 = 0;

//---Converts Time to minutes and seconds---
function convertTime(s){
var minutes = floor(s / 60);
var seconds = s % 60;
return nf(minutes,2) + "m " + nf(seconds,2) + "s"; // formats to look like "00m 00s"
}

function setup() {
createCanvas(xLen, yLen);
serial = new p5.SerialPort();
// now set a number of callback functions for SerialPort
serial.on('list', printList);
serial.on('connected', serverConnected);
serial.on('open', portOpen);
serial.on('data', serialEvent);
serial.on('error', serialError);
serial.on('close', portClose);

serial.list();
serial.open(portName);

// setting task squares as well as accomplished "dots" through objects
for (let i=0; i<5; i++){
for(let j =0; j<3; j++){
let x = 0 + 200 * i;
let y = 550;
let w = 200;
let h = 150;
let gridX = 50;
let gridY = 625;
let offset = 50;
let gridR = 10;

squares[i] = new Square(x,y,w,h);

bubbles0[j] = new Bubble(gridX + offset*j, gridY, gridR);
bubbles1[j] = new Bubble(200 + gridX + offset*j, gridY, gridR);
bubbles2[j] = new Bubble(400 + gridX + offset*j, gridY, gridR);
bubbles3[j] = new Bubble(600 + gridX + offset*j, gridY, gridR);
bubbles4[j] = new Bubble(800 + gridX + offset*j, gridY, gridR);

}
}
}

function draw() {
// put drawing code here
// background(255);

checkIncoming(); // checks the incoming state and runs the proper timer
statusBar(); // keeps the tabs with what tasks, right now classes
bubbleKeeper(); // keeps the circles that tick when time has been accomplished

}

function bubbleKeeper(){

for(let i=0; i < bubbles0.length; i++){ // accomplish bubbles for thesis
noStroke();
// bubbles[i].show(0);
if (count0 == 1){
bubbles0[0].show(0);
}
if (count0 == 2){
bubbles0[0].show(0);
bubbles0[1].show(0);
}
if (count0 == 3){
bubbles0[0].show(0);
bubbles0[1].show(0);
bubbles0[2].show(0);
}
}

for(let i=0; i < bubbles1.length; i++){ // accomplish bubbles for RME
noStroke();
// bubbles[i].show(0);
if (count1 == 1){
bubbles1[0].show(0);
}
if (count1 == 2){
bubbles1[0].show(0);
bubbles1[1].show(0);
}
if (count1 == 3){
bubbles1[0].show(0);
bubbles1[1].show(0);
bubbles1[2].show(0);
}
}

for(let i=0; i < bubbles2.length; i++){ // accomplish bubbles for MTI
noStroke();
// bubbles[i].show(0);
if (count2 == 1){
bubbles2[0].show(0);
}
if (count2 == 2){
bubbles2[0].show(0);
bubbles2[1].show(0);
}
if (count2 == 3){
bubbles2[0].show(0);
bubbles2[1].show(0);
bubbles2[2].show(0);
}
}

for(let i=0; i < bubbles3.length; i++){ // accomplish bubbles for CDF
noStroke();
// bubbles[i].show(0);
if (count3 == 1){
bubbles3[0].show(0);
}
if (count3 == 2){
bubbles3[0].show(0);
bubbles3[1].show(0);
}
if (count3 == 3){
bubbles3[0].show(0);
bubbles3[1].show(0);
bubbles3[2].show(0);
}
}

for(let i=0; i < bubbles4.length; i++){ // accomplish bubbles for Passion Projects
noStroke();
// bubbles[i].show(0);
if (count4 == 1){
bubbles4[0].show(0);
}
if (count4 == 2){
bubbles4[0].show(0);
bubbles4[1].show(0);
}
if (count4 == 3){
bubbles4[0].show(0);
bubbles4[1].show(0);
bubbles4[2].show(0);
}
}

}

function statusBar(){
textSize(20);
textAlign(CENTER);
textStyle(BOLD);
var textY = 575;

//---Using these to change the color of the timer background based on the class
thesisColor = color(236,195,211);
rmeColor = color(247,161,171);
mtiColor = color(250,116,86);
cdfColor = color(252,195,135);
personalColor = color(242,240,181);

//---Setting up the squares based on color
for(let i =0; i<squares.length; i++){
noStroke();
squares[0].show(thesisColor);
squares[1].show(rmeColor);
squares[2].show(mtiColor);
squares[3].show(cdfColor);
squares[4].show(personalColor);
}

fill(0);
noStroke();
text("THESIS", 100, textY);
text("RME", 300, textY);
text("MTI", 500, textY);
text("CDF", 700, textY);
text("PASSION", 900, textY);

}

function checkIncoming(){
textSize(200);
textAlign(CENTER);

if (caseState == 1){ // THESIS
if (frameCount % 60 == 0 && timer0 > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
timer0 --;
}
if (timer0 == 0){ // if time reaches zero, task accomplished
timer0 = time; // timer resets to 25minutes (1500 seconds)
count0++; // counter adds one
accomplishState = 6; // sends notification to arudino to light up light
} else{
accomplishState = 5;
}
if (count0 > 3){
count0=0; // resets after three rounds
}

background(color(236,195,211));
fill(0);
noStroke();
text(convertTime(timer0), width/2, height*.5);

}

if (caseState == 2){ //RME
if (frameCount % 60 == 0 && timer1 > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
timer1 --;
}
if (timer1 == 0){
timer1 = time;
count1++;
accomplishState = 6;
} else{
accomplishState = 5;
}
if (count1 > 3){
count1=0;
}

background(color(247,161,171));
fill(0);
noStroke();
text(convertTime(timer1), width/2, height*.5);

}

if (caseState == 3){ // MTI
if (frameCount % 60 == 0 && timer2 > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
timer2 --;
}
if (timer2 == 0){
timer2 = time;
count2++;
accomplishState = 6;
} else{
accomplishState = 5;
}
if (count2 > 3){
count2=0;
}

background(color(250,116,86));
fill(0);
noStroke();
text(convertTime(timer2), width/2, height*.5);

}

if (caseState == 4){ // CDF
if (frameCount % 60 == 0 && timer3 > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
timer3 --;
}
if (timer3 == 0){
timer3 = time;
count3++;
accomplishState = 6;
} else{
accomplishState = 5;
}
if (count3 > 3){
count3=0;
}

background(color(252,195,135));
fill(0);
noStroke();
text(convertTime(timer3), width/2, height*.5);
}

if (caseState == 5){ // PERSONAL
if (frameCount % 60 == 0 && timer4 > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
timer4 --;
}
if (timer4 == 0){
timer4 = time;
count4++;
accomplishState = 6;
} else{
accomplishState = 5;
}
if (count4 > 3){
count4=0;
}
background(color(242,240,181));
fill(0);
noStroke();
text(convertTime(timer4), width/2, height*.5);
}

serial.write(accomplishState);

}

class Square{ // object class for bottom squares
constructor(x,y,w,h){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}

show(c){
fill(c);
rect(this.x, this.y, this.w, this.h);
}
}

class Bubble { // onject class for dots
constructor(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}

show(c) {
// stroke(90);
// strokeWeight(1);
fill(c);
ellipse(this.x, this.y, this.r * 2);
}
}

//-----SERIAL FUNCTIONS-----

function printList(portList) {
for (var i = 0; i < portList.length; i++) {
print(i + " " + portList[i]);
}
}

function serverConnected() {
print('serverConnected');
}

function portOpen() {
print('portOpen');
}

function serialEvent() {

var incoming = serial.read();
caseState = incoming;

}

function serialError(err) {
print('serialError ' + err);
}

function portClose() {
print('portClose');
}

 

Assignment Four Files: Fritzing, p5.js, Arduino

Assignment Three

Hot/Cold Game with a p5 twist

For this assignment I moved the switch button functionality for state changes to the p5 sketch. Through the web browser you can change the state from start screen to play mode and back again. The Arduino sets the target value and then sends five states back to p5 in order to determine how close the player is to the target. The status of the player, hot/cold/warmer/colder/winner, is then displayed on screen instead of the LED in the previous version.

password: MakingThingsInteractive

Arduino Code:
//--------NEOPIXEL SETUP --------
#include
#ifdef __AVR__
#include <avr/power.h>
#endif
static const int PIN = 40;
static const int NUMPIXELS = 1;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

//--------ULTRASONIC PINS N'AT--------
static const int trigPin = A0;
static const int echoPin = A1;
long duration;
int distance;

//--------INCOMING CASE STATE--------
int caseState;

//--------OUTGOING CASE STATE--------
static const int neutralState = 0;
static const int winState = 1;
static const int hotState = 2;
static const int warmerState = 3;
static const int colderState = 4;
static const int iceState = 5;
int sendState = neutralState; // current state of the button

//--------TIME--------
unsigned long lastSampleTime = 0;
unsigned long sampleInterval = 30000; // in ms

unsigned long lastSampleTime2 = 0;
unsigned long sampleInterval2 = 250; // in ms

int target;

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

pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);

randomSeed(analogRead(2));
pixels.begin();

}

void loop() {
unsigned long now = millis();
unsigned long now2 = millis();

if (Serial.available() > 0) {
caseState = Serial.read();
}

switch (caseState) {
case 0:
pixelBlinkGreen();
if (lastSampleTime + sampleInterval < now) {
lastSampleTime = now;
target = random(10, 150);
// pixelOff();
// Serial.print("Target Set");
}
break;
case 1:
pixelBLUE();
if (lastSampleTime2 + sampleInterval2 < now2) {
lastSampleTime2 = now2;
Serial.write(target);
// Serial.print("T,");
// Serial.println(target);
}

// Serial.print("Find ");
// Serial.println(target);
hotCold(target);
break;
default:
pixelBlinkYellow();
// Serial.println("Push Button For New Game");
// statements
}
}

void hotCold(int x) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);
distance = duration / 10 / 2 ;

unsigned long now2 = millis();
if (lastSampleTime2 + sampleInterval2 < now2) {
lastSampleTime2 = now2;
pixelOff();
if ((distance <= (x + 5)) && (distance >= (x - 5))) {
pixelState1();
sendState = winState;
// Serial.write("ON FIRE!");
} else if ((distance <= (x + 15)) && (distance >= (x - 15))) {
pixelState2();
sendState = hotState;
// Serial.println("Things are heating up");
} else if ((distance <= (x + 25)) && (distance >= (x - 25))) {
pixelState3();
sendState = warmerState;
// Serial.println("Warmer..."); // instead of print line, then you can do score value
} else if ((distance <= (x + 35)) && (distance >= (x - 35))) {
pixelState4();
sendState = colderState;
// Serial.println("Cooler...");

} else if ((distance <= (x + 45)) && (distance >= (x - 45))) {
pixelState5();
sendState = iceState;
// Serial.println("Pretty Cold");

} else {
pixelOff();
//Serial.println("Something is wrong");
}
Serial.write (sendState);
}
}

void pixelChange (int y) {

}

void pixelBlinkGreen() {
pixels.setPixelColor(0, pixels.Color(0, 255, 0));
pixels.show(); // This sends the updated pixel color to the hardware.
delay(500);
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show(); // This sends the updated pixel color to the hardware.
delay(500);
}

void pixelBlinkYellow() {
pixels.setPixelColor(0, pixels.Color(255, 200, 0, 75));
pixels.show(); // This sends the updated pixel color to the hardware.
delay(250);
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show(); // This sends the updated pixel color to the hardware.
delay(250);
}

void pixelState1() {
pixels.setPixelColor(0, pixels.Color(255, 0, 100));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void pixelState2() {
pixels.setPixelColor(0, pixels.Color(215, 13, 138));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void pixelState3() {
pixels.setPixelColor(0, pixels.Color(150, 55, 150));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void pixelState4() {
pixels.setPixelColor(0, pixels.Color(138, 70, 215));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void pixelState5() {
pixels.setPixelColor(0, pixels.Color(100, 0, 255));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void pixelBLUE() {
pixels.setPixelColor(0, pixels.Color(0, 0, 255));
pixels.show(); // This sends the updated pixel color to the hardware.
}

void pixelOff() {
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show(); // This sends the updated pixel color to the hardware.
}
p5 Code:
var serial;
var portName = '/dev/cu.usbmodem1411';

var button;
var count = 0;
var buttonCount;
var findState;
var targetSet;

var target;

var time1 = 30000;
var time2 = 20;

var noiseScale = 0.01;

var caseState;
var lineMap;
var redVal;
var blueVal;

var testRect;
var ranVal;

var lastSampleTime = 0;
var sampleInterval = 250; // in ms

function setup() {
serial = new p5.SerialPort();
// now set a number of callback functions for SerialPort
serial.on('list', printList);
serial.on('connected', serverConnected);
serial.on('open', portOpen);
serial.on('data', serialEvent);
serial.on('error', serialError);
serial.on('close', portClose);

serial.list();
serial.open(portName);

colorMode(RGB);
createCanvas(windowWidth, windowHeight);

testRect = new Rectangle();
}

function draw() {
background(255); // set the background to white
startScreen();

ranVal = random(0,150);

}

function startScreen(){
fill(0); // fill with black
textSize(32);
textStyle(BOLD);
textAlign(LEFT);
text("The Hot/Cold Game", 75, 100);

startButton();

if (count % 2 == 1){
playScreen();
}

}

function playScreen (){
var startX = windowWidth -200;
var startY = 75;
var endX = windowWidth -200;
var endY = windowHeight - 75;
var topWall = startY+5;
var bottomWall = endY-5;

var xc = constrain(ranVal, topWall, bottomWall);
var lineLength = endY - startY;
// console.log("line length: " + lineLength);

// var mapVal = map(xc, topWall, bottomWall, 0, 150);
// lineMap = int(mapVal);

background(255);
fill(0); // fill with black
textSize(32);
textStyle(BOLD);
textAlign(LEFT);
text("The Hot/Cold Game", 75, 100);

if (target > 6 && target < 150) {
fill(0);
textSize(20);
textStyle(NORMAL);
textAlign(LEFT);
text("Target Set", 400, 100);
}

/*
stroke(0);
strokeWeight(2);
line (startX, startY, endX, endY);
line (startX - 10, startY, startX+10, startY);
line (endX - 10, endY, endX+10, endY);

ellipse(startX, xc, 10, 10);
// text ("map val " + mapVal, startX+75, xc);
*/


rectColor();
hotColdLevel();
// winnerWinner();
backButton();

if (count % 2 == 0){
startScreen();
}
}

function rectColor() {

var from = color(255, 0, 100);
var to = color(100, 0, 255);
var interA = lerpColor(from, to, 0.25);
var interB = lerpColor(from, to, 0.5);
var interC = lerpColor(from, to, 0.75);

var textX = windowWidth - 230;
var textY = windowHeight - 60;

// testRect.display();

noStroke();
textSize(24);
textStyle(NORMAL);
textAlign(CENTER);

if (findState == 1) {
fill(from);
testRect.display();
fill(255);
text("WINNER", textX, textY);
} else if (findState == 2) {
fill(interA);
testRect.display();
fill(255);
text("hot", textX, textY);
} else if (findState == 3) {
fill(interB);
testRect.display();
fill(255);
text("warmer", textX, textY);
} else if (findState == 4) {
fill(interC);
testRect.display();
fill(255);
text("colder", textX, textY);
} else if (findState == 5) {
fill(to);
testRect.display();
fill(255);
text("ice cold", textX, textY);
}
}

function hotColdLevel() {
// var printTarget = int(targetSet);
// console.log(printTarget);
var startX = windowWidth -200;
var startY = 100;
var endX = windowWidth; -150
var endY = windowHeight - 140;
var topWall = startY+5;
var bottomWall = endY-5;
var lineLength = endY - startY;

for (var x = 0; x < windowWidth; x++) {

var noiseVal = noise((ranVal + x) * noiseScale, mouseY * noiseScale);

var alpha1 = noiseVal * 255 + 50;
var from = color(255, 0, 100, alpha1);
var to = color(100, 0, 255, alpha1);
var interA = lerpColor(from, to, 0.25, alpha1);
var interB = lerpColor(from, to, 0.5, alpha1);
var interC = lerpColor(from, to, 0.75, alpha1);

var xc;

var increase1 = startY +100;
var increase2 = startY +200;
var increase3 = startY +300;

if (findState == 1) {
stroke(from);
xc = constrain(startY, topWall, bottomWall);
} else if (findState == 2) {
stroke(interA);
xc = constrain(increase1, topWall, bottomWall);
} else if (findState == 3) {
stroke(interB);
xc = constrain(increase2, topWall, bottomWall);
} else if (findState == 4) {
stroke(interC);
xc = constrain(increase3, topWall, bottomWall);
} else if (findState == 5) {
stroke(to);
xc = constrain(endY - 100, topWall, bottomWall);
}

// stroke(colorVal, 0, 100, alpha1);
line(x, xc + noiseVal * 30, x, endY);
// line(x, xc + noiseVal * 30, x, endY);

}
}

function winnerWinner(){

if (mouseY <= (target+5) && mouseY >= (target-5)){
background (255);
fill(0); // fill with black
textSize(32);
textStyle(BOLD);
textAlign(LEFT);
text("The Hot/Cold Game", 75, 100);
fill(0); // fill with black
textSize(60);
textStyle(BOLD);
textAlign(CENTER);
text("Winner Winner!", windowWidth*.5, windowHeight*.5);

}

}

function Rectangle() {
this.x = windowWidth-380;
this.y = windowHeight - 90;
this.width = 300;
this.height = 40;
this.corner = 3;

this.display = function() {
rect(this.x, this.y, this.width, this.height, this.corner);
// stroke(0);
// line(75,100, windowWidth-75, 100);
}
}

function startButton(){

var x = 80;
var y = 125;
var buttonWidth = 200;
var buttonHeight = 40;

var startY = 100;
var endY = windowHeight - 200;

fill(255, 0, 110);
rect(x, y, buttonWidth, buttonHeight,2);

fill(255);
noStroke();
textSize(24);
textStyle(NORMAL);
textAlign(CENTER);
text("Start Game", x + 100 , y + 30);

// if (mouseIsPressed){
// caseState = 1;
// serial.write(caseState);
// console.log(caseState);
// }

/*
if (count % 3 == 1){
noStroke();
fill(255, 0, 89);
} else if (count % 3 == 2){
noStroke();
fill(177);
} else {
noStroke();
fill(255);
}
ellipse (windowWidth*.5, windowHeight*.5, 100,100);
*/


}

function backButton(){
var x = 80;
var y = windowHeight - 90;
var buttonWidth = 200;
var buttonHeight = 40;

var startY = 100;
var endY = windowHeight - 200;

fill(225);
noStroke();
rect(x, y, buttonWidth, buttonHeight,3);

fill(0);
noStroke();
textSize(24);
textStyle(NORMAL);
textAlign(CENTER);
text("Back", x + 100 , y + 30);
//
// if (mouseIsPressed){
// target = int(random(startY,endY));
// }

}

function mousePressed(){
var backHeight = windowHeight - 60
var r1 = dist(mouseX, mouseY, 180, 155);
var r2 = dist(mouseX, mouseY, 180, backHeight - 30);
if (r1 < 100){
button = 1;
caseState = 1;
console.log("start button pressed");
count ++;
} else if(r2 <100){
button = 2;
caseState = 0;
console.log("back button pressed")
count ++;
}else {
button = 0;
console.log("button NOT pressed");
}
serial.write(caseState);
}

//-----SERIAL FUNCTIONS-----

function printList(portList) {
for (var i = 0; i < portList.length; i++) {
print(i + " " + portList[i]);
}
}

function serverConnected() {
print('serverConnected');
}

function portOpen() {
print('portOpen');
}

function serialEvent() {
// TODO now here's a problem. What if we want to read both
// the blueLed and redLed values? All we know in p5.js is
// that there is same data to be read, we don't have a context
// for this value
//
// this is where a state machine represented by an integer is
// valuable, we just just pass the state up as an int then
// p5.js can switch/caes that integer

// distanceRead = Number(serial.read());
// button = Number(serial.read());

// var inByte = serial.read();
// inData = inByte;
//

var incoming = serial.read();
if (incoming > 6){
targetSet = incoming;
} else if (incoming < 6){
findState = incoming;
}

/*
// now we're reading a string
// TODO how does a string end?
var stringRead = serial.readStringUntil('\r\n');

// TODO now we're off in object oriented programming
// what type is stringRead? Note we didn't define it
if (stringRead.length > 0 ) {
var potString = split(stringRead, ',');

// potString[0] B
// potString[1] 159
// potString[2] R
// potString[3] 60

if (potString.length == 2) { // ignore any tiny strings
targetSet = potString[1];
}
}
*/


}

function serialError(err) {
print('serialError ' + err);
}

function portClose() {
print('portClose');
}

Arduino + p5js + Fritzing files

Assignment Two

Hot/Cold

I wanted to build upon and improve the previous assignment. The goal is to balance at a certain distance in order to turn on the LED, but done through a classic game of hot or cold. While it’s rather trivial, it has helped me to better understand the ultrasonic sensor and its possibilities. refining the sensor data and perfecting the timing is something that I’d like to explore further down the road.

The states are used in order to guide you through the game. State one lets you now that the game is ready, state two sets a random number for you to find using the ultrasonic sensor, and in state three…you find the number. Prompted in the serial monitor if you are getting warmer or colder.

Code:
//--------NEOPIXEL SETUP --------
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
static const int PIN = 40;
static const int NUMPIXELS = 1;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

//--------ULTRASONIC PINS--------
static const int trigPin = A0;
static const int echoPin = A1;

//--------LIGHTS--------
static const int ledPin = 4;

//--------SWITCH PIN--------
static const int switchPin = 3;

//------------------------------------------------------------------------------------

//--------Global variables--------

const bool isInterrupt = true;

// button state
int buttonState = 0; // current state of the button

// Target
int target;

// Time
unsigned long lastSampleTime = 0;
unsigned long sampleInterval = 5000; // in ms

unsigned long lastSampleTime2 = 0;
unsigned long sampleInterval2 = 250; // in ms

unsigned long lastSampleTime3 = 0;
unsigned long sampleInterval3 = 500; // in ms

// Ultrasonic
long duration;
int distance;

//------------------------------------------------------------------------------------

void SwitchPressed()
{
 if (digitalRead(switchPin) == HIGH) {
 // this is why people hate C
 buttonState == 3 ? buttonState = 0 : buttonState++;
 }
 // Serial.println(buttonState);
}

//------------------------------------------------------------------------------------

void setup() {

Serial.begin(9600);

pinMode(ledPin, OUTPUT);
 pinMode(switchPin, INPUT);
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);

// attach the interrupt pin to a method
 if (isInterrupt) {
 attachInterrupt (digitalPinToInterrupt (switchPin), SwitchPressed, CHANGE);
 }
 randomSeed(analogRead(2));
 pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {
 unsigned long now = millis();

switch (buttonState) {
 case 0:
 pixelBlinkGreen();
 Serial.println ("Ready To Start Game");
 break;
 case 1:
 if (lastSampleTime + sampleInterval < now) {
 lastSampleTime = now;
 target = random(1, 150);
 Serial.print("Target Set");
 }
 pixels.setPixelColor(0, pixels.Color(0, 255, 0));
 break;
 case 2:
 pixels.setPixelColor(0, pixels.Color(255, 200, 0));
 // Serial.print("Find ");
 // Serial.println(target);
 hotCold(target);
 break;
 default:
 pixelBlinkYellow();
 Serial.println("Push Button For New Game");
 // statements
 }
}
/*
 if (buttonState == 0) {
 pixelBlinkGreen();
 Serial.println ("GREEN BLINK");
 }
 else if (buttonState == 1) {
 if (lastSampleTime + sampleInterval < now) {
 lastSampleTime = now;
 target = random(1, 150);
 Serial.print("Target = ");
 Serial.println(target);
 }
 pixelBlinkYellow();
 }
 else if (buttonState == 2) {
 pixels.setPixelColor(0, pixels.Color(255, 200, 0));
 // Serial.print("Find ");
 // Serial.println(target);
 hotCold(target);
 }
 }
*/


//------------------------------------------------------------------------------------

void hotCold(int x) {
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);
 distance = duration / 10 / 2 ;

unsigned long now2 = millis();
 if (lastSampleTime2 + sampleInterval2 < now2) {
 lastSampleTime2 = now2;
 if ((distance <= (target + 5)) && (distance >= (target - 5))) {
 Serial.println("ON FIRE!");
 ledOn();
 pixelBlinkPink();
 } else if ((distance <= (target + 10)) && (distance >= (target - 10))) {
 Serial.println("Things are heating up");
 ledOff();
 } else if ((distance <= (target + 20)) && (distance >= (target - 20))) {
 Serial.println("Warmer...");
 ledOff();
 } else if ((distance <= (target + 30)) && (distance >= (target - 30))) {
 Serial.println("Cooler...");
 ledOff();
 } else if ((distance <= (target + 40)) && (distance >= (target - 40))) {
 Serial.println("Pretty Cold");
 ledOff();
 } else if ((distance <= (target + 50)) && (distance >= (target - 50))) {
 Serial.println("Ice Cold, Elsa");
 ledOff();
 } else {
 ledOff();
 //Serial.println("Something is wrong");
 }
 }
}

void pixelBlinkGreen() {
 pixels.setPixelColor(0, pixels.Color(0, 255, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(500);
 pixels.setPixelColor(0, pixels.Color(0, 0, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(500);
}

void pixelBlinkYellow() {
 pixels.setPixelColor(0, pixels.Color(255, 200, 0, 75));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(250);
 pixels.setPixelColor(0, pixels.Color(0, 0, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(250);
}

void pixelBlinkWhite() {
 pixels.setPixelColor(0, pixels.Color(255, 255, 255));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(300);
 pixels.setPixelColor(0, pixels.Color(0, 0, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(250);
}

void pixelBlinkPink() {
 pixels.setPixelColor(0, pixels.Color(254, 6, 141));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(300);
 pixels.setPixelColor(0, pixels.Color(0, 0, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
 delay(250);
}

void pixelOff() {
 pixels.setPixelColor(0, pixels.Color(0, 0, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
}

void ledOn() {
 digitalWrite(ledPin, HIGH);
}

void ledOff() {
 digitalWrite(ledPin, LOW);
}
Files:

Fritzing & Arduino Files

Assignment One

Serial “Hot or Cold”

The first code combines the stat code we learned in class with an ultrasonic sensor to play an alternate version of the game “Hot or Cold.” The closer to the sensor, the hotter. The further away, the colder. It prints the results to serial.

VIDEO LINK password: MakingThingsInteractive

//--------NEOPIXEL SETUP --------
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
static const int PIN = 40;
static const int NUMPIXELS = 1;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

//--------ULTRASONIC PINS--------
static const int trigPin = A0;
static const int echoPin = A1;

//--------SAMPLE ARRAY--------
static const int sampleSize = 30;
int readings[sampleSize];
unsigned int sampleIndex = 0;

//--------TIME--------
unsigned long lastSampleTime = 0;
unsigned long sampleInterval = 100; // in ms
// we need to move these out of the loop() as well

//--------STATS--------
unsigned int median = 0;
unsigned int low = 0;
unsigned int high = 0;
unsigned int mean = 0;

//--------LIGHTS--------
static const int statusLed = 13;
unsigned int lastRedVal = 0;

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

pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 pinMode(statusLed, OUTPUT);

pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {

//--------SENDING OUT THE SIGNAL--------
 long duration, distance;
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 distance = duration / 29 / 2 ; //CENTIMETERS

// TODO what happens if you try to set a negative color?
 unsigned int redVal = 0;

// TODO
 // don't read the input on every loop to help stabilize the data
 // sampling over time is also a UI change, you have to actively
 // block light for
 // sampleSize * sampleInterval milliseconds to create a change

unsigned long now = millis();
 if (lastSampleTime + sampleInterval < now) {
 lastSampleTime = now;

// good for debugging:
 // Serial.print(now);
 // Serial.print(" ");
 //
 // Serial.println(distance);

readings[sampleIndex] = distance;
 sampleIndex < (sampleSize - 1) ? sampleIndex++ : sampleIndex = 0;

//digitalWrite(photoPin, HIGH);
 for (int i = 0; i < sampleSize; i++) {
 mean += readings[i];
 if (readings[i] < low) {
 low = readings[i];
 }
 if (readings[i] > high) {
 high = readings[i];
 }
 }

if (distance > 120) {
 Serial.println ("Frozen");
 Serial.println(" ");
 } else if (distance < 120 && distance > 70) {
 Serial.println ("Ice Cold");
 Serial.println(" ");
 } else if (distance < 70 && distance > 40) {
 Serial.println ("Pretty Cold");
 Serial.println(" ");
 } else if (distance < 40 && distance > 20) {
 Serial.println ("Cool...");
 Serial.println(" ");
 } else if (distance < 20 && distance > 15) {
 Serial.println ("Warmer...");
 Serial.println(" ");
 } else if (distance < 15 && distance > 11) {
 Serial.println ("Things are heating up!");
 Serial.println(" ");
 } else if (distance < 11 && distance > 6) {
 Serial.println ("HOT");
 Serial.println(" ");
 } else if (distance < 6 && distance > 2) {
 Serial.println ("On. Fire.");
 Serial.println(" ");
 } else {
 Serial.println (distance);
 Serial.println(" ");
 }

mean = mean / sampleSize;
 bubbleSort();
 median = readings[sampleSize / 2];
 }

redVal = map(median, 2, 150, 0, 200);

int tolerance = 3;

// This looks like it should work, right?
 // what happens if lastRedVal is 0?
 if (
 (redVal > (lastRedVal + tolerance)) || (redVal < (lastRedVal - tolerance))
 ) {

pixels.setPixelColor(0, pixels.Color(redVal, 0, 0));
 pixels.show(); // This sends the updated pixel color to the hardware.
 lastRedVal = redVal;
 }
}


// tigoe's sort for an array
void bubbleSort() {
 int out, in, swapper;
 for (out = 0 ; out < sampleSize; out++) { // outer loop
 for (in = out; in < (sampleSize - 1); in++) { // inner loop
 if ( readings[in] > readings[in + 1] ) { // out of order?
 // swap them:
 swapper = readings[in];
 readings [in] = readings[in + 1];
 readings[in + 1] = swapper;
 }
 }
 }
}

Finding the balance

I wanted to use the values to inform color–both red and blue values. Using mapping to reverse the color values of 0-255, the more light you let in, the LED becomes more red, the less light…blue. However, if you hover in the middle and find the balance between the two values, within 10. This causes the LED to blink.

VIDEO LINK password: MakingThingsInteractive

// -*-c++-*-
/*
 The MIT License (MIT)

Copyright (c) 2014 J. Eric Townsend

Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

/* basic stats with analogRead()

intputs
 A0 photoresitro

output
 D13 LED
 40 NEOPIXEL

*/

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 40
#define NUMPIXELS 1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

static const int photoPin = 0;
static const int sampleSize = 16;
int readings[sampleSize];
int sampleIndex = 0;

static const int statusLed = 13;
int lastRedVal = 0;

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

pinMode(photoPin, INPUT);

pinMode(statusLed, OUTPUT);

pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {


 int photo = analogRead(photoPin);
 readings[sampleIndex] = photo;
 sampleIndex < (sampleSize - 1) ? sampleIndex++ : sampleIndex = 0;

digitalWrite(photoPin, HIGH);
 // Serial.println(photo);
 int median = 0;
 int low = 1024;
 int high = 0;
 int mean = 0;
 for (int i = 0; i < sampleSize; i++) {
 mean += readings[i];
 if (readings[i] < low) {
 low = readings[i];
 }
 if (readings[i] > high) {
 high = readings[i];
 }
 }
 mean = mean / sampleSize;
 bubbleSort();
 median = readings[sampleSize / 2];

int redVal = map(median, 40, 1023, 0, 100);
 int blueVal = map(median, 40, 1023, 100, 0);

Serial.print ("redVal = ");
 Serial.println (redVal);
 Serial.print ("blueVal = ");
 Serial.println (blueVal);

// use a tolerance to limit to a range
 // by making this not a const we can change it in the code
 // as needed

int tolerance = 3;

// This looks like it should work, right?
 // what happens if lastRedVal is 0?
 if (
 (redVal > (lastRedVal + tolerance))
 || (redVal < (lastRedVal - tolerance))
 ) {

pixels.setPixelColor(0, pixels.Color(redVal, 0, blueVal));
 pixels.show(); // This sends the updated pixel color to the hardware.
 lastRedVal = redVal;
 }

//----Difference code http://forum.arduino.cc/index.php?topic=105383.0 
 int difference = redVal - blueVal;

difference = abs(difference); // 'abs' is the absolute value, the result is always positive.
 Serial.println (difference);
 if (difference < 10) { // it's always higher or equal than zero
 pixels.setPixelColor(0, pixels.Color(redVal, 0, blueVal));
 pixels.show();
 delay(200);
 pixels.setPixelColor(0, 0, 0, 0);
 pixels.show();
 delay(200);
 }
 else {
 pixels.setPixelColor(0, pixels.Color(redVal, 0, blueVal));
 }

}


// tigoe's sort for an array
void bubbleSort() {
 int out, in, swapper;
 for (out = 0 ; out < sampleSize; out++) { // outer loop
 for (in = out; in < (sampleSize - 1); in++) { // inner loop
 if ( readings[in] > readings[in + 1] ) { // out of order?
 // swap them:
 swapper = readings[in];
 readings [in] = readings[in + 1];
 readings[in + 1] = swapper;
 }
 }
 }
}

Assignment Two Zip Files