úterý 8. března 2016

RoboCar: Arduino Motor Shield L293D with Raspberry Pi B+ (part 2)

Last time I wrote about the Motors Shield and I tried to describe how the L293D modul and the 74HC595 module work. And now is time for programming. But we have to wire it up first. You can connect PINs according this image. (image update - 05.09.2016 - fixed wiring of blue and brow wire on motor shield, thanks to Maxime)



And when you have it connected we can start talking about using python to run the motors.

Requirements

  1. Raspbery Pi with installed OS (I have Raspbian)
  2. Installed Git, Python3 and RPi.GPI - sudo aptitude install python3 python3-rpi.gpio
  3. Connectected Motor Shield to Raspberry Pi

Controlling motors from Python

I've wrote Python class for controlling motors using this Motor Shield. You can download it from my github.

git clone https://github.com/lipoja/AMSpi.git

Using AMSpi class

from AMSpi import AMSpi

# For BOARD pin numbering use AMSpi(True) otherwise BCM is used
with AMSpi() as amspi:
    # Set PINs for controlling shift register (GPIO numbering)
    amspi.set_74HC595_pins(21, 20, 16)
    # Set PINs for controlling all 4 motors (GPIO numbering)
    amspi.set_L293D_pins(5, 6, 13, 19)
    # Run motors
    amspi.run_dc_motors([amspi.DC_Motor_1, amspi.DC_Motor_2, amspi.DC_Motor_3, amspi.DC_Motor_4])

When you are creating object you can specify what pin numbering you will use.
  • AMSpi() - for GPIO.BCM
  • AMSpi(True) - for GPIO.BOARD
In this example I am using BCM. BCM is the GPIO number. BOARD is the number in the circle (on the image above). 

Then you have to set the pins for shift register. It is done by set_74HC595_pins method.
amspi.set_74HC595_pins(DIR_LATCH=21, DIR_CLK=20, DIR_SER=16)

After that you must specify used pins for enabling the motors. This is done by set_L293D_pins method.
amspi.set_L293D_pins(5, 6, 13, 19)

You can choose which motor do you want to use. If you have only two motors you can set it like this: 
amspi.set_L293D_pins(PWM2A=13, PWM2B=19)

Now the exciting part. Spinning the wheel :-]. You can start one or multiple motors at time. Using run_dc_motors method and specifying which motor you want to run.
For this you can use class variable DC_Motor_X where X is number of the motor.
(DC_Motor_1, DC_Motor_2, DC_Motor_3, DC_Motor_4)

Running all 4 motors:
amspi.run_dc_motors([amspi.DC_Motor_1, amspi.DC_Motor_2, amspi.DC_Motor_3, amspi.DC_Motor_4])

Running only two motors:
amspi.run_dc_motors([amspi.DC_Motor_1, amspi.DC_Motor_2])

If you want to run only one motor you can use same method:
amspi.run_dc_motors([amspi.DC_Motor_1])

Or you can use this method for running only one specific motor:
amspi.run_dc_motor(amspi.DC_Motor_1)

Now the direction of the motor. How do you switch it. Easily. 
Just add False as second parameter of method:
amspi.run_dc_motors([amspi.DC_Motor_1, amspi.DC_Motor_2, amspi.DC_Motor_3, amspi.DC_Motor_4], clockwise=False)

OK, now you car is driving super fast forward but how do you stop it? Piece of cake. Just call:
amspi.stop_dc_motors([amspi.DC_Motor_1, amspi.DC_Motor_2, amspi.DC_Motor_3, amspi.DC_Motor_4])

The metod stop_dc_motors works same as run_dc_motors. 
Just specify the motors which you want to stop.
On the git repository is commented example.py file. 
You can look at it and see what it can do.

OK, that was easy, right? If you have questions just ask me. I will try to answer them. 


