Project tutorial
Arduino Baby Mobile (Marvel Inspired)

Arduino Baby Mobile (Marvel Inspired) © CC BY

I built my baby a mobile for entertainment, soothing, and to help him learn to track objects.

  • 1,744 views
  • 3 comments
  • 8 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
SparkFun Slip Ring
Slip rings allowed the semi-circle arcs to turn infinitely without tangling the wires that powered the LEDs.
×1
Adafruit industries ada1609 image 75px
Perma-Proto Breadboard Half Size
×1
Uploads2ftmp2faf14b478 ba93 4677 99f7 371c74d0b9472fck645switch mi2efafyps
C&K Switches PTS 645 Series Switch
Four buttons provided simple inputs for changing the mobile behavior during operation.
×1
5320360
Rocker Switch, Non Illuminated
A simple power switch
×1
1304 05
Adafruit USB Li Ion Battery Charger
This simple USB power supply powered the Arduino and the downstream lights and motors.
×1
SparkFun Servo - Generic High Torque Continuous Rotation (Standard Size)
Two servos turned the semi-circle arcs. I chose this item because it was in a drop-down list, but in reality the servos used were not high in torque, the were deliberately weak.
×1
EVA foam - Interlocking Fitness Mat
This was used to build the semi-circle arcs, which were the rotating members of the mobile.
×1
Rhxvhx2dhljmbtloxexc
Arduino Proto Shield
I didn't use this and I should've.
×1

Necessary tools and machines

3drag
3D Printer (generic)
Contact cement
Craft Knife

Apps and online services

About this project

My first kid needed stimulation, relaxation, and lots of shape/color/movement data for developing his brain, so I decided to build him a mobile.

Typically I like to conceptualize fully-formed projects before starting, but in this case I didn't know what would appeal to him, so it was very iterative and hacked together. I'm going to write this guide primarily as instructions based on the outcome, but I'll share some of the development process because I think it'll be useful to anyone looking to build a mobile, particularly if you want to pick ideas from this while building something unique.

Concept Development

I wanted a lightweight object moved by a servo to entertain my new roommate. I wanted it to hold his attention when he was bored and fussy, but also not be so exciting as to keep him awake.

Most mobiles hang directly in front of a child, but my immediate concern was keeping the mounting system simple and I didn't like the idea of an object suspended directly above him with a cantilevered attachment to the side of the crib.

Instead, I opted to have the moving element attach to a post rising vertically from the side of the crib where it clipped. That led to the idea to have a servo on the top of a post, and for symmetry I could have one on each side.

This concept brought to mind the chair used to brainwash Bucky Barnes in the Marvel films:

This struck me as a funny joke, because my husband and I love Bucky and like to joke about parenting as a form of well-intended indoctrination. More practically, though, the two semi-circular arms rotating around motors at the top of posts seemed visually pleasing.

One of the most challenging elements of this project was developing the aesthetic and behavior of the mobile. For most functional designs, physics sets the design parameters. But in this case, the usefulness of the device is measured by my son's subjective rating of it's entertainment value and its ability to soothe him. With that in mind, I looked at a few commercial mobiles and then made my best guess as to what a baby would find appealing. I then prototyped and iterated to see what his response was and assure the safety as development proceeded. With Calvin's help we were able to produce something which he clearly enjoyed and which I felt confident could cause him no harm.

The following steps walk through building the mechanical arms, assembling the control electronics, and coding the script that controls rotation and lights.

Step 1: Build the mechanical arms

1.1: 3D print the following parts:

  • Clips that mount to the crib sides (x2)
  • The post swivel peg on which each arm is mounted (x2)
  • The upper arm (x2)
  • The big and little gears (x2)
  • The pivot spine (x2)
  • The curvature spines for the semi-circle arcs (x4)
  • Light caps with fun shapes and colors
  • Crib-cliping wire guides (x6)

These parts are listed on Thingiverse here: www.thingiverse.com/thing:4490957

1.2: Assemble the foam semi-circle arcs

