Final Project
Final Project – Smart Dice
what does it do?
When rolled, the dice report their orientation and the value of the roll when determined.
who’s done what beforehand?
what did you design?
- Almost everything :)
- but seriously…
- Form
- Software
- Embedded Software
- Circuit Design
what materials and components were used?
where did they come from?
- Digikey – pins
- Sparkfun – accelerometer
- Adafruit – batteries
how much did they cost?
- RFduino $14
- Accelerometer $4
- Charging circuit
- Resistors
- Capacitors
- LEDs
what parts and systems were made?
- 3D printed case
- Custom PCBs
- Accelerometer
- Charging circuit
- Programming spring board
- iPhone app
- C-code for RFduino
- Mold for charging base
what processes were used?
- CAD – SolidWorks, Rhino, Illustrator, Eagle
- Software – Xcode, Arduino
- Fabrication – FormLabs, Makerbot, Epilog Laser Cutter, ShopBot
- Soldering – solder paste, incredibly still hands :)
what questions were answered?
- For me, this was very much an exercise in limits of size. While many of the components were small enough to fit in a package, ultimately some more system design for connections would have helped make everything fit and work together.
how was it evaluated?
- We are about to find out!
what are the implications?
- No more small stuff. Okay, I will still make small stuff, but with a little more planning.
C code for dice smoothing accelerometer data and calculating angle of rotation. Sending the calculated angle in a message for a connected BLE iPhone or Android device.
/*
This RFduino sketch demonstrates a Bluetooth Low Energy 4 connection
between an iPhone application and an RFduino.This sketch works with the the Dice++ iPhone application.
This sketch demonstrates publishing x, y, and z rotational values for
the dice, and the iPhone app will receive this information formatted in
a friendly constant length string to be parsed and inform the visualization.
*/#include
int x, y, z;
const int smoothVal = 30;
const int timeDelay = 10;const int timeDetermineRoll = 100; // 10th of a second
int xVals[smoothVal];
int yVals[smoothVal];
int zVals[smoothVal];int xSum, ySum, zSum;
int xAvg, yAvg, zAvg;
int prevX, prevY, prevZ;boolean newRoll = false;
String data;
double prevTime;
// Input pins for accelerometer data
const int xpin = 2; // x-axis of the accelerometer
const int ypin = 3; // y-axis
const int zpin = 4; // z-axis (only on 3-axis models)void setup() {
// this is the data we want to appear in the advertisement
// (if the deviceName and advertisementData are too long to fix into the 31 byte
// ble advertisement packet, then the advertisementData is truncated first down to
// a single byte, then it will truncate the deviceName)
RFduinoBLE.advertisementData = “dice++”;// start the BLE stack
RFduinoBLE.begin();Serial.begin(9600);
}void loop() {
x = getDegreeValueFrom8bitValue(analogRead(xpin));
y = getDegreeValueFrom8bitValue(analogRead(ypin));
z = getDegreeValueFrom8bitValue(analogRead(zpin));
// X
calculateXAvg();// Y
calculateYAvg();// Z
calculateZAvg();// TODO:
// Check values vs. previous values
// if changed values, then set to rolling
// if values stay constant for longer than the time to determine rool
// send a message that the value is determined, and set roll to true// Publish information over BLE after each specified amount of time
//wait .01 seconds (publishing ~100 messages per second!!)
if( millis() > prevTime + timeDelay) {prevTime = millis();
data = getStringWithXYZ(xAvg,yAvg,zAvg);
char charBuf[data.length()];
data.toCharArray(charBuf, data.length());int length = strlen(charBuf);
if( length <= 20){ RFduinoBLE.send(charBuf,length); }else{ RFduinoBLE.send(charBuf,20); // BLE packet is 20 bytes max. } Serial.println(charBuf); } } // void calculateXAvg() { // shift x values back in array for(int i=smoothVal-1; i>0; i–){
xVals[i] = xVals[i-1];
}
xVals[0] = x;// sum x values
xSum = 0;
for(int i=0; i<smoothVal; i++){ xSum += xVals[i]; } // calculate avg x xAvg = int(xSum / smoothVal); } // void calculateYAvg() { // shift y values back in array for(int i=smoothVal-1; i>0; i–){
yVals[i] = yVals[i-1];
}
yVals[0] = y;// sum y values
ySum = 0;
for(int i=0; i<smoothVal; i++){ ySum += yVals[i]; } // calculate avg y yAvg = int(ySum / smoothVal); } // void calculateZAvg() { // shift z values back in array for(int i=smoothVal-1; i>0; i–){
zVals[i] = zVals[i-1];
}
zVals[0] = z;// sum z values
zSum = 0;
for(int i=0; i<smoothVal; i++){
zSum += zVals[i];
}// calculate avg z
zAvg =int(zSum / smoothVal);
}// return a value between 0 and 180 from voltage levels
int getDegreeValueFrom8bitValue(int val)
{
int degree;degree = int(90 * (val – 520) / 50.0); // approx 512
// clamp value between -90 and 90
if(degree < -90) degree = -90; else if(degree > 90)
degree = 90;degree += 90; // put in the range of 0-180 :)
return degree;
}// create a string from int values for rotation
String getStringWithXYZ(int x, int y, int z)
{
String str;str = “x”;
str+=getThreeDigitString(x);
str+=”y”;
str+=getThreeDigitString(y);
str+=”z”;
str+= getThreeDigitString(z);
str+=”/”; // this last character gets lost in transmissionreturn str;
}// create a string from an integer to take up 3 characters of space
// this is inefficient, but keeps formatting nice
String getThreeDigitString(int val) {String str;
if(val < 10) {
str = “00”;
str += val;
}
else if(val < 100) {
str = “0”;
str += val;
}
else {
str = “”; // needs to add the integer like so, otherwise it complains about the type
str += val;
}return str;
}void RFduinoBLE_onDisconnect()
{
}