Note: I’ve finally gotten around to a much-needed rewrite for WiFi. You can find that code and another video here.
Back at Veracode’s last Hackathon, I published the video below. People have started discovering this and asking questions about it, so here is the code for it:
/* Weasley Clock ------------- Created by Doug "LegoDoug" Wilcox for Veracode Hackathon IX. Video of the completed project is at https://www.youtube.com/embed/oRUViFnxKsg. "Share and enjoy." */ // Arduino SPI (Serial Peripheral Interface) library - https://www.arduino.cc/en/Reference/SPI #include <SPI.h> // Arduino Ethernet library - https://www.arduino.cc/en/Reference/Ethernet #include <Ethernet.h> // Arduino Stepper library - https://www.arduino.cc/en/Reference/Stepper #include <Stepper.h> // Adafruit REST IO library - https://learn.adafruit.com/adafruit-io/arduino // See also https://www.arduino.cc/en/Tutorial/WebClientRepeating #include "Adafruit_IO_Client.h" // assign a MAC address for the ethernet controller. byte mac[] = { 0x8C, 0xDC, 0xD4, 0x4A, 0xC9, 0xC2 }; // initialize the library instance: EthernetClient client; // last time the Arduino connected to the server, in milliseconds unsigned long lastConnectionTime = 0; // delay between retrieving updates, in milliseconds const unsigned long requestInterval = 5000L; // Configure Adafruit IO access. You will need to create your own // Adafruit IO account (free), and set up a feed, and provide your // feed and AIO key in the code below. #define AIO_FEED "weasleyclockstatus" #define AIO_KEY "XXXXXXXXXXXXXXXXXXXXXXXXXXX" // Create an Adafruit IO Client instance. Notice that this needs to take a // WiFiClient object as the first parameter, and as the second parameter a // default Adafruit IO key to use when accessing feeds (however each feed can // override this default key value if required, see further below). Adafruit_IO_Client aio = Adafruit_IO_Client(client, AIO_KEY); // Alternatively to access a feed with a specific key: Adafruit_IO_Feed clockFeed = aio.getFeed(AIO_FEED, AIO_KEY); // States - These are the codes that correspond to specific clock positions. const String LD_HOME = "ld_na"; const String LD_TRAVELING = "ld_tr"; const String LD_VERACODE = "ld_of"; const String LD_CHURCH = "ld_ch"; const String LD_MORTAL_PERIL = "ld_mp"; const String LD_GLOUCESTER = "ld_gl"; // Steps - How many steps the motor needs to move to point to a specific position // on the clock. const int STEPS_HOME = 0; const int STEPS_TRAVELING = 750; const int STEPS_VERACODE = 1600; const int STEPS_CHURCH = 2450; const int STEPS_MORTAL_PERIL = 3350; const int STEPS_GLOUCESTER = 4350; // Someday, I will determine what this actually does. (I don't think, functionally, // it has any affect.) const int stepsPerRevolution = 200; long motorPosition = 0L; // Number of steps the motor has taken. String fValue = ""; // Feed value. Stepper clockStepper(stepsPerRevolution, 7, 6, 5, 4, 8); void setup() { // start serial port: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native // USB port only, on certain Arduino models. } // give the ethernet module time to boot up: delay(1000); // start the Ethernet connection using a fixed IP address and DNS server: //Ethernet.begin(mac, ip, myDns); // Or, just start it with dynamic DNS by giving it a MAC address. Ethernet.begin(mac); // print the Ethernet board/shield's IP address: Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); clockStepper.setSpeed(20); } void loop() { // Wait for a bit and read the current feed value. Serial.println(F("Waiting ...")); delay(requestInterval); // To read the latest feed value call the receive function on the feed. // The returned object will be a FeedData instance and you can check if it's // valid (i.e. was successfully read) by calling isValid(), and then get the // value either as a text value, or converted to an int, float, etc. FeedData latest = clockFeed.receive(); if (latest.isValid()) { Serial.print(F("Received value from feed: ")); Serial.println(latest); // By default the received feed data item has a string value, however you // can use the following functions to attempt to convert it to a numeric // value like an int or float. Each function returns a boolean that indicates // if the conversion succeeded, and takes as a parameter by reference the // output value. // Want some fun? Learning about "conversion from 'FeedData' to non-scalar // type 'String' requested" the hard way. // // If I remember correctly, it was a casting error caused by trying to use // the 'latest' variable as a String, directly. // The following line casts 'latest' to a string and lets us use it as 'fValue'. fValue = latest; if(fValue == LD_HOME) { Serial.println("Nashua"); stepBySteps(STEPS_HOME); } if(fValue == LD_TRAVELING) { Serial.println("Traveling"); stepBySteps(STEPS_TRAVELING); } if(fValue == LD_VERACODE) { Serial.println("Veracode"); stepBySteps(STEPS_VERACODE); } if(fValue == LD_CHURCH) { Serial.println("Church"); stepBySteps(STEPS_CHURCH); } if(fValue == LD_MORTAL_PERIL) { Serial.println("Mortal Peril!"); stepBySteps(STEPS_MORTAL_PERIL); } if(fValue == LD_GLOUCESTER) { Serial.println("Glostah"); stepBySteps(STEPS_GLOUCESTER); } } else { Serial.print(F("Failed to receive the latest feed value!")); } } void stepBySteps(int newPosition) { if(motorPosition == newPosition) { Serial.println("No movement required."); return; } long steps = newPosition - motorPosition; clockStepper.step(steps); motorPosition = newPosition; Serial.print("position should now be:" ); Serial.println(motorPosition); }
Would you give me the names of the hardware used to build this clock. I am a newbie to computer program so please be specific. Also the namessage of the software utilized. Thank you
Here’s what I used:
The software is just the Arduino IDE, which is free. There is a browser-based version and a standalone version. (I recommend the standalone, but they both work almost identically.)
Note that I used a shield with a wired Internet connection. If you wanted to use wireless, use this shield (Wifi UNO Based Esp8266), or a compatible one, instead.
You could also go with an UNO-with-WiFi board, such as the Adafruit Feather, which takes the place of the Arduino and the WiFi board.
Would it be possible to use four stepper motors (for four hands) and connect them all to one arduino?
Absolutely. The trick would be coming up with a four-cylinder cocentric shaft system. You might (in that case) also need to add a motor driver that would simplify the connection between the Arduino and the motors, but those are easy. (Here’s one I found, but have not used personally.)