Final Project: “SMART Pyramid” | Casey

IMG_9958

Project Name: SMART Pyramid — Wireless Integrated Domestic Switch;

Participants:  Casey Pan, Audrey Zheng;

Materials: Compressed wooden board, switch, hard-core wire, touch sensor, relay, LED light band,                     motor;

Tools: Arduino UNO, Xbee Module, Processing 3, XCTU;

Process:

Part Zero: Ideation

Our project was greatly inspired by Alberto Sartori’s project SMART CUBE, as explained in detail in my earlier essay About “Interaction” and Things Written Before Final Project

SMART CUBE pic2

Me and my partner things that even though this invention simplified the control over domestic devices, but since it included a phone app and other complex components, there’s still a rather high threshold on user body. So we decided to focus on this point, and create a even more user-friendly product, that could help a broader range of users facing severer limits.

Our story board:

StoryBook_01

StoryBook_02StoryBook_03

StoryBook_04

 

Part I: Major technical issue — Wireless Communication with Xbee module

Establishing wireless communication between Arduinos & between Arduino and computer has been our major technical issue. However, even though using Xbee modules can seem a little intimidating, but after this process, we found out that as soon as you understand the principle, everything becomes easier.

To establish the wireless communication, we need to use a software called XCTU to configure the Xbees first. Xbees can send signals (as commanded by the Arduino) and receive signals (then pass them on to Arduino) through serial. They can be understood as ports, and has their own address and signal destination address. Through XCTU, we set an address for each of them, and then set the address of the receiving Xbees as the destination address of the sending Xbee.

We referred to the instruction materials from the following link from Network Everything course:

Configure Xbees – Network Everything

Configuring Xbees with XCTU:

IMG_9472 IMG_9473

Established wireless communication between Arduinos:

  • In order to have one sending Xbee (Attached to the Arduino inside the Pyramid) and two receiving Xbees (one attached to the Arduinos on Demo House and one attached to the computer), we assigned the same address to the two receiving Xbees, so they will both be receiving signals from the sending Xbee.
  • However, this method has some short comes we haven’t yet been able to solve. Since the two receiving Xbees are seen as identical by the sending Arduino, they are receiving the same signals. But since they both only use part of the signals, the “extra” signals (targeted at the over receiving Xbee) can cause a delay.
  • This short come was even worse at an earlier stage of our project, where we used the same code for both receiving and sending Xbees, therefore all the Xbees are writing and reading and the same time. As a result, the delay was really severe:

 

The Arduino Code at Stage 1:

(Not efficient , don’ use. Final version is attached below)

int ledButtonPin = 5;
int ledPin = 12;

int motorButtonPin = 6;
int motorPin = 11;
int potPin = A0;

int ledButtonState;
int motorButtonState;
int potState;

int mappedPotState;
boolean lightSwitch;

//boolean buttonState;

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

 pinMode(ledButtonPin, INPUT);
 pinMode(ledPin, OUTPUT);

 pinMode(motorButtonPin, INPUT);
 pinMode(motorPin, OUTPUT);


 ledButtonState = 0;
 motorButtonState = 0;
 lightSwitch=false;

}

void loop() {
 ledButtonState = digitalRead(ledButtonPin);
 motorButtonState = digitalRead(motorButtonPin);
 potState = analogRead(potPin);

 //Writing Xbee
 if (ledButtonState == 1) {
 lightSwitch=!lightSwitch;
 }
 if (lightSwitch){
 Serial.write(1);
 } if(lightSwitch==false){
 Serial.write(0);
 }

 if (motorButtonState == 1) {
 Serial.write(2);
 } else {
 Serial.write(3);
 }

 potState = map(potState, 0, 1023, 4, 255);
 Serial.write(potState);

 //Reading Xbee

 if (Serial.read() == 1) {
 digitalWrite(ledPin, HIGH);
 } else if (Serial.read() == 0) {
 digitalWrite(ledPin, LOW);
 }

 if (Serial.read() == 2) {
 digitalWrite(motorPin, HIGH);
 } else if (Serial.read() == 3) {
 digitalWrite(motorPin, LOW);
 }

 if (Serial.read() > 3) {
 mappedPotState = map(Serial.read(), 4, 255, 0, 255);
 analogWrite(A2 , mappedPotState);
 }
}

 

