Homework - W.A. Wichers

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 image has been resized to fit in the page. Click to enlarge.

Comments

  • My code so far:

    // 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);
      }
    }

  • Did a quick design for a temporary mechanism. I'll try to get it printed and maybe actually get something working. Now back to programming!


  • Cyril WichersCyril Wichers ✭✭✭
    edited May 2015
    Electronics are working, although there's still some finetuning to do.
    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.





  • 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 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);   
      }
    }

  • Code 2:

    #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
      }
    }

  • I've connected the servo's and the neopixels to the slipring, so the platform can now rotate continuously. The cabling has been tidied up a bit and everything seems to be working. I'm currently printing a new top plate, as the openings for the servo horns were a bit too narrow. Once that is finished, I can connect the servo's to the diaphragms and the mechanism will be finished.

    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:





  • Another update.

    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.



    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
      }
    }




  • Cyril WichersCyril Wichers ✭✭✭
    edited May 2015
    Last update for this course.
    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.
    Post edited by Cyril Wichers on
  • Cyril WichersCyril Wichers ✭✭✭
    edited May 2015
    Here's the main code (everything but the audio):

    #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);
    }



    Post edited by Cyril Wichers on
  • And here's the code for the audio:

    #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
      }
    }



  • And a final video:


  • Chris EllerbyChris Ellerby Los Angeles Admin
    Looking great!   Every time I watch your progress videos I get that song stuck in my head! ;)

    /Chris
Sign In or Register to comment.