Pursuits of Design and Robotics

The documentation of concept development and general processes


Leave a comment

Smart 3D Pen Research

“FreeD” by Amit Zoran. 2013

More

Amit references

“Haptic Intelligentsia” by Joong Han Lee. 2012

More

Amit uses magnets for 3D tracking. I found this website that appears to be a DIY. Maybe I can work on this for another project if the Leap works.

I was worried it wouldn’t so I did a lot of research on 3D magnet tracking, which is still an option maybe…maybe I’ll save it for another project. I’ll post some links just so people can see what I was thinking about if you’re interested.

DIY Magnet Tracker Sites
1 2 3 4 5

 Understanding the limitations of the pen. Make sure it can work with how I want to use it.

Understanding the limitations of the pen. Make sure it can work with how I want to use it.

THE LEAP WORKS!

Pen over Leap


Leave a comment

Independent Study

My independent study is going to be a continuation of my project for the embedded wearable technology in Ali Momeni’s Hybrid Instruments course.

I want to make my cat bowl smart enough to determine what cat is approaching it, whether it should let the cat eat, how much, and how many times through out the day. The bowl will relay information to me through a phone application. With the app I can see how many times each of my cats tried to eat today, what cat interrupted what cat from eating, how much the cats ate so far today, and I can control everything.

I found a few precedent examples of people who have thought about this, but I don’t think anybody did it as well as I will do it.

http://gatefeeder.com/

Gatefeeder is decently designed, the door is clever for not needing a servo and having the cat open the door. The inset depth of the door is presumably to prevent a second cat from pushing his head in and keeping the door open for himself to eat. I could consider a design that accomplishes similar results. Gatefeeder is doing a lot of what I want except that it doesn’t differentiate between cats and it is not intelligently learning about the cat’s behavior. Actually, there are no cat bowls that actually monitor the feeding. They only open and close.

http://petsweekly.com/en/all-about-cats/cat-health/cat-behavior/663-feeding-individual-diets-in-multi-cat-households

This website shows some other examples of cat feeders, mainly SureFlap and Meow Space. Both use the idea of a cat-door to a confined space to allow certain cats in to eat. Again, these lack control over how much is eaten by different cats who have access to the same bowl.

The precedents are there and it’s reassuring to see that there are no data-interpreting bowls like I intend to make, but the bowls are similar enough to help me understand the best actuation methods. RFID was the right way to go, yay!

I have ordered online an RFID reader component and an antenna for it to allow a range of up to 3 feet. This way if one cat tries to sneak up on the one eating, the bowl will just shut down and they’ll have to give up on eating at the same time. I also got tags that should be perfect for the collar.


Leave a comment

Enchanted Object: “SoapBox: Lonely Dog Up For Adoption” by Priya Granadas and Yeliz Karadayi

SoapBox: Lonely dog up for adoption from Priya Ganadas on Vimeo.

SoapBox is a puppy who likes pretending he goes on adventures though really he just likes to sit on his couch. SoapBox is lonely and looking for love, however, if you hit him he will like you less and less. He is forgiving though, of course, and if you hold your hand out to him gently and wait to pet him, you might win him over and he’ll reach back out for your love. He gets confused when you disappear out of view, and he gets bummed when he’s alone. Voice reactions indicate his mood, and he moves when he’s reaching out for you to pet him. SoapBox wants to learn to love!

Alone Soap sits, waiting for someone to love

Alone Soap sits, waiting for someone to love

Could it be? Will somebody take me?

Could it be? Will somebody take me?

Alas, no. I continue to sit here sobbing on my SoapBox.

Alas, no. I continue to sit here sobbing on my SoapBox.

 


Leave a comment

Sing To Me Physical Process

The first model of the flower was too stiff for the servo to work. Also the box was ugly. I did really like the idea of wood, though, because of the warm ambiance it gives off. I thought the ribbons might look nice but they look terrible and desperate. The flower was too big to get a lot of movement out of a small servo, and I hadn’t considered until after seeing this that the string should not be out in the open like that all the way down to the base. There should be some kind of protection.

I redid it to make it look a bit more planned and smooth. See the final product in the final post for this.

Elevation view, closed.

Elevation view, closed.

No hardware could fit down here. I did not plan well.

No hardware could fit down here. I did not plan well.

Flower Opened

Flower Opened

Flower Closed

Flower Closed


Leave a comment

SoapBox Code

Well, this code kicked my face. But I think I got it. 

