Tower Crane: control 4 dc motors

I'm still trying to nut out the scales issue but until I get on top of it I'll outline the next part of the process. I need to drive 4 small dc motors with 2 joysticks. Initial research looks like I might need two Arduino Unos because I need, I think, 8 of those outputs with the tildes on them. I have the two joysticks and a couple of L298Ns. Do I need two Arduinos?

To drive a DC motor, you need a PWM pin, a direction pin, and possibly a brake pin, assuming you have the right motor drive hardware.

Word salad, anyone?

You have not provided enough details about your project, but in general this would not be a good idea to spread your code over different MCUs, in case you need to synchronise it. Why not get another board with more PWM pins?

You’ll be good with a single PWM pin plus a direction pin for each motor.

An H-bridge takes a DIRECTION pin and a PWM speed input. 0% = stop. 100% = full speed.

Hence 4 bridges/motors need 8 pins total.

Depending on when you do run out of pins… you can easily step up to a single MEGA2560 with lots of I/O and extra serial ports.

I’ve run 4 bi-di motors, 3x servos and several other devices with room to spare.

Remember to plan your code as non-blocking, so all functions can occur simultaneously.

Hint:; For motors I use a system with the ‘current’ position, and a ‘target’ position… then the repeated call to update handles moving the current position to the target. This can handle all motors running at different speeds to arrive at the same time if required, speed ramping (s-curves etc) and other features.

Thank you, that is very helpful. I think it means the direction pin doesn't have to be a pin with a tilde which would mean there are enough pins on one Arduino Uno.

I will provide more details, I just needed to understand how many Uno I might need.

The tilde just means it's potentially* a hardware PWM pin.
PWM is used for speed control, and some simpler motor drive hardware may require one PWM for forward and another for backward.

* Potentially, because if you use the Servo library, you will lose use of PWM pins.

I don't mind stepping up to a Mega but if a single Uno will do it, I'll go with that. Thanks everybody. I'll set up what I can and come running back when I hit a wall.

Ooops, looks like a Mega now.

Is there stuff you haven't told us about?

Did you read reply #4?

Yes I did, I thought that made sense but then I got confused.
There's not a lot more to know. I have 4 dc motors doing different not important things and I would like to understand how to make them go forwards, backwards and alter the speed. I thought I might be able to do that with an Arduino Uno, two L298Ns and a couple of joysticks. I'm pretty sure I can get two to work so I'll do that then see what I need to do to get the other two to work. Once I can do that I can work out whether to use steppers or dcs for the top end of the crane. Sorry if I'm being a pain.

So last century

It's what popped up most often when searching.

Here is a code to drive two motors using one joystick. My problem with this code is that it is basically to drive a little car around. It drives both motors forwards at the same speed by pushing the joystick forwards and both motors backwards by pushing the joystick backwards. Left drives the car left and right drives the car right. Can this code be changed to drive one motor clockwise by pushing forwards and anticlockwise by pushing backwards? Pushing to the left would drive the other motor clockwise and right anticlockwise. If yes, I believe more modifications would
eventually allow me to drive four motors CW and ACW with two joysticks and two L298Ns. This code and wiring diagram only uses 3 of the tilde pins for two motors and there are six. I apologise for not using the correct technical jargon.

  L298N Motor Control Demonstration with Joystick
  Demonstrates use of Joystick control with Arduino and L298N Motor Controller
  DroneBot Workshop 2017
// Motor A

int enA = 9;
int in1 = 8;
int in2 = 7;

// Motor B

int enB = 3;
int in3 = 5;
int in4 = 4;

// Joystick Input

int joyVert = A0; // Vertical  
int joyHorz = A1; // Horizontal

// Motor Speed Values - Start at zero

int MotorSpeed1 = 0;
int MotorSpeed2 = 0;

// Joystick Values - Start at 512 (middle position)

int joyposVert = 512;
int joyposHorz = 512;  

void setup()


  // Set all the motor control pins to outputs

  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  // Start with motors disabled and direction forward
  // Motor A
  digitalWrite(enA, LOW);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  // Motor B
  digitalWrite(enB, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);