36 komentářů:

  1. Hey Jan :) thank you for that great tutorial and the awesome library. I'm afraid that my motors doesn't stop turning after the stop_dc_motors call (i use the example.py). I already tried to clean up GPIO pins but that has no effect. Do you have any idea whats wrong? Best, Sascha

    OdpovědětVymazat
    Odpovědi
    1. It might be because of the shift register (74HC595) on the board. It has still set the pins to "HIGH". Can you try stop each motor separately using stop_dc_motor? Did they stop?

      Vymazat
    2. I have the same problem. stop_dc_motor does not help.

      Vymazat
    3. Same from my side. I stopped each motor separatly by calling the stop_dc_motor method. but nothing changed, all attached motors start turning.

      Vymazat
    4. Hi, thank you for your reactions and testing. I've released newer version. It is on github. Can you test it, please?
      Thank you!

      Vymazat
    5. hi
      i don't know if this was already fixed but i have same problem running the dc_example.py
      to fix this problem i added the next line at the end of the dc_example.py

      amspi.__exit__(1,1,1)

      it generate an error but it stop my motor after quit the script, as i understand it close the gpio ports

      Thanks jan for your program

      Vymazat
  2. Hi, Thx for the tutorial! What's the pwm adjusted for the run_dc_motors? is it max speed?

    OdpovědětVymazat
    Odpovědi
    1. Hi, it is default for output. Probably the max speed. I will add speed (pwm) regulation in next update.

      Vymazat
  3. Hi Jan, thank you for this tutorial, the only one found on internet to connect an arduino motor shield on a raspberry.
    In the next step, I would like to connect one stepper motor, do you think it's possible with your program ? how do for control the sens and the speed ?
    Regards

    OdpovědětVymazat
    Odpovědi
    1. Hi Kris,
      you can't use stepper motors, yet.
      I am going to write support for it. Same goes for speed control. I just need time to finished it, but as you can see I had no time in past few months.
      Controlling speed will use just software implementation of PWM. That means it is not as good as it is on Arduino.
      As far as I know Raspberry Pi has only one pin supporting PWM.

      Vymazat
    2. sir it is already 2019 just asking. have you integrate it with servo ??

      Vymazat
  4. Hi Jan,
    Thanks for the great work. Just a question, with the current wiring I don't have it working, I have weird behavior, motor working or not working... Therefore, I investigated the code proposed by the pigpio library:
    http://abyz.co.uk/rpi/pigpio/ex_motor_shield.html

    In this code one can see:
    D12 MOTORLATCH
    D11 PMW motor 1

    However, on your diagram LATCH is connected to 13 and PMW motor 1 to 12. Furthermore, I read that 13 is unused:

    http://playground.arduino.cc/Main/AdafruitMotorShield
    // Digital pins: used: 3,4,5,6,7,8,9,10,11,12
    // Pin 9 and 10 are only used for the servo motors.
    // Already in use: 0 (RX) and 1 (TX).
    // Unused: 2,13
    // Pin 2 has an soldering hole on the board,
    // easy to connect a wire.
    // Pin 13 is also connected to the system led.

    If I connect the blue wire to 11 (PMW motor 1) and the brown wire to 12 (latch), then everything works like a charm :-)

    Could you confirm it and evantually update the diagram?

    Thanks!
    Maxime

    OdpovědětVymazat
  5. Thank you Maxime! I was looking for this "bug" for long time and I did not see it :(
    I've updated the image here on blog and also on github giving you creadit. https://github.com/lipoja/AMSpi

    Thank you for your time and really good investigation of my mistake :)

    OdpovědětVymazat
  6. i wont work on my pi i have done everything right
    even used example code too

    OdpovědětVymazat
  7. Hello.
    First, thanks for library. I can to control my dc motors.
    Now, I like to control my servo motors.
    With this library is it possible to control my servo motors?

    OdpovědětVymazat
    Odpovědi
    1. Hi Mateus,
      not yet. I was working on that but it is not ready yet. But working with servo is little bit tricky. Because controlling server from raspi using RPi.GPIO does not work well as it works on Arduino (because of software PWM).

      Vymazat
  8. How would you create a simple loop? I can get it to run with no issue, but once I put it into a if else statement it errors out.

    OdpovědětVymazat
  9. Hi, thanks for this python class, saved me a lot of work. However, when I wired everything up like in your diagram, the 74HC595 shift register didn't do anything (motors worked, speed changes worked, direction changes didn't). Only after I connected another ground to the gnd pin on the shield it started to function properly. I didnt realize this until I took out the 74HC595 and wired it up separately to see if it was faulty.

    OdpovědětVymazat
    Odpovědi
    1. Hi, thank you for your comment. To which pin on the shield did you connected the ground? To the GND pin next to 5V input?
      I will mark it in the picture maybe it will help others.
      Thanks

      Vymazat
    2. I used the gnd header between pin 13 and aref for mine :)

      Vymazat
  10. Zdravim Jan,

    diky za super navod. Velmi mi pomohol.

    OdpovědětVymazat
  11. Zdravim, chcel by som sa spytat uplne laicku otazku, zapojil som vsetko podla vasho obrazka, ako externe napajanie pre motor shield pouzivam 9v nabijaciu baterku, raspberry mam zapojene na micro-usb nabijacke v zasuvke. Ked pustim vas skript dc_example.py tak pocujem ze v motoroch cvaka ale nekruti sa nic, som uplne elektrotechnicke nemehlo, chcel by som vas poprosit o radu. Dakujem.

    OdpovědětVymazat
  12. Dobry den,
    a jake pouzivate motorky (jake vyzaduji napeti pro svuj chod)?

    OdpovědětVymazat
    Odpovědi
    1. Je to prava cina :) https://www.aliexpress.com/item/Damping-balance-Tank-Robot-Chassis-Platform-high-power-Remote-Control-DIY-crawle-SINONING/32449063532.html?spm=a2g0s.9042311.0.0.y7w3h2

      Uvadzaju tam nieco taketo:
      Motor: 260
      Voltage: 3V-9V

      Ked pripojim 9V baterku napriamo k jednemu alebo druhemu, tak funguju.

      Inak prepisal som vasu python classu do typescriptu pre nodejs ak by sa to niekedy niekomu zislo rad poskytnem... Motory sa snazim najprv ale rozchodit s vasimi skriptami.

      Dakujem za kazdu radu.

      M.

      Vymazat
  13. Tuto chlapici rozoberaju podobny problem: https://www.raspberrypi.org/forums/viewtopic.php?f=45&t=16118

    vyzera ze dospeli k nazoru ze ta 9v baterka na to asi nestaci?

    OdpovědětVymazat
    Odpovědi
    1. Je to tak, ked som to cele pripojil namiesto 9v baterky na 5V/2A DC adapter tak to slape jak vinko...

      Vymazat
  14. Super, tak to je dobre vedet. Dekuji za informaci. Asi je tam potreba vetsi proud nez ta baterka zvlada. Ja to mel pouze napajene tim 5V (2A) z powerbanky. A to asi bylo dostacujici.

    OdpovědětVymazat
  15. How to control Servo Motor 1 & 2 from your AMSpi Class ?

    OdpovědětVymazat
  16. Hi,

    Really great tutorial!! Looking forward for your update in controlling the servo.

    Thanks

    OdpovědětVymazat
  17. can it be used for the servo motor??

    OdpovědětVymazat
  18. Thanks for the great tutorial!
    I used your class to control two bipolar stepper motors. Unfortunately, it's not possible to tabulate in the blog. Therefore I deleted the posted program snippets.

    OdpovědětVymazat
  19. I also found that (as was written in a previous post) there is no regular ground connection between RaspberryPi and the motor shield. The only ground connection is used to pull pin 13 of IC 74HC595 to LOW. It would therefore be advisable to connect, for example, pin 6 (GND) from the RaspberryPi to one of the pins next to the 5V connection on the motor shield.

    OdpovědětVymazat
    Odpovědi
    1. Hi, thank you for using this library. Unfortunately I can not help you much. The car is already disassembled and I do not have free time to do updates. But if you have any suggestions/improvements (even of the picture as you mentioned) please send a Pull Request to Github repository. I will accept it right a way. https://github.com/lipoja/AMSpi

      Vymazat
  20. Hi,

    I found a solution for this problem, you just need to add time.sleep(1) in the last to allow for the python program to set the GPIO state before exiting

    Thanks jan for your program

    OdpovědětVymazat