Let’s start with the obvious information: I have a distance sensor, and I have a servo. When the distance provides some desired information, Soap will return a desired output. I start with smoothing, because I’m starting to think everything should always be smoothed, at least a little, for better results. After I smooth, I track. I track by putting the smoothed distance values in an array for 10 frames [so trackingArray.length = 10] which is no time at all, but better than tracking for seconds, meaning high tolerances, and thus lower reflexes. So the dog tracks your movement for 10 frames which is probably around a second. Then the dog runs some tests on this information. If you mass addition the differences between the distances from one frame to the next, the result will yield whether or not you are approaching the dog or distancing from it. This result also tells you, on average for the past 10 frames, how fast the movement was as well. 

Additionally there are factors such as slow movement while being close to the dog versus fast movement far away from the dog, and so on. My favorite aspect of this puppy, though, is that he knows if you are hitting him, and he gets upset with you. For every frame that the dog interprets your movements as a hit, he will become jaded and less friendly to your approach. If you patiently hover your hand slowly to him, however, he will grow to like you again.

I was pretty proud of this code for a first project. Priya and I faced a lot of struggles in dealing with the COM Port communicating while the servo was plugged in, which I learned today [also known as too late] was the fault of the cable I was using to load the code to the Arduino. Additionally, we also struggled heavily with the sound output which Priya took charge of and failed after I failed first. We still don’t know why that didn’t work. It worked on all of the example files, but not on ours. However I know the rest of the code works due to the most lovely Serial.println function.

So, all you need is a Servo and a distance sensor and this disastrous code will tell you what’s up.

#include <Servo.h>
//orange to ground
//red to 24
//green outputs 24
Servo arms;
Servo head;

int distThresh = 600;
int soundThresh = 600;

int distSensor = 0;
int microphone = 1;

int armsPin = 9;
int headPin = 10;

int const smootheFC = 3;
int thisSmooth = 0;
int smoother[smootheFC];
int average;
int total;

int const trackFC = 10;
int thisFrame = 0;
int trackMovement[trackFC];

int frameCounter= 0;
int timeToMove = 1000;
int averageGen = 0;

int const stateCount = 5;
int stateIndex = 0;
int states= 0;
int saveStates[stateCount];

void setup()
{
arms.attach(armsPin);
pinMode(7, OUTPUT);
pinMode(distSensor, INPUT);

Serial.begin(57600);

for(int i = 0; i < smootheFC; i++){
//smoothes
smoother[i] = 0;
}
}

void loop() {

frameCounter ++;
int distance = analogRead(distSensor);
averageGen = 0;

if (frameCounter == timeToMove){
// Serial.println(thisSmooth);

total = total – smoother[thisSmooth];
smoother[thisSmooth] = distance;
total = total + smoother[thisSmooth];
thisSmooth ++;

if (thisSmooth >= smootheFC)
{
// Serial.println(“thisSmooth = 0”);
thisSmooth = 0;
}

Serial.print(“[“);
for(int i = 0; i < trackFC-1; i++){

Serial.print(trackMovement[i]);
Serial.print(“, “);
}

Serial.println(“]”);

average = total / smootheFC;

for(int i = trackFC -1; i > 0; i–)
{
trackMovement[i] = trackMovement[i-1];
trackMovement[0] = average;
}

for(int i = 0; i < trackFC-1; i++) averageGen += (trackMovement[i+1] – trackMovement[i]);

int score = 0;
boolean sameState = false;

for(int i = 0; i < stateCount-1; i++)
{
if (saveStates[i] == saveStates[i-1]) score++;
if (score > 2) {
sameState = true;
Serial.println(“^” );
}
}

Serial.println(averageGen );
if ((averageGen <= -400) && (trackMovement[trackFC-1] != 0))
{
states = 4;
timeToMove = 2000;
Serial.println(“DON’T HIT ME!!!” );
arms.write(0);
}
else if (average < 200 && averageGen < 50 && averageGen > -50 )
{

states = 0;
timeToMove = 1000;
Serial.println(“Guess I’m alone!” );

arms.write(0);
}
else if (average > distThresh && averageGen < 50 && averageGen > -50)
{
states = 1;
timeToMove = 3000;
Serial.println(“PET ME!” );
arms.write(120);
}
else if ((averageGen <= 0) && (averageGen > -200))
{
states = 2;
timeToMove = 1000;
Serial.println(“you are getting closerclosercloser to me!” );
}
else if ((averageGen >= 0) && (averageGen < 200))
{
states = 3;
timeToMove = 2000;
Serial.println(“you are getting farther from me!”);
}
else if (averageGen >= 400)
{
states = 5;
timeToMove = 5000;
Serial.println(“WHERE DID YOU GO!?”);
}
Serial.write(states);

saveStates[stateIndex] = states;
stateIndex++;
if (stateIndex == stateCount) stateIndex = 0;

frameCounter = 0;
}
}

 


Leave a comment

SoapBox Physical Process

This week was a total mess and I have only just now felt comfortable sitting down and reflecting. But before I reflect, I should talk about the process.

