Design Process
Background
Combining the work and experience gained from my different classes at NYU IMA, I created a combined physical and digital interface for the course search that used buttons, dials, and faders to filter through the most popular courses/majors available to IMA students. I felt that by detatching the user from the nebulousness of the poorly designed online course search and by then grounding the user in a physical reality they could more naturally explore their interests and pursuits. I also wanted to add an element of exploration and experimentation to the process, as natural discovery is lacking in the online system when you need to know what you're looking for in advance.
Filter Selection
I began with deciding on which filters would be best to include in the search:
User Flow
Next, I moved into figuring out the user flow within the project. There are two main phases, the selection phase and the search display phase. In the selection phase, the user decides which filters to use and adjusts those filter parameters. In the Display phase the user can scroll through the search results and choose to reset/redo the search.
Physical Construction
With the basic plan for the digital and combined framework for the project, I moved to working on the planning the physical arrangment of the dashboard and used that to determine how the digital interface would mimic it. I had some buttons, dials, and faders lying around from past projects, so those would form the basis of the arrangement. I found the wood board and dark acrylic lying around the ITP Shop discard area. It might not be the best quality wood, but it works well with a certain artistic 'work in progress' aesthetic that is a good representation of the major itself. I set up the layout in an illustrator file compatible with the laser cut in the ITP shop. Here is what the file looked like digitally
And here is the resulting wood panel after laser cutting. I ended up having to flip the panel over and recut a second time because I had to transition from the 50W to the 75W laser midway through the cut, but I think the darker wood better suits the dark side panels anyway.
Development
Background
With the physical prototype completed, I moved onto the digital software prototype. Like many of my other physical interaction projects, this prototype was constructed around a Node server running on a local laptop connected to the Arduino over USB Serial.
Server Setup
The server is setup as most other local NodeJS servers are and contains two different routes for data requests and webpage requests. Files are served froma public folder, courses are parsed from a local JSON file, and physical input data is handled within the app.js file itself in the Johnny Five code.
// Module Requirements
var express = require('express');
var path = require('path');
var fs = require ('fs');
var app = express();
// Get Courses
var IMACourseFile = JSON.parse(fs.readFileSync('data/IMACourses.json'));
// Set public folder for client-side access
app.use(express.static('public'));
// Send index.html at '/'
app.get('/', function(req, res){
res.sendFile(path.join(__dirname + '/views/index.html'));
});
//Send AJAX data stream at '/data'
app.get('/data', function(req,res) {
console.log(IMACourseFile);
// Compile individual variables into object
var dataToSendToClient = {
IMACourseFile
};
// Convert javascript object to JSON
var JSONdata = JSON.stringify(dataToSendToClient);
//Send JSON to client
res.send(JSONdata);
});
//Set app to port 8080
app.listen(8080);
//Log start of app
console.log("App Started");
Hardware Interface
Below is the Johnny Five Code. It initializes the instance of the board and sets up the variables to be updated upon any of the button or dial states being changed.
var five = require("johnny-five");
var board = new five.Board();
board.on("ready", function() {
// Major Dial
var majorPotentiometer = new five.Sensor({
pin: majorPotentiometerPin,
freq: 250
});
majorPotentiometer.on("data", function() {
//console.log("major Potentiometer: " + this.value);
majorPotentiometerValue = this.value;
});
// Credit Dial
var creditPotentiometer = new five.Sensor({
pin: creditPotentiometerPin,
freq: 250
});
creditPotentiometer.on("data", function() {
//console.log("major Potentiometer: " + this.value);
creditPotentiometerValue = this.value;
});
// Time Faders
var timeBeforePotentiometer = new five.Sensor({
pin: timeBeforePotentiometerPin,
freq: 250
});
timeBeforePotentiometer.on("data", function() {
//console.log("major Potentiometer: " + this.value);
timeBeforePotentiometerValue = this.value;
});
var timeBeforePotentiometer = new five.Sensor({
pin: timeAfterPotentiometerPin,
freq: 250
});
timeAfterPotentiometer.on("data", function() {
//console.log("major Potentiometer: " + this.value);
timeAfterPotentiometerValue = this.value;
});
// Button
var majorConfirmButton = new five.Button(majorConfirmButtonPin);
majorConfirmButton.on("press", function() {
//console.log("major PRESS!");
majorConfirmValue = true;
});
majorConfirmButton.on("release", function() {
//console.log("major RELEASE!");
majorConfirmValue = false;
});
var unitConfirmButton = new five.Button(majorConfirmButtonPin);
unitConfirmButton.on("press", function() {
//console.log("major PRESS!");
unitConfirmValue = true;
});
unitConfirmButton.on("release", function() {
//console.log("major RELEASE!");
unitConfirmValue = false;
});
var generalSearchButton = new five.Button(generalSearchButtonPin);
generalSearchButton.on("press", function() {
//console.log("SEARCH PRESS!");
generalSearchButtonValue = true;
});
generalSearchButton.on("release", function() {
//console.log("SEARCH RELEASE!");
generalSearchButtonValue = false;
});
// Buttons
var generalResetButton = new five.Button(generalResetButtonPin);
generalResetButton.on("press", function() {
console.log("RESET PRESS!");
generalResetButtonValue = true;
});
generalResetButton.on("release", function() {
console.log("RESET RELEASE!");
generalResetButtonValue = false;
majorConfirmLED.on();
});
});