# Midterm: Little Bird Pet

The little bird jumps all the time. If you feed her by clicking the colorful ball, she will sing happily. But if you get closer, she will jump crazily and scream.

There’s a photoresistor, a flex sensor and a servo inside.

Code:

#include <Servo.h>

Servo myservo1; //360
int val1 = 0;
int val2 = 0;
int t1 = 80;
int t2 = 120;

int pos = 0;
int pos_l = 20;
int dir = 1;

int toneSpeed = 1800;
int speakerPin = 7;
int freq = 2000;
int feed = 2200;

int lightPin = 0;
int flexPin = 1;
int flexVal = 0;

void setup() {
myservo1.attach(9);
Serial.begin(9600);
pinMode(speakerPin, OUTPUT);
}
void loop() {
//Serial.println(val1);
val1 = map(val1, 300, 800, 0, 180);
// Serial.println(val1);

Serial.println(flexVal);

if(flexVal < 8) {
tone(speakerPin, feed+flexVal*5, 8);
delay(10);
tone(speakerPin, feed+flexVal*5-150, 16);
noTone(speakerPin);
}

if(val1 <= t1) {
pos += 2 * dir;
noTone(speakerPin);
if(pos < pos_l) {
pos = pos_l;
dir *= -1;
}
else if(pos > pos_l+60) {
pos = pos_l+60;
dir *= -1;
}
}
else if(val1 > t1 && val1 <= t2) {
pos += 4 * dir;
noTone(speakerPin);

if(pos < pos_l) {
pos = pos_l;
dir *= -1;
}
else if(pos > pos_l+60) {
pos = pos_l+60;
dir *= -1;
}
}
else if(val1 > t2) {
pos += 5 * dir;
tone(speakerPin, freq+val1*5);
if(pos < pos_l) {
pos = pos_l;
dir *= -1;
}
else if(pos > pos_l+30) {
pos = pos_l+30;
dir *= -1;
}
}
// Serial.println(pos);
myservo1.write(pos);
delay(10);
}

# homework for week 5: Music Box

The two dancers dance elegantly with the music Canon, and the colorful light blinking inside the box as well.

Code:

/*
Canon for summer night (with LED) by aNdY 2013
*/

#include “pitches.h”
#include <Servo.h>

Servo myservo1; //180
Servo myservo2; //360
int value1 = 360;
int value2 = 0;

// notes in the melody:
int CanonTone[] = {
NOTE_E3, NOTE_G4, NOTE_C5, NOTE_E5, NOTE_B2, NOTE_G4, NOTE_B4, NOTE_D5,
NOTE_C3, NOTE_E4, NOTE_A4, NOTE_C5, NOTE_G2, NOTE_E4, NOTE_G4, NOTE_B4,
NOTE_A2, NOTE_C4, NOTE_F4, NOTE_A4, NOTE_E1, NOTE_C4, NOTE_E4, NOTE_G4,
NOTE_A2, NOTE_D4, NOTE_F4, NOTE_A4, NOTE_B2, NOTE_D4, NOTE_G4, NOTE_B4,
NOTE_E3, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5,
NOTE_E5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_F4, NOTE_G4,
NOTE_F4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4,
NOTE_F4, NOTE_A4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_G5,
NOTE_E5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4,
NOTE_C5, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_C5, NOTE_B4, NOTE_C5,
NOTE_A4, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5,
NOTE_A4, NOTE_C5, NOTE_B4, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_C5, NOTE_A4, NOTE_B4,
NOTE_C5,0
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
8,16,16,8,16,16,16,16,16,16,16,16,16, 16,
1
};

int toneSpeed = 1800; // set music speed
int ledPin;
int speakerPin = A0;
int thisNote;