Priya and I began with a similar practice to the one Ali Momeni had us do in class where we jot down 10 ideas in 5 minutes. After doing this we took turns telling each other our ideas and building off each one, after which we cycled through and eliminated one each round until we found the one we were most excited about. Our favorite ideas were a drink that tells how long it will be desirable for, a robot that dodges your punches, and a simple DJ that determines your mood or color and plays music based on that.

The robot dodging punches seemed particularly cool. We knew we couldn’t make a robot really dodge punches though. We could, however, experiment with how far we could take a simple distance sensor and interpret the input to general a wide range of responses, as opposed to a simple activation once a target distance is reached. The fastest solution to a robot that would do this was most easily an old used toy of mine from my childhood that we could bring to life. We originally envisioned the bot being a dramatic bratty character who always looks like it’s about to cry, and would ask needy questions or act abused. Since using the toy dog, the character changed a bit to a more loving but still needy puppy. The biggest struggle with this pup was his skeleton.

Here’s some documentation of our struggle:

Materials considered for skeleton- No idea what I’m doing.

We thought this could be a decent skeleton. We didn’t think how this would hold a Servo.

This is what the arms would look like in wood.

As you can see, these pieces puzzle together so that while we glue it while inside of the puppy, the skeleton will hold itself together to a helpful extent.

IMG_20140901_211327

This is what we came up with in a half hour after failing for 8 straight hours with the other skeleton alternatives. We thought we could just use sticks and metal. How wrong we were. This worked better than everything else.

IMG_20140901_213734

We felt we were successful in making him look pitiful. Nobody seemed to notice in class though 😦

IMG_20140901_213739

I liked the simplicity of his design. Why does he need anything more if it’s just for the sake of character? I think for me it was the fact that I’ve had him for a very long time that made him exciting just as he was.

For the final design we made him a couch made of foam and covered with old bed sheets. We put the sensors in goggles around his eyes, so I guess we did add to his character, and in a functional way which was nice. See the more recent post on this project for the final product!


Leave a comment

Sing To Me Code

Just a brief of the code before showing the gold. HAH! Rhymes. Didn’t really make sense since they’re referring to the same thing..anyway. 

With the FFFT library I can use the microphone to pick up sound across the spectrum and store each frequency value in an array. From the tutorial, this array is size 64. I decided to reduce it to half that size by adding every pair of numbers in the array, which also allows for higher tolerance of sound input.

Next step was to figure out the prominent note which was a simple find max value loop with some smoothing thrown in there to, well, smooth things out.

For the buttons I have one to set a new password and one to test new input against the password. This was done by recording the loudest note for 30 frames and saving that to an array. The saved array from the set password would then be compared to the new input. There is an error tolerance to accommodate for offsets in timing or being off-key.  If you are too off in timing or too off key, you’ll get a point, and after 5 points out of the 30, you got the password wrong. This makes the input pretty picky, considering how sketchy the microphone seems to be with ambiance and the like.

I could have done more with the buttons. I wanted to have a light turn on to indicate that a password is being set and stay on once it is set. A light for the new input as well, which would blink a couple times to celebrate your correctness. I wanted to incorporate protection around the premise of inputting a password before setting one, which currently means that you automatically got it right. There are a few other simple situations I could have delved in to to enrich the experience and make it more fluid, easy to understand, and functional. But hey, at least writing about it shows awareness. 

 

Here is my very, very messy code. Stick THAT in your Arduino and run it.

#include <stdint.h>
#include <ffft.h>
#include <Servo.h>

//SOUND STUFF

volatile byte position = 0;
volatile long zero = 0;

int16_t capture[FFT_N]; /* Wave captureing buffer */
complex_t bfly_buff[FFT_N]; /* FFT buffer */
uint16_t spektrum[FFT_N/2]; /* Spectrum output buffer */

//AUDIO INPUT
#define IR_AUDIO 0 // ADC channel to cap

//SOUND AVG

const int fftNum = int(FFT_N / 2);

//SOUND SMOOTHE
const int smoothFrames = 5;
int sIndex = 0;
uint16_t readings[smoothFrames][fftNum/2];
uint16_t average[fftNum/2];
uint16_t total[fftNum/2];

//INPUT RECORDER
const int totalFrames = 30;
int thisFrame = 0;
int indexRec[totalFrames];
bool recorded = false;

//INPUT PASSWORD
int passFrame = 0;
int indexPass[totalFrames];
bool passworded = false;
int worked = 0;

//BUTTON STUFF
//int ledPin1 = 12; // choose the pin for the LED
//int ledPin2 = 13;
int butPin1 = 7; // choose the input pin (for a pushbutton)
int butPin2 = 6;
int butVal1 = 0; // variable for reading the pin status
int butVal2 = 0;

