RyanZotti / Self-Driving-Car

1.02k stars 327 forks source link

Using a Servo motor for Steering #123

Open alxtee opened 6 years ago

alxtee commented 6 years ago

I am attempting to implement a servo motor to steer the car.

This allows for more precise and variable turns, since the servo is able to turn to a specific angle instead of just switching directions (left or right in this case).

So far I have got the car to turn right and left when the corresponding arrow keys are pushed. However, when I press the up and down arrows the car doesn't move and the servo makes a slight hum, but doesn't move much.

These are the additions I made to the drive_api.py program, mostly found online.

Declaring the servo at the top of the program:


import argparse
import tornado.ioloop
import tornado.web
from datetime import datetime
import os
from operator import itemgetter
import RPi.GPIO as GPIO
import requests
from time import sleep

GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
pwm=GPIO.PWM(12, 50)
pwm.start(0)

SetAngle function near the bottom of the program that handles servo movement and logic

def SetAngle(angle):
    duty = angle / 18 + 2
    GPIO.output(12 , True)
    pwm.ChangeDutyCycle(duty)
    sleep(1)
    GPIO.output(12, False)
    pwm.ChangeDutyCycle(0)

if __name__ == "__main__":

    # Parse CLI args
    ap = argparse.ArgumentParser()
    ap.add_argument("-s", "--speed_percent", required=True, help="Between 0 and 100")
    args = vars(ap.parse_args())
    GPIO.setmode(GPIO.BOARD)
    motor = Motor(16, 18, 22, 19, 21, 23)
    log_entries = []
    settings = {'speed':float(args['speed_percent'])}
    app = make_app(settings)
    app.listen(81)
    tornado.ioloop.IOLoop.current().start()

Setting the angles for left, right and stop:

def forward(self, speed):
        """ pinForward is the forward Pin, so we change its duty
             cycle according to speed. """
        self.pwm_backward.ChangeDutyCycle(0)
        self.pwm_forward.ChangeDutyCycle(speed)    

    def forward_left(self, speed):
        """ pinForward is the forward Pin, so we change its duty
             cycle according to speed. """
        self.pwm_backward.ChangeDutyCycle(0)
        self.pwm_forward.ChangeDutyCycle(speed)  
        # self.pwm_right.ChangeDutyCycle(0)
        # self.pwm_left.ChangeDutyCycle(100)   
        SetAngle(120)

    def forward_right(self, speed):
        """ pinForward is the forward Pin, so we change its duty
             cycle according to speed. """
        self.pwm_backward.ChangeDutyCycle(0)
        self.pwm_forward.ChangeDutyCycle(speed)
        # self.pwm_left.ChangeDutyCycle(0)
        # self.pwm_right.ChangeDutyCycle(100)
        SetAngle(0)

    def backward(self, speed):
        """ pinBackward is the forward Pin, so we change its duty
             cycle according to speed. """

        self.pwm_forward.ChangeDutyCycle(0)
        self.pwm_backward.ChangeDutyCycle(speed)

    def left(self, speed):
        """ pinForward is the forward Pin, so we change its duty
             cycle according to speed. """
        # self.pwm_right.ChangeDutyCycle(0)
        # self.pwm_left.ChangeDutyCycle(speed)  

    def right(self, speed):
        """ pinForward is the forward Pin, so we change its duty
             cycle according to speed. """
        # self.pwm_left.ChangeDutyCycle(0)
        # self.pwm_right.ChangeDutyCycle(speed)   

    def stop(self):
        """ Set the duty cycle of both control pins to zero to stop the motor. """

        self.pwm_forward.ChangeDutyCycle(0)
        self.pwm_backward.ChangeDutyCycle(0)
        # self.pwm_left.ChangeDutyCycle(0)
        # self.pwm_right.ChangeDutyCycle(0)
        SetAngle(50)

If anyone might know why I am getting the issues above, please comment.

Thanks.

zfhall commented 6 years ago

Does the car move forward when you press left and right arrow keys? Or do the front wheels just turn?

Have you defined self.pwm_forward and self.pwm_backward?

alxtee commented 6 years ago

@zfhall Just the front wheels turn, self.pwm_forward and self.pwm_backward are already defined.

The only changes made were the declaration of the servo, the SetAngle function and setting the angles inside of the def's, as posted above.

Thanks

RyanZotti commented 6 years ago

I have also had the humming-but-no-movement issue before, but it’s been awhile since I last had that problem so I don’t recall the fix off the top of my head. I’ll reply back here if I remember though.

RyanZotti commented 6 years ago

Actually, I had a temporary issue earlier today where I couldn’t turn but only move forward/backward, but that was due to crossed/touching wires (I did a poor job soldering and have exposed wire metal). As soon as I moved the wires apart from each other the car was able to turn again. Not sure if that’s your extact issue though. If it’s never worked for you I would also double check that you plugged the wires into the correct GPIO pins on the Pi.

zfhall commented 6 years ago

What motor control chip are you using? The L293D and L298N cannot handle high current DC motors. If you are using one of these chips, it's likely that the voltage drop across them is so large when a load is applied, that there is next to no voltage being sent the motor. Try the Cytron MD10C DC Motor Driver instead.

alxtee commented 6 years ago

@RyanZotti I doubled checked the wiring and I don't see any issues. I can try a deep check.

@zfhall I am using the L293D motor contoller, but I don't know if thats the issue since the servo is connected to the RPI and there's only one motor being run from the controller.

I think it might be an issue with the edited code because after some more testing it seems that with my servo code up top- I get really bad latency/performance issues with driving forward and back: I would press the up arrow and a few seconds later the motors would come on shortly and then full power for a few seconds.

However, with servo steering there is a bit a latency at first but later little. I also tried running the servo code with servo unplugged and got same issues moving back and forth.

zfhall commented 6 years ago

@Charlieglider I may be missing something here, but if the motor connected to the L293D is used for forward/backward control, and you are having problems driving forward/backward, then the L293D could still be at fault. Does the forward/backward motor ever run continuously without cutting out? What car are you using? Does the DC motor (not servo) have a serial number? It sounds like you have the same setup as I do, and I had this exact problem until I switched to the MD10C. If you have a multimeter, try measuring the voltage sent to the motor when you tell it to drive forward/backward. If the voltage is lower than your battery voltage, you likely have a problem with the chip.

alxtee commented 6 years ago

@zfhall Apologies for any confusion, when I run the normal drive_api.py (no changes/servo added in) I get decent driving performance forward and back (no left and right capability because I am using a servo). However, when I run drive_api.py with my changes made above and the servo added in, I get the steering capabilities but get choppy driving or have the forward/back motor running continuously without cutting out.

I can try measuring the voltage at the motor, I also think I'm losing power/performance somewhere, but it might be a separate issue to the one with the servo.

zfhall commented 6 years ago

@Charlieglider Ah OK, that makes sense now. I'll try and have another look at your issue when I next get the chance. But I'm going to quite busy over the next few days so hopefully, someone else can chime in with a solution. Good luck!

alxtee commented 6 years ago

@zfhall Ok, thank you.

alxtee commented 6 years ago

I know it has been a while since the last post on this issue.

Nonetheless, any ideas for getting this car to work with the servo?