Clock with servo motors

Hey .. i am new to arduino. And i am working on a project consisting of making a "clock" drived by servo motors, so i have to control 21 servo motors independently, and every servo motor is switching between to positions ( lets' say 0 Gd, and 45 Gd ), depending on if it is "on" or "off". The servo motors will almost have to load at all.

i know that i have to calculate the power needed for these motors, and that i can't power them directly from the Arduino board.

My question is, how can i hook / control that much motors from an arduino board, i was thinking about Shift registers, but i cant figure out how to hook them the servo motors, or if it is going to work.

any suggestions ? .. any help will be appreciated .

My question is, how can i hook / control that much motors from an arduino board

Use a Mega.

What kind of clock needs 21 motors?

You could get a servo controller to connect to the arduino and let it handle operating the servos as directed by the arduino.

Thanks for the quick answers

@PaulS : somethings like binary system, where in stead of switching the LED on … the Servo moves.

I can see that getting An Arduino Mega or servo controllers will be a solution … but what about using an ordinary Arduino and multiplexing servo-motors ? … And how can i get these to be synchronised with an external clock ?

do you really need a servo if its just going to move forward and back, how bout some solenoids

It is just because i need a "circular motion", i was experimenting with DIY flip-dots .. but i got confused, because i had no idea how to hook a shifter register to a H-bridge. so i changed the design using servomotors in stead

Servo motors need a servo pulse every 20 milliseconds, to make them hold still. You would need to completely re-write the Servo library to send that signal through a shift register. With the cost of 21 servos, shift registers, and an Arduino. compared to the cost of 21 servos and a Mega, I would think that the cost difference for using the Mega would be a fraction of the total cost.

The time and effort involved in rewriting the servo library needs to be considered, too.

@PaulS … so i guess i will go for 21 servos and a mega ! it sounds more achievable, since i am only beginning in electronics and programming.

For the programming part, any suggestions how to synchronize the motion of the Motors so i can have a functional clock, i was think about using 7 servos for hours, 7 + 7 for the minutes ( 12-hour clock ) … and i will be using an RTC for clock pulses.

It is not clear to me why you need 7 servos to represent numbers from 0 to 12, and 14 servos to represent numbers from 0 to 60. It is not clear what synchronization issues you expect. So, no, I'm sorry, I can not help you.

What exactly are the servos supposed to do to represent the advancement of time?

i am sorry ... it's just me ! .. i understand that you are confused !

in fact i need more than that .. i will need 12 for the hours, 24 for the minuts ( 12 for the decimal digits and 12 for the others ) , and they will be 2 marks on every servo ( one at the 0 degree and one on the 45 degree ), so lets say the time is "6:45" then 6 of the 12 servos ( for the hours ) will be on 45 Dg, while the others on 0 , and 4 of the 12 will be active ( for decimals ) and then 5 out of 12.

I hope that make sans.

Following that logic, you need 9 servos for each digit, except the 10's place in the hour value, where you need 1, for a total of 29 servos. Each servo will be at 0 degrees to represent 0, and at 45 degrees to represent 1. The time is then read by counting the number of 1's in each of the 4 columns: (0->1)(0->9):(0->9)(0->9);

There should not be any difficulty with synchronizing the servos, since each is moving independent of the others.

Affording, powering, positioning, and wiring 28 servos might be a problem.

@PaulS ... that's exactly what i need . thanks.

so so far i will need an Arduino Mega ( being able to control up to 48 servo motors ) and the i have to hook one servo motor to one digital pin on the board. I will use a DS1307 as an external clock. and a couple of push buttons to set the hours and the minutes.

For the powering, as far as i understood from the references i read, so i have to put the ground for all servos together, and the power for all these together and connect them to an external power source with a power regulator.

it's my raisonnement right ? ( is should be quite banal, but i am still learning )

what i have trouble understanding now, is how to use the buttons to set those servos ? I''ll see if i can manage to write a primary code for the clock

Yes, your reasoning is correct.

You need to separate the setting of the time from the displaying of the time. The switches are use to set the time on the clock, not the servo positions.

The time is used to set to the servo positions.

You will probably need more than 2 buttons to set the time. I would use 5 - 2 for up and down, to increment or decrement a value, 2 for left and right, to choose which value you are setting (tens for hour, ones for hours, tens for minutes, ones for minutes, and 1 for select/enter, to accept the current value. Some way of showing that value would be useful, too.

That made a lot of sense ! thanks

I will post an update as soon as i write some code.

Here is the "Code"

// include libraries

#include "Wire.h"
#include "Servo.h"

// defining the Pins

#define hour_servo1 1
#define hour_servo2 2
#define hour_servo3 3
#define hour_servo4 4
#define hour_servo5 5
#define hour_servo6 6
#define hour_servo7 7
#define hour_servo8 8
#define hour_servo9 9
#define hour_servo10 10

#define DS1307_I2C_ADDRESS 0x68

// defining variables

int realhour = 0;
int hours = 0;
int minutes = 0;

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,byte minute,byte hour,byte dayOfWeek,byte dayOfMonth,byte month,byte year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
  Wire.send(decToBcd(minute));
  Wire.send(decToBcd(hour));     
  Wire.send(decToBcd(dayOfWeek));
  Wire.send(decToBcd(dayOfMonth));
  Wire.send(decToBcd(month));
  Wire.send(decToBcd(year));
  Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
  Wire.endTransmission();
}

void getDateDs1307(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month,byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

// Function to Set time
/////
/////
////
/////

void setup() {

  pinMode(hour_servo1, OUTPUT);
  pinMode(hour_servo2, OUTPUT);
  pinMode(hour_servo3, OUTPUT);
  pinMode(hour_servo4, OUTPUT);
  pinMode(hour_servo5, OUTPUT);
  pinMode(hour_servo6, OUTPUT);
  pinMode(hour_servo7, OUTPUT);
  pinMode(hour_servo8, OUTPUT);
  pinMode(hour_servo9, OUTPUT);
  pinMode(hour_servo10, OUTPUT);

  second = 0;
  dayOfWeek = 1;
  dayOfMonth = 24;
  month = 5;
  year = 10;

// Set up the time using the buttons then ->

setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);


}

void loop() {

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  realhour = int(hour);

  if (realhour==0) // if it is 0000h, that should be 1200h in 12 hour time
  {
    realhour=12;
  }

  if (hour>=13)
  {
      realhour=realhour-12; // convert 24h hours to 12h hours
  }

  hours=realhour*14;
  minutes=minute*3;
  
    switch(hours) {
      case '1':
        hour_servo1.write(45); // if active set position to 45 degree
        hour_servo2.write(0); // if inactive set position to 0 degree
    hour_servo3.write(0);
    hour_servo4.write(0);
    hour_servo5.write(0);
    hour_servo6.write(0);
    hour_servo7.write(0);
    hour_servo8.write(0);
    hour_servo9.write(0);
    hour_servo10.write(0);
        break;
      case '2':
    .
    .
    .
    .

      case '12':
        .

        break;
    }

  delay(100);     // servos need time to move

    switch(minutes) {
      case '1':
        .

        break;
      case '2':
    .
    .
    .
    .

      case '60':
    .

        break;
    }
  delay(100);

}

1 ) - i have problems setting time with buttons ... i cant figure out how to do it ? 2 ) - As you can see the case method will be quite long, is there another way to do it ? i was reading about arrays, but can anyone show me an example, because i am not sure how to do it neither.

