Arduino, L298N motor driver, Linear actuator

Hey! I’m working on a project where I need to control the tilt of a platform using a gyroscope (MPU6050) and three 12V linear actuators. The setup is controlled by an Arduino Mega, and each actuator is connected through its own L298N motor driver.

The actuators are powered by an external 12V supply, and I’m using IN1/IN2 + ENA (PWM) to control them from the Arduino.

Here’s the issue:

If I send:

digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW); // extend

...and then:

digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW); // stop

→ the actuator doesn't move at all. Even trying HIGH-HIGH (brake) doesn’t help.
It only seems to work if I use a long delay(), but that blocks the code and I can't stop it in time when I need to — I want real-time control (like inside a while() or based on sensor feedback).

My questions:
:backhand_index_pointing_right: Has anyone faced this?

  • Is L298N not suitable for this kind of control?
  • Should I switch to relays instead?

For context:

  • The actuators have encoders, and I plan to implement a control algorithm (probably PID) later, so I need precise movement and real-time stopping — no blocking delays.

Any advice or experience would really help. Thanks in advance!

  • Always show us a good schematic of your proposed circuit.
    Show us good images of your ‘actual’ wiring.
    Give links to components.

  • In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.
    Use the < CODE / > icon from the ‘posting menu’ to attach the copied sketch.

Sure, here’s my current setup (using 3 linear actuators with 3x L298N modules):

  • Each actuator is powered from a 12V/14Ah lead-acid battery.
  • For each actuator:
    • OUT1 and OUT2 of L298N go to the actuator motor wires.
    • VCC of L298N = 12V from the battery.
    • GND of L298N = GND of battery.
    • GND of L298N is also connected to Arduino GND (common ground).
    • Control pins from Arduino:
      • Actuator 1: ENA = 9, IN1 = 6, IN2 = 5
      • Actuator 2: ENA = 10, IN3 = 7, IN4 = 8
      • Actuator 3: ENA = 11, IN5 = 12, IN6 = 4
  • I use analogWrite(ENA, HIGH) for full speed.
  • Then I control direction with digitalWrite(INx, HIGH/LOW).
    The issue is:
    If I do something like this:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
// then immediately
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);

…then the actuator doesn’t move at all.
It only works if I insert a delay (e.g., delay(500)) between those commands.

But I don’t want to use delay() — I need to stop the actuator at a specific position later using feedback (encoders), so delay() just blocks everything and messes up the timing.
:backhand_index_pointing_right: This is essential for the control algorithm I want to implement (probably PID), so I’m trying to figure out how to make it work without relying on fixed delays.

Let me know if this wiring and approach looks fine, or if I should change something. I’ll also upload a schematic and photos shortly.

Thanks in advance!

Post a link to the linear actuators. Many 12V ones draw over 5 Amperes every time they start moving, which is far above the maximum current that the L298 can handle.

I bought them from Ali Express



  • Schematics are the best way to communicate your circuit connections to us.
    Good images are needed to confirm wiring.

  • Code needs to be attached for us to examine.

digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);

  • If you are using the 4 lines of code as above, you must realize each line is executed in micros seconds.
    Not enough time for the actuator to respond.

The product page is not entirely clear, but it appears that the rated maximum steady state current is 3A, so the start/stall current could be as high as 10A.

The L298 can handle only 1 Ampere steady state, so it is totally inadequate. Pololu has the best selection of motor drivers, and I recommend this one.

Using a relay can not be a better option? Pololu is quite expensive for a bachelor thesis

const int ENA1_PIN = 9;
const int IN1_PIN = 6;
const int IN2_PIN = 5;

const int ENA2_PIN = 10;
const int IN3_PIN = 7;
const int IN4_PIN = 8;

const int ENA3_PIN = 11;
const int IN5_PIN = 12;
const int IN6_PIN = 4;

void setup() {
  pinMode(ENA1_PIN, OUTPUT);
  pinMode(IN1_PIN, OUTPUT);
  pinMode(IN2_PIN, OUTPUT);

  pinMode(ENA2_PIN, OUTPUT);
  pinMode(IN3_PIN, OUTPUT);
  pinMode(IN4_PIN, OUTPUT);

  pinMode(ENA3_PIN, OUTPUT);
  pinMode(IN5_PIN, OUTPUT);
  pinMode(IN6_PIN, OUTPUT);

  digitalWrite(ENA1_PIN, HIGH);
  digitalWrite(ENA2_PIN, HIGH);
  digitalWrite(ENA3_PIN, HIGH);
}

void loop() {
  //extend all actuators
  digitalWrite(IN1_PIN, HIGH);
  digitalWrite(IN2_PIN, LOW);

  digitalWrite(IN3_PIN, HIGH);
  digitalWrite(IN4_PIN, LOW);

  digitalWrite(IN5_PIN, HIGH);
  digitalWrite(IN6_PIN, LOW);

  delay(10000);

  // retract all actuators
  digitalWrite(IN1_PIN, LOW);
  digitalWrite(IN2_PIN, HIGH);

  digitalWrite(IN3_PIN, LOW);
  digitalWrite(IN4_PIN, HIGH);

  digitalWrite(IN5_PIN, LOW);
  digitalWrite(IN6_PIN, HIGH);

  delay(10000);
}

Simple code for extending and retracting my actuators.

Automotive relays are cheap and would work well. Contacts typically support around 30A.

It takes one DPDT or two SPDT relays to have forward and reverse.

Achieving precise actuator movement with a relay would be very difficult if not impossible.
In order to make a 1mm adjustment with an 80mm/second speed you would have to close and open the relay in 12.5 milliseconds. Depending on the relay, that just may not be possible.

After your answers I found another motor driver: BTS7960 43 A Motor Driver. What do you think? It’s a cheaper version and something easy to find.

That will work!

The L298N is a bipolar transistor-based H-bridge driver that has a significant voltage drop (up to 2V or more),
It is not ideal for inductive loads like actuators. It provides poor braking control (particularly with HIGH/HIGH). L298N is outdated compared to modern MOSFET-based drivers.
When you write:

digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);

You disconnect both ends of the motor coil, leaving it floating (a condition called coasting). If you’re also writing analogWrite(ENA, 255), it’s irrelevant in this case since there's no path for current.
Replace L298N with a MOSFET-based H-Bridge like VNH5019 https://www.st.com/resource/en/datasheet/vnh5019a-e.pdf

Did you mean it is ideal for inductive loads.

Sorry, I put my words in a wrong way. I wanted to say that L298 is not good for inductive loads like many of the linear actuators, which draw a lot of current.

So it is OK for non-inductive loads even if that draw a lot of current?

Ok, so with the new driver BTS7960 43A, controlling the motors will surely be easier, I just need to find out how to determine the piston position for control algorithm. Do you have any suggestions?

You said your actuators have encoders. You use the encoder to count the number of turns the motor has made. From that you can determine the actuator movement.