void loop() {

	// Read the Joystick X and Y positions

	joyposVert = analogRead(joyVert); 
	joyposHorz = analogRead(joyHorz);

	// Determine if this is a forward or backward motion
	// Do this by reading the Verticle Value
	// Apply results to MotorSpeed and to Direction

	if (joyposVert < 460)
		// This is Backward

		// Set Motor A backward

		digitalWrite(in1, LOW);
		digitalWrite(in2, HIGH);

		// Set Motor B backward

		digitalWrite(in3, LOW);
		digitalWrite(in4, HIGH);

		//Determine Motor Speeds

		// As we are going backwards we need to reverse readings

		joyposVert = joyposVert - 460; // This produces a negative number
		joyposVert = joyposVert * -1;  // Make the number positive

		MotorSpeed1 = map(joyposVert, 0, 460, 0, 255);
		MotorSpeed2 = map(joyposVert, 0, 460, 0, 255);

	else if (joyposVert > 564)
		// This is Forward

		// Set Motor A forward

		digitalWrite(in1, HIGH);
		digitalWrite(in2, LOW);

		// Set Motor B forward

		digitalWrite(in3, HIGH);
		digitalWrite(in4, LOW);

		//Determine Motor Speeds

		MotorSpeed1 = map(joyposVert, 564, 1023, 0, 255);
		MotorSpeed2 = map(joyposVert, 564, 1023, 0, 255); 

		// This is Stopped

		MotorSpeed1 = 0;
		MotorSpeed2 = 0; 

	// Now do the steering
	// The Horizontal position will "weigh" the motor speed
	// Values for each motor

	if (joyposHorz < 460)
		// Move Left

		// As we are going left we need to reverse readings

		joyposHorz = joyposHorz - 460; // This produces a negative number
		joyposHorz = joyposHorz * -1;  // Make the number positive

		// Map the number to a value of 255 maximum

		joyposHorz = map(joyposHorz, 0, 460, 0, 255);

		MotorSpeed1 = MotorSpeed1 - joyposHorz;
		MotorSpeed2 = MotorSpeed2 + joyposHorz;

		// Don't exceed range of 0-255 for motor speeds

		if (MotorSpeed1 < 0)MotorSpeed1 = 0;
		if (MotorSpeed2 > 255)MotorSpeed2 = 255;

	else if (joyposHorz > 564)
		// Move Right

		// Map the number to a value of 255 maximum

		joyposHorz = map(joyposHorz, 564, 1023, 0, 255);

		MotorSpeed1 = MotorSpeed1 + joyposHorz;
		MotorSpeed2 = MotorSpeed2 - joyposHorz;

		// Don't exceed range of 0-255 for motor speeds

		if (MotorSpeed1 > 255)MotorSpeed1 = 255;
		if (MotorSpeed2 < 0)MotorSpeed2 = 0;		  


	// Adjust to prevent "buzzing" at very low speed

	if (MotorSpeed1 < 8)MotorSpeed1 = 0;
	if (MotorSpeed2 < 8)MotorSpeed2 = 0;

	// Set the motor speeds

	analogWrite(enA, MotorSpeed1);
	analogWrite(enB, MotorSpeed2);


Build that ‘model’ on your dev bench, to understand what’s going on.
There are definitely better h-bridges, but the idea is exactly the same.

Note: The drivers and motors must be matched for voltage & current

Once you figure out what’s going on, migrate the knowledge to your crane project.

One point worth mentioning, is that you’ll probably need reduction gearing of some sort, because while ‘speed control’ theoretically runs from zero to 100%, you’ll probably find friction and mass will interfere with the low-end of the power band.

In a complex real world system (unlikely here - yet) would use PID to modulate the PWM with feedback from the load.

1 Like

I'm pretty sure the motors are geared. It's a cheapie robotic arm with a grabber powered by 4.5 v. The motors, as supplied, are controlled by simple on off switches with either forward or reverse. I've seen it operating on youtube and is rough as guts so I'm hoping to calm all that down with pots to control the speed. I'll post a vid if I get it going. Thanks a lot for your input.

No, 1 arduino is enough. Each of your 4 motors needs 2 digital pins and one PWM pin to control the speed and direction (using your 2 L298N's). That's a total of 4 PWM pins and 8 digital pins - a total of 12 pins.
Your arduino has 14 pins - so you've got 2 left over.

Awesome. That is very encouraging. I've knocked off now. Today I got two little dc motors to go backwards and forwards. Tomorrow I pack for a couple of days in the bush and tackle this problem again Monday, hopefully refreshed.

Ah, well I'm back. This time I have the L298N set up with a joystick and two DC motors. I've wired it up as per the diagram above with a small difference by using a breadboard to get the 5v and grounds happening. Then I found this sketch but the pinmode numbers didn't look right so I changed them to what you see now. I uploaded it but nothing happens which is normal for me so I haven't panicked but I do hope it is something simple that I got wrong.


int joystrick1 = A1;
int joystrick2 = A2;
int val1;
int val2;

void setup() {
  // put your setup code here, to run once:
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
pinMode(5, OUTPUT);
pinMode(4, OUTPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);

void loop() {
  // put your main code here, to run repeatedly:
int val1 = analogRead(joystrick1);
int val2 = analogRead(joystrick2);

if(val1 > 1 && val1 < 490){
val1 = map(val1, 1, 490, 255, 0);


if(val1 > 530 && val1 < 1023){
val1 = map(val1, 530, 1023, 0, 255);


if(val1 > 491 && val1 < 529){
val1 = map(val1, 491, 529, 0, 0);


if(val2 > 1 && val2 < 490){
val2 = map(val2, 1, 490, 255, 0);


if(val2 > 530 && val2 < 1023){
val2 = map(val2, 530, 1023, 0, 255);


if(val2 > 491 && val2 < 529){
val2 = map(val2, 491, 529, 0, 0);


Not even the serial prints?