Cut four two-inch strips from the EVA foam mats. Apply contact cement to the pivoting spines, allow the glue to dry for 10 minutes or so and then apply it to the center of one of the cut strips, curving the foam. Repeat with two more of the standard spines to give the foam a consistent-radius arc. Then apply contact cement to the inner face of the curve and to one side of another foam strip. Let it dry for ten minutes and then press them together to permanently affix a second foam strip to the first. Repeat this a second time to get the two semi-circle arcs.

Use a drill to create holes in the foam that align with the holes in the pivot spine that screw the pivot spine onto the large gear and test-screw the pivot spine onto the large gear. Screw the slip ring onto the top of the post. Glue and/or screw the small gear onto a servo horn and attach the horn and gear to the servo. Slide it into place and tighten the three set screws on the side of the arm so that the servo motor turns the large gear.

1.3: Insert the lights and wire them to the slip ring

Mark where you want your LEDs to sit and then poke holes in the foam for them. Solder a resister to each and solder wires that lead from the positive and ground pins of the LEDs. Run these along the back of the arc and solder them to the slip ring, making sure to mark which color attaches to which LED.

Check your wiring guide twice and then attach the wires from the slip ring and the servo motor to a CAT5 jack so that the CAT5 plug coming from the control module will match each Arduino pin with the correct component (see below).

Once all the lights are soldered and heat shrinked, insert them into the holes in the foam so they stick out where you want them to, and use a craft knife to make cuts that the tabs on the colored light covers will wedge into. I found no glue was needed. I printed the caps in white and colored them with sharpies to save the effort of switching filament, but there's no wrong way to do this.

Step 2: Assemble the control module

The control module consists of an Arduino, several buttons, a USB battery with a power switch, and the wires that connect the controller to each arm. The control module is connected to the arms using a CAT5 ethernet cable, which has eight wires and was lying around. You'll want to (1) identify which components connect to which Arduino pins, then (2) decide how to connect the Arduino pin headers to everything else, (3) determine how long the wire between the controller and the arms needs to be, and then (4) get to building.

2.1: Matching components to pins

Below you can see a system diagram and a list of which component each Arduino pin connected to.

2.2: Deciding how to connect the Arduino to the components

I connected the Arduino to the rest of the electronics by soldering on right-angle header pins to a perma-protoboard which connected to the main digital pins and then soldered wires with header connectors to connect to the power, ground, and analog pins which were used to read the four buttons. I think the more professional approach would've been to use an Arduino shield. You can see a model of what I did below. The key thing is that you'll want to be able to plug the buttons into the analog pins (plus power and ground) and the wires from the two CAT5 cables (a total of 16 wires) to digital pins 0 - 11, plus a 5V pin and a ground pins for each of the two cables.

2.3: Cutting the CAT5 cables to length

