Homework - W.A. Wichers
Yukako Shimada
Moderator
edited April 2015 in Animatronic Control Systems - Arduino Programming Basics with David Covarrubias
Ok, so at first I was thinking about building a gun with a nozzle that opens before it shoots some sort of laser. Whilst looking for a solution for opening the nozzle, I found these really cool iris diaphragms. Then I got the idea to use two of them as "eyelids" and put some kind of controllable LED behind them.
This reminded me of Bubo, the mechanical owl from "Clash of the Titans" So a new idea was born: build an owl with servo-controlled iris diaphragms for eyelids and glowing eyes.
Whilst rummaging through the stuff I still had lying around, I found a slip ring. It has six wires going through it and I thought it would be cool if the owl's head could spin limitlessly. I still had a steppermotor and driver, so I'm thinking about using that for spinning the head. I'll have to see how I'm going to attach the motor to the head. Maybe I can print a ring gear and pinion, otherwise I'll have to see if I can find a pre-made one (they're expensive though, so rather not)
For the LED's, I ordered a pair of neopixel-jewels (they're almost the same size as the opening in the diaphragms)
I have some extra servo's, so if there's enough space in the head, I could try to animate the beak also.
As I'm not sure if the slip ring will allow me to use it for serial communication, I've got a pair of XBees for backup.
I also found a text-to speach module that I'd like to incorporate, which should give it a nice mechanical, "robot-like" voice.
Finally, I found some joysticks, which I could use for controlling the figure.
So it looks like I have most of the stuff I need (I ordered the diaphragms immediately when I found them and they came in yesterday, the LED's should come in hopefully tomorrow) The only thing missing is the owl figure itself.
I actually found a Bubo-prop, but if I'm not mistaken, it's made out of foam-latex, so I'm not going to be able to use it as-is.
I ordered it anyway, because I'd like to try and 3D scan it, so I can make a 3D print. The nice thing about that would be that I'll be able to match the size of the eyes exactly to the size of the diaphragms. The only thing is, that my 3D printer is down at the moment. So I'm hoping to get it fixed in the next couple of days.
Other stuff like breadboards, hook-up wire, prototype boards, buttons etc. I should have plenty of. For now, I'm just going to use a bench power supply for power and a set of computer speakers for sound. Maybe later on, I'll exchange those with a battery and an internal speaker and amplifier.
So that's the basic idea. I hope to be able to actually build it (no idea how much time we'll be allowed to put it all together). Otherwise, getting the electronics to work will be a nice challenge by itself.
This reminded me of Bubo, the mechanical owl from "Clash of the Titans" So a new idea was born: build an owl with servo-controlled iris diaphragms for eyelids and glowing eyes.
Whilst rummaging through the stuff I still had lying around, I found a slip ring. It has six wires going through it and I thought it would be cool if the owl's head could spin limitlessly. I still had a steppermotor and driver, so I'm thinking about using that for spinning the head. I'll have to see how I'm going to attach the motor to the head. Maybe I can print a ring gear and pinion, otherwise I'll have to see if I can find a pre-made one (they're expensive though, so rather not)
For the LED's, I ordered a pair of neopixel-jewels (they're almost the same size as the opening in the diaphragms)
I have some extra servo's, so if there's enough space in the head, I could try to animate the beak also.
As I'm not sure if the slip ring will allow me to use it for serial communication, I've got a pair of XBees for backup.
I also found a text-to speach module that I'd like to incorporate, which should give it a nice mechanical, "robot-like" voice.
Finally, I found some joysticks, which I could use for controlling the figure.
So it looks like I have most of the stuff I need (I ordered the diaphragms immediately when I found them and they came in yesterday, the LED's should come in hopefully tomorrow) The only thing missing is the owl figure itself.
I actually found a Bubo-prop, but if I'm not mistaken, it's made out of foam-latex, so I'm not going to be able to use it as-is.
I ordered it anyway, because I'd like to try and 3D scan it, so I can make a 3D print. The nice thing about that would be that I'll be able to match the size of the eyes exactly to the size of the diaphragms. The only thing is, that my 3D printer is down at the moment. So I'm hoping to get it fixed in the next couple of days.
Other stuff like breadboards, hook-up wire, prototype boards, buttons etc. I should have plenty of. For now, I'm just going to use a bench power supply for power and a set of computer speakers for sound. Maybe later on, I'll exchange those with a battery and an internal speaker and amplifier.
So that's the basic idea. I hope to be able to actually build it (no idea how much time we'll be allowed to put it all together). Otherwise, getting the electronics to work will be a nice challenge by itself.
This image has been resized to fit in the page. Click to enlarge.
1
Comments
// for servos
#include <Adafruit_TiCoServo.h>
#include <known_16bit_timers.h>
Adafruit_TiCoServo servo1;
Adafruit_TiCoServo servo2;
int potpin1 = A0;
int potpin2 = A1;
int newval1, oldval1;
int newval2, oldval2;
//for Neopixels
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#define PIN1 6
#define PIN2 7
#define NUMPIXELS 7
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
int delayval = 0;
// for Emic2
#include <SoftwareSerial.h>
#define rxPin 11 // connects to Emic 2's SOUT pin
#define txPin 12 // connects to Emic 2's SIN pin
#define ledPin 13
#define buttonPin1 2
#define buttonPin2 3
SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin);
void setup()
{
Serial.begin(9600);
// for servos
servo1.attach(9);
servo2.attach(10);
// for Neopixels
pixels1.begin();
pixels2.begin();
// for Emic2
pinMode(ledPin, OUTPUT);
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
emicSerial.begin(9600);
digitalWrite(ledPin, LOW);
emicSerial.print('\n');
while (emicSerial.read() != ':');
delay(10);
emicSerial.flush();
}
void loop()
{
moveServos();
lightPixels();
playAudio();
}
void moveServos() {
newval1 = analogRead(potpin1);
newval1 = map(newval1, 506, 1023, 10, 169);
if (newval1 < (oldval1-1) || newval1 > (oldval1+1)){
servo1.write(newval1);
Serial.print("Servo 1 ");
Serial.println(newval1);
oldval1=newval1;
}
newval2 = analogRead(potpin2);
newval2 = map(newval2, 506, 1023, 10, 169);
if (newval2 < (oldval2-1) || newval2 > (oldval2+1)){
servo2.write(newval2);
Serial.print("Servo 2 ");
Serial.println(newval2);
oldval2=newval2;
}
delay(25);
}
void lightPixels() {
int lightInput1 = analogRead(potpin1);
int lightInputA = map(lightInput1, 506, 1023, 0, 150);
lightInputA = constrain(lightInputA, 0, 150);
int lightInputB = map(lightInput1, 606, 1023, 0, 10);
lightInputB = constrain(lightInputB, 0, 10);
pixels1.setPixelColor(0, pixels1.Color(lightInputA,0,0));
for(int i=1; i<NUMPIXELS; i++){
pixels1.setPixelColor(i, pixels1.Color(lightInputB,0,0));
}
int lightInput2 = analogRead(potpin2);
int lightInputC = map(lightInput2, 506, 1023, 0, 150);
lightInputC = constrain(lightInputC, 0, 150);
int lightInputD = map(lightInput2, 606, 1023, 0, 10);
lightInputD = constrain(lightInputD, 0, 10);lightInputB = constrain(lightInputB, 0, 10);
pixels2.setPixelColor(0, pixels2.Color(lightInputC,0,0));
for(int i=1; i<NUMPIXELS; i++){
pixels2.setPixelColor(i, pixels2.Color(lightInputD,0,0));
}
pixels1.show();
pixels2.show();
delay(delayval);
}
void playAudio() {
int joystickButton1 = digitalRead(buttonPin1);
if(joystickButton1 == 0) {
Serial.println("Button 1 pressed");
emicSerial.print('S');
emicSerial.print("Hello. My name is Bubo. I'm the owl from the movie clash of the tytans.");
emicSerial.print('\n');
digitalWrite(ledPin, HIGH);
while (emicSerial.read() != ':');
digitalWrite(ledPin, LOW);
}
int joystickButton2 = digitalRead(buttonPin2);
if(joystickButton2 == 0) {
Serial.println("Button 2 pressed");
emicSerial.print("D1\n");
digitalWrite(ledPin, HIGH);
while (emicSerial.read() != ':');
digitalWrite(ledPin, LOW);
}
}
https://www.youtube.com/watch?v=_54eOVEidnw
The servo and neopixel functions are still creating some lag. I had to set the steppermotor to full steps to get it up to speed.
Also, I havent't gotten the audio fragments to trigger randomly.
I'd like to get all the functions working randomly and be able to have them overruled by live input, but that will probably have to wait.
Mechanically, I have to do some adaptations to the gears I bought and I'll have to make some rollers, as the ones I printed didn't come out very nicely. I'll also have to come up with a way to connect the servo's to the diaphragms.
So, we're getting there, but still enough to do.
https://www.youtube.com/watch?v=QtfO__N774E
// for servos
#include <Adafruit_TiCoServo.h> //special library that lets servo's work together with neopixels
#include <known_16bit_timers.h>
Adafruit_TiCoServo servo1; //servo 1
Adafruit_TiCoServo servo2; //servo 2
int potpin1 = A0; //potentiometer for servo 1 position
int potpin2 = A1; //potentiometer for servo 2 position
int newval1; //for storing new value potentiometer 1 / servo 1
int oldval1; //for storing current value potentiometer 1 / servo 1
int newval2; //for storing new value potentiometer 2 / servo 2
int oldval2; //for storing current value potentiometer 2 / servo 2
//for Neopixels
#include <Adafruit_NeoPixel.h> //library for controlling neopixels
#include <avr/power.h>
#define PIN1 6 //pin attached to neopixel jewel 1
#define PIN2 7 //pin attached to neopixel jewel 2
#define NUMPIXELS 7 //number of pixels in each neopixel jewel
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
// for Emic2
#define audioEffectPin1 11 //this pin sends the signal to the second arduino to play a sentence or song
#define buttonPin1 2 //when button is pushed, a sentence or song plays
// for steppermotor
#define stepPin 3 //step pin
#define dirPin 4 //direction pin
#define clockwiseButtonPin A2 //when button is pushed, motor turns clockwise
#define counterClockwiseButtonPin A3 //when button is pushed, motor turns counterclockwise
int stepperSpeed = 100; //delay between step pulses. Higher number means motor spins faster
void setup()
{
// for servos
servo1.attach(9); //servo 1 attaches to pin 9
servo2.attach(10); //servo 2 attaches to pin 10
// for Neopixels
pixels1.begin(); //initiate neopixel jewel 1
pixels2.begin(); //initiate neopixel jewel 2
// for Emic2
pinMode(buttonPin1, INPUT);
digitalWrite(buttonPin1, HIGH);
pinMode(audioEffectPin1, OUTPUT);
// for steppermotor
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(clockwiseButtonPin, INPUT);
pinMode(counterClockwiseButtonPin, INPUT);
digitalWrite(stepPin, LOW);
digitalWrite(dirPin, LOW);
digitalWrite(counterClockwiseButtonPin, HIGH);
digitalWrite(clockwiseButtonPin, HIGH);
}
void loop()
{
moveServos();
lightPixels();
playAudio();
moveStepper();
}
void moveServos() {
//reads the value of a potentiometer and adjusts the position of a servo accordingly
newval1 = analogRead(potpin1); //reads the value of potentiometer 1
newval1 = map(newval1, 0, 1023, 600, 2000); //maps the value of potentiometer 1 to microseconds
if (newval1 < (oldval1 - 5) || newval1 > (oldval1 + 5)) { //prevents jitter. if the change in value is too small, it is ignored
servo1.write(newval1); //sends the new value to servo 1
oldval1 = newval1; //updates the current position of the servo
}
//same as above, but for servo 2
newval2 = analogRead(potpin2);
newval2 = map(newval2, 0, 1023, 600, 2000);
if (newval2 < (oldval2 - 5) || newval2 > (oldval2 + 5)) {
servo2.write(newval2);
oldval2 = newval2;
}
//delay(5);
}
void lightPixels() {
//reads the value of a potentiometer and adjusts the brightness of an led accordingly
//written for neopixel jewel, which consits of a ring of 6 led's, with one led in the center.
//when the value of the potentiometer increases, first the center pixel lights up, then the other 6 follow.
int lightInput1 = analogRead(potpin1); //reads the value of potentiometer 1
int lightInputA = map(lightInput1, 0, 1023, 0, 150); //maps value to brightness for pixel 0
lightInputA = constrain(lightInputA, 0, 150); //makes sure the value can never be lower or higher than the desired values
int lightInputB = map(lightInput1, 250, 1023, 0, 25); //maps value to brightness for pixels 1-6
lightInputB = constrain(lightInputB, 0, 25); //makes sure the value can never be lower or higher than the desired values
pixels1.setPixelColor(0, pixels1.Color(lightInputA, 0, 0)); //sets colour and brightness for pixel 0
for (int i = 1; i < NUMPIXELS; i++) {
pixels1.setPixelColor(i, pixels1.Color(lightInputB, 0, 0)); //sets colour and brightness for pixels 1-6
}
//same as above, but for neopixel 2
int lightInput2 = analogRead(potpin2);
int lightInputC = map(lightInput2, 0, 1023, 0, 150);
lightInputC = constrain(lightInputC, 0, 150);
int lightInputD = map(lightInput2, 250, 1023, 0, 25);
lightInputD = constrain(lightInputD, 0, 25);
pixels2.setPixelColor(0, pixels2.Color(lightInputC, 0, 0));
for (int i = 1; i < NUMPIXELS; i++) {
pixels2.setPixelColor(i, pixels2.Color(lightInputD, 0, 0));
}
pixels1.show();
pixels2.show();
}
void playAudio() {
//reads the value of a button.
//if the button is pressed, pin 11 is set high. This pin is connected to another arduino, that plays a entence or song if it detects that the pin is high
int audioButton1 = digitalRead(buttonPin1);
if (audioButton1 == 0) {
digitalWrite(audioEffectPin1, HIGH);
delay(500); //delay, so the other arduino notices the state change, even if it's busy when the signal is given (has to be changed to work with millis)
digitalWrite(audioEffectPin1, LOW);
}
}
void moveStepper() {
//spins a steppermotor when a button is pressed. One button makes it spin clockwise, the other one makes it spin countercokwise
int leftButton = digitalRead(clockwiseButtonPin); //reads the state of the button for clockwise rotation
int rightButton = digitalRead(counterClockwiseButtonPin); //reads the state of the button for counterclockwise rotation
if (leftButton == 0 && rightButton == 1) { //if the button for clockwise rotation is pressed and the button for counterclockwise rotation isn't...
digitalWrite(dirPin, LOW); //set the direction pin to low (= spin clockwise)
digitalWrite(stepPin, HIGH); //enable motor (= spin motor)
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
digitalWrite(stepPin, LOW); //disable motor
delayMicroseconds(stepperSpeed); ////pause for the set time (should be changed to work with millis) longer pause = motor spins slower
}
//same as above, but for counterclockwise rotation
else if (leftButton == 1 && rightButton == 0) {
digitalWrite(dirPin, HIGH);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepperSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepperSpeed);
}
}
#include <TrueRandom.h>
// for timer
#include <Event.h> //library for handling millis
#include <Timer.h>
int period1 = 10000;
Timer speakText;
// for Emic2
#include <SoftwareSerial.h> //library that makes a second port available for serial communication with the EMIC2
#include <SD.h> // Needed by the EMIC2 library, though not utilized in this example
#include <EMIC2.h> //library for the Emic2
#define rxPin 11 // connects to Emic 2's SOUT pin
#define txPin 12 // connects to Emic 2's SIN pin
#define buttonPin1 3 //pin attached to second arduino. when pin is set high by other arduina, a sound is played
SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin);
EMIC2 emic; // Creates an instance of the EMIC2 library
//SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
String sentence[]={"__ My name is Bubo", "I'm the owl from the movie __clash of the __tytans", "My creator is called Cyril", "__Cyril taught __ me how to speak", "__Daivid taught __Cyril how to program", "__Matt likes to tease Daivid"}; //possible sentences that can be spoken
String nextSentence; //holds the next sentence to be played
int totalSentences = 6; //total number of sentences available
void setup()
{
// for timer
speakText.every(period1, playRandomAudio); //initiates the function playRandomAudio every 10 seconds (=period1)
// for Emic2
emicSerial.begin(9600);
emic.begin(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
emic.setVolume(10); //sets the desired volume
pinMode(buttonPin1, INPUT);
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
}
void loop()
{
speakText.update(); //checks if it's time to run the playRandomAudio function
playAudio(); //runs the playAudio function
}
void playRandomAudio() {
nextSentence=sentence[TrueRandom.random(totalSentences)]; //selects a random sentence out of the total available sentences
emic.setVoice(1); //sets a voice (9 choices: 0 - 8)
emic.speak(nextSentence); //play the random selected sentence
}
void playAudio() {
int trackButton1 = digitalRead(buttonPin1); //read the state of the pushbutton connected to pin 3
if(trackButton1 == 1) { //if the button is pushed
emicSerial.print("D1\n"); //play the preconfigured example
}
}
The code is working, but I'd still like to build some more randomness into it. That will probably have to wait untill monday.
Code1:
// for servos
#include <Adafruit_TiCoServo.h> //special library that lets servo's work together with neopixels
#include <known_16bit_timers.h>
Adafruit_TiCoServo servo1; //servo 1
Adafruit_TiCoServo servo2; //servo 2
int potpin1 = A0; //potentiometer for servo 1 position
int potpin2 = A1; //potentiometer for servo 2 position
int newval1; //for storing new value potentiometer 1 / servo 1
int oldval1; //for storing current value potentiometer 1 / servo 1
int newval2; //for storing new value potentiometer 2 / servo 2
int oldval2; //for storing current value potentiometer 2 / servo 2
//for Neopixels
#include <Adafruit_NeoPixel.h> //library for controlling neopixels
#include <avr/power.h>
#define PIN1 7 //pin attached to neopixel jewel 1
#define PIN2 6 //pin attached to neopixel jewel 2
#define NUMPIXELS 7 //number of pixels in each neopixel jewel
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
// for Emic2
#define audioEffectPin1 11 //this pin sends the signal to the second arduino to play a sentence or song
#define buttonPin1 2 //when button is pushed, a sentence or song plays
// for steppermotor
#define stepPin 3 //step pin
#define dirPin 4 //direction pin
#define clockwiseButtonPin A2 //when button is pushed, motor turns clockwise
#define counterClockwiseButtonPin A3 //when button is pushed, motor turns counterclockwise
int stepperSpeed = 100; //delay between step pulses. Higher number means motor spins faster
void setup()
{
// for servos
servo1.attach(9); //servo 1 attaches to pin 9
servo2.attach(10); //servo 2 attaches to pin 10
// for Neopixels
pixels1.begin(); //initiate neopixel jewel 1
pixels2.begin(); //initiate neopixel jewel 2
// for Emic2
pinMode(buttonPin1, INPUT);
digitalWrite(buttonPin1, HIGH);
pinMode(audioEffectPin1, OUTPUT);
// for steppermotor
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(clockwiseButtonPin, INPUT);
pinMode(counterClockwiseButtonPin, INPUT);
digitalWrite(stepPin, LOW);
digitalWrite(dirPin, LOW);
digitalWrite(counterClockwiseButtonPin, HIGH);
digitalWrite(clockwiseButtonPin, HIGH);
}
void loop()
{
moveServos();
lightPixels();
playAudio();
moveStepper();
}
void moveServos() {
//reads the value of a potentiometer and adjusts the position of a servo accordingly
newval1 = analogRead(potpin1); //reads the value of potentiometer 1
newval1 = map(newval1, 0, 1023, 600, 2000); //maps the value of potentiometer 1 to microseconds
if (newval1 < (oldval1 - 5) || newval1 > (oldval1 + 5)) { //prevents jitter. if the change in value is too small, it is ignored
servo1.write(newval1); //sends the new value to servo 1
oldval1 = newval1; //updates the current position of the servo
}
//same as above, but for servo 2
newval2 = analogRead(potpin2);
newval2 = map(newval2, 0, 1023, 600, 2000);
if (newval2 < (oldval2 - 5) || newval2 > (oldval2 + 5)) {
servo2.write(newval2);
oldval2 = newval2;
}
//delay(5);
}
void lightPixels() {
//reads the value of a potentiometer and adjusts the brightness of an led accordingly
//written for neopixel jewel, which consits of a ring of 6 led's, with one led in the center.
//when the value of the potentiometer increases, first the center pixel lights up, then the other 6 follow.
int lightInput1 = analogRead(potpin1); //reads the value of potentiometer 1
int lightInputA = map(lightInput1, 0, 1023, 0, 150); //maps value to brightness for pixel 0
lightInputA = constrain(lightInputA, 0, 150); //makes sure the value can never be lower or higher than the desired values
int lightInputB = map(lightInput1, 250, 1023, 0, 25); //maps value to brightness for pixels 1-6
lightInputB = constrain(lightInputB, 0, 25); //makes sure the value can never be lower or higher than the desired values
pixels1.setPixelColor(0, pixels1.Color(lightInputA, 0, 0)); //sets colour and brightness for pixel 0
for (int i = 1; i < NUMPIXELS; i++) {
pixels1.setPixelColor(i, pixels1.Color(lightInputB, 0, 0)); //sets colour and brightness for pixels 1-6
}
//same as above, but for neopixel 2
int lightInput2 = analogRead(potpin2);
int lightInputC = map(lightInput2, 0, 1023, 0, 150);
lightInputC = constrain(lightInputC, 0, 150);
int lightInputD = map(lightInput2, 250, 1023, 0, 25);
lightInputD = constrain(lightInputD, 0, 25);
pixels2.setPixelColor(0, pixels2.Color(lightInputC, 0, 0));
for (int i = 1; i < NUMPIXELS; i++) {
pixels2.setPixelColor(i, pixels2.Color(lightInputD, 0, 0));
}
pixels1.show();
pixels2.show();
}
void playAudio() {
//reads the value of a button.
//if the button is pressed, pin 11 is set high. This pin is connected to another arduino, that plays a entence or song if it detects that the pin is high
int audioButton1 = digitalRead(buttonPin1);
if (audioButton1 == 0) {
digitalWrite(audioEffectPin1, HIGH);
delay(500); //delay, so the other arduino notices the state change, even if it's busy when the signal is given (has to be changed to work with millis)
digitalWrite(audioEffectPin1, LOW);
}
}
void moveStepper() {
//spins a steppermotor when a button is pressed. One button makes it spin clockwise, the other one makes it spin countercokwise
int leftButton = digitalRead(clockwiseButtonPin); //reads the state of the button for clockwise rotation
int rightButton = digitalRead(counterClockwiseButtonPin); //reads the state of the button for counterclockwise rotation
if (leftButton == 0 && rightButton == 1) { //if the button for clockwise rotation is pressed and the button for counterclockwise rotation isn't...
digitalWrite(dirPin, LOW); //set the direction pin to low (= spin clockwise)
digitalWrite(stepPin, HIGH); //enable motor (= spin motor)
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
digitalWrite(stepPin, LOW); //disable motor
delayMicroseconds(stepperSpeed); ////pause for the set time (should be changed to work with millis) longer pause = motor spins slower
}
//same as above, but for counterclockwise rotation
else if (leftButton == 1 && rightButton == 0) {
digitalWrite(dirPin, HIGH);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepperSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepperSpeed);
}
}
Code2:
#include <TrueRandom.h>
// for timer
#include <Event.h> //library for handling millis
#include <Timer.h>
int period1 = 10000;
Timer speakText;
// for Emic2
#include <SoftwareSerial.h> //library that makes a second port available for serial communication with the EMIC2
#include <SD.h> // Needed by the EMIC2 library, though not utilized in this example
#include <EMIC2.h> //library for the Emic2
#define rxPin 11 // connects to Emic 2's SOUT pin
#define txPin 12 // connects to Emic 2's SIN pin
#define buttonPin1 3 //pin attached to second arduino. when pin is set high by other arduina, a sound is played
SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin);
EMIC2 emic; // Creates an instance of the EMIC2 library
//SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
String sentence[]={"__ My name is Bubo", "I'm the owl from the movie __clash of the __tytans", "My creator is called Cyril", "__Cyril taught __ me how to speak", "__Daivid taught __Cyril how to program", "__Matt likes to tease Daivid"}; //possible sentences that can be spoken
String nextSentence; //holds the next sentence to be played
int totalSentences = 6; //total number of sentences available
void setup()
{
// for timer
speakText.every(period1, playRandomAudio); //initiates the function playRandomAudio every 10 seconds (=period1)
// for Emic2
emicSerial.begin(9600);
emic.begin(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
emic.setVolume(10); //sets the desired volume
pinMode(buttonPin1, INPUT);
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
}
void loop()
{
speakText.update(); //checks if it's time to run the playRandomAudio function
playAudio(); //runs the playAudio function
}
void playRandomAudio() {
nextSentence=sentence[TrueRandom.random(totalSentences)]; //selects a random sentence out of the total available sentences
emic.setVoice(1); //sets a voice (9 choices: 0 - 8)
emic.speak(nextSentence); //play the random selected sentence
}
void playAudio() {
int trackButton1 = digitalRead(buttonPin1); //read the state of the pushbutton connected to pin 3
if(trackButton1 == 1) { //if the button is pushed
emicSerial.print("D1\n"); //play the preconfigured example
}
}
Video:
https://www.youtube.com/watch?v=xmuktJ04b8o&feature=youtu.be
I got the steppermotor and the audio working both through manual input and randomly. I didn't have time to do the servo's too, so at the moment they can only be controlled manually.
https://www.youtube.com/watch?v=xvT7H120QyI
Code 1:
#include <TrueRandom.h> //library that generates true random numbers
// for servos
#include <Adafruit_TiCoServo.h> //special library that lets servo's work together with neopixels
#include <known_16bit_timers.h>
Adafruit_TiCoServo servo1; //servo 1
Adafruit_TiCoServo servo2; //servo 2
int potpin1 = A0; //potentiometer for servo 1 position
int potpin2 = A1; //potentiometer for servo 2 position
int newval1; //for storing new value potentiometer 1 / servo 1
int oldval1; //for storing current value potentiometer 1 / servo 1
int newval2; //for storing new value potentiometer 2 / servo 2
int oldval2; //for storing current value potentiometer 2 / servo 2
//for Neopixels
#include <Adafruit_NeoPixel.h> //library for controlling neopixels
#include <avr/power.h>
#define PIN1 7 //pin attached to neopixel jewel 1
#define PIN2 6 //pin attached to neopixel jewel 2
#define NUMPIXELS 7 //number of pixels in each neopixel jewel
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800); //sets values to neopixel jewel 1
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800); //sets values to neopixel jewel 2
// for Emic2
#define audioEffectPin1 11 //this pin sends the signal to the second arduino to play a sentence or song
#define buttonPin1 2 //when button is pushed, a sentence or song plays
long timerDelayAudioEffectPin; //timer for audiopin
int delayAudioEffectPin = 1000; //how long the pin is set high
// for steppermotor
int nextPosition; //position the steppermotor has to reach
int stepperDirection = 0; //direction in which the steppermotor is turning
boolean buttonPressed = false; //state of the buttons for manually controlling the steppermotor
long timerDelayBetweenRotations; //timer for random rotations
int delayBetweenRotations; //delay between random rotations (set by function setDelayBetweenRotations)
#define stepPin 3 //step pin
#define dirPin 4 //direction pin
#define clockwiseButtonPin A2 //when button is pushed, motor turns clockwise
#define counterClockwiseButtonPin A3 //when button is pushed, motor turns counterclockwise
#define stopPin A4 //when button is pushed, the motor doesn't turn at random
int stepperSpeed = 50; //delay between step pulses. Higher number means motor spins slower
void setup() {
// for servos
servo1.attach(9); //servo 1 attaches to pin 9
servo2.attach(10); //servo 2 attaches to pin 10
// for Neopixels
pixels1.begin(); //initiate neopixel jewel 1
pixels2.begin(); //initiate neopixel jewel 2
// for Emic2
pinMode(buttonPin1, INPUT);
digitalWrite(buttonPin1, HIGH);
pinMode(audioEffectPin1, OUTPUT);
timerDelayBetweenRotations = millis();
// for steppermotor
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(clockwiseButtonPin, INPUT);
pinMode(counterClockwiseButtonPin, INPUT);
digitalWrite(stepPin, LOW);
digitalWrite(dirPin, LOW);
digitalWrite(counterClockwiseButtonPin, HIGH);
digitalWrite(clockwiseButtonPin, HIGH);
digitalWrite(stopPin, HIGH);
setNextPosition();
setDelayBetweenRotations();
timerDelayBetweenRotations = millis();
}
void loop()
{
moveServos();
lightPixels();
playAudio();
moveStepper();
}
void moveServos() {
//reads the value of a potentiometer and adjusts the position of a servo accordingly
newval1 = analogRead(potpin1); //reads the value of potentiometer 1
newval1 = map(newval1, 0, 1023, 600, 2000); //maps the value of potentiometer 1 to microseconds
if (newval1 < (oldval1 - 5) || newval1 > (oldval1 + 5)) { //prevents jitter. if the change in value is too small, it is ignored
servo1.write(newval1); //sends the new value to servo 1
oldval1 = newval1; //updates the current position of the servo
}
//same as above, but for servo 2
newval2 = analogRead(potpin2);
newval2 = map(newval2, 0, 1023, 600, 2000);
if (newval2 < (oldval2 - 5) || newval2 > (oldval2 + 5)) {
servo2.write(newval2);
oldval2 = newval2;
}
}
void lightPixels() {
//reads the value of a potentiometer and adjusts the brightness of an led accordingly
//written for neopixel jewel, which consits of a ring of 6 led's, with one led in the center.
//when the value of the potentiometer increases, first the center pixel lights up, then the other 6 follow.
int lightInput1 = analogRead(potpin1); //reads the value of potentiometer 1
int lightInputA = map(lightInput1, 0, 1023, 0, 30); //maps value to brightness for pixel 0
lightInputA = constrain(lightInputA, 0, 30); //makes sure the value can never be lower or higher than the desired values
int lightInputB = map(lightInput1, 600, 1023, 0, 15); //maps value to brightness for pixels 1-6
lightInputB = constrain(lightInputB, 0, 15); //makes sure the value can never be lower or higher than the desired values
pixels1.setPixelColor(0, pixels1.Color(lightInputA, 0, 0)); //sets colour and brightness for pixel 0
for (int i = 1; i < NUMPIXELS; i++) {
pixels1.setPixelColor(i, pixels1.Color(lightInputB, 0, 0)); //sets colour and brightness for pixels 1-6
}
//same as above, but for neopixel 2
int lightInput2 = analogRead(potpin2);
int lightInputC = map(lightInput2, 0, 1023, 0, 30);
lightInputC = constrain(lightInputC, 0, 30);
int lightInputD = map(lightInput2, 600, 1023, 0, 15);
lightInputD = constrain(lightInputD, 0, 15);
pixels2.setPixelColor(0, pixels2.Color(lightInputC, 0, 0));
for (int i = 1; i < NUMPIXELS; i++) {
pixels2.setPixelColor(i, pixels2.Color(lightInputD, 0, 0));
}
pixels1.show();
pixels2.show();
}
void playAudio() {
//reads the value of a button.
//if the button is pressed, pin 11 is set high. This pin is connected to another arduino, that plays a entence or song if it detects that the pin is high
int audioButton1 = digitalRead(buttonPin1);
if (audioButton1 == 0) {
digitalWrite(audioEffectPin1, HIGH);
if (millis() - timerDelayAudioEffectPin > delayAudioEffectPin) { //delay, so the other arduino notices the state change, even if it's busy when the signal is given
digitalWrite(audioEffectPin1, LOW);
timerDelayAudioEffectPin = millis();
}
}
}
void moveStepper() {
//spins a steppermotor when a button is pressed.
//One button makes it spin clockwise, the other one makes it spin countercokwise, the third one disables turning
int leftButton = digitalRead(clockwiseButtonPin); //reads the state of the button for clockwise rotation
int rightButton = digitalRead(counterClockwiseButtonPin); //reads the state of the button for counterclockwise rotation
int stopButton = digitalRead(stopPin); ////reads the state of the button that stops the random rotation
if (leftButton == 0 && rightButton == 1) { //if the button for clockwise rotation is pressed and the button for counterclockwise rotation isn't...
digitalWrite(dirPin, LOW); //set the direction pin to low (= spin clockwise)
digitalWrite(stepPin, HIGH); //enable motor (= spin motor)
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
digitalWrite(stepPin, LOW); //disable motor
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
buttonPressed = true; //sets the state of the button to true, so random turning is disabled
}
else if (leftButton == 1 && rightButton == 0) { //same as above, but for counterclockwise rotation
digitalWrite(dirPin, HIGH);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepperSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepperSpeed);
buttonPressed = true;
}
else if (stopButton == 0) {
buttonPressed = true;
}
else {
buttonPressed = false;
}
//if none of the buttons is pressed, the steppermotor turns a random number of degrees clockwise,
//then waits for a random period, then turns a random number of degrees counterclockwise
if(buttonPressed == false) {
if (stepperDirection == 0) { //if the steppermotor is turning clockwise
if (nextPosition > 0) { //if the next position hasn't been reached yet
digitalWrite(dirPin, LOW); //set the direction pin to low (= spin clockwise)
digitalWrite(stepPin, HIGH); //enable motor (= spin motor)
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
digitalWrite(stepPin, LOW); //disable motor
delayMicroseconds(stepperSpeed); ////pause for the set time (should be changed to work with millis) longer pause = motor spins slower
nextPosition--; //decreases the value of nextposition by 1
}
else if (nextPosition <= 0) { //when the steppermotor has reached it's position
if (millis() - timerDelayBetweenRotations > delayBetweenRotations) { //if the randomly set delaytime has been reached
stepperDirection = 1; //reverse the direction the steppermotor rotates in
setNextPosition(); //set new position for the steppermotor to reach
setDelayBetweenRotations(); //set new delaytime between rotations
timerDelayBetweenRotations = millis(); //reset timer for random rotations
}
}
}
//same as above, but for when the steppermotor is turning counterclockwise
if (stepperDirection == 1) {
if (nextPosition > 0) {
digitalWrite(dirPin, HIGH);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepperSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepperSpeed);
nextPosition--;
}
if (nextPosition <= 0) {
if (millis() - timerDelayBetweenRotations > delayBetweenRotations) {
stepperDirection = 0;
setNextPosition();
setDelayBetweenRotations();
timerDelayBetweenRotations = millis();
}
}
}
}
}
//function for randomly determining the nxt position the steppermotor has to travel to
void setNextPosition() {
nextPosition = (TrueRandom.random(4, 50)*100);
}
//function for randomly determining the delay between rotations
void setDelayBetweenRotations() {
delayBetweenRotations = (TrueRandom.random(5, 10)*1000);
}
Code 2:
#include <TrueRandom.h> //library that generates true random numbers
//for triggering audio at random and at random times
long timerAudio; //timer for triggering audio at random
int timeToWaitAudio; //delay between random audio playback (set by function setNewWaitTime)
// for Emic2
#include <SoftwareSerial.h> //library that makes a second port available for serial communication with the EMIC2
#include <EMIC2.h> //library for the Emic2
#include <SD.h> // Needed by the EMIC2 library, though not utilized in this example
#define rxPin 11 // connects to Emic 2's SOUT pin
#define txPin 12 // connects to Emic 2's SIN pin
#define buttonPin1 3 //pin attached to second arduino. when pin is set high by other arduina, a sound is played
EMIC2 emic; // Creates an instance of the EMIC2 library
SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
String sentence[]={"__ My name is Bubo", "I'm the owl from the movie __clash of the __tytans", "My creator is called Cyril", "__Cyril taught __ me how to speak", "__Daivid taught __Cyril how to program", "__Matt likes to tease Daivid"}; //possible sentences that can be spoken
String nextSentence; //holds the next sentence to be played
int totalSentences = 6; //total number of sentences available
void setup()
{
//for triggering audio at random and at random times
timerAudio = millis();
setNewWaitTime();
// for Emic2
emicSerial.begin(9600); //sets speed of communication between arduino & Emic2
emic.begin(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
emic.setVolume(10); //sets the desired volume
pinMode(buttonPin1, INPUT);
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
}
void loop()
{
playRandomAudio(); //runs the playRandomAudio function
playAudio(); //runs the playAudio function
}
void playRandomAudio() {
if (millis() - timerAudio > timeToWaitAudio) { //if the randomly set delaytime has been reached
nextSentence=sentence[TrueRandom.random(totalSentences)]; //selects a random sentence out of the total available sentences
emic.setVoice(1); //sets a voice (9 choices: 0 - 8)
emic.speak(nextSentence); //play the random selected sentence
setNewWaitTime(); //set a new delaytime between sentences
timerAudio = millis(); //reset timer for random audio
}
}
//function for randomly determining the time between audio playback
void setNewWaitTime() {
timeToWaitAudio = (TrueRandom.random(5, 20)*1000);
}
//function for playing a specific audio track when a button is pushed
void playAudio() {
int trackButton1 = digitalRead(buttonPin1); //read the state of the pushbutton connected to pin 3
if(trackButton1 == 1) { //if the button is pushed
emicSerial.print("D1\n"); //play the preconfigured example
}
}
I finally got all the functions to work as intended. If there is no manual input for a certain/random time, each function starts working autonomously, which means:
- diaphragms move to random positions, with random delays between movements.
- LED's behind diaphragms light up simultaniously.
- platform rotates to random positions, with random delays between movements.
- audiofragments are triggered randomly, with random delays between triggers.
The mechanism uses two arduino's because the code for the audio is blocking. By using a seperate arduino for the audio, all functions can be run simultaniously.
There's a slipring built into the platform, so it can turn without restrictions.
#include <TrueRandom.h> //library that generates true random numbers
// for servos
#include <Adafruit_TiCoServo.h> //special library that lets servo's work together with neopixels
#include <known_16bit_timers.h>
Adafruit_TiCoServo servo1; //servo 1
Adafruit_TiCoServo servo2; //servo 2
int potpin1 = A0; //potentiometer for servo 1 position
int potpin2 = A1; //potentiometer for servo 2 position
int newval1; //for storing new value potentiometer 1 / servo 1
int oldval1; //for storing current value potentiometer 1 / servo 1
int newval2; //for storing new value potentiometer 2 / servo 2
int oldval2; //for storing current value potentiometer 2 / servo 2
long timerDelayBetweenServoMovements; //timer for determining time between random servomovements
int delayBetweenServoMovements; //time before next random movement is determined
long timerWaitBeforeRandom; //timer for determining time between manual movements and random movements
int waitBeforeRandom = 5000; //number of milliseconds to wait between last change of potmeter and start of random movements
int randomServoPosition; //holds the next randomly chosen servoposition
boolean potActive; //holds value of potentiometer activity
//for Neopixels
#include <Adafruit_NeoPixel.h> //library for controlling neopixels
#include <avr/power.h>
#define PIN1 7 //pin attached to data in of neopixel jewel 1
#define PIN2 6 //pin attached to data in of neopixel jewel 2
#define NUMPIXELS 7 //number of pixels in each neopixel jewel
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800); //sets values to neopixel jewel 1
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800); //sets values to neopixel jewel 2
// for Emic2
#define audioEffectPin1 11 //this pin sends the signal to the second arduino to play a sentence or song
#define buttonPin1 2 //when button is pushed, a sentence or song plays
long timerDelayAudioEffectPin; //timer for audiopin
int delayAudioEffectPin = 1000; //how long the pin is set high
// for steppermotor
int nextPosition; //position the steppermotor has to reach
int stepperDirection = 0; //direction in which the steppermotor is turning
boolean buttonPressed = false; //state of the buttons for manually controlling the steppermotor
long timerDelayBetweenRotations; //timer for random rotations
int delayBetweenRotations; //delay between random rotations (set by function setDelayBetweenRotations)
#define stepPin 3 //step pin
#define dirPin 4 //direction pin
#define clockwiseButtonPin A2 //when button is pushed, motor turns clockwise
#define counterClockwiseButtonPin A3 //when button is pushed, motor turns counterclockwise
#define stopPin A4 //when button is pushed, the motor doesn't turn at random
int stepperSpeed = 1000; //delay between step pulses. Higher number means motor spins slower
void setup() {
// for servos
servo1.attach(9); //servo 1 attaches to pin 9
servo2.attach(10); //servo 2 attaches to pin 10
timerDelayBetweenServoMovements = millis(); //starts "clock"
timerWaitBeforeRandom = millis(); //starts "clock"
setDelayBetweenServoMovements(); //sets first delay
setRandomServoPosition(); //sets first random servo position
// for Neopixels
pixels1.begin(); //initiate neopixel jewel 1
pixels2.begin(); //initiate neopixel jewel 2
// for Emic2
pinMode(buttonPin1, INPUT); //sets pin as input
digitalWrite(buttonPin1, HIGH); //pulls input high
pinMode(audioEffectPin1, OUTPUT); //sets pin as output
timerDelayBetweenRotations = millis(); //starts "clock"
// for steppermotor
pinMode(stepPin, OUTPUT); //sets pin as output
pinMode(dirPin, OUTPUT); //sets pin as output
pinMode(clockwiseButtonPin, INPUT); //sets pin as input
pinMode(counterClockwiseButtonPin, INPUT); //sets pin as input
digitalWrite(stepPin, LOW); //pulls pin low
digitalWrite(dirPin, LOW); //pulls pion low
digitalWrite(counterClockwiseButtonPin, HIGH); //pulls pin high
digitalWrite(clockwiseButtonPin, HIGH); //pulls pin high
digitalWrite(stopPin, HIGH); //pulls pin high
setNextPosition(); //sets first random position
setDelayBetweenRotations(); //sets first random delay
timerDelayBetweenRotations = millis(); //starts "clock"
}
void loop()
{
moveServos();
playAudio();
moveStepper();
}
void moveServos() {
//read the value of both potentiometers and convert them to microseconds
readPotOnePosition();
readPotTwoPosition();
//determine if the value of the potentiometers has changed (yes = true, no = false)
if (newval1 < (oldval1 -10) || newval1 > (oldval1 +10) || newval2 < (oldval2 -10) || newval2 > (oldval2 +10)) { //see if the value of potentiometer has changed
potActive = true;
}
else {
potActive = false;
}
switch (potActive) {
//if the value has changed, set the servo's to the new positions
case true: //if the value of the potentiometer has changed
timerWaitBeforeRandom = millis(); //reset the timer
servo1.write(newval1); // update the position of servo1
servo2.write(newval2); // update the position of servo1
oldval1 = newval1; //set current position
oldval2 = newval2; //set current position
lightPixels(); //lights up the led's according to the position of the servo"s
//if the value has not changed, wait for the set time
case false:
if ((millis() - timerWaitBeforeRandom) <= waitBeforeRandom) {
}
//if the value still hasn't changed, set the servo's to the randomly determined position
else {
servo1.write(randomServoPosition); //set servo 1 to randomly determined position
servo2.write(randomServoPosition); //set servo 1 to randomly determined position
lightRandomPixels();
//after a random delay, set a new random position and random delay
if ((millis() - timerDelayBetweenServoMovements) > delayBetweenServoMovements) { //if the random period between positionchanges has expired
setRandomServoPosition(); //set a new random position
setDelayBetweenServoMovements(); //set a new random period between positionchanges
timerDelayBetweenServoMovements = millis(); //reset the timer for the period between servo movements
}
}
}
}
//function for reading the value of potentiometer 1 and converting it to microseconds
void readPotOnePosition() {
newval1 = analogRead(potpin1); //reads the value of potentiometer 1
newval1 = map(newval1, 0, 1023, 600, 1900); //maps the value of potentiometer 1 to microseconds
}
//function for reading the value of potentiometer 2 and converting it to microseconds
void readPotTwoPosition() {
newval2 = analogRead(potpin2); //reads the value of potentiometer 1
newval2 = map(newval2, 0, 1023, 600, 1900); //maps the value of potentiometer 1 to microseconds
}
//function for randomly determining the next servo position
void setRandomServoPosition() {
randomServoPosition = (TrueRandom.random(3, 9) * 200);
}
//function for randomly determining the delay between servo movements
void setDelayBetweenServoMovements() {
delayBetweenServoMovements = (TrueRandom.random(5, 10)*1000);
}
void lightPixels() {
//takes the position of the servo's when in manual mode and adjusts the brightness of an led accordingly
//written for neopixel jewel, which consits of a ring of 6 led's, with one led in the center.
//when the value increases, first the center pixel lights up, then the other 6 follow.
//for NeoPxel 1
int lightInputA = map(newval1, 600, 1900, 1, 30); //maps value to brightness for pixel 0
lightInputA = constrain(lightInputA, 1, 30); //makes sure the value can never be lower or higher than the desired values
int lightInputB = map(newval1, 1050, 1900, 0, 15); //maps value to brightness for pixels 1-6
lightInputB = constrain(lightInputB, 0, 15); //makes sure the value can never be lower or higher than the desired values
pixels1.setPixelColor(0, pixels1.Color(lightInputA, 0, 0)); //sets colour and brightness for pixel 0
for (int i = 1; i < NUMPIXELS; i++) {
pixels1.setPixelColor(i, pixels1.Color(lightInputB, 0, 0)); //sets colour and brightness for pixels 1-6
}
//same as above, but for neopixel 2
int lightInputC = map(newval2, 600, 1900, 1, 30);
lightInputC = constrain(lightInputC, 1, 30);
int lightInputD = map(newval2, 1050, 1900, 0, 15);
lightInputD = constrain(lightInputD, 0, 15);
pixels2.setPixelColor(0, pixels2.Color(lightInputC, 0, 0));
for (int i = 1; i < NUMPIXELS; i++) {
pixels2.setPixelColor(i, pixels2.Color(lightInputD, 0, 0));
}
pixels1.show(); //sends the values to the led's
pixels2.show(); //sends the values to the led's
}
//takes the position of the servo's when in random mode and adjusts the brightness of an led accordingly
//written for neopixel jewel, which consits of a ring of 6 led's, with one led in the center.
//when the value increases, first the center pixel lights up, then the other 6 follow.
void lightRandomPixels() {
int lightInputA = map(randomServoPosition, 600, 1900, 1, 30); //maps value to brightness for pixel 0
lightInputA = constrain(lightInputA, 0, 30); //makes sure the value can never be lower or higher than the desired values
int lightInputB = map(randomServoPosition, 1350, 1900, 0, 15); //maps value to brightness for pixels 1-6
lightInputB = constrain(lightInputB, 0, 15); //makes sure the value can never be lower or higher than the desired values
pixels1.setPixelColor(0, pixels1.Color(lightInputA, 0, 0)); //sets colour and brightness for pixel 0
for (int i = 1; i < NUMPIXELS; i++) {
pixels1.setPixelColor(i, pixels1.Color(lightInputB, 0, 0)); //sets colour and brightness for pixels 1-6
}
pixels2.setPixelColor(0, pixels2.Color(lightInputA, 0, 0)); //sets colour and brightness for pixel 0
for (int i = 1; i < NUMPIXELS; i++) {
pixels2.setPixelColor(i, pixels2.Color(lightInputB, 0, 0)); //sets colour and brightness for pixels 1-6
}
pixels1.show(); //sends the values to the led's
pixels2.show(); //sends the values to the led's
}
void playAudio() {
//reads the value of a button.
//if the button is pressed, pin 11 is set high. This pin is connected to another arduino, that plays a entence or song if it detects that the pin is high
int audioButton1 = digitalRead(buttonPin1);
if (audioButton1 == 0) {
digitalWrite(audioEffectPin1, HIGH);
if (millis() - timerDelayAudioEffectPin > delayAudioEffectPin) { //delay, so the other arduino notices the state change, even if it's busy when the signal is given
digitalWrite(audioEffectPin1, LOW);
timerDelayAudioEffectPin = millis();
}
}
}
void moveStepper() {
//spins a steppermotor when a button is pressed.
//One button makes it spin clockwise, the other one makes it spin countercokwise, the third one disables turning
int leftButton = digitalRead(clockwiseButtonPin); //reads the state of the button for clockwise rotation
int rightButton = digitalRead(counterClockwiseButtonPin); //reads the state of the button for counterclockwise rotation
int stopButton = digitalRead(stopPin); ////reads the state of the button that stops the random rotation
if (leftButton == 0 && rightButton == 1) { //if the button for clockwise rotation is pressed and the button for counterclockwise rotation isn't...
digitalWrite(dirPin, LOW); //set the direction pin to low (= spin clockwise)
digitalWrite(stepPin, HIGH); //enable motor (= spin motor)
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
digitalWrite(stepPin, LOW); //disable motor
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
buttonPressed = true; //sets the state of the button to true, so random turning is disabled
}
else if (leftButton == 1 && rightButton == 0) { //same as above, but for counterclockwise rotation
digitalWrite(dirPin, HIGH);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepperSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepperSpeed);
buttonPressed = true;
}
else if (stopButton == 0) {
buttonPressed = true;
}
else {
buttonPressed = false;
}
//if none of the buttons is pressed, the steppermotor turns a random number of degrees clockwise,
//then waits for a random period, then turns a random number of degrees counterclockwise
if(buttonPressed == false) {
if (stepperDirection == 0) { //if the steppermotor is turning clockwise
if (nextPosition > 0) { //if the next position hasn't been reached yet
digitalWrite(dirPin, LOW); //set the direction pin to low (= spin clockwise)
digitalWrite(stepPin, HIGH); //enable motor (= spin motor)
delayMicroseconds(stepperSpeed); //pause for the set time (should be changed to work with millis) longer pause = motor spins slower
digitalWrite(stepPin, LOW); //disable motor
delayMicroseconds(stepperSpeed); ////pause for the set time (should be changed to work with millis) longer pause = motor spins slower
nextPosition--; //decreases the value of nextposition by 1
}
else if (nextPosition <= 0) { //when the steppermotor has reached it's position
if (millis() - timerDelayBetweenRotations > delayBetweenRotations) { //if the randomly set delaytime has been reached
stepperDirection = 1; //reverse the direction the steppermotor rotates in
setNextPosition(); //set new position for the steppermotor to reach
setDelayBetweenRotations(); //set new delaytime between rotations
timerDelayBetweenRotations = millis(); //reset timer for random rotations
}
}
}
//same as above, but for when the steppermotor is turning counterclockwise
if (stepperDirection == 1) {
if (nextPosition > 0) {
digitalWrite(dirPin, HIGH);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepperSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepperSpeed);
nextPosition--;
}
if (nextPosition <= 0) {
if (millis() - timerDelayBetweenRotations > delayBetweenRotations) {
stepperDirection = 0;
setNextPosition();
setDelayBetweenRotations();
timerDelayBetweenRotations = millis();
}
}
}
}
}
//function for randomly determining the next position the steppermotor has to travel to
void setNextPosition() {
nextPosition = (TrueRandom.random(4, 50)*100);
}
//function for randomly determining the delay between rotations
void setDelayBetweenRotations() {
delayBetweenRotations = (TrueRandom.random(5, 10)*1000);
}
#include <TrueRandom.h> //library that generates true random numbers
//for triggering audio at random and at random times
long timerAudio; //timer for triggering audio at random
int timeToWaitAudio; //delay between random audio playback (set by function setNewWaitTime)
// for Emic2
#include <SoftwareSerial.h> //library that makes a second port available for serial communication with the EMIC2
#include <EMIC2.h> //library for the Emic2
#include <SD.h> // Needed by the EMIC2 library, though not utilized in this example
#define rxPin 11 // connects to Emic 2's SOUT pin
#define txPin 12 // connects to Emic 2's SIN pin
#define buttonPin1 3 //pin attached to second arduino. when pin is set high by other arduina, a sound is played
EMIC2 emic; // Creates an instance of the EMIC2 library
SoftwareSerial emicSerial = SoftwareSerial(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
String sentence[]={"__ My name is Bubo", "I'm the owl from the movie __clash of the __tytans", "My creator is called Cyril", "__Cyril taught __ me how to speak", "__Daivid taught __Cyril how to program", "__Matt likes to tease Daivid"}; //possible sentences that can be spoken
String nextSentence; //holds the next sentence to be played
int totalSentences = 6; //total number of sentences available
void setup()
{
//for triggering audio at random and at random times
timerAudio = millis();
setNewWaitTime();
// for Emic2
emicSerial.begin(9600); //sets speed of communication between arduino & Emic2
emic.begin(rxPin, txPin); //opens up the second serial port and sets the tx and rx pins
emic.setVolume(10); //sets the desired volume
pinMode(buttonPin1, INPUT);
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
}
void loop()
{
playRandomAudio(); //runs the playRandomAudio function
playAudio(); //runs the playAudio function
}
void playRandomAudio() {
if (millis() - timerAudio > timeToWaitAudio) { //if the randomly set delaytime has been reached
nextSentence=sentence[TrueRandom.random(totalSentences)]; //selects a random sentence out of the total available sentences
emic.setVoice(1); //sets a voice (9 choices: 0 - 8)
emic.speak(nextSentence); //play the random selected sentence
setNewWaitTime(); //set a new delaytime between sentences
timerAudio = millis(); //reset timer for random audio
}
}
//function for randomly determining the time between audio playback
void setNewWaitTime() {
timeToWaitAudio = (TrueRandom.random(5, 20)*1000);
}
//function for playing a specific audio track when a button is pushed
void playAudio() {
int trackButton1 = digitalRead(buttonPin1); //read the state of the pushbutton connected to pin 3
if(trackButton1 == 1) { //if the button is pushed
emicSerial.print("D1\n"); //play the preconfigured example
}
}
https://www.youtube.com/watch?v=dOyUVhs-wTg
/Chris