-
Notifications
You must be signed in to change notification settings - Fork 0
/
curious_cube.ino
130 lines (111 loc) · 4.19 KB
/
curious_cube.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <CapacitiveSensor.h>
// A curious cube that acts like a cat
// its default state is asleep
// when it detects a person approaching, it lights up in recognition
// and enters either PEACE or SENSITIVE mode
// if person pets cube in PEACE mode, it can enter either HAPPY or ANGRY mode
// if person pets cube in SENSITIVE mode, it will 100% enter ANGRY mode
// from ANGRY mode, it can either stay in ANGRY mode or go back to SENSITIVE mode
// from SENSITIVE mode it can either stay in SENSITIVE mode or go to PEACE mode
#define PEACE 0
#define SENSITIVE 1
#define HAPPY 2
#define ANGRY 3
#define ASLEEP 4
#define distancePin 2 // currently a button, replace with actual sensor later
#define awakeTime 60000 // milliseconds cube will stay awake
#define evaluateTime 5000 // evaluate next state every N seconds
CapacitiveSensor capSensor = CapacitiveSensor(4,6); // 10M resistor between pins 4 & 6, pin 6 is sensor pin
long capSensorThreshold = 10000; // if capacitive sensor reading is over threshold, then cube is touched
// when user is not interacting with cube
// then state will be revaluated every N seconds
int possibleNextStates[5][3] = {
{PEACE, SENSITIVE, 80}, // from PEACE, probability of staying PEACE is 80%
{SENSITIVE, PEACE, 80}, // from SENSITIVE
{HAPPY, PEACE, 60}, // from HAPPY
{ANGRY, SENSITIVE, 60}, // from ANGRY
{PEACE, SENSITIVE, 60} // from ASLEEP
};
// when user touches the cube, reevaluate state
int touchNextStates[5][3] = {
{HAPPY, ANGRY, 90}, // from PEACE
{ANGRY, ANGRY, 100}, // from SENSITIVE
{HAPPY, HAPPY, 100}, // from HAPPY
{ANGRY, ANGRY, 100}, // from ANGRY
{ANGRY, ANGRY, 100} // from ASLEEP
};
int currentState = ASLEEP;
int lastWakeupTime = -1;
int lastEvaluateTime = -1;
void setup() {
Serial.begin(9600);
// temporary for button, will be replaced with sensor later
pinMode(distancePin, INPUT_PULLUP);
// make sure random() is truly random
randomSeed(analogRead(0));
}
void loop() {
// get distance sensor reading (temp button)
int distanceReading = digitalRead(distancePin);
long touchReading = capSensor.capacitiveSensor(30);
int seePerson = distanceReading == LOW;
int touchCube = touchReading > capSensorThreshold;
int currentTime = millis();
// if we have positive reading on distance sensor
// update lastWakeupTime to current time so we can reset countdown for cube sleeping
if (seePerson) {
lastWakeupTime = currentTime;
}
if (touchCube) {
// if cube is touched, determine next state based on
// probabilities outlined in touchNextStates
determineNextState(touchNextStates);
// since we've evaluated state, also update lastEvaluateTime to now
lastEvaluateTime = currentTime;
// also reset wakeup time since we've touched it
lastWakeupTime = currentTime;
} else {
// if cube is not touched
// case when cube is asleep
if (currentState == ASLEEP) {
// cube sees person so it wakes up
if (seePerson) {
// TODO: first light up cube for 1 second
// determine next state
determineNextState(possibleNextStates);
}
} else {
// cube is awake
// check if it should go to sleep
// if current time is more than lastWakeupTime + awakeTime
if (currentTime > (lastWakeupTime + awakeTime)) {
currentState = ASLEEP;
Serial.println("went to sleep!");
} else {
// if it doesn't need to go to sleep yet
// evaluate what next state should be every N seconds
if (currentTime > (lastEvaluateTime + evaluateTime)) {
determineNextState(possibleNextStates);
lastEvaluateTime = currentTime;
}
}
}
}
}
void determineNextState(int nextStates[5][3]) {
int randomNum = random(100);
// get probability of current state going to the first option of next state
int probability = nextStates[currentState][2];
Serial.print("current state: ");
Serial.print(currentState);
Serial.print(", random number: ");
Serial.print(randomNum);
// update current state
if (randomNum < probability) {
currentState = nextStates[currentState][0];
} else {
currentState = nextStates[currentState][1];
}
Serial.print(", next state: ");
Serial.println(currentState);
}