Mine were 50 cm (20") each. Make sure this size allows each cable to reach from the control module to the base of each arm.

2.4: Building the controller

Strip the CAT5 wires and solder them to your board. The other end is going to connect to your slip ring. I recommend soldering a CAT5 jack to the slip ring wires so that the controller can be easily connected and disconnected.

Some Design Notes

During the design I frequently considered and then changed my mind about including a sound board and speaker (and ultimately chose not to). I also considered upgrading the board to an Arduino Mega so that I could enable all the lights to dim. Due to the limited number of PWM-capable pins on the Uno, I couldn't make ten lights fade in and out while still controlling two servo motors. I ultimately chose not to do this either.
There are many things I considered doing that I didn't, including replacing the first prototype arm with the illuminated version and designing a variety of movement routines. The reason why was that despite appearances, this wasn't just a vanity project: as a new dad, my time is valuable and is spent finding ways to help my son, so once something worked I tended to move on to solving new problems. This was meant to help him sleep and calm him when he cried, and to my surprise it worked quite well: he liked the spinning, he liked the lights, and he liked the way it moved so left each as they were. But now you know there are ways to add even more razzle-dazzle, if you're looking to show me up. (Please do and post updates!)

3: Coding the mobile

Obviously you can copy and paste the code I used, however I'm guessing that you'll want to use this as a platform for further improvements. To do so, I recommend setting up a breadboard with the LEDs and servos connected to another CAT5 ethernet jack and then connecting the controller with the Arduino to make yourself a prototyping dummy of the mobile. Then, either modify the attached code or start making your own from scratch.

Be aware that if you're using the code attached that I never coded in the lights for the second arm or specific commands for the second servo (it just rotates at a constant speed). As I've mentioned, the mobile worked without these so I didn't bother. If you want to include these you'll have to do a bit of coping and posting, or just mirror values from one arm to the other.

3.1: Getting started with coding the mobile

The way I made this code was by first preparing a loop that actuated a component in turn: it would set the speed on the servo, then blink light 1, 2, 3, 4, etc. to confirm that everything was connected. Then, I experimented with servo movements I liked by setting a delay after which the servo speed would change and a set of rules on when it reached its max speed in either direction how to begin slowing down and reversing direction the other way. It was a little tricky for me to imagine how I wanted it to move, so I suggest two strategies.

Strategy 1: start the servo turning and adjust the speed in various ways and experiment until you stumble on to something you like.

Strategy 2: Hold it in your hand and turn the arc back and forth at different speeds to develop a sense of what you'd like it to do, then try to translate that into code.

I used the first strategy, which led to the oscilating pattern I ended up with. I did a similar thing to program the lights to simply cycle 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 ...

3.2 Coding simultaneous events

This project introduced me to a tricky challenge I've seen experts address many times in YouTube videos I watch but never had to deal with myself: I want two servos and 10 LEDs to react at the same time, which means I can't have any of them on delays or everything else will be delayed while one of them is reacting. The solution is fairly simple, but takes a bit of puzzle solving anyway. Instead of telling a light to turn on and then delay, we need to tell it to turn on when a countdown timer reaches zero, then set a new countdown timer that will trigger it to turn off. This same principle gets applied to all events, including every change in speed of the servos.

In the process of adding these timers you'll wind up with a lot of variables and state switches, and these provide useful tools for controlling behavior with the buttons. For instance, you might want to be able to turn off rotation and just allow the lights to play. You may want to set it on a 10 minute cycle and use the buttons to add additional time. I used mine mostly for debugging, but then found some of the debugging actions useful. I instructed the LED on the Arduino to blink after each press for diagnostic purposes.

Conclusions

And that's it. This was a fun project because I got to apply many new techniques I'd never used. I also got to see my baby examine and interact with it. I delighted in watching his little potato brain try and parse its mysteries, and I also was grateful for the relief it provided at times when he needed more engagement than I or his other parent had the energy for.

Lastly, I want to address recurrent safety concerns that have emerged. Although I'll list several specifics, my primary point is to reassure any reader that Calvin's safety is always on my mind and my husband's. After extensive use I want to assure anyone reading this that I would not post these plans if experience ever suggested to me or my husband that this device presented risks of harm to a child. Whatever the appearance in the video below, please rest easy: he's safe and well cared for.

The major concern expressed is that it will collide with the baby. First, it should be known that its distance at its closest is much further than it appears in the video. Additionally, babies do not sit up spontaneously. It was a gradual process before he developed the ability to even reach up and touch it.

Additionally, its speed is deceiving. It moves more gradually than it appears. Its weight is incredibly low, and the motors weak. Even if it collided with Calvin's head, it would stop without eliciting a cry. Lastly, because it's on a post, any collision causes the whole arm to rotate rather than apply any force on the obstruction in its path. So even though the motor stops easily, it doesn't need to: any obstruction experiences a force roughly equivalent to that resulting from dropping a stuffed toy from around six inches height.


Code

Mobile run codeArduino
This Arduino code controls the mobile
/* Andrew R Gross - Mobile v1
 *  
 */

#include <Servo.h>

const int button1Pin = A0;     // the number of the pushbutton pin
const int button2Pin = A1;
const int button3Pin = A2;
const int button4Pin = A3;

const int led0 = 0;
const int led1 = 1;
const int led2 = 2;
const int led3 = 3;
const int led4 = 4;

const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

//Parameters
int maxSpeedL = 120;
int minSpeedL = 60;
int maxSpeedR = 110;
int minSpeedR = 80;
int leftSpeed = 88;
int slDelay = 50;
int slDelayDelay = 5000;
int adjuster = -1;
int pauseButton = 0;
int cycleNumber = 50;
int lightDelay = 1000;
int timer = 13000;

int currentLed = 0;

Servo servoLeft;  // create servo object to control a servo
Servo servoRight;

unsigned long currentMillis;
unsigned long slMillis;
unsigned long slDelayMillis;
unsigned long lightMillis;

void setup() {      ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  servoLeft.attach(10);  // attaches the servo on pin 9 to the servo object
  servoRight.attach(11);

  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);     
  pinMode(led0, OUTPUT);   
  pinMode(led1, OUTPUT); 
  pinMode(led2, OUTPUT); 
  pinMode(led3, OUTPUT); 
  pinMode(led4, OUTPUT); 
  
  // initialize the pushbutton pin as an input:
  pinMode(button1Pin, INPUT);     
  pinMode(button2Pin, INPUT); 
  pinMode(button3Pin, INPUT); 
  pinMode(button4Pin, INPUT); 

          
  digitalWrite(led0, LOW); 
  digitalWrite(led1, LOW); 
  digitalWrite(led2, LOW); 
  digitalWrite(led3, LOW); 
  digitalWrite(led4, LOW); 
        

}