void setup() {
myservo1.attach(13);
myservo2.attach(0);

thisNote = 0;
for(int pin = 1; pin <= 12; pin++) {
pinMode(pin, OUTPUT);
}
}
void loop() {
while(CanonTone[thisNote] > 0) {
// int flag = 0;
// if (flag == 0) {
// value1 += 10;
// if (value1 == 180) {
// flag = 1;
// }
// }
// else if (flag == 1){
// value1 -= 10;
// if (value1 == 0) {
// flag = 0;
// }
// }
if(thisNote < 32)
value1 -= 45;
else
value1 -= 30;
value2 += 1;
if(value1 <= 0) {
value1 += 360;
}
if(value2 >= 360) {
value1 -= 360;
}
myservo1.write(value1);
myservo2.write(value2);

int toneLevel = CanonTone[thisNote]; // get tone pitch
switch(toneLevel) {
case 262: // if C4, pin = 1
ledPin = 1;
break;
case 294: // if D4, pin = 2
ledPin = 2;
break;
case 330: // if E4, pin = 3
ledPin = 3;
break;
case 349:
ledPin = 4;
break;
case 392:
ledPin = 5;
break;
case 440:
ledPin = 6;
break;
case 494:
ledPin = 7;
break;
case 523:
ledPin = 8;
break;
case 587:
ledPin = 9;
break;
case 659:
ledPin = 10;
break;
case 698:
ledPin = 11;
break;
case 784:
ledPin = 12;
break;
default:
ledPin = 1;
break;
}
digitalWrite(ledPin, HIGH);

int noteDuration = toneSpeed / noteDurations[thisNote];
tone(speakerPin, CanonTone[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note’s duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
digitalWrite(ledPin, LOW);
delay(2);
thisNote++;
if(thisNote >= 144)
thisNote -= 144;
}
// noTone(speakerPin); // turn speaker off
}

# Step Sequencer for Generative art and music

It consists of 2 oscillators (40106), frequency divider (4040), shift register(4015), multiplexer (4051) and a teensy.

I found this really helpful: http://milkcrate.com.au/_other/sea-moss/

CODE:

const int numInputs = 12;
const int teensyPins[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
const int scaleMods[][numInputs] = {
{0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19}, // major
{0, 2, 3, 5, 7, 8, 10, 12, 14, 15, 17, 19}, // minor
{0, 1, 3, 5, 7, 8, 10, 12, 13, 15, 17, 19}, // phrygian
{0, 1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18}, // locrian
};

int MIDIchannel = 1;
int velocity = 110;
int lastNotes[numInputs];

void setup() {
for (int i=0; i<numInputs; i++) {
pinMode(teensyPins[i], INPUT);
}
}

void loop() {
int scaleSel = 0;
if (digitalRead(3) == HIGH) scaleSel += 1;
if (digitalRead(4) == HIGH) scaleSel += 1;

int octaveMod = 0;
if (digitalRead(17) == HIGH) octaveMod += 12;
if (digitalRead(18) == HIGH) octaveMod += 12;

for (int i=0; i<numInputs; i++) {
int note = 36+scaleMods[scaleSel][i]+octaveMod;
usbMIDI.sendNoteOn(note, velocity, MIDIchannel);
lastNotes[i] = note;
}
usbMIDI.sendNoteOff(lastNotes[i], 0, MIDIchannel);
}
}
}

# Midterm-Music Evolution

CONCEPT

As can be seen from contemporary music industry, the way of presenting music is shifting from three to two dimensions. It is hard to find tape, vinyl, or any other form of physical CD in the shops currently. More applications showed up, like Spotify, iTunes, which transfer a piece of music into one single file with the same icon. The more applications appeared in music industry seems to undermines the essence of music. But the physical should never be completely dismissed.

The aim of doing this project is trying to gather people together through music. It is quite different when you’re listening music alone and a bunch of friends listening together. Through this project, I want people to think the evolution of music, why the form of music is transforming from physical to digital. I connected the Arduino board with MAXMsp to complete this project. Because I think MAXMsp is a great platform to process the music, and I will explore more possibility of combing Arduino and MAXMsp. I used two photoresistors, right and left separately, on this music note object. So I can receive the fluctuant data from user’s movement to change the possibility of music. When there is no interaction, you only can hear vinyl noise, just like when we listen vinyl. If one hand/one person interacts with this object, you will get some oldie songs. Only when two hands/two persons interact with it, it will trigger the toggle to play the pop-music. The whole series of interaction is Evolution of Music.

————————————————

CODE(Arduino):

/*

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
version 2.1 of the License, or (at your option) any later version.

See file LICENSE.txt for further informations on licensing terms.

formatted using the GNU C formatting and indenting
*/

/*
* TODO: use Program Control to load stored profiles from EEPROM
*/

#include <Servo.h>
#include <Firmata.h>

/*==============================================================================
* GLOBAL VARIABLES
*============================================================================*/

int analogInputsToReport = 0; // bitwise array to store pin reporting

/* digital input ports */
byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent

/* pins configuration */
byte pinConfig[TOTAL_PINS]; // configuration of every pin
byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
int pinState[TOTAL_PINS]; // any value that has been written

/* timer variables */
unsigned long currentMillis; // store the current value from millis()
unsigned long previousMillis; // for comparison with currentMillis
int samplingInterval = 19; // how often to run the main loop (in ms)

Servo servos[MAX_SERVOS];

/*==============================================================================
* FUNCTIONS
*============================================================================*/

void outputPort(byte portNumber, byte portValue, byte forceSend)
{
// pins not configured as INPUT are cleared to zeros
portValue = portValue & portConfigInputs[portNumber];
// only send if the value is different than previously sent
if(forceSend || previousPINs[portNumber] != portValue) {
Firmata.sendDigitalPort(portNumber, portValue);
previousPINs[portNumber] = portValue;
}
}

/* —————————————————————————–
* check all the active digital inputs for change of state, then add any events
* to the Serial output queue using Serial.print() */
void checkDigitalInputs(void)
{
/* Using non-looping code allows constants to be given to readPort().
* The compiler will apply substantial optimizations if the inputs
* to readPort() are compile-time constants. */
if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}

// —————————————————————————–
/* sets the pin mode to the correct state and sets the relevant bits in the
* two bit-arrays that track Digital I/O and PWM status
*/
void setPinModeCallback(byte pin, int mode)
{
if (IS_PIN_SERVO(pin) && mode != SERVO && servos[PIN_TO_SERVO(pin)].attached()) {
servos[PIN_TO_SERVO(pin)].detach();
}
if (IS_PIN_ANALOG(pin)) {
reportAnalogCallback(PIN_TO_ANALOG(pin), mode == ANALOG ? 1 : 0); // turn on/off reporting
}
if (IS_PIN_DIGITAL(pin)) {
if (mode == INPUT) {
portConfigInputs[pin/8] |= (1 << (pin & 7));
} else {
portConfigInputs[pin/8] &= ~(1 << (pin & 7));
}
}
pinState[pin] = 0;
switch(mode) {
case ANALOG:
if (IS_PIN_ANALOG(pin)) {
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
}
pinConfig[pin] = ANALOG;
}
break;
case INPUT:
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
pinConfig[pin] = INPUT;
}
break;
case OUTPUT:
if (IS_PIN_DIGITAL(pin)) {
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
pinConfig[pin] = OUTPUT;
}
break;
case PWM:
if (IS_PIN_PWM(pin)) {
pinMode(PIN_TO_PWM(pin), OUTPUT);
analogWrite(PIN_TO_PWM(pin), 0);
pinConfig[pin] = PWM;
}
break;
case SERVO:
if (IS_PIN_SERVO(pin)) {
pinConfig[pin] = SERVO;
if (!servos[PIN_TO_SERVO(pin)].attached()) {
servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin));
} else {
Firmata.sendString(“Servo only on pins from 2 to 13”);
}
}
break;
case I2C:
pinConfig[pin] = mode;
Firmata.sendString(“I2C mode not yet supported”);
break;
default:
Firmata.sendString(“Unknown pin mode”); // TODO: put error msgs in EEPROM
}
// TODO: save status to EEPROM here, if changed
}

