#include <Wire.h>
#define TONE_USE_INT
#define TONE_PITCH 440
#include <TonePitch.h>
#define spkOne 12
const int playbackSpeed = 2;
//the i2c address of your Arduino
#define SLAVE_ADDRESS 0x03 // change this to 0x01, 0x02, 0x03, 0x04 or 0x05, depending on the values chosen by your teammates
//used for communicating the emotion values
#define NUM_VALUES 5 // number of values to send
int state_machine_values[NUM_VALUES]; // array to store the received emotion values
//These are the values you can change by giving them te value -1, 1, or 0 (no change)
byte change_in_happy = 0; //the statemachine value for happy ranges from 0 (sad) to 1000 (happy)
byte change_in_energy = 0; //the statemachine value for energy ranges from 0 (lethargic) to 1000 (energetic)
byte change_in_friendly = 0; //the statemachine value for friendly ranges from 0 (hostile) to 1000 (friendly)
byte change_in_assertive = 0; //the statemachine value for assertive ranges from 0 (shy) to 1000 (assertive)
byte change_in_delight = 0; //the statemachine value for delight ranges from 0 (disgust) to 1000 (delight)
int emotions[10];
void setup()
{
//needed for i2c communication between state machine and your arduino
Wire.begin(SLAVE_ADDRESS); // join the I2C bus as a slave
Wire.onRequest(requestEvent); // register the request event handler
Wire.onReceive(receiveEvent); // register event to handle incoming data
//used for showing data in the serial monitor
Serial.begin(9600); // start serial communication
pinMode(spkOne, OUTPUT);
}
void loop()
{
doSomething(); //example function
mainFeeling();
printStateMachineValues();
//printStateMachineValues(); //show the values that the state machine communicated
delay(50); // an arbitrary delay, can be changed to whatever you need
}
void calculateEmotion(int currentStateMachineIndex)
{
if (state_machine_values[currentStateMachineIndex] < 500)
{
emotions[currentStateMachineIndex] = abs(state_machine_values[currentStateMachineIndex] - 500);
emotions[currentStateMachineIndex + 1] = 0;
return;
}
emotions[currentStateMachineIndex] = 0;
emotions[currentStateMachineIndex + 1] = state_machine_values[currentStateMachineIndex] - 500;
}
void mainFeeling()
{
int maxEmotionValue = emotions[0]; // Initialize with the first emotion value
int maxEmotionIndex = 0; // Initialize index for the emotion with the highest value
for (int i = 0; i < sizeof(state_machine_values) / sizeof(state_machine_values[0]); i++)
{
calculateEmotion(i);
}
// Find the index of the emotion with the highest value
for (int i = 1; i < 10; i++) {
if (emotions[i] > maxEmotionValue) {
maxEmotionValue = emotions[i];
maxEmotionIndex = i;
}
}
maxEmotionValue = emotions[0]; // Initialize with the first emotion value
maxEmotionIndex = 0; // Initialize index for the emotion with the highest value
// Find the index of the emotion with the highest value
for (int i = 1; i < 10; i++)
{
if (emotions[i] > maxEmotionValue)
{
maxEmotionValue = emotions[i];
maxEmotionIndex = i;
}
}
// Output the predominant emotion based on the index
switch (maxEmotionIndex)
{
case 0:
Serial.println("Mainly sad: ");
Serial.print(emotions[maxEmotionIndex]);
sadSound();
break;
case 1:
Serial.println("Happy");
happySound();
break;
case 2:
Serial.println("Lethargic");
lethargicSound();
break;
case 3:
Serial.println("Energetic");
energeticSound();
break;
case 4:
Serial.println("Hostile");
hostileSound();
break;
case 5:
Serial.println("Friendly");
friendlySound();
break;
case 6:
Serial.println("Shy");
shySound();
break;
case 7:
Serial.println("Assertive");
assertiveSound();
break;
case 8:
Serial.println("Disgusted");
disgustedSound();
break;
case 9:
Serial.println("Delighted");
delightedSound();
break;
}
}
void sadSound()
{
Serial.println("Playing Sad Sound - Sad Violin");
tone(spkOne, NOTE_E6, 290); //high
delay(300*playbackSpeed);
tone(spkOne, NOTE_D6, 0); //high
delay(150*playbackSpeed);
tone(spkOne, NOTE_E6, 140); //high
delay(150*playbackSpeed);
tone(spkOne, NOTE_C6, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_D6, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_C6, 140); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_B5, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_C6, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_B5, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_A5, 300); //high
delay(300*playbackSpeed);
delay(2000);
}
void happySound()
{
Serial.println("Playing Happy Sound");
}
void lethargicSound()
{
tone(spkOne, NOTE_C4, 500); //do
delay(300*playbackSpeed);
tone(spkOne, NOTE_B3, 500); //do
delay(300*playbackSpeed);
tone(spkOne, NOTE_AS3, 500); //do
delay(300*playbackSpeed);
tone(spkOne, NOTE_A3, 500); //do
delay(300*playbackSpeed);
tone(spkOne, NOTE_GS3, 2000); //do
delay(300*playbackSpeed);
delay(2000);
}
void energeticSound()
{
Serial.println("Playing Energetic Sound - Do a Deer");
tone(spkOne, NOTE_C4, 500); //do
delay(300*playbackSpeed);
tone(spkOne, NOTE_D4, 500); //a
delay(100*playbackSpeed);
tone(spkOne, NOTE_E4, 500); //deer
delay(300*playbackSpeed);
tone(spkOne, NOTE_C4, 500); //a
delay(100*playbackSpeed);
tone(spkOne, NOTE_E4, 500); //fe-
delay(200*playbackSpeed);
tone(spkOne, NOTE_C4, 500); //-male
delay(200*playbackSpeed);
tone(spkOne, NOTE_E4, 500); //deer
delay(400*playbackSpeed);
tone(spkOne, NOTE_D4, 500); //ray
delay(300*playbackSpeed);
tone(spkOne, NOTE_E4, 500); //a
delay(100*playbackSpeed);
tone(spkOne, NOTE_F4, 50); //drop
delay(100*playbackSpeed);
tone(spkOne, NOTE_F4, 50); //of
delay(100*playbackSpeed);
tone(spkOne, NOTE_E4, 500); //gold-
delay(100*playbackSpeed);
tone(spkOne, NOTE_D4, 500); //-en
delay(100*playbackSpeed);
tone(spkOne, NOTE_F4, 500); //sun
delay(400*playbackSpeed);
}
void hostileSound()
{
tone(spkOne, NOTE_F4, 50); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_FS4, 50); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_E5, 50); //high
delay(150*playbackSpeed);
tone(spkOne, NOTE_F4, 50); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_FS4, 50); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_E5, 59); //high
delay(150*playbackSpeed);
tone(spkOne, NOTE_F4, 0); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_FS4, 0); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_F4, 0); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_FS4, 0); //high
delay(75*playbackSpeed);
tone(spkOne, NOTE_F4, 0); //high
delay(150*playbackSpeed);
}
void friendlySound()
{
}
void shySound()
{
tone(spkOne, NOTE_E7, 50); //high
delay(150*playbackSpeed);
tone(spkOne, NOTE_C7, 50); //high
delay(150*playbackSpeed);
tone(spkOne, NOTE_D7, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_CS7, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_C7, 0); //high
delay(50*playbackSpeed);
tone(spkOne, NOTE_B6, 0); //high
delay(150*playbackSpeed);
}
void assertiveSound()
{
}
void disgustedSound()
{
}
void delightedSound()
{
}
//Yes, this is written inefficient, but very easy to understand ;)
//It sets each of the 5 values for changing the emotions by randomly assigning a 0, 1 or -1 to each
void doSomething()
{
//just as an example sending random 0, -1 or +1 for each of the 5 emotions
Serial.print("Changing values: ");
//for happy
int rnd = random(-100, 100);
if(rnd < -75) { change_in_happy = -1; Serial.print("-1 "); }
else if(rnd > 75) { change_in_happy = 1; Serial.print("1 "); }
else { change_in_happy = 0; Serial.print("0 "); }
//for energy
rnd = random(-100, 100);
if(rnd < -75) { change_in_energy = -1; Serial.print("-1 "); }
else if(rnd > 75) { change_in_energy = 1; Serial.print("1 "); }
else { change_in_energy = 0; Serial.print("0 "); }
//for friendly
rnd = random(-100, 100);
if(rnd < -75) { change_in_friendly = -1; Serial.print("-1 "); }
else if(rnd > 75) { change_in_friendly = 1; Serial.print("1 "); }
else { change_in_friendly = 0; Serial.print("0 "); }
//for assertive
rnd = random(-100, 100);
if(rnd < -75) { change_in_assertive = -1; Serial.print("-1 "); }
else if(rnd > 75) { change_in_assertive = 1; Serial.print("1 "); }
else { change_in_assertive = 0; Serial.print("0 "); }
//for delight
rnd = random(-100, 100);
if(rnd < -75) { change_in_delight = -1; Serial.print("-1 "); }
else if(rnd > 75) { change_in_delight = 1; Serial.print("1 "); }
else { change_in_delight = 0; Serial.print("0 "); }
Serial.println(); // print a new line
}
//example how to print the values from the state machine
void printStateMachineValues()
{
Serial.print("State Machine Values: ");
for (int i = 0; i < NUM_VALUES; i++)
{
Serial.print(state_machine_values[i]);
Serial.print(" ");
}
Serial.println();
}
//###############
//below functions are for sending and receiving data to the state machine, they should not be changed
//###############
//The response for the request made by the statemachine to receive change values
void requestEvent()
{
byte change[NUM_VALUES] = { change_in_happy, change_in_energy, change_in_friendly, change_in_assertive, change_in_delight }; // array to store the change of each emotion
Wire.write(change, NUM_VALUES); // send the bytes to the master
}
// function that executes whenever data is received from the state machine
void receiveEvent(int howMany)
{
// check if the number of bytes received matches the expected number
if (howMany == NUM_VALUES * 2)
{
// read the bytes and store them in the values array
for (int i = 0; i < NUM_VALUES; ++i)
{
byte x1, x2;
x1 = Wire.read(); //x1 holds upper byte of received numPWMChannels
x2 = Wire.read(); //x2 holds lower byte of received numPWMChannels
state_machine_values[i] = (int)x1 << 8 | (int)x2;
}
}
}