Later on, we used different codes for sending and receiving Arduinos, and it got better.

I wrote the codes for:

Sending (Writing) Arduino code:

[gistid=”ddd9d58e878610fb106c9fb748988932″]

 

Receiving (Reading) Arduino code:

[“e91e7789f23ee1130ee3ddcbdf4df55d”]

(Codes Also shown later in Part IV, since I forgot how to use gist id exactly)

Outcomes of the codes:

(Another final demo is at the end of the post.)

Part II: Switches

We want the SMART Pyramid to be able to control different types of electronics, and given the fact that electronic vary in the type of switches they use, we decided to use as many types of switches as we can.

1. “Boat-Shaped” Switch

IMG_9586

The three iron feet of this switch are power input, power out put, and ground. Power input should be connected to the power source, power output should be connected to the power receiver (e.g. signal pin), and ground foot to ground.

*The three feet are really close to each other, so I figured it might be a good idea to wrap them up with unconductive materials.

*I also thought about using the type of switch for actual houses, which looked like the picture below, but fellows suggested that the rated voltage might be a problem for it to work, so we decided to stick to the switch we had for now. But later on, I found that it was also written on the small switch that the rated voltage is “250V”, so maybe the big switch could work as well.  This would be a question to figure out in the future.

IMG_9548

2. Touch sensor as a tap-switch

IMG_9551

 

We used the pre-condition mechanism to turn the touch sensor into a switch at first, but later used the boolean function.

*However, since the sensor is constantly sensing touches, sometimes if your finger is touching it for a longer time (e.g. one second), the light will keep blinking at a very high speed. This made me wonder whether using pre-condition method in coding would’ve been a better choice.

3. Potentiameter

We used a potentiameter to control the rate of a music piece played in processing.

IMG_9840

 

Part III: Circuits

IMG_9589

Key points in building the circuits for our project was to keep everything “concise” so that they can all fit in to the limited space inside the Pyramid. We joined all the power wires and ground wires in order to save space.

IMG_9724

Wrapping un-conductive material around soldered wires

Also, I found it really important to wrap un conductive materials around “naked” wires, for it not only stables the connection, but also prevents short circuits and signal intervention.

I didn’t realize the signal intervention part until it cause some problem while we’re presenting out project at the IMA final show. Two different signal wires touched each other at their unwrapped parts, and the signals messed up a little. So I think it would be a good idea to keep that in mind.

 

Part IV: Coding

1. Arduino

After Xbees are configured, they can be seen as ports to the Arduino, so we can use them to do serial communication.

As mentioned above, using identical codes for both reading and writing Arduinos and including everything in that code caused very bad delay, so I split the code into two codes, one for the writing Arduino and one for the reading Arduino.

//Code for Reading Xbee
//int ledButtonPin = 5;
int ledPin = 12;

//int motorButtonPin = 6;
int motorPin = 11;
//int potPin = A0;

//int ledButtonState;
//int motorButtonState;
//int potState;

//int mappedPotState;
boolean lightSwitch;

//boolean buttonState;

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

 //pinMode(ledButtonPin, INPUT);
 pinMode(ledPin, OUTPUT);

 //pinMode(motorButtonPin, INPUT);
 pinMode(motorPin, OUTPUT);


 //ledButtonState = 0;
 //motorButtonState = 0;
 lightSwitch=false;

}

