Introduction: Powered Mobility Training Device for Toddlers
This instructable will go through the steps required for building a powered mobility training device for young children. The device consists of a 4 wheel platform, of which two are drive wheels controlled by a standard 9 pin direction input interface. This instructable offers two approaches to build this device. One approach uses an off the shelf baby cruizer as the platform, while the other requires a DIY platform. The second, DIY approach, is the one this instructable will focus on. Both approaches require a standard car seat for the child to use the device.
Step 1: Parts List
Please find the parts list attached.
Do note that the parts list is not exhaustive. Things that are NOT listed include:
- Tools and equipment that you might require to assemble the parts, such as soldering irons and screwdrivers.
- Standard fasteners such as screws, bolts and nuts.
The following steps are a guideline to construct this device. Please feel free to modify the size and design of the device to fit your purpose.
Step 2: Electronics: Introduction
The electronics are crucial to the operation of the device, and this is likely the most complicated step of the entire instructable. To begin this step, please ensure that you have a good soldering iron, as well as a roll of solder. Other equipment you might find useful includes desoldering braids to help remove bad solders, and a set of vices to help you hold the part in place.
We will be using an Arduino Uno as the main microcontroller. This is the device which the code will be uploaded to. The two motor shields will be our interface between the Arduino board and the motors. The reason why they are called "shields", is because they were designed to be stacked on top of the Arduino Uno, or on each other; that is precisely what we will be doing.
Look at the motor shields. You should see two sets of two-column pins in the middle of the board, labelled DIR and PWM.
- For the first board, place a jumper connector (circled red in the image) at row labelled D2 for DIR, and row labelled D3 for PWM.
- For the second board, place a jumper connector (circled red in the image) at row labelled D4 for DIR, and row labelled D5 for PWM.
Step 3: Electronics: Circuit Board
In this step, we will be constructing our own "shield" to wire up the electronics. Before you begin, cut the copper prototyping board to size, i.e. 22 holes x 35 holes.
Follow the illustrations for soldering the components and wires on the copper prototyping board. The placement of the components are shown on the illustration of the bottom of the board, while the points to solder are indicated by the illustration of the top of the board with the white pill shapes. Ensure that the areas indicated by the pill shapes are soldered together.
Use the solid core wires for all wiring, with the exception of the wires going to the battery.
This are the connections that we will establish:
- D8, D9, D10, D11, Ground to Controller 9 Pin input.
- Current Sensor A: Ground to Ground, VCC to 5V, Out to A1.
- Current Sensor B: Ground to Ground, VCC to 5V, Out to A0.
- Potentiometer: Left pin to Ground, Right pin to 5V, Middle pin to A3.
Step 4: Electronics: Direction Buttons
The input device requires a DB9 connection for it to deliver the correct input. Enabling Devices carries a variety of options for different capabilities: https://enablingdevices.com/catalog/capability_switches
Connect your controller to the DB9 connector. Using a multimeter to check for connectivity, ensure that:
- D8 is connected to Forward
- D9 is connected to Reverse
- D10 is connected to Right
- D11 is connected to Left
Step 5: Electronics: Power
Connect the voltage regulator to the circuit board as per the illustration in step 3 if you have not done so. Plug the battery to the circuit using the battery cable provided, and switch on the circuit. You should see the voltage regulator's display light up, indicating the input voltage (see image). Press the "O" button on the voltage regulator, this displays the output voltage. Press either "+" or "-" to add or subtract the number till the display reads 9.0. This ensures that 9V is supplied to the Arduino Board.
Turn off the circuit.
Plug the barrel jack from the voltage regulator into the Arduino Board. Following the illustration in step 3, connect the ground (black) cables from the circuit board to the - (negative) input on the motor shields, and the power (red) cables from the circuit board to the + (positive) input on the motor shields.
Turn on the circuit.
Press the A button on the motor shields, you should see a red LED labelled A light up. Do the same for the B button, you should see a red LED labelled B light up. You have now successfully powered the electronics!
Step 6: Electronics: Current Sensors & Motors
We will now prepare the wiring to connect the motor shield to the motors. To ensure that the 2 drive motors drive consistently, we will run one of the wires going to each motor through a current sensor.
Prepare 2 x 4" length of 16 gauge red primary wire. Connect them to the A outputs on the motor shields. Next, we will solder them to the corresponding current sensors:
- Solder the wire from the motor shield with D2 connected to DIR to the hole at the start of the arrow on Current Sensor A.
- Solder the wire from the motor shield with D4 connected to DIR to the hole at the start of the arrow on Current Sensor B.
Prepare 2 x 2 feet length of 16 gauge red primary wire, and 2 x 2 feet length of 16 gauge black primary wire. Solder the ends of the red primary wire to the holes at the end of the arrow for each current sensor. Connect the black primary wire to the B outputs on each motor shield. At the ends of these long primary wires, attach the female spade connectors. These will connect to the motors.
Insert the shields and circuit board on top of one another. The Arduino Uno board forms the bottom layer, followed by the two motor shields, and lastly the circuit board goes on top. Ensure that you push the male header pins into the female headers, and make sure that all the pins are aligned.
Make sure that you group the correct pair of wires together. Ensure that the red wire from Current Sensor A is paired with the black wire from the motor shield with D2 connected to DIR, and that the red wire from Current Sensor B is paired with the black wire from the motor shield with D4 connected to DIR.
Step 7: Electronics: Upload Code
Upload the following code to the Arduino Uno board. You can find instructions on how to set up your arduino here:https://www.arduino.cc/en/Guide/HomePage
//start of code
const int DIR_A = 2, //Motor Shield A DIR pin
DIR_B = 4, //Motor Shield B DIR pin PWM_A = 3, //Motor Shield A PWM pin PWM_B = 5, //Motor Shield A PWM pin POT = A3, //Potentiometer pin FORWARD = 8, //Forward pin REVERSE = 9, //Reverse pin LEFT = 11, //Left pin RIGHT = 10, //Right pin CURRENT_A = A1, //Current Sensor A pin CURRENT_B = A0; //Current Sensor B pinint DIR, OLD_DIR; // Controller Input and Input history boolean stop_all = false; //Decrease speed to 0
//Declaring variables int MAX_SPEED = 230, MIN_SPEED = 60; float acc = 0; float LEFT_SPEED = 0; float RIGHT_SPEED = 0; float COMP_A = 0; float COMP_B = 0; int LEFT_MOTOR_DIR = 0; int RIGHT_MOTOR_DIR = 0; double TIME_TO_MAX_SPEED = 5000; int DELAY = 100;
void setup() {
//Defining Input and Output pins pinMode(DIR_A, OUTPUT); pinMode(DIR_B, OUTPUT); pinMode(PWM_A, OUTPUT); pinMode(PWM_B, OUTPUT); pinMode(RIGHT, INPUT_PULLUP); pinMode(LEFT, INPUT_PULLUP); pinMode(FORWARD, INPUT_PULLUP); pinMode(REVERSE, INPUT_PULLUP); pinMode(POT, INPUT); pinMode(CURRENT_A, INPUT); pinMode(CURRENT_B, INPUT);
//Initializes serial port for monitoring if necessary Serial.begin(9600);
DIR = (digitalRead(FORWARD) << 3) + (digitalRead(REVERSE) << 2) + (digitalRead(LEFT) << 1) + (digitalRead(RIGHT)); OLD_DIR = DIR;
//Decrease PWM frequency to reduce motor whine setPwmFrequency(3,1); setPwmFrequency(5,1); }
void loop() {
//Reads the controller input //FORWARD: B0111 //REVERSE: B1011 //LEFT: B1101 //RIGHT: B1110 DIR = (digitalRead(FORWARD) << 3) + (digitalRead(REVERSE) << 2) + (digitalRead(LEFT) << 1) + (digitalRead(RIGHT));
//READS THE POTENTIOMETER AND MAPS IT TO THE MINIMUM AND MAXIMUM SPEED int SPEED = map(analogRead(POT), 0, 1023, MIN_SPEED, MAX_SPEED);
//READS THE CURRENT SENSOR TO BALANCE THE LOAD GOING INTO BOTH MOTORS double I_A = ((((double)analogRead(CURRENT_A)) * 5/ 1023.0) - 2.5) / 0.1; double I_B = ((((double)analogRead(CURRENT_B)) * 5/ 1023.0) - 2.5) / 0.1;
//IF NO BUTTONS PRESSED, STOP THE MOTORS if (DIR==B1111) { stop_all = true; } if (stop_all) { LEFT_SPEED = (LEFT_SPEED <= 0) ? 0 : LEFT_SPEED-(SPEED/TIME_TO_MAX_SPEED*DELAY*2); RIGHT_SPEED = (RIGHT_SPEED <= 0) ? 0 : RIGHT_SPEED-(SPEED/TIME_TO_MAX_SPEED*DELAY*2); } if (LEFT_SPEED==0 && RIGHT_SPEED==0 && B1111) { stop_all = false; OLD_DIR = DIR; }
//IF MOTORS ARE INACTIVE, LISTEN FOR CONTROLLER INPUT if (stop_all==false) { if (DIR != OLD_DIR && digitalRead(FORWARD) != B0) { DIR = OLD_DIR; } switch(DIR) {
case B0111: //FORWARD
// current sensor compensation if (abs(I_A-I_B) > 0.1) { if (I_A>I_B) { COMP_A = (I_A-I_B)*SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; COMP_B = (I_A-I_B)*-SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; } else { COMP_A = (I_A-I_B)*-SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; COMP_B = (I_A-I_B)*SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; } } else { COMP_A = 0; COMP_B = 0; }
// calculate acceleration acc = (SPEED-LEFT_SPEED)*0.1; acc = (acc >= 6) ? 6 : acc; acc = (acc <= 1) ? 1 : acc;
// add acceleration and compensation to the left and right motors LEFT_SPEED = LEFT_SPEED+acc+COMP_B; RIGHT_SPEED = RIGHT_SPEED+acc+COMP_A; LEFT_SPEED = (LEFT_SPEED >= SPEED) ? SPEED : LEFT_SPEED; RIGHT_SPEED = (RIGHT_SPEED >= SPEED) ? SPEED : RIGHT_SPEED;
//Set motor directions, 1=forward, -1=reverse LEFT_MOTOR_DIR = 1; RIGHT_MOTOR_DIR = 1;
break; case B0101: //steer left when moving forward LEFT_SPEED = LEFT_SPEED*0.9; RIGHT_SPEED = RIGHT_SPEED; break; case B0110: //steer right when moving forward LEFT_SPEED = LEFT_SPEED; RIGHT_SPEED = RIGHT_SPEED*0.9; break;
case B1011: //REVERSE
// current sensor compensation if (abs(I_A-I_B) > 0.1) { if (I_A>I_B) { COMP_A = (I_A-I_B)*SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; COMP_B = (I_A-I_B)*-SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; } else { COMP_A = (I_A-I_B)*-SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; COMP_B = (I_A-I_B)*SPEED/TIME_TO_MAX_SPEED*DELAY*0.1; } } else { COMP_A = 0; COMP_B = 0; }
// calculate acceleration acc = (SPEED-LEFT_SPEED)*0.1; acc = (acc >= 6) ? 6 : acc; acc = (acc <= 1) ? 1 : acc;
// add acceleration and compensation to the left and right motors LEFT_SPEED = LEFT_SPEED+acc+COMP_B; RIGHT_SPEED = RIGHT_SPEED+acc+COMP_A; LEFT_SPEED = (LEFT_SPEED >= SPEED) ? SPEED : LEFT_SPEED; RIGHT_SPEED = (RIGHT_SPEED >= SPEED) ? SPEED : RIGHT_SPEED;
//Set motor directions, 1=forward, -1=reverse LEFT_MOTOR_DIR = -1; RIGHT_MOTOR_DIR = -1; break;
case B1101: //LEFT
// calculate acceleration acc = (SPEED-LEFT_SPEED)*0.1; acc = (acc >= 15) ? 8 : acc; acc = (acc <= 1) ? 1 : acc;
// add acceleration and compensation to the left and right motors LEFT_SPEED = LEFT_SPEED+acc; RIGHT_SPEED = RIGHT_SPEED+acc; LEFT_SPEED = (LEFT_SPEED >= SPEED) ? SPEED : LEFT_SPEED; RIGHT_SPEED = (RIGHT_SPEED >= SPEED) ? SPEED : RIGHT_SPEED;
//Set motor directions, 1=forward, -1=reverse LEFT_MOTOR_DIR = -1; RIGHT_MOTOR_DIR = 1; break;
case B1110: //RIGHT
// calculate acceleration acc = (SPEED-LEFT_SPEED)*0.1; acc = (acc >= 15) ? 8 : acc; acc = (acc <= 1) ? 1 : acc;
// add acceleration and compensation to the left and right motors LEFT_SPEED = LEFT_SPEED+acc; RIGHT_SPEED = RIGHT_SPEED+acc; LEFT_SPEED = (LEFT_SPEED >= SPEED) ? SPEED : LEFT_SPEED; RIGHT_SPEED = (RIGHT_SPEED >= SPEED) ? SPEED : RIGHT_SPEED;
//Set motor directions, 1=forward, -1=reverse LEFT_MOTOR_DIR = 1; RIGHT_MOTOR_DIR = -1; break; } }
//set motor directions if (RIGHT_MOTOR_DIR > 0) { digitalWrite(DIR_A, LOW); } else { digitalWrite(DIR_A, HIGH); } if (LEFT_MOTOR_DIR > 0) { digitalWrite(DIR_B, LOW); } else { digitalWrite(DIR_B, HIGH); }
//set motor speed LEFT_SPEED = LEFT_SPEED <= 0 ? 0 : LEFT_SPEED; RIGHT_SPEED = RIGHT_SPEED <= 0 ? 0 : RIGHT_SPEED; analogWrite(PWM_A, RIGHT_SPEED); analogWrite(PWM_B, LEFT_SPEED);
OLD_DIR = DIR;
Serial.print(SPEED); Serial.print(" | "); Serial.print("LEFT:"); Serial.print(LEFT_SPEED); Serial.print(" | "); Serial.print("RIGHT:"); Serial.println(RIGHT_SPEED);
delay(DELAY);
}
// Sets the frequency of the PWM void setPwmFrequency(int pin, int divisor) { byte mode; if(pin == 5 || pin == 6 || pin == 9 || pin == 10) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 64: mode = 0x03; break; case 256: mode = 0x04; break; case 1024: mode = 0x05; break; default: return; } if(pin == 5 || pin == 6) { TCCR0B = TCCR0B & 0b11111000 | mode; } else { TCCR1B = TCCR1B & 0b11111000 | mode; } } else if(pin == 3 || pin == 11) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 32: mode = 0x03; break; case 64: mode = 0x04; break; case 128: mode = 0x05; break; case 256: mode = 0x06; break; case 1024: mode = 0x7; break; default: return; } TCCR2B = TCCR2B & 0b11111000 | mode; } }
//end of code
Step 8: Electronics Box
If you want, you can package the electronics in a box. Attached is a pdf file for a box design that you can laser cut out of a 0.12" acrylic sheet. Remember to insulate any metal parts near the electronics to minimize the chance of short circuiting.
Attachments
Step 9: Cart: Overview of the Cart
Two carts were made to secure a child's car seat to the powered wheels. A 3/4" plywood sheet was used as the foundation for both carts. One cart was adapted to fit onto an existing product, the Travelmate Deluxe Cruizer, and the other cart was made with 2x4's attached to the plywood. These are minimal designs and there is much room for variation based on specific additional needs.
The 3/4" plywood was cut to approximately 14"x31" on both carts. The 14" width was used based on the width of the Travelmate Deluxe Cruizer and worked for 2x4 cart to secure the child's car seat. The length of 31" was used to utilize fastening to plastic holes on the bottom of the Travelmate Deluxe Cruizer and overhang appoximately 7" to accommodate the electronics box and battery. The image above provides an overview of the assembly and each component for the 2x4 cart.
Step 10: Cart: Cart Underside Assembly
Starting with four 2x4's(step 1) attach a small plywood piece to mount the front casters(step 2). Next attach the foundation plywood with the motor assemblies(step 3). Finally attach the front casters inset at least a few inches to allow for clearance of the pvc tray holder in a later stage(step 4). This may be a good time to connect and test the wires to the motors that will run to the green current sensors in the step 3 graphic of the bottom circuit diagram. Once tested label the wires since the connection order will affect the controller input for direction commands to the motors. For instance, if the controller inputs for forward and reverse are opposite you will need to switch the connections on the motor wire terminals. The cut pipe holders(described in next step) can be attached at this point as well.
Step 11: Cart: Attaching the Car Seat
To secure the cart seat we attached four eye lag screws to the top and sides of the 2x4 base. The existing car seat connections were used when possible but an adjustable strap secured with carabiners had to be made for securing the front of the seat. With the seat secured you can determine the proper size for next step making the pvc tray holder and footrests. The battery and electronics box can be added and secured with velcro or straps.
Step 12: Cart: PVC Tray Holder
We built a few variations of the tray holders out of 1" pvc plumbing pipe and standard T and 45/90 degree joints. The lengths and configurations depend on the size of the child and any specific accommodations for limitations of mobility or body support. A tray holder is used to support the enabling device controller that will be used for directional input to the cart. The pvc structure is connected to the cart with pipe holders modified to allow for a friction fit. This allowed a relatively easy attachment and detachment from the cart to allow entry into the car seat. We added a footrest for larger children or to attach a foot pedal input on one of the pvc tray holders.
Step 13: Cart: Travelmate Baby Cruizer
The construction of the cart is similar using the Baby Cruizer but the cost increases significantly. Some advantages are the existing car seat attachment straps, front casters, and assistive handle. Removing the rear wheel and screwing the foundation platform onto the underside of the Baby Cruizer. Marking the existing holes on the underside of the Baby Cruizer with chalk or wax pencil then pressing the plywood against it will transfer the hole locations for pre drilling the plywood. Hand tighten the screws to avoid stripping the plastic.