Just wanted know if it were possible to control a DC motor with an L298 driver? I have a code that uses the Accelstepper library and stepper motor. I wanted to experiment with a dc motor to see if it can perform the same task as a stepper motor but in a smaller, lightweight package. Still learning!
Small, low power brushed DC motors can be controlled by the L298, as long as the current draw does not exceed about 1 Ampere.
The motor will not behave like a stepper, and the AccelStepper library is of no use.
Yes. You can drive DC motor with L298. It receives basic TTL (Transistor Transistor Logic) logic levels and is able to operate the different loads such as DC motors, stepper motors, relays etc.
You can get all the details regarding this IC:
If the motor had an encoder attached you could mimic a stepper to some extent. But not using the AccelStepper library.
There are much smaller and lighter DC motor drivers than the ancient and inefficient POS L298 driver. Check out the line of DC brushed motor drivers that Pololu offers. Reasonably priced and Pololu has good instructional pages for each of their products as well as good tech support.
The L298 is especially bad for battery powered projects. It will drop 2V to over 4V of the motor supply voltage and dissipate that power as heat. Lots of heat. There goes your battery. Compare the heat sink on the L298 to the Pololu drivers.
Thanks for the feedback. I not really concerned about voltage drop at the moment. Just concerned about the feasability of replacing my current configuration which utilizes a stepper and sub in a DC motor without having to have the entire code re-written. The LN298 I just happen to have and was using that for testing.
Been awhile since I touched on this topic. Hoping someone with coffee can help me some....again. I am still working on a diy automatic telescope cover. I have had great success with using a stepper motor and a servo motor. Both motors utilizing the same code but modified to work with either motor. What I would like to do now is to use a DC worm gear motor and a couple of Hall Effect sensors. My goal is to reduce the amount of additional weight being added to scope. I still need the functionality of the code as it aslso controls the light. I am using the L298N still as this is just and experiment and if it works then I will get a better driver. The original, unmodified code this is based off (hopefully I can remember to to post it):
/*
What: ArduinoFlatBox - PC controlled lightbox implmented using the
Alnitak (Flip-Flat/Flat-Man) command set found here:
https://www.optecinc.com/astronomy/catalog/alnitak/resources/Alnitak_GenericCommandsR4.pdf
Who:
Created By: Jared Wellman - jared@mainsequencesoftware.com
Adapted to V4 protocol, motor handling added By: Igor von Nyssen - igor@vonnyssen.com
Modified to work with servo motors by Marco Cipriani, (GitHub @marcocipriani01)
When:
Last modified: 2021/03/12
Typical usage on the command prompt:
Send : >SOOO\r //request state
Recieve : *S19OOO\n //returned state
Send : >B128\r //set brightness 128
Recieve : *B19128\n //confirming brightness set to 128
Send : >JOOO\r //get brightness
Recieve : *B19128\n //brightness value of 128 (assuming as set from above)
Send : >LOOO\r //turn light on (uses set brightness value)
Recieve : *L19OOO\n //confirms light turned on
Send : >DOOO\r //turn light off (brightness value should not be changed)
Recieve : *D19OOO\n //confirms light turned off.
Tested with an Arduino Nano and the NINA imaging software (https://nighttime-imaging.eu)
*/
#define LED_PIN 6
#define SERVO_PIN 9
#define CLOSED_ANGLE 171
#define OPEN_ANGLE 0
#define SERVO_DELAY 25
#define SERVO_INITIAL_WAIT 2000
#include <Servo.h>
Servo servo;
enum devices {
FLAT_MAN_L = 10,
FLAT_MAN_XL = 15,
FLAT_MAN = 19,
FLIP_FLAT = 99
};
enum motorStatuses {
STOPPED = 0,
RUNNING
};
enum lightStatuses {
OFF = 0,
ON
};
enum shutterStatuses {
NEITHER_OPEN_NOR_CLOSED = 0, // ie not open or closed...could be moving
CLOSED,
OPEN,
TIMED_OUT
};
enum motorDirection {
OPENING = 0,
CLOSING,
NONE
};
int deviceId = FLIP_FLAT; //set this to FLAT_MAN if you want to remove or not use the motor handling
int motorStatus = STOPPED;
int coverStatus = CLOSED;
int motorDirection = NONE;
int targetAngle = CLOSED_ANGLE;
int currentAngle = CLOSED_ANGLE;
int lightStatus = OFF;
int brightness = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
analogWrite(LED_PIN, 0);
servo.attach(SERVO_PIN, 500, 2500);
servo.write(171);
}
void loop() {
handleSerial();
handleMotor();
}
void handleSerial() {
if (Serial.available() >= 6) { // all incoming communications are fixed length at 6 bytes including the \n
char* cmd;
char* data;
char temp[10];
char str[20];
memset(str, 0, 20);
Serial.readBytesUntil('\r', str, 20);
cmd = str + 1;
data = str + 2;
switch (*cmd) {
/*
Ping device
Request: >POOO\r
Return : *PiiOOO\n
id = deviceId
*/
case 'P':
sprintf(temp, "*P%dOOO\n", deviceId);
Serial.write(temp);
break;
/*
Open shutter
Request: >OOOO\r
Return : *OiiOOO\n
id = deviceId
This command is only supported on the Flip-Flat, set the deviceId accordingly
*/
case 'O':
sprintf(temp, "*O%dOOO\n", deviceId);
setShutter(OPEN);
Serial.write(temp);
analogWrite(LED_PIN, 0);
break;
/*
Close shutter
Request: >COOO\r
Return : *CiiOOO\n
id = deviceId
This command is only supported on the Flip-Flat, set the deviceId accordingly
*/
case 'C':
sprintf(temp, "*C%dOOO\n", deviceId);
setShutter(CLOSED);
Serial.write(temp);
break;
/*
Turn light on
Request: >LOOO\r
Return : *LiiOOO\n
id = deviceId
*/
case 'L':
sprintf(temp, "*L%dOOO\n", deviceId);
Serial.write(temp);
lightStatus = ON;
if (coverStatus == CLOSED) {
analogWrite(LED_PIN, brightness);
}
break;
/*
Turn light off
Request: >DOOO\r
Return : *DiiOOO\n
id = deviceId
*/
case 'D':
sprintf(temp, "*D%dOOO\n", deviceId);
Serial.write(temp);
lightStatus = OFF;
analogWrite(LED_PIN, 0);
break;
/*
Set brightness
Request: >Bxxx\r
xxx = brightness value from 000-255
Return : *Biiyyy\n
id = deviceId
yyy = value that brightness was set from 000-255
*/
case 'B': {
double db = (double) (atoi(data) - 3);
brightness = constrain((int) (0.00403 * db * db), 0, 255);
if ((lightStatus == ON) && (coverStatus == CLOSED)) {
analogWrite(LED_PIN, brightness);
}
sprintf(temp, "*B%d%03d\n", deviceId, brightness);
Serial.write(temp);
break;
}
/*
Get brightness
Request: >JOOO\r
Return : *Jiiyyy\n
id = deviceId
yyy = current brightness value from 000-255
*/
case 'J':
sprintf(temp, "*J%d%03d\n", deviceId, brightness);
Serial.write(temp);
break;
/*
Get device status:
Request: >SOOO\r
Return : *SidMLC\n
id = deviceId
M = motor status( 0 stopped, 1 running)
L = light status( 0 off, 1 on)
C = Cover Status( 0 moving, 1 closed, 2 open, 3 timed out)
*/
case 'S':
sprintf(temp, "*S%d%d%d%d\n", deviceId, motorStatus, lightStatus, coverStatus);
Serial.write(temp);
break;
/*
Get firmware version
Request: >VOOO\r
Return : *Vii001\n
id = deviceId
*/
case 'V': // get firmware version
sprintf(temp, "*V%d003\n", deviceId);
Serial.write(temp);
break;
}
}
}
void setShutter(int val) {
if (val == OPEN && coverStatus != OPEN) {
motorDirection = OPENING;
targetAngle = OPEN_ANGLE;
} else if (val == CLOSED && coverStatus != CLOSED) {
motorDirection = CLOSING;
targetAngle = CLOSED_ANGLE;
}
}
void handleMotor() {
if ((currentAngle > targetAngle) && (motorDirection == OPENING)) {
motorStatus = RUNNING;
coverStatus = NEITHER_OPEN_NOR_CLOSED;
servo.write(--currentAngle);
if (currentAngle <= targetAngle) {
motorStatus = STOPPED;
motorDirection = NONE;
coverStatus = OPEN;
}
delay(SERVO_DELAY);
} else if ((currentAngle < targetAngle) && (motorDirection == CLOSING)) {
motorStatus = RUNNING;
coverStatus = NEITHER_OPEN_NOR_CLOSED;
servo.write(++currentAngle);
if (currentAngle >= targetAngle) {
motorStatus = STOPPED;
motorDirection = NONE;
coverStatus = CLOSED;
if (lightStatus == ON) {
analogWrite(LED_PIN, brightness);
}
}
delay(SERVO_DELAY);
}
}
How Can I modify this to use the L298N and the Hall effect sensors? Would appareciate any type of help. Thanks
Do you have data sheet for the Hall sensors? There are analog and there are digital (switch) Hall sensors. There are latching and non latching. Some are sensitive to field polarity. So we need to know exactly what sensor you have to code for it.
Description:
The KY-003 Magnetic Hall Effect Sensor Module is an A3141 IC-based breakout board that can be used as a magnetic switch. The sensor has a GND, +5V supply and a digital output pin. The signal line pin goes HIGH when a magnetic field is detected, and LOW when no field is detected.
Specifications:
Operating voltage: 4.5V – 24V
Operating temperature: -40c – 85c
Dimensions: 18.5mm x 15mm
Pin Specifications:
Pin 1: GND
Pin 2: +5V
Pin 3: Digital output
Best description I can get. Bought it off Amazon, so I had to search elswhere for the specs.
OK, taking a closer look, the module I have uses the A3144 sensor.
Hall Effect Magnetic Sensor Module, 3144E A3144 Hall Effect Sensor KY-003 DC 5V for Arduino
That is the sensor that I use. The A3144 is an open collector output. The module has the required pullup on the sensor output (Arduino input).
So just treat them like switches.
How would I incorpoarte the L298N into the code to replace the current motor? Inparticular the within the handlMotor() and setShutter() part of the code.
So you want to replace the servo, with built in positional feedback, with a DC motor with limit switches for positional feedback? Correct?
Can you connect the motor to the L298 and programmatically control the motor, forward, reverse stop?
Have you tried to reliably read the Hall switched in code?
That is correct. Servo motors work great except they tend to burn out on me. Stepper motors are wonderful but they are too heavy, creates to much forward weight and makes for difficult balancing. I can connect the L298N and it does move forward, reverse and stop. The above code I posted is an unmodified (by me) that works. I have a very poorly modified version I was ashamed to post but can. In that version, I can get the motor to move to its home position on start up but thats pretty much it. At times I can get it to move forward when issued the open command through ASCOM and N.I.N.A but it just keeps spinning. Always have to force it to stop. I am obviously no programmer but I'm trying. I tried chaging various variales and tried using interupts with no luck. The interupt being the last thing I tried.
OK, son't judge me but here is what I'm workin with right now. It is a horrible mess.
#include <L298N.h>
const unsigned int IN1 = 8;
const unsigned int IN2 = 7;
const unsigned int EN = 9;
int SW1 = 2;
int SW2 = 3;
L298N motor(EN, IN1, IN2);
volatile int ledPin = 6; // the pin that the LED is attached to, needs to be a PWM pin.
int brightness = 0;
enum devices {
FLAT_MAN_L = 10,
FLAT_MAN_XL = 15,
FLAT_MAN = 19,
FLIP_FLAT = 99
};
enum motorStatuses {
STOPPED = 0,
RUNNING
};
enum lightStatuses {
OFF = 0,
ON
};
enum shutterStatuses {
NEITHER_OPEN_NOR_CLOSED = 0, // ie not open or closed...could be moving
CLOSED,
OPEN,
TIMED_OUT
};
enum motorDirection {
OPENING = 0,
CLOSING,
NONE
};
int deviceId = FLIP_FLAT; //set this to FLAT_MAN if you want to remove or not use the motor handling
int motorStatus = STOPPED;
int lightStatus = OFF;
int coverStatus = CLOSED;
int targetAngle = SW1;
int currentAngle = SW1;
int motorDirection = NONE;
void setup() {
// initialize the serial communication:
Serial.begin(9600);
// initialize the ledPin as an output:
pinMode(ledPin, OUTPUT);
pinMode(interSW1, INPUT);
pinMode(interSW2, INPUT);
analogWrite(ledPin, 0);
while (digitalRead(SW1)) { // Do this until the switch is activated
motor.setSpeed(255);
motor.backward();
motor.stop()
}
}
void loop() {
handleSerial();
handleMotor();
}
void handleSerial() {
if ( Serial.available() >= 6 ) { // all incoming communications are fixed length at 6 bytes including the \n
char* cmd;
char* data;
char temp[10];
int len = 0;
char str[20];
memset(str, 0, 20);
Serial.readBytesUntil('\r', str, 20);
cmd = str + 1;
data = str + 2;
// useful for debugging to make sure your commands came through and are parsed correctly.
if ( false ) {
sprintf( temp, "cmd = >%c%s\n", cmd, data);
Serial.write(temp);
}
switch ( *cmd )
{
/*
Ping device
Request: >POOO\r
Return : *PiiOOO\n
id = deviceId
*/
case 'P':
sprintf(temp, "*P%dOOO\n", deviceId);
Serial.write(temp);
break;
/*
Open shutter
Request: >OOOO\r
Return : *OiiOOO\n
id = deviceId
This command is only supported on the Flip-Flat, set the deviceId accordingly
*/
case 'O':
sprintf(temp, "*O%dOOO\n", deviceId);
setShutter(OPEN);
Serial.write(temp);
break;
/*
Close shutter
Request: >COOO\r
Return : *CiiOOO\n
id = deviceId
This command is only supported on the Flip-Flat, set the deviceId accordingly
*/
case 'C':
sprintf(temp, "*C%dOOO\n", deviceId);
setShutter(CLOSED);
Serial.write(temp);
break;
/*
Turn light on
Request: >LOOO\r
Return : *LiiOOO\n
id = deviceId
*/
case 'L':
sprintf(temp, "*L%dOOO\n", deviceId);
Serial.write(temp);
lightStatus = ON;
analogWrite(ledPin, brightness);
break;
/*
Turn light off
Request: >DOOO\r
Return : *DiiOOO\n
id = deviceId
*/
case 'D':
sprintf(temp, "*D%dOOO\n", deviceId);
Serial.write(temp);
lightStatus = OFF;
analogWrite(ledPin, 0);
break;
/*
Set brightness
Request: >Bxxx\r
xxx = brightness value from 000-255
Return : *Biiyyy\n
id = deviceId
yyy = value that brightness was set from 000-255
*/
case 'B':
brightness = atoi(data);
if ( lightStatus == ON )
analogWrite(ledPin, brightness);
sprintf( temp, "*B%d%03d\n", deviceId, brightness );
Serial.write(temp);
break;
/*
Get brightness
Request: >JOOO\r
Return : *Jiiyyy\n
id = deviceId
yyy = current brightness value from 000-255
*/
case 'J':
sprintf( temp, "*J%d%03d\n", deviceId, brightness);
Serial.write(temp);
break;
/*
Get device status:
Request: >SOOO\r
Return : *SidMLC\n
id = deviceId
M = motor status( 0 stopped, 1 running)
L = light status( 0 off, 1 on)
C = Cover Status( 0 moving, 1 closed, 2 open, 3 timed out)
*/
case 'S':
sprintf( temp, "*S%d%d%d%d\n", deviceId, motorStatus, lightStatus, coverStatus);
Serial.write(temp);
break;
/*
Get firmware version
Request: >VOOO\r
Return : *Vii001\n
id = deviceId
*/
case 'V': // get firmware version
sprintf(temp, "*V%d003\n", deviceId);
Serial.write(temp);
break;
}
while ( Serial.available() > 0 ) {
Serial.read();
}
}
}
void setShutter(int val)
{
if ( val == OPEN && coverStatus != OPEN )
{
motorDirection = OPENING;
targetAngle = SW2;
}
else if ( val == CLOSED && coverStatus != CLOSED )
{
motorDirection = CLOSING;
targetAngle =SW1;
}
}
void handleMotor()
{
if ((currentAngle != LOW) && (motorDirection == OPENING)) {
motorStatus = RUNNING;
coverStatus = NEITHER_OPEN_NOR_CLOSED;
motor.setSpeed(255);
motor.forward();
currentAngle = digitalRead(SW2);
if (currentAngle == LOW) {
motorStatus = STOPPED;
motorDirection = NONE;
coverStatus = OPEN;
motor.stop();
}
} else if (currentAngle != LOW && motorDirection == CLOSING) {
motorStatus = RUNNING;
coverStatus = NEITHER_OPEN_NOR_CLOSED;
motor.setSpeed(255);
motor.backward();
currentAngle = digitalRead(SW1);
if (currentAngle == LOW) {
motorStatus = STOPPED;
motorDirection = NONE;
coverStatus = CLOSED;
motor.stop();
}
}
}
OK, my problem is in testing the handleMotor function, the motor will move to the open position and stop but will not go to the closed position. I'm betting it's something simple but I'm scratching my head and drinking a lot of coffee.
It's a PITA becuse I have to use the another piece of software to test it!
oh well, guess I'll stick with a stepper for the time being.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.