void loop() {
 //ledButtonState = digitalRead(ledButtonPin);
 //motorButtonState = digitalRead(motorButtonPin);
 //potState = analogRead(potPin);

 //Writing Xbee
// if (ledButtonState == 1) {
// lightSwitch=!lightSwitch;
// }
// if (lightSwitch){
// Serial.write(1);
// } if(lightSwitch==false){
// Serial.write(0);
// }
//
// if (motorButtonState == 1) {
// Serial.write(2);
// } else {
// Serial.write(3);
// }
//
// potState = map(potState, 0, 1023, 4, 255);
// Serial.write(potState);

 //Reading Xbee

 if (Serial.read() == 1) {
 digitalWrite(ledPin, HIGH);
 } else if (Serial.read() == 0) {
 digitalWrite(ledPin, LOW);
 }

 if (Serial.read() == 2) {
 digitalWrite(motorPin, HIGH);
 } else if (Serial.read() == 3) {
 digitalWrite(motorPin, LOW);
 }

// if (Serial.read() > 3) {
// mappedPotState = map(Serial.read(), 4, 255, 0, 255);
// analogWrite(A2 , mappedPotState);
// }
 
}

//Code for Writing Xbee

int ledButtonPin = 5;
//int ledPin = 12;

int motorButtonPin = 6;
//int motorPin = 11;
int potPin = A0;

int ledButtonState;
int motorButtonState;
int potState;

int mappedPotState;
boolean lightSwitch;

//boolean buttonState;

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

 pinMode(ledButtonPin, INPUT);
 //pinMode(ledPin, OUTPUT);

 pinMode(motorButtonPin, INPUT);
 //pinMode(motorPin, OUTPUT);


 ledButtonState = 0;
 motorButtonState = 0;
 lightSwitch=false;

}

void loop() {
 ledButtonState = digitalRead(ledButtonPin);
 motorButtonState = digitalRead(motorButtonPin);
 potState = analogRead(potPin);

 //Writing Xbee
 if (ledButtonState == 1) {
 lightSwitch=!lightSwitch;
 }
 if (lightSwitch){
 Serial.write(1);
 } if(lightSwitch==false){
 Serial.write(0);
 }

 if (motorButtonState == 1) {
 Serial.write(2);
 } else {
 Serial.write(3);
 }

 potState = map(potState, 0, 1023, 4, 255);
 Serial.write(potState);


 

// //Reading Xbee
//
// if (Serial.read() == 1) {
// digitalWrite(ledPin, HIGH);
// } else if (Serial.read() == 0) {
// digitalWrite(ledPin, LOW);
// }
//
// if (Serial.read() == 2) {
// digitalWrite(motorPin, HIGH);
// } else if (Serial.read() == 3) {
// digitalWrite(motorPin, LOW);
// }
//
// if (Serial.read() > 3) {
// mappedPotState = map(Serial.read(), 4, 255, 0, 255);
// analogWrite(A2 , mappedPotState);
// }
}
2. Processing
//Processing: Music

import processing.serial.*;

Serial myPort;
int sensorValue;

import processing.sound.*;

SoundFile BGM;

int u;

void setup() {
 size(1440, 900);
 background(0);

 printArray(Serial.list());
 // this prints out the list of all available serial ports on your computer.
 
 myPort = new Serial(this, Serial.list()[ 1 ], 9600);

 BGM = new SoundFile(this, "AllWeKnow.mp3");
 BGM.play();
 
}


void draw() {
 // to read the value from the Arduino
 while ( myPort.available() > 0) {
 sensorValue = myPort.read();
 //println(frameCount + ": " + sensorValue);
 }
 // println(valueFromArduino);
 
 if (sensorValue >= 4 && sensorValue <= 125 ) {
 u = u+10;
 } else if (sensorValue >= 126 && sensorValue <= 255) {
 u = u-10;
 }
 //if (sensorValue >= 1023) {
 // v = v - 5;
 //} else if (sensorValue <= 0) {
 // v = v + 5;
 //}
 
 //BGM.amp(map(u, 0, height, 1.0, 0.0));
 //BGM.pan(map(u, 0, width, -1.0, 1.0));
 BGM.rate(map(u, 0, width, 0.5, 1.5));
 
 
 // add your code here
}