void analogWriteCallback(byte pin, int value)
{
if (pin < TOTAL_PINS) {
switch(pinConfig[pin]) {
case SERVO:
if (IS_PIN_SERVO(pin))
servos[PIN_TO_SERVO(pin)].write(value);
pinState[pin] = value;
break;
case PWM:
if (IS_PIN_PWM(pin))
analogWrite(PIN_TO_PWM(pin), value);
pinState[pin] = value;
break;
}
}
}

void digitalWriteCallback(byte port, int value)
{

if (port < TOTAL_PORTS) {
// create a mask of the pins on this port that are writable.
lastPin = port*8+8;
if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
for (pin=port*8; pin < lastPin; pin++) {
// do not disturb non-digital pins (eg, Rx & Tx)
if (IS_PIN_DIGITAL(pin)) {
// only write to OUTPUT and INPUT (enables pullup)
// do not touch pins in PWM, ANALOG, SERVO or other modes
if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) {
pinState[pin] = ((byte)value & mask) ? 1 : 0;
}
}
}
}
}
// —————————————————————————–
/* sets bits in a bit array (int) to toggle the reporting of the analogIns
*/
//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
//}
void reportAnalogCallback(byte analogPin, int value)
{
if (analogPin < TOTAL_ANALOG_PINS) {
if(value == 0) {
} else {
}
}
// TODO: save status to EEPROM here, if changed
}

void reportDigitalCallback(byte port, int value)
{
if (port < TOTAL_PORTS) {
reportPINs[port] = (byte)value;
}
// do not disable analog reporting on these 8 pins, to allow some
// pins used for digital, others analog. Instead, allow both types
// of reporting to be enabled, but check if the pin is configured
// scanning digital pins, portConfigInputs will mask off values from any
// pins configured as analog
}

/*==============================================================================
* SYSEX-BASED commands
*============================================================================*/