//SERVO
Servo box;
int boxPint = 13;

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

box.attach(boxPint);
pinMode(13, OUTPUT);
Serial.println(fftNum);
box.write(180);

}

void loop()
{

//SOUND STUFF
if (position == FFT_N)
{
fft_input(capture, bfly_buff);
fft_execute(bfly_buff);
fft_output(bfly_buff, spektrum);

position = 0;
}

int ind = 0;

// //SMOOTHER
for(int i = 0; i < fftNum/2; i++)
{

total[i] = total[i] – readings[sIndex][i];
readings[sIndex][i] = spektrum[ind] + spektrum[ind + 1];
total[i] += readings[sIndex][i];

average[i] = total[i]/smoothFrames;

ind += 2;
}

//FOR DEBUGGING INPUT WITH SMOOTHING
// Serial.println(“THIS IS A SPEKTRUM”);
// Serial.print(“[“);
//
// for (byte i = 0; i < fftNum/2; i++){
// Serial.print(average[i]);
// Serial.print(“,”);
// }
// Serial.println(“]”);

sIndex ++;
if (sIndex >= smoothFrames) sIndex = 0;
int thisNote = getNote(average);
Serial.println(thisNote);

//BUTTON STUFF

// if (recorded) digitalWrite(ledPin1, HIGH); // turn LED ON

butVal1 = digitalRead(butPin1); // read input value

if (butVal1 == HIGH) { // check if the input is HIGH (button released)
// digitalWrite(ledPin1, LOW); // turn LED OFF
}
else {
// digitalWrite(ledPin1, HIGH); // turn LED ON
//RECORDER
if(!recorded)
{
if (thisFrame < totalFrames){

Serial.println(“RECORDING!”);
indexRec[thisFrame] = thisNote;
thisFrame ++;
}
else{
Serial.println(“DONE RECORDING!”);
recorded = true;
delay(5000);
}
}
}

butVal2 = digitalRead(butPin2); // read input value

// if (passworded) digitalWrite(ledPin2, HIGH);

if (butVal2 == HIGH) { // check if the input is HIGH (button released)
// digitalWrite(ledPin2, LOW); // turn LED OFF
}
else {
// digitalWrite(ledPin2, HIGH); // turn LED ON

//PASSWORD

if(!passworded)
{
Serial.println(“INPUT PASSWORD”);
indexPass[passFrame] = thisNote;
passFrame ++;

if (passFrame >= thisFrame){
Serial.println(“DONE”);
passworded = true;
}
}
if(passworded)
{
Serial.println(“PASSWORD ENTERED”);
for(int i = 0; i < thisFrame; i++)
{
//FOR DIRECT COMPARISON OF INPUTS
// Serial.println(“RECORDER:”);
// Serial.println(indexRec[i]);
// Serial.println(“PASSWORD:”);
// Serial.println(indexPass[i]);

if(abs(indexPass[i] – indexRec[i]) > 2)
{
Serial.println(“THIS WAS WRONG!”);
worked ++;
}
}
Serial.println(“DID IT WORK?”);
if (worked < 5) {

box.write(0);
delay(1000);
passworded = false;
passFrame = 0;

}
Serial.println( worked<10);
delay(3000);
passFrame = 0;
}
}

}

// free running ADC fills capture buffer
ISR(ADC_vect)
{
if (position >= FFT_N)
return;

capture[position] = ADC + zero;
if (capture[position] == -1 || capture[position] == 1)
capture[position] = 0;

position++;
}
void adcInit(){
/* REFS0 : VCC use as a ref, IR_AUDIO : channel selection, ADEN : ADC Enable, ADSC : ADC Start, ADATE : ADC Auto Trigger Enable, ADIE : ADC Interrupt Enable, ADPS : ADC Prescaler */
// free running ADC mode, f = ( 16MHz / prescaler ) / 13 cycles per conversion
ADMUX = _BV(REFS0) | IR_AUDIO; // | _BV(ADLAR);
// ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1) //prescaler 64 : 19231 Hz – 300Hz per 64 divisions
ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // prescaler 128 : 9615 Hz – 150 Hz per 64 divisions, better for most music
sei();
}
void adcCalb(){
Serial.println(“Start to calc zero”);
long midl = 0;
// get 2 meashurment at 2 sec
// on ADC input must be NO SIGNAL!!!
for (byte i = 0; i < 2; i++)
{
position = 0;
delay(100);
midl += capture[0];
delay(900);
}
zero = -midl/2;
Serial.println(“Done.”);
}

int getNote(uint16_t thisInput[])
{
int index = 0;
uint16_t note = 0;

for(int i = 4; i < fftNum/2; i++)
{
if (thisInput[i] > note)
{
note = thisInput[i];
index = i;
}
}
return index;
}