That code won't work. hour_servo1, and all the others, need to be instances of the Servo class, not constants.

You need to call hour_servo1.attach() to establish a relationship between the instance and a pin number that the signal will be sent to.

The Servo class manages the pin mode for the pins it uses. You don't need to.

Arrays will be very useful.

Thanks for the comments .. i changed the code.

Can anyone help to make arrays, in this exemple, i've been looking around and i can't figure it out

// include libraries

#include "Wire.h"
#include "Servo.h"

Servo  hour_servo1
Servo  hour_servo2
Servo  hour_servo3
Servo  hour_servo4
Servo  hour_servo5
Servo  hour_servo6
Servo  hour_servo7
Servo  hour_servo8
Servo  hour_servo9
Servo  hour_servo10

#define DS1307_I2C_ADDRESS 0x68

// defining variables

int realhour = 0;
int hours = 0;
int minutes = 0;

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,byte minute,byte hour,byte dayOfWeek,byte dayOfMonth,byte month,byte year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
  Wire.send(decToBcd(minute));
  Wire.send(decToBcd(hour));     
  Wire.send(decToBcd(dayOfWeek));
  Wire.send(decToBcd(dayOfMonth));
  Wire.send(decToBcd(month));
  Wire.send(decToBcd(year));
  Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
  Wire.endTransmission();
}

void getDateDs1307(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month,byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

// Function to Set time
/////
/////
////
/////

void setup() {

hour_servo1.attach(1);
hour_servo1.attach(2);
hour_servo1.attach(3);
hour_servo1.attach(4);
hour_servo1.attach(5);
hour_servo1.attach(6);
hour_servo1.attach(7);
hour_servo1.attach(8);
hour_servo1.attach(9);
hour_servo1.attach(10);

  second = 0;
  dayOfWeek = 1;
  dayOfMonth = 24;
  month = 5;
  year = 10;

// Set up the time using the buttons then ->

setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);


}

void loop() {

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  realhour = int(hour);

  if (realhour==0) // if it is 0000h, that should be 1200h in 12 hour time
  {
    realhour=12;
  }

  if (hour>=13)
  {
      realhour=realhour-12; // convert 24h hours to 12h hours
  }

  hours=realhour*14;
  minutes=minute*3;
  
    switch(hours) {
      case '1':
        hour_servo1.write(45); // if active set position to 45 degree
        hour_servo2.write(0); // if inactive set position to 0 degree
    hour_servo3.write(0);
    hour_servo4.write(0);
    hour_servo5.write(0);
    hour_servo6.write(0);
    hour_servo7.write(0);
    hour_servo8.write(0);
    hour_servo9.write(0);
    hour_servo10.write(0);
        break;
      case '2':
    .
    .
    .
    .

      case '12':
        .

        break;
    }

  delay(100);     // servos need time to move

    switch(minutes) {
      case '1':
        .

        break;
      case '2':
    .
    .
    .
    .

      case '60':
    .

        break;
    }
  delay(100);

}

PaulS: Following that logic, you need 9 servos for each digit, except the 10's place in the hour value, where you need 1, for a total of 29 servos. Each servo will be at 0 degrees to represent 0, and at 45 degrees to represent 1. The time is then read by counting the number of 1's in each of the 4 columns:

(0->1)(0->9):(0->9)(0->9);

Should this be:

(0->1)(0->9):(0->5)(0->9);

Trying to imagine 11:73 in the morning makes my head hurt.

Should this be:

(0->1)(0->9):(0->5)(0->9);

Well, it was about 2:73 in the morning when I wrote that. Yes, you are right. That, of course, drops by 4 the number of servos needed.

i have problems setting time with buttons ... i cant figure out how to do it ? it is specially, how can can get the servos to react when sitting the time .. so i can visualize the time setting ( if that made sense )

any suggestions on how to do it ? pls