This project outlines, without going into too much detail, how to build a small XZ robot based on Arduino Uno and Firgelli miniature linear actuators. The electronics and programming skills needed are low. Mechanical skills required (to build something sturdy) are average to okay, meaning, you have to be able to make something solid ;)

What you'll need

Put it all together

The complete system is drawn schematically in Figure 1. The Arduino will hold the firmware to control the motor shield and read the current position of the linear actuators, while displaying any useful information on the LCD.

Motor shield

The Velleman motor shield is a nice product, apart from the fact that Arduino pin A5 is used to monitor the external power supply, since we need pin A5 for I2C control of the LCD. So, if you plan to install an LCD (or other I2C hardware), remove (or don't mount) R9, R10 and C3 (10k, 100k and 22uF) from the Velleman board. Jumper settings for this project are: PWMA:6, DIRA:7, PWMB:9, DIRB:8, power:EXT. After the motor shield is correctly assembled and configured, place it on the Arduino board.

Alternative, the official Arduino motor shield can be used. In this case, change PWM and DIR pins in /libraries/XY/XY.cpp to the pins used by this shield. Also, disable (cut) the current sensing jumpers on the back of the board.

Linear actuators

The Firgelli linear actuators are composed of two parts. A servo motor controls the speed at which the actuator moves. A multiturn potentiometer is connected to the servo motor and is used for position feedback. Simply: the resistance of the potentiometer gives the position of the actuator. Since we want to accurately control the position of the actuators, the firmware has a so-called PID controller that reads the current position (from the potentiometer) and sets the speed of the actuator until the actual position equals the desired position.

For each actuator, connect the red wire to output 1/3 of the motor shield. Black wire goes to 2/4. Connect the yellow wires to Arduino's AREF pin, and the orange wires to GND. The purple wires each go to an Arduino analog input: A0 and A1.

yellowblackredpurpleorange
X-axisArduino::AREFMotorShield::2MotorShield::1Arduino::A1Arduino::GND
Z-axisArduino::AREFMotorShield::4MotorShield::3Arduino::A0Arduino::GND

LCD

If you want to connect an I2C LCD, connect SDA and SCL to Arduino pins A4 and A5, respectively, and connect the power supply wires to GND and 5V. For LCDs with the LCD03 protocol, the firmware works out of the box. For different LCDs, change /sketches/dipcoater.ino to suit your needs: change the include at the top to the desired library, then change the instantiation and initialization of the LCD in the code.

Power supply

Connect the 12V power supply both to the Arduino power input and to the motor shield power input.

Running the dip coater

The idea behind this dip coater is that it can submerge something in a solution for a certain time, a second solution for a certain time, a third ... etc., while repeating this cycle as often as you want. The firmware (/sketches/dipcoater.ino) has few parameters to control the sequence, which are stated at the top of the code just below the includes. A short explanation follows.

ParameterTypeUnitDescription
NUM_CYCLESint#The total number of cycles the dip coater has to run.
NUM_STEPint#The total number of steps in each cycle.
x_dist[NUM_STEP]doublecmDistance between each dipping container. Starting at X=X_START, the dipping sequence advances by x_dist(current_step) between steps.
x_wait[NUM_STEP]intsecThe number of seconds the dip coater is down (dipping) at each step.
X_STARTdoublecmStarting position in the X direction. Should only be changed for a good reason (e.g. obstruction of the dip coater at X=0). If the first dipping jar is not at X=0, set the position using the first number in the x_dist[] array.
Y_UPdoublecmUp position of the dip coater.
Y_DOWNdoublecmDown position of the dip coater.

Running your own program

The sketch /sketches/random/random.ino contains the bare minimum code, and does random walks over the entire range the actuators can span. Use this sketch if you want to build your own functionality into anything containing one or two linear actuators. IMPORTANT:If you change the linear actuator stroke (mine are 10 and 14 cm for the L12-P and L16-P, respectively), you have to change the TRAVERSE_X and TRAVERSE_Y constants in /libraries/XY/XY.h to match the maximum actual stroke difference you measure between fully retracted and fully contracted actuator shafts.

Fine-tuning the PID

Adjust the PID values according to the forces the actuators have to exert on the system you built them into. To do this, change the values in /libraries/XY/XY.cpp. Parameters given to the functions PIDX.SetTunings(0.1,0.1,0) and PIDY.SetTunings(0.1,0.1,0) are P, I and D, respectively. A quick guide to heuristic PID tuning can be found here.