void sysexCallback(byte command, byte argc, byte *argv)
{
switch(command) {
case SERVO_CONFIG:
if(argc > 4) {
// these vars are here for clarity, they’ll optimized away by the compiler
byte pin = argv[0];
int minPulse = argv[1] + (argv[2] << 7);
int maxPulse = argv[3] + (argv[4] << 7);

if (IS_PIN_SERVO(pin)) {
// servos are pins from 2 to 13, so offset for array
if (servos[PIN_TO_SERVO(pin)].attached())
servos[PIN_TO_SERVO(pin)].detach();
servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
setPinModeCallback(pin, SERVO);
}
}
break;
case SAMPLING_INTERVAL:
if (argc > 1)
samplingInterval = argv[0] + (argv[1] << 7);
else
Firmata.sendString(“Not enough data”);
break;
case EXTENDED_ANALOG:
if (argc > 1) {
int val = argv[1];
if (argc > 2) val |= (argv[2] << 7);
if (argc > 3) val |= (argv[3] << 14);
analogWriteCallback(argv[0], val);
}
break;
case CAPABILITY_QUERY:
Serial.write(START_SYSEX);
Serial.write(CAPABILITY_RESPONSE);
for (byte pin=0; pin < TOTAL_PINS; pin++) {
if (IS_PIN_DIGITAL(pin)) {
Serial.write((byte)INPUT);
Serial.write(1);
Serial.write((byte)OUTPUT);
Serial.write(1);
}
if (IS_PIN_ANALOG(pin)) {
Serial.write(ANALOG);
Serial.write(10);
}
if (IS_PIN_PWM(pin)) {
Serial.write(PWM);
Serial.write(8);
}
if (IS_PIN_SERVO(pin)) {
Serial.write(SERVO);
Serial.write(14);
}
Serial.write(127);
}
Serial.write(END_SYSEX);
break;
case PIN_STATE_QUERY:
if (argc > 0) {
byte pin=argv[0];
Serial.write(START_SYSEX);
Serial.write(PIN_STATE_RESPONSE);
Serial.write(pin);
if (pin < TOTAL_PINS) {
Serial.write((byte)pinConfig[pin]);
Serial.write((byte)pinState[pin] & 0x7F);
if (pinState[pin] & 0xFF80) Serial.write((byte)(pinState[pin] >> 7) & 0x7F);
if (pinState[pin] & 0xC000) Serial.write((byte)(pinState[pin] >> 14) & 0x7F);
}
Serial.write(END_SYSEX);
}
break;
case ANALOG_MAPPING_QUERY:
Serial.write(START_SYSEX);
Serial.write(ANALOG_MAPPING_RESPONSE);
for (byte pin=0; pin < TOTAL_PINS; pin++) {
Serial.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
}
Serial.write(END_SYSEX);
break;
}
}
/*==============================================================================
* SETUP()
*============================================================================*/
void setup()
{
byte i;

Firmata.setFirmwareVersion(2, 2);

Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
Firmata.attach(SET_PIN_MODE, setPinModeCallback);
Firmata.attach(START_SYSEX, sysexCallback);

// TODO: load state from EEPROM here

/* these are initialized to zero by the compiler startup code
for (i=0; i < TOTAL_PORTS; i++) {
reportPINs[i] = false;
portConfigInputs[i] = 0;
previousPINs[i] = 0;
}
*/
for (i=0; i < TOTAL_PINS; i++) {
if (IS_PIN_ANALOG(i)) {
// turns off pullup, configures everything
setPinModeCallback(i, ANALOG);
} else {
// sets the output to 0, configures portConfigInputs
setPinModeCallback(i, OUTPUT);
}
}

Firmata.begin(57600);

/* send digital inputs to set the initial state on the host computer,
* since once in the loop(), this firmware will only send on change */
for (i=0; i < TOTAL_PORTS; i++) {
}
}

/*==============================================================================
* LOOP()
*============================================================================*/
void loop()
{
while (Serial.available()) {
switch(inChar) {
case ‘1’:
digitalWrite(13, HIGH);
break;
case ‘0’:
digitalWrite(13, LOW);
break;
}
Serial.println(inChar);
}
byte pin, analogPin;

/* DIGITALREAD – as fast as possible, check for changes and output them to the
* FTDI buffer using Serial.print() */
checkDigitalInputs();

/* SERIALREAD – processing incoming messagse as soon as possible, while still
* checking digital inputs. */
while(Firmata.available())
Firmata.processInput();

/* SEND FTDI WRITE BUFFER – make sure that the FTDI buffer doesn’t go over
* 60 bytes. use a timer to sending an event character every 4 ms to
* trigger the buffer to dump. */

currentMillis = millis();
if (currentMillis – previousMillis > samplingInterval) {
previousMillis += samplingInterval;
/* ANALOGREAD – do all analogReads() at the configured sampling interval */
for(pin=0; pin<TOTAL_PINS; pin++) {
if (IS_PIN_ANALOG(pin) && pinConfig[pin] == ANALOG) {
analogPin = PIN_TO_ANALOG(pin);
if (analogInputsToReport & (1 << analogPin)) {
}
}
}
}
}

————————————————

CODE(MAXMsp):

(in terms of the code is too long, I decided to use screenshot…)

# Midterm Breathing Device

The “Breathing Device”, equipped with the same mechanical motion as “The breathing paper bag” but translated into an object that the user has to carry close to her/his hand. The device is shaped to fit the users hand. The tiny shape evokes feelings of protection. Additionally, through the intimate contact, the user feels the movement of the breathing tangible on the skin. The purpose of the object is to create a playful experience with it and raise deeper questions about how to evoke feelings for artificial objects. On another hand, it is used as a stress relief.

https://vimeo.com/111303016

# Midterm – Autonomous Car

Inputs: distance sensor and photocell
The distance sensor looks ahead of the car and if it senses something too close it backs up and turns and then continues on it’s way.
The photocell senses when it is too dark and turns on the headlights on the car.
Here is a link to my documentation: http://youtu.be/LsgcDeVzgE0
CODE:
//code edited from Arduino documentation about motors, h-bridges, and distance sensorsconst int motor1Pin = 9; //back motor
const int motor2Pin = 8; //back motor
const int motor3Pin = 11; //front motor
const int motor4Pin = 10; //front motor
const int enablePin = 7;
const int photocellPin = A0;
const int ledPin1 = 5;
const int ledPin2 = 3;