void loop() {        ///////////////////////////////////////////////////////////////////////////////////////////////////////////

  currentMillis = millis();


  //// Run through Routine
  
  if(currentMillis < timer){                          // If the cycle hasn't run down, proceed
    
    if(pauseButton == 0){                       // Check if pause is on. If it isn't, proceed

      if(currentMillis - slMillis > slDelay) {  // Check if it's time to adjust servoLeft based on delay
        slMillis = currentMillis;
        leftSpeed = leftSpeed + adjuster;
        servoLeft.write(leftSpeed);
        //servoRight.write(leftSpeed);

        if(leftSpeed <= minSpeedL) {
          adjuster = 1;
          slMillis = slMillis - slDelay;
          } // If the servo speed hits its minimum, reverse accelleration direction
        else if(leftSpeed >= maxSpeedL) {
          adjuster = -1;
          slMillis = slMillis - slDelay;
          }// If the servo speed hits its max, reverse acceleration direction. I think I need else if
      }

      else if(currentMillis - slDelayMillis > slDelayDelay) { // Check if it's time to adjust the delay
        slDelayMillis = currentMillis;
        slDelay = slDelay + 1;
//        cycleNumber = cycleNumber -1;
      }


      if(currentMillis - lightMillis > lightDelay) {
        lightMillis = currentMillis;
        
        digitalWrite(led0, LOW); 
        digitalWrite(led1, LOW); 
        digitalWrite(led2, LOW); 
        digitalWrite(led3, LOW); 
        digitalWrite(led4, LOW); 
        
        if(currentLed == 0){
          digitalWrite(led0, HIGH);
          currentLed = 1;
        }
        else if(currentLed == 1){
          digitalWrite(led1, HIGH);
          currentLed = 2;
        }
        else if(currentLed == 2){
          digitalWrite(led2, HIGH);
          currentLed = 3;
        }
        else if(currentLed == 3){
          digitalWrite(led3, HIGH);
          currentLed = 4;
        }
        else if(currentLed == 4){
          digitalWrite(led4, HIGH);
          currentLed = 0;
        }

        
      }

/*
  digitalWrite(led0, HIGH); delay(500); digitalWrite(led0, LOW); 
//  digitalWrite(led1, HIGH); delay(500); digitalWrite(led1, LOW); 
//  digitalWrite(led2, HIGH); delay(500); digitalWrite(led2, LOW); 
//  digitalWrite(led3, HIGH); delay(500); digitalWrite(led3, LOW); 
//  digitalWrite(led4, HIGH); delay(500); digitalWrite(led4, LOW); 


  if(leftSpeed <= minSpeed){adjuster = 1;} // If the left speed is less than the minimum speed, reverse speed 
  if(leftSpeed >= maxSpeed){               // If the left speed is greater than the max: 
    adjuster = -1;                         // the adjuster flips...
    leftDelay = leftDelay + 5;             // ... the 
    cycleNumber = cycleNumber - 1;
    }

  //servoLeft.attach(11);
  servoLeft.write(leftSpeed);
  delay(leftDelay);
  leftSpeed = leftSpeed + adjuster;
*/

    }
    else {                                      // If pause button is ON:
      servoLeft.detach();                       // Stop the servo
      //leftDelay = 10;
      }
  }
  
  else {                                        // If the cycle has run down
    servoLeft.detach();                         // Shut the servos off
    //servoRight.detach(10);
    }

  //// Button programs
  
  if (digitalRead(button1Pin) == HIGH) {                    // turn LED on:    
    digitalWrite(ledPin, HIGH); delay(200); digitalWrite(ledPin, LOW); delay(500); 
    slDelay = 10;
    slDelayDelay = 1000;
  }  

  else if (digitalRead(button2Pin) == HIGH) {                    // turn LED on: 
    timer = currentMillis + 3000;   
    digitalWrite(ledPin, HIGH); delay(200); digitalWrite(ledPin, LOW); delay(200); 
    digitalWrite(ledPin, HIGH); delay(200); digitalWrite(ledPin, LOW); delay(200); 
  }  

  else if (digitalRead(button3Pin) == HIGH) {                    // turn LED on:    
    digitalWrite(ledPin, HIGH); delay(200); digitalWrite(ledPin, LOW); delay(200); 
    digitalWrite(ledPin, HIGH); delay(100); digitalWrite(ledPin, LOW); delay(100); 
    digitalWrite(ledPin, HIGH); delay(100); digitalWrite(ledPin, LOW); delay(100); 
    pauseButton = 0;
    cycleNumber = cycleNumber + 10;
    servoLeft.attach(10);
  }  

  else if (digitalRead(button4Pin) == HIGH) {                    // turn LED on:    
    digitalWrite(ledPin, HIGH); delay(50); digitalWrite(ledPin, LOW); delay(50); 
    digitalWrite(ledPin, HIGH); delay(50); digitalWrite(ledPin, LOW); delay(50); 
    digitalWrite(ledPin, HIGH); delay(50); digitalWrite(ledPin, LOW); delay(50); 
    digitalWrite(ledPin, HIGH); delay(50); digitalWrite(ledPin, LOW); delay(50); 
   // servoRight.write(85);
    pauseButton = 1;
    servoLeft.detach();
   // if (pauseButton == 0){pauseButton = 1}
   // else if (pauseButton == 1){pauseButton = 0;}
    }
    
  else {    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
  //servoLeft.detach();
}

Custom parts and enclosures

Baby Mobile Parts
All the 3D printed parts

Schematics

System diagram
This is the total system diagram. It's the same as the version in the text above.
Mobile sketch 2 bb 2 e7ibflkosg ztilqoqxht

Comments

Similar projects you might like

Joy Robot (Robô Da Alegria)

Project tutorial by Igor Fonseca Albuquerque

  • 6,007 views
  • 6 comments
  • 36 respects

Child Assistant

Project tutorial by Md. Khairul Alam

  • 3,609 views
  • 0 comments
  • 20 respects

LOL Surprise Doll Hotel Elevator controled by mobile phone

Project in progress by Dkovacic74

  • 1,875 views
  • 0 comments
  • 10 respects

Long Range Remote Controller PCB for RC Robot

Project tutorial by Jithin Sanal

  • 4,043 views
  • 2 comments
  • 19 respects

How to Make a Walking Robot

Project tutorial by MEGA DAS

  • 1,174 views
  • 0 comments
  • 7 respects

Brainium Bridge Baby Monitor

Project tutorial by Alejandro Sanchez and Victor Altamirano

  • 675 views
  • 0 comments
  • 4 respects
Add projectSign up / Login