A Tale of Two Motor Controllers (or Controlling a Chicken Coop Door with an Arduino: L9958 vs. L298N)
Driving an HY-DIV268N-5A with a Raspberry Pi
The SONXUA SX8847 motor controller offers quite a lot! The eBay listing said 240 watt high-power H-bridge PWM motor driver module/smart driver for Arduino, for only $13.88! In addition it has programmable current limits, an SPI interface, and all kinds of indicators for under voltage, over voltage, over temperature, open load, etc. In brief, it offers lots of fancy features, and at a very reasonable price.
Here is a link to the eBay auction I used: http://www.ebay.com/itm/111153750411
The other motor controller I tried is based on the simpler L298N, which offers two H-bridges, but less amperage. It is even less expensive at $5.99 (including shipping).
Here is the link I used: http://www.ebay.com/itm/290899895209
The chicken coop door I designed is 18"x18", and made out of 1/4" plywood. Other people have designed similar systems (here is one with a particularly clever locking door), and they used relays to control a cordless drill motor to raise and lower the door (link). For my design, I wanted to control the door more carefully (avoiding letting it bump against its stops), so I decided to try using these motor controllers with a cordless Ryobi 12v drill I picked up for $5 at a garage sale.
I used a cadmium-sulfide photocell to detect when to open and close the door. Open when it has been consistently light for the last 60 seconds, and close if it has been consistently dark.
I used three switches to detect where the door currently is. One at the very top, one almost at the top, and the third in the middle (which triggers when the top of the door passes by it and stops depressing the switch). I probably should have used two switches in the middle — one to detect when to decelerate from full to slow speed, and the second to detect when to stop, however I only had three on hand. The reason I didn’t place the lower switches at the bottom, was I wanted them to be as far as possible from the chickens, mud and other sources of trouble. Also, I arranged the almost top and middle switches so that the levers are hanging down, so that they will be less likely to have rain water drip into them. I suppose I could have used magnets and Hall effect sensors, but this is one of my first outdoor Arduino project, and I wanted to keep it simple to start with.
At first when I was working on this project I favored the L9958 because of all of its fancy features. I felt more secure with all the different protections and diagnostics it offered, but I found myself struggling to get it to actually work! I only found one reference on the net for how to work with the SPI interface (which is why I decided to write this and share my code). The first problem I had was that the 5v Vcc is somehow connected to the 12v Vss, but it shouldn’t be! Even if the Arduino was separately powered, if I tried to change the motor’s speed from 0 to 100%, it would go into an endless cycle of resetting the Arduino. The solution to this was to run the motor at reduced power. This actually worked pretty well, however after a while I decided that taking ~40 seconds to raise or lower the door was not quite to my liking, so I tried to have the motor accelerate to full power, and then decelerate back to half power before stopping. Now the good thing is that when controlling the motor with L9958 at half power, it would stop on a dime. However, even though it would happily switch speeds from 0% to 50%, 50% to 100%, and 50% to 0%, it would halt and become unresponsive when commanded to switch from 100% to 50%! In this case the SPI interface didn’t provide any useful debugging information. Resetting the device did cure the problem, but that is undesireable. Also, the L9958 caused the the motor to shake when run at other speeds besides 0%, 50% and 100%, so gradually ramping the speed from 50% up to 100% didn’t work well, and ramping the speed from 100% down to 50% always caused the lockup. Argh! This drove me to try the L298N.
The L298N simply worked. It worked at a wide variety of speeds, it smoothly ramped between speeds, and the only problem I had was that I couldn’t find a speed where it would reliably lift and lower the door, and stop on a dime. To solve this problem, I decided to start at a slow initial speed (a brushed DC motor draws the maximum current when starting, so starting it slowly keeps it from initially drawing too much current), and ramping up to full speed within a second, and then down to an extremely slow speed, before stopping and reversing for a brief period (to avoid overrunning where I wanted it to stop). This raises or lowers the door in less than 10 seconds.
So in summary, the advantages of the L9958 are:
The advantages of the L298N are:
In the end, I decided that the L298N would be best for my application!
Here is a link to the Arduino sketch for the L298N version of my chicken coop door controller: ChickenDoor_L298N.ino
For comparison, here is a link to the Arduino sketch for the L9958 version of my chicken coop door controller: ChickenDoor_L9958.ino
A few notes:
I sure learned a lot of lessons in the course of this project!
Many thanks to the folks from Sparkfun and Maui Makers who put on an Arduino course here on Maui!
I’d originally planned to do this project using relays and a Raspberry Pi, and they mentioned that an L298N might be sufficient. My original measurements with this drill’s motor indicated that it draws up to 7 amps, which is why I tried using the L9958 first.
The HY-DIV268N-5A is an inexpensive, powerful and flexible stepper motor controller which can drive motors rated between 200ma and 5 amps, at volages between 12v and 50v. Using a higher voltage is more desirable, because it makes the steppers run faster.
Here is a link to the one I purchased on eBay for $22.84, including shipping: http://www.ebay.com/itm/221245537239
I ordered it on Sunday July 28 and it arrived on Friday August 9, 10 business days later. Not bad!
I couldn't find much useful documentation online on the Toshiba TB6600 chip, which is at the heart of this device, and the Chinglish instructions from the manufacturer weren't much help, either.
On YouTube, I found a two minute video by some chaps with English accents who said to tie all of the lines EN+, DIR+, and PUL+ (enable, direction, and pulse) high (to 5v), and then they drove the EN-, DIR-, and PUL- lines using a transistor and pulled them to ground. Unfortunately, messing with transistors is outside of my expertise. Here is the link: http://www.youtube.com/watch?v=mvxOuDw4JeY
I found a fellow who mentioned that he'd tied EN+, EN-, DIR-, and PUL- to ground, and then used an Arduino to drive DIR+ and PUL+. Note: he wrote, “The direction plus pin must be changed when the pulse pin is low,” however I tested this, and the direction pin worked correctly no matter what the pulse pin's state was. Here is the link: http://forum.arduino.cc/index.php?PHPSESSID=objlfu9417jhvo7006es9l64a0&topic=172537.msg1290522#msg1290522
I used a Raspberry Pi, which uses 3.3v logic (unlike the Arduino, which uses 5v), but it still worked fine for me. Here's how I connected the wires:
|DIR-||RPi GPIO GND|
|DIR+||RPi GPIO #18|
|PUL-||RPi GPIO GND|
|PUL+||RPi GPIO #23|
|EN-||RPi GPIO GND|
|EN+||RPi GPIO #4 or GND|
|A+||stepper green wire|
|A-||stepper gray wire|
|B+||stepper red wire|
|B-||stepper yellow wire|
|DC-||GND (black on PC power supply)|
|DC+||+12v (yellow on PC power supply)|
The NEMA 14 stepper motor I tested with was this one, from AdaFruit Industries for $14: http://www.adafruit.com/products/324
Of course, much larger steppers will work with this controller. For this test I set the DIP switches for 0.2A and 1/16 microstepping, which yields 200*16=3200 steps per revolution.
For power, I used an old ATX power supply. By connecting pin #14 (green) to ground (pin #15, black), it turns on when plugged in. Here is the reference I used: http://pinouts.ru/Power/atxpower_pinout.shtml
Here is the Python program I used to test it with:
#!/usr/bin/python # # Written by Haydn Huntley (firstname.lastname@example.org) on 08/16/2013. # Feel free to use this code any way you want. # Runs on a Raspberry Pi and drives an HY-DIV268N-5A stepper motor controller. # # Note: this program must be run as root in order to use the GPIO calls. import time import RPi.GPIO as GPIO enablePin = 4 # Note enable is active low! directionPin = 18 pulsePin = 23 pulseState = 0 delay = 0.000001 # 1 microsecond def setup(): GPIO.setmode(GPIO.BCM) GPIO.setup(enablePin, GPIO.OUT) GPIO.setup(directionPin, GPIO.OUT) GPIO.setup(pulsePin, GPIO.OUT) GPIO.output(enablePin, 0) return def forward(steps): global pulseState print "forward delay=%0.3fms steps=%d" % (delay * 1000, steps) GPIO.output(directionPin, 1) for i in range(steps): pulseState += 1 GPIO.output(pulsePin, pulseState % 2) time.sleep(delay) pulseState %= 2 return def backwards(steps): global pulseState print "backwards delay=%0.3fms steps=%d" % (delay * 1000, steps) GPIO.output(directionPin, 0) for i in range(steps): pulseState += 1 GPIO.output(pulsePin, pulseState % 2) time.sleep(delay) pulseState %= 2 return def main(): # For the NEMA 14 12v 350mA (#324) stepper motors from AdaFruit: # http://www.adafruit.com/products/324 # Driving it with 12v using a delay of 1 microsecond. revolutions = 3 steps = revolutions * 200 * 16 setup() forward(steps) time.sleep(0.5) backwards(steps) GPIO.cleanup() return try: main() except: print "something went wrong!" GPIO.cleanup() raise GPIO.cleanup() exit(0)
It steps the motor at 1 microsecond per step, which is the fastest I could get it to work with Python's time.sleep() function for the delays. With 1/16 microstepping and 200 steps/revolution, it does about 136RPM, which is much better than when I tried this using an LM293D!
For about 20 years I've had a dream of building my own CNC machine for milling wood, plastic, etc., and I'm finally making it happen! :-)
I hope this proves useful to others. If you have any questions, just email me...
|huntley@nLogN.com||Last Modified:||Tuesday, November 20, 2:25 pm||Copyright © 1997-2021 Haydn Huntley, all rights reserved.|