Simple Mechanics Lab: Cuckoo Clock Assignment

Cuckoo Clock Design:

Our Halloween-themed cuckoo clock design uses a servo motor, lever and pulley system to lower a drawbridge door revealing the little Frankenstein cuckoo within.  In addition, an RGB LED configuration emits an orange glow, and a spooky soundtrack is choreographed to the motion of the door opening.

Videos:

Mechanism video:  http://youtu.be/HoQ6tPiJjig

Final video:  http://youtu.be/kaBN8YUE9gw

Hardware Materials Used:

Wood Boards, Hinges, Eyelet Screws, Plastic Pillars, Twine, Cardboard, Paint, Duct Tape, Marshmallow Frankenstein, Assorted Candy...

Software Used: 

We implemented our clock controller in Java, using Processing's serial library to move the servo. We used the badlogic audio-analysis library (http://code.google.com/p/audio-analysis/) to play a music file. The music is played by a separate thread (MusicPlayerThread.java) so that we can send serial messages while the music is playing. Finally, the Arduino controls the LEDs and door movement.

========

ClockController.java

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.FileNotFoundException;

import javax.swing.*;

import processing.serial.*;

import threads.MusicPlayerThread;

public class ClockController {

private static String musicFile = "/Users/nick/Documents/Courses/11Fall/I262/Labs/Cuckoo clock/Halloween TUI.mp3";

private static MusicPlayerThread mpt;

private static Serial port;

private static JButton playButton;

public static void createAndShowGUI() {

JFrame frame = new JFrame("Clock controller");

frame.setLayout(new FlowLayout());

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JButton chooseButton = new JButton("Choose music");

chooseButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

}

});

 

try {

mpt = new MusicPlayerThread(musicFile);

} catch (FileNotFoundException e2) {

// TODO Auto-generated catch block

e2.printStackTrace();

} catch (Exception e2) {

// TODO Auto-generated catch block

e2.printStackTrace();

}

 

playButton = new JButton("Play music");

playButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

 

if(playButton.getText().equals("Play music")) {

//playButton.setText("Stop music");

 

// Play music

mpt.start();

 

// Send serial stuff

try {

Thread.sleep(5800);

port.write('2');

Thread.sleep(11000);

port.write('1');

} catch (InterruptedException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

else {

playButton.setText("Play music");

//mpt.cancel(true);

//mpt.interrupt();

//mpt.stop();

//port.write('0');

}

}

});

 

//frame.add(chooseButton);

frame.add(playButton);

frame.pack();

frame.setVisible(true);

 

// Initialize serial stuff

String portname = Serial.list()[0];

port = new Serial(portname, 9600);

}

 

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

}

MusicPlayerThread.java

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.FileNotFoundException;

 

import javax.swing.*;

import processing.serial.*;

import threads.MusicPlayerThread;

 

public class ClockController {

private static String musicFile = "/Users/nick/Documents/Courses/11Fall/I262/Labs/Cuckoo clock/Halloween TUI.mp3";

private static MusicPlayerThread mpt;

private static Serial port;

private static JButton playButton;

public static void createAndShowGUI() {

JFrame frame = new JFrame("Clock controller");

frame.setLayout(new FlowLayout());

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JButton chooseButton = new JButton("Choose music");

chooseButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

}

});

 

try {

mpt = new MusicPlayerThread(musicFile);

} catch (FileNotFoundException e2) {

// TODO Auto-generated catch block

e2.printStackTrace();

} catch (Exception e2) {

// TODO Auto-generated catch block

e2.printStackTrace();

}

 

playButton = new JButton("Play music");

playButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

if(playButton.getText().equals("Play music")) {

//playButton.setText("Stop music");

 

// Play music

mpt.start();

// Send serial stuff

try {

Thread.sleep(5800);

port.write('2');

Thread.sleep(11000);

port.write('1');

} catch (InterruptedException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

}

else {

playButton.setText("Play music");

//mpt.cancel(true);

//mpt.interrupt();

//mpt.stop();

//port.write('0');

}

}

});

 

//frame.add(chooseButton);

frame.add(playButton);

frame.pack();

frame.setVisible(true);

 

// Initialize serial stuff

String portname = Serial.list()[0];

port = new Serial(portname, 9600);

}

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

}

 

Arduino clock controller:

/*

 * INFO262 - Cuckoo Clock controller

 */

// Pin assignments

int doorServo = 7;

int rPin = 10;

int gPin = 9;

int bPin = 11;

int doorTime = 1000; // 1 second

long beginTime = 0;

 

// General servo variables

long lastPulse = 0;    // the time in millisecs of the last pulse

int refreshTime = 20;  // the time in millisecs needed in between pulses

int val;               // variable used to store data from potentiometer

int openPulse = 520;

int closePulse = 2200;

 

char serInString[100];  // array that will hold the different bytes of the string. 100=100characters;

                        // -> you must state how long the array will be else it won't work properly

                        

void setup() {

  pinMode(doorServo, OUTPUT);

  pinMode(rPin, OUTPUT);

  pinMode(gPin, OUTPUT);

  pinMode(bPin, OUTPUT);

  moveDoor(closePulse);

  Serial.begin(9600);

}

void loop() {  

    readSerialString(serInString);

    if(serInString[0] == '1') {

      Serial.println("Close door");

      analogWrite(rPin,0);   

      analogWrite(gPin,0);   

      analogWrite(bPin,0);  

      moveDoor(closePulse);    

    } else if(serInString[0] == '2') {

      Serial.println("Open door");

      analogWrite(rPin,254); 

      analogWrite(gPin,20);

      analogWrite(bPin,0);

      moveDoor(openPulse);

    }

    memset(serInString,0,100);

}

 

void moveDoor(int pulseWidth) {

  beginTime = millis();

  while(millis() - beginTime < doorTime) {

    updateServo(doorServo, pulseWidth);

  }

}

 

// called every loop(). 

void updateServo(int pin, int pulseWidth) {

  // pulse the servo again if the refresh time (20 ms) has passed:

  if (millis() - lastPulse >= refreshTime) {

    digitalWrite(pin, HIGH);   // Turn the motor on

    delayMicroseconds(pulseWidth);  // Length of the pulse sets the motor position

    digitalWrite(pin, LOW);    // Turn the motor off

    lastPulse = millis();           // save the time of the last pulse

  }

}

 

//read a string from the serial and store it in an array

//you must supply the array variable

void readSerialString (char *strArray) {

  int i = 0;

  if(!Serial.available()) {

    return;

  }

  while (Serial.available()) {

    strArray[i] = Serial.read();

    i++;

  }

}

0
Your rating: None