In the processing code, I made the rate of the music piece changed accordingly to signals sent by the potentiameter.  In the future, this input of potentiamenter can be used for different functions, for example, the volume of the music and others.

One thing to be noticed is that, since analog read from the potentiameter and serial write had different ranges, the values had to be mapped accordingly for multiple times.

I’m really proud of myself for the improvements I made in coding. I figured out the codes for this project with the help of IMA fellows. Jiwon wrote a sample code for me at first, later on I tried to write a code on my own to establish the same function, and surprisingly I got it mostly right. Yay~

Demo of the Pyramid – Processing communication:

Part V: Physical Model

1. the Pyramid

Building the physical model of the Pyramid was another part to highlight in our project, because it has brought us problems and reflections.

We planned to laser-cut wooden boards to build the Pyramid and put all the circuits inside.

Evan told us a really useful website called MakerCase, handy for case sketches.

The final illustrator sketch:

Illustrator Sketch

Some good things about the sketch:

  1.  I got a lot of practice and now have a better hang of illustrator. I understood and learned how to use a lot of its functions. I really liked the little graphics I drew.
  2.  I drew the 4 circles on the upper left side to stick together and make a handle for the potentiameter.
  3.  The three big pieces (for Demo House) fit together pretty well.

Some bad things about the sketch:

  1. The size of the Pyramid is a little too small, and we realized later that we could’t fit a battery box inside.

    * Should’ve done measurements and calculations more carefully. It’s essential for a remote control.

  2. We took the sides of a cube off and joined them as three triangles for the Pyramid. Though we made the sides match, but we underestimated the influence of the angles not being 90 degree. The sides couldn’t go together.

IMG_9568   IMG_9571

The problem showed in the prototype we made with card boards, but we thought it was mostly because of the thickness of the material, and only made the size bigger.

As a result, our model pieces couldn’t stay together well, because the tip of the Pyramid doesn’t fit.

To fix this, we first used a electrical saw to file off the edges of the triangle’s tips, so that they become thinner and can fit together.

But they still can’t fit well, so secondly we pressed them together and taped it in order to glue them together with hot glue.

IMG_9708

IMG_9709      IMG_9710

Looks like it survived a car crush.

It stayed together pretty well after we hot-glued it. But the base could fit because now it’s too big.

IMG_9717

I also made some micro adjustment to it so it would function better.

I gound the hole for the touch sensor tap button, so that it fits better for people’s finger tips and at the same time won’t show too much of the touch sensor.

IMG_9725    IMG_9727

2. the demo house

The function of the Demo House is to demonstrate how the smart Pyramid would work, by carrying different corresponding “reactors”.

We tried to use different kind of reactors, so we decided to put LED light, and motor on Demo House. (And music in Processing)

We bought a 5V LED light band and tiny furnitures on Taobao:

IMG_9538

My partner Audrey did most of the job in building up and decorating the Demo House:

IMG_9819 IMG_9835

Other Videos:

  1. Final Demo Video:

 

2. Me & my partner testing the distance limit for SMART Pyramid to work:

 

According to Google, Xbee modules seem to work at a fairly long distance.

WechatIMG206

However, this is only when the modules are straightly alined and has no barriers in between. It’s also shown in our experiment, since the SMART Pyramid worked event when we are standing apart across the room, but didn’t work anymore when there’s a glass wall or a wooden door in between.

3. User test

 

I’ve learned a lot in terms of practical skills as well as team-working and communication skills; It was a truly enjoyable to work on this project with my partner Audrey and with the help of all the IMA fellows. I had a lot of fun, and is grateful for everything in this project and this class.

Thanks everyone! ❤️

 

 

One thought on “Final Project: “SMART Pyramid” | Casey

  1. Hi Casey,

    I’m pretty happy you caught up with the class, since you started a little bit slow. It was great to see you improving so much and also enjoying it.
    I love the model you made and it was great you worked with Audrey for the final, I could see you worked hard.
    Thanks for exhibiting at the show, I hope you received a lot of feedback.
    Well done Casey!

Leave a Reply