int LEDbrightness;

#define echoPin 13 // Echo Pin
#define trigPin 12 // Trigger Pin
long duration, distance; // Duration used to calculate distance
int minRange = 30; // min range before reverse

void setup() {
Serial.begin(9600);
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
pinMode(motor3Pin, OUTPUT);
pinMode(motor4Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(photocellPin, INPUT);
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);

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

void loop() {

LEDbrightness = constrain(map(photocellReading, 500, 300, 0, 255), 0, 255);
analogWrite(ledPin1, LEDbrightness);
analogWrite(ledPin2, LEDbrightness);

// set enablePin high so that motor can turn on:
digitalWrite(enablePin, HIGH);
/* The following trigPin/echoPin cycle is used to determine the
distance of the nearest object by bouncing soundwaves off of it. */
digitalWrite(trigPin, LOW);
delayMicroseconds(2);

digitalWrite(trigPin, HIGH);
delayMicroseconds(10);

digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);

//Calculate the distance (in cm) based on the speed of sound.
distance = duration/58.2;
Serial.println(distance);

if (distance >= minRange){
fwd();
straight();
}
else {
bkwd();
right();
delay(2000);
}
delay(10);

}

void fwd() {
digitalWrite(motor1Pin, LOW);
digitalWrite(motor2Pin, HIGH);
}
void bkwd() {
digitalWrite(motor1Pin, HIGH);
digitalWrite(motor2Pin, LOW);
}
void left() {
digitalWrite(motor3Pin, LOW);
digitalWrite(motor4Pin, HIGH);
}
void right() {
digitalWrite(motor3Pin, HIGH);
digitalWrite(motor4Pin, LOW);
}
void straight() {
digitalWrite(motor3Pin, LOW);
digitalWrite(motor4Pin, LOW);
}

# mid term zen circle drawing

People like  zazen to improve their self control .  It’s through the control of breathing and heartbeat . So i want to try to use a pulse sensor to  make some interaction with zen arts , a  brush pen draw a circle according to the BPM.

#include <Stepper.h>

const int stepsPerRevolution = 512; // change this to fit the number of steps per revolution

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8,9,10,11);

// VARIABLES
int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13; // pin to blink led at each beat

// these variables are volatile because they are used during the interrupt service routine!
volatile int BPM; // used to hold the pulse rate
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // holds the time between beats, the Inter-Beat Interval
volatile boolean Pulse = false; // true when pulse wave is high, false when it’s low
volatile boolean QS = false;
int times=0;// becomes true when Arduoino finds a beat.
void setup(){
pinMode(5,OUTPUT);
pinMode(4,OUTPUT);
pinMode(6,OUTPUT);
Serial.begin(115200);
myStepper.setSpeed(30); // we agree to talk fast!
interruptSetup();
// sets up to read Pulse Sensor signal every 2mS
// UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor AT LOW VOLTAGE,
// AND APPLY THAT VOLTAGE TO THE A-REF PIN
//analogReference(EXTERNAL);
}

void loop(){
sendDataToProcessing(‘S’, Signal);
steps=map(BPM,50,150,140,20); // send Processing the raw Pulse Sensor data
if (QS == true){ // Quantified Self flag is true when arduino finds a heartbeat

sendDataToProcessing(‘B’,BPM); // send heart rate with a ‘B’ prefix
sendDataToProcessing(‘Q’,IBI); // send time between beats with a ‘Q’ prefix
QS = false;
times=times+1; // reset the Quantified Self flag for next time
}
if (times ==5){

myStepper.step(steps);
times=0;
}
if (times ==1){

}
if (times ==2){

}
if (times ==3){

}
if (times ==4){

}

delay(20); // take a break
}

}
void sendDataToProcessing(char symbol, int data ){
Serial.print(symbol); // symbol prefix tells Processing what type of data is coming
Serial.println(data); // the data to send culminating in a carriage return
}

# Midterm / Haptic Feedback + Visual Feedback User Test For Physical Rehabilitation

CONCEPT

The machines designed for motor rehabilitation are aesthetically unpleasant and often not engaging or stimulating to the patient. I am interested in exploring the areas of healthcare and rehabilitation through art and new technologies in order to five people with motor challenges better health through inclusive design and interactive experiences. Rehabilitation is a slow and boring process, so how can the algorithm behind the interaction I am creating suggest a more engaging process?

I am currently researching the domains of motivation, agency and especially self-efficacy. What would keep my user from loosing interest? How is kinetic movement rewarding? How does externalization affect stress? How can haptic feedback be utilized to enhance muscle memory? My entire concept is grounded in my users experience, practically approaching the problems that people with disabilities face. I am particularly focusing on people that are very physically restrained – to the extent that even jumping on a wheelchair is exhausting.

For my midterm, I needed to prototype the experience with my peers in order to send out a package to different healthcare facilities in order to consult a specialist and ideally work with them for future prototyping. I conducted a short User Test Questionnaire in conjunction with the test, and below are some of my key insights:

• Vibrational feedback needs to be more clear, not using time but rather number of vibrations to indicate if you have done the exercises too slow/fast.
• People generally found the feedback to be helpful/rewarding/important, and would like to see this as a developed product.
• People did not pay so much attention to the visual feedback, and where more focused and grateful for the haptic feedback.

PROTOTYPE

The piece is based on a simple exercise routine: the bicep curl. Often times, it is difficult for people to stay with their routines, especially when highly disabled and check-ins with physical therapists are scarce. In this instance, haptic feedback lets you know if you have done the basic routine of ten bicep curls within the right time frame by giving you one long vibration. Two short tells you that you’ve done them too fast, and two long ones too slow. The origami works as a supplement in lifting all of it’s legs if you have done it right, and only some of them if wrong, simply to test the viability of visual stimuli in a simple way.

/*
VIBRATIONAL FEEDBACK BASED ON IF YOU HAVE DONE YOUR BICEP ROUTINES CORRECTLY. MOREOVER, YOU WILL SEE ORIGAMI MOVE AS FEEDBACK.
BY FABIOLA EINHORN FALL 2014 FOR THESIS AND PHYSICAL COMPUTING
*/

int vibration = 6;
int sensorValue = 0;
int flex = A3;
int counter = 0;
int timer;
int startTime;
int endTime;
int trainTime;
int flexinolA = 2;
int flexinolB = 3;
int flexinolC = 4;
int flexinolD = 5;

void setup() {
pinMode(vibration, OUTPUT);
pinMode(flexinolA, OUTPUT);
pinMode(flexinolB, OUTPUT);
pinMode(flexinolC, OUTPUT);
pinMode(flexinolD, OUTPUT);

Serial.begin(9600);
}

void loop() {
//Serial.println(sensorValue);

delay(1); // delay in between reads for stability

if(sensorValue == 300){
if(counter == 0){
startTime = millis();
}

Serial.println(counter);
Serial.println(sensorValue);

counter = counter + 1;

delay(1000);

}

if(counter > 3){
analyze();
counter = 0;
}
}

void analyze(){
endTime = millis();
trainTime = endTime – startTime;
Serial.println(trainTime);

// IF YOU DID THE EXERCISES TOO FAST, GIVE TWO SHORT VIBRATIONS

if(trainTime <= 15000){
motor(500);
delay(1000);
motor(500);
Serial.println(“FLEEEXINOOOL”);

digitalWrite(flexinolA, HIGH);
delay(2000);
digitalWrite(flexinolA, LOW);

digitalWrite(flexinolC, HIGH);
delay(2000);
digitalWrite(flexinolC, LOW);
}

// IF YOU DID THE EXERCISES CORRECTLY, GIVE ONE LONG VIBRATION

if(trainTime > 15000 && trainTime < 25000){
motor(2000);
Serial.println(“FLEEEXINOOOL”);

digitalWrite(flexinolA, HIGH);
delay(2000);
digitalWrite(flexinolA, LOW);

digitalWrite(flexinolB, HIGH);
delay(2000);
digitalWrite(flexinolB, LOW);

digitalWrite(flexinolC, HIGH);
delay(2000);
digitalWrite(flexinolC, LOW);

digitalWrite(flexinolD, HIGH);
delay(2000);
digitalWrite(flexinolD, LOW);
}
// IF YOU DID THE EXERCISES TOO SLOWLY, GIVE TWO LONG VIBRATIONS
if(trainTime > 25000){
motor(2000);
delay(1000);
motor(2000);
Serial.println(“FLEEEXINOOOL”);

digitalWrite(flexinolC, HIGH);
delay(2000);
digitalWrite(flexinolC, LOW);

digitalWrite(flexinolD, HIGH);
delay(2000);
digitalWrite(flexinolD, LOW);
}

}

void motor(int valueLong) {
digitalWrite(vibration, HIGH);
delay(valueLong);
digitalWrite(vibration, LOW);
}

# midterm-rc car with ultrasonic sensor

I made an obstacle avoiding rc car.

The sensor is mounted on the servo. For some reason when the servo is attached in the setup, the dc motors stop running, but the servo works and prints information to the console as it should.

here is simple version my code without the servo running-

int pinSpeaker=8;

float sinVal;
int toneVal;
unsigned long echo = 0;
int ultraSoundSignal = 7; // Ultrasound signal pin
unsigned long ultrasoundValue = 0;
#include <Servo.h> // Enables the Servo library
int pingPin = 7 ; // Ping sensor is connected to port A0
int centerDist, leftDist, rightDist, backDist; // Define variables center, left, right and back distance
long duration, inches, cm; // Define variables for Ping sensor

#include “MotorDriver.h”

#include “Servo.h”
Servo PingServo;
void setup()
{
Serial.begin(9600);

pinMode(pinSpeaker,OUTPUT);
pinMode(ultraSoundSignal,OUTPUT);
motordriver.init();
motordriver.setSpeed(110,MOTORA);
motordriver.setDirection(200,MOTORB);
// PingServo.attach(10); // Servo is attached to pin 10 in the motor shield
PingServo.write(90); // Center the Ping sensor (puts it at 90 degrees)
}

unsigned long ping(){
pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output
digitalWrite(ultraSoundSignal, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(ultraSoundSignal, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(ultraSoundSignal, LOW); // Holdoff
pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
digitalWrite(ultraSoundSignal, HIGH); // Turn on pullup resistor
// please note that pulseIn has a 1sec timeout, which may
// not be desirable. Depending on your sensor specs, you
// can likely bound the time like this — marcmerlin
// echo = pulseIn(ultraSoundSignal, HIGH, 38000)
echo = pulseIn(ultraSoundSignal, HIGH); //Listen for echo
ultrasoundValue = (echo / 58.138) * .39; //convert to CM then to inches
return ultrasoundValue;
}

void loop()
{

int x = 0;
x = ping();
Serial.println(x);
delay(250); //delay 1/4 seconds.

if (x >= 15){
motordriver.rotateWithID(MOTOR_CLOCKWISE, MOTORA);
}
else{
tone (8,100,76);
delay(105);
motordriver.rotateWithID(MOTOR_ANTICLOCKWISE, MOTORA);
motordriver.rotateWithID(MOTOR_CLOCKWISE, MOTORB);
delay(4000);

————————-

and here is the code that isn’t running with the servo-
#include “MotorDriver.h”
#include “Servo.h”// Enables the Servo library
Servo PingServo;

int minSafeDist = 11 ; // Minimum distance for ping sensor to know when to turn
int pingPin = 7 ;
int centerDist, leftDist, rightDist, backDist; // Define variables center, left, right and back distance
long duration, inches, cm; // Define variables for Ping sensor
void setup() {
Serial.begin(9600); // Enables Serial monitor for debugging purposes
Serial.println(“Serial test!”); // Test the Serial communication
PingServo.attach(3); // Servo is attached to pin 10 in the motor shield
PingServo.write(90); // Center the Ping sensor (puts it at 90 degrees)
motordriver.init();

motordriver.setSpeed(140,MOTORA);
motordriver.setDirection(200,MOTORB);
}

void loop()
{
Serial.print(inches);
Serial.println(” inches”); // Prints a line in the serial monitor
if(inches >= minSafeDist) /* If the inches in front of an object is greater than or equal to the minimum safe distance (11 inches), react*/
{
motordriver.goForward();
delay(110); // Wait 0.11 seconds
}else // If not:

{
motordriver.stop(MOTORA);
motordriver.stop(MOTORB);
LookAround(); // Check your surroundings for best route
if(rightDist > leftDist) // If the right distance is greater than the left distance , turn right
{
motordriver.rotateWithID(MOTOR_CLOCKWISE, MOTORA);
motordriver.rotateWithID(MOTOR_CLOCKWISE, MOTORB);
}else if (leftDist > rightDist) // If the left distance is greater than the right distance , turn left
{
motordriver.rotateWithID(MOTOR_CLOCKWISE, MOTORA);
motordriver.rotateWithID(MOTOR_ANTICLOCKWISE, MOTORB);
}else if (leftDist&&rightDist<minSafeDist) // If the left and right distance is smaller than the min safe distance (11 inch) go back
{
motordriver.rotateWithID(MOTOR_ANTICLOCKWISE, MOTORA);
}
}
}

unsigned long ping() {
pinMode(pingPin, OUTPUT); // Make the Pingpin to output
digitalWrite(pingPin, LOW); //Send a low pulse
delayMicroseconds(2); // wait for two microseconds
digitalWrite(pingPin, HIGH); // Send a high pulse
delayMicroseconds(5); // wait for 5 micro seconds
digitalWrite(pingPin, LOW); // send a low pulse
pinMode(pingPin,INPUT); // switch the Pingpin to input
duration = pulseIn(pingPin, HIGH); //listen for echo

/*Convert micro seconds to Inches
————————————-*/

inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
}

long microsecondsToInches(long microseconds) // converts time to a distance
{
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) // converts time to a distance
{
return microseconds / 29 / 2;
}

PingServo.write(90);// angle to look forward
delay(175); // wait 0.175 seconds
ping();
}

void LookAround(){
PingServo.write(180); // 180° angle
delay(320); // wait 0.32 seconds
ping();
rightDist = inches; //get the right distance
PingServo.write(0); // look to the other side
delay(620); // wait 0.62 seconds
ping();
leftDist = inches; // get the left distance
PingServo.write(90); // 90° angle
delay(275); // wait 0.275 seconds

// Prints a line in the serial monitor
Serial.print(“RightDist: “);
Serial.println(rightDist);
Serial.print(“LeftDist: “);
Serial.println(leftDist);
Serial.print(“CenterDist: “);
Serial.println(centerDist);
}

# midterm

#include <NewPing.h>
#include <Servo.h>

#define MAX_DISTANCE 200
#define TRIG_PIN  4
#define ECHO_PIN  2

#define LEFT 0
#define CENTER 90
#define RIGHT 180
#define ENABLE1 3
#define INPUT1 9
#define INPUT2 8
#define ENABLE2 11
#define INPUT3 7
#define INPUT4 6

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
Servo ultrasonicServo;

float dangerThreshold = 40.0;

int currentPos = 0;

#define LEFT_FORWARD_RIGHT_FORWARD {HIGH, HIGH, LOW, HIGH, HIGH, LOW}
#define LEFT_OFF_RIGHT_FORWARD {LOW, HIGH, LOW, LOW, HIGH, LOW}
#define LEFT_FORWARD_RIGHT_OFF {HIGH, LOW, LOW, HIGH, LOW, LOW}
#define LEFT_REVERSE_RIGHT_FORWARD {HIGH, HIGH, HIGH, LOW, HIGH, LOW}
#define LEFT_FORWARD_RIGHT_REVERSE {HIGH, HIGH, LOW, HIGH, LOW, HIGH}
#define LEFT_REVERSE_RIGHT_REVERSE {HIGH, HIGH, HIGH, LOW, LOW, HIGH}
#define LEFT_OFF_RIGHT_OFF {HIGH, HIGH, LOW, LOW, LOW, LOW}
#define LEFT_FREEWHEEL_RIGHT_FREEWHEEL {LOW, LOW, LOW, LOW, LOW, LOW}

#define FORWARD LEFT_FORWARD_RIGHT_FORWARD
#define REVERSE LEFT_REVERSE_RIGHT_REVERSE
#define LEFT_TURN LEFT_OFF_RIGHT_FORWARD
#define RIGHT_TURN LEFT_FORWARD_RIGHT_OFF
#define ROTATE_LEFT LEFT_REVERSE_RIGHT_FORWARD
#define ROTATE_RIGHT LEFT_FORWARD_RIGHT_REVERSE
#define BRAKE LEFT_OFF_RIGHT_OFF
#define FREEWHEEL LEFT_FREEWHEEL_RIGHT_FREEWHEEL

#define SLOW 130;
#define MEDIUM 195;
#define FAST 255;

int throttle = MEDIUM;

void setup() {

pinMode(ENABLE1, OUTPUT);
pinMode(ENABLE2, OUTPUT);
pinMode(INPUT1, OUTPUT);
pinMode(INPUT2, OUTPUT);
pinMode(INPUT3, OUTPUT);
pinMode(INPUT4, OUTPUT);

ultrasonicServo.attach(5);

servo_position(CENTER);
}

void loop() {

float distanceForward = ping();

if (distanceForward > dangerThreshold)
{
drive_forward();
}
else
{
brake();

servo_position(LEFT);
float distanceLeft = ping();

servo_position(RIGHT);
float distanceRight = ping();

if (distanceLeft > distanceRight && distanceLeft > dangerThreshold)       //if left is less obstructed
{

rotate_left();
}
else if (distanceRight > distanceLeft && distanceRight > dangerThreshold) //if right is less obstructed
{

rotate_right();
}
else
{

u_turn();
}

servo_position(CENTER);
}
}

void freewheel(){
const int driveControl[] = FREEWHEEL;
drive(driveControl);
delay(25);

void brake(){
const int driveControl[] = BRAKE;
drive(driveControl);
delay(25);
}

void drive_forward(){
const int driveControl[] = FORWARD;
drive(driveControl);
}

void drive_backward(){
const int driveControl[] = REVERSE;
drive(driveControl);
}

void turn_left(){
const int driveControl[] = LEFT_TURN;
drive(driveControl);
delay(600);

}

void turn_right(){
const int driveControl[] = RIGHT_TURN;
drive(driveControl);
delay(600);

}

void rotate_left(){
const int driveControl[] = ROTATE_LEFT;
drive(driveControl);
delay(300);
}
void rotate_right(){
const int driveControl[] = ROTATE_RIGHT;
drive(driveControl);
delay(300);
}

void u_turn(){
const int driveControl[] = ROTATE_RIGHT;
drive(driveControl);
delay(600);
}

void drive(const int settings[6]){

if (settings[0] == HIGH)
analogWrite(ENABLE1, throttle);
else
digitalWrite(ENABLE1, LOW);

if (settings[1] == HIGH)
analogWrite(ENABLE2, throttle);
else
digitalWrite(ENABLE2, LOW);

digitalWrite(INPUT1, settings[2]);
digitalWrite(INPUT2, settings[3]);
digitalWrite(INPUT3, settings[4]);
digitalWrite(INPUT4, settings[5]);
}

void servo_position(int newPos){

if (newPos > currentPos){
for(int pos=currentPos; pos < newPos; pos += 1)
{
ultrasonicServo.write(pos);
delay(15);
}
currentPos = newPos;
}
else if (newPos < currentPos){
for(int pos=currentPos; pos > newPos; pos -= 1)
{
ultrasonicServo.write(pos);
delay(15);
}
currentPos = newPos;
}
}

float ping(){
delay(50);

unsigned int seconds = sonar.ping();

if (seconds == 0)
return MAX_DISTANCE;
else
return seconds / US_ROUNDTRIP_CM;
}