One of the objects that has raised the most questions for me about how to design it has been the object responsible for controlling DC motors, and not necessarily because of its complexity or the possible technical difficulties involved, but because of the different possibilities we have for controlling it, ranging from a simple on/off for the motor to controlling the speed and direction of its rotation. The challenge was not to create several objects for each configuration, and to do it in a simple, efficient and elegant way. I hope I have succeeded.
The method I decided to use is to put a constant as the second parameter to the MotorDC object when it is created. This predefined constant that the object receives determines the control options that we have on the motor, and also forces us to pass object interfaces of a particular class and with a number minimal output channels.
As you know, the GPIO outputs of our Raspberry Pi don’t support large currents or voltages higher than 3.3V. To protect the channels on an electronic level, we will need components such as relays, transistors or integrated circuits that prevent over-currents or over voltages such as the typical voltage peaks generated by the motor windings when starting or stopping.
Below, I will try to describe each of the operating modes defined for the DC motor with a small design of its connection.
GPIO_SIMPLE : This operation mode is simply designed to turn a DC motor on and off. The MotorDC object must receive an InterfaceGPIO with an output channel. This output channel will be used to excite a relay or transistor as you can see in the schematic.
GPIO_REVERSIBLE : If you also want to control the direction of rotation of the motor, we will have to use this mode, just like the way GPIO_SIMPLE receives an InterfaceGPIO but with two output channels. To function properly, these channels should excite an H-bridge configuration of transistors, with which we can change the direction of rotation by reversing the flow of current through the motor.
PWM_SIMPLE : Works exactly like the GPIO_SIMPLE mode, but allows us to control the speed of rotation. This is achieved using an InterfacePWM with one channel. The InterfacePWM send a pulsed signal to the motor with pulse width modulation (PWM).
PMW_REVERSIBLE : As with PWM_SIMPLE mode, this gives us the ability to control the speed and also the direction of rotation of the motor. On a logic level, it requires an InterfacePWM with two channels and four transistors in H-bridge configuration for proper functioning.
ADV_REVERSIBLE : This mode is designed to control DC motors via integrated circuits such as the L298N, L293D, DRV8833 or similar. For an interface, it should receive a tuple with an InterfaceGPIO with two channels and an InterfacePWM interface with one channel. The InterfaceGPIO channels will control the transistors that determine the direction of rotation and the InterfacePWM object will or will not excite the inhibitor of the output of these transistors. This way, we can control the speed and direction of rotation with a single integrated circuit.
For testing, I used an integrated circuit that incorporates the L298N, which you can get in many stores or online at a reasonable price. With this integrated circuit, you can test all examples of DC motors that are in the "tests" folder. In this case, I will use the ADV_REVERSIBLE mode, the most complex since it requires two interfaces and three output channels to control the motor, but it will give us an idea of how easy it is to manage.
#!/usr/bin/env python # -+- coding: utf-8 -+- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# # # Name: tests/motordc5 # Purpose: Test MotorDC in ADV_REVERSIBLE mode # # Created: 12/04/2015 # Modified: 12/17/2015 # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# from __future__ import print_function from raspybot.devices.motor import MotorDC from raspybot.io.interface import InterfaceManager, InterfaceGPIO, InterfacePWM #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# def show_help(): print('Testing MotorDC in ADV_REVERSIBLE mode') print(' f : Move motor to right side') print(' b : Move motor to left side') print(' + : increment speed') print(' - : decrement speed') print(' s : stop motor') print(' q : quit...') print(' h : show this help\n\n') #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# manager = InterfaceManager() iface1 = InterfacePWM(manager, pinout=14) iface2 = InterfaceGPIO(manager, pinout=(15, 18)) motor1 = MotorDC((iface1, iface2), MotorDC.ADV_REVERSIBLE, name='Motor DC') try: while True: cmd = raw_input('Enter command (h for help) : ') if cmd == 'f': motor1.forward() elif cmd == 'b': motor1.backward() elif cmd == '+': motor1.speed_up(5) elif cmd == '-': motor1.speed_down(5) elif cmd == 's': motor1.stop() elif cmd == 'h': show_help() elif cmd == 'q': raise KeyboardInterrupt except KeyboardInterrupt: print('\nScript stopped...') except Exception as error: print('Error :', error) finally: motor1.stop() manager.delete(iface1) manager.delete(iface2) manager.cleanup()