Voiture poursuivant une petite balle

Tutoriel vidéo 9 - La voiture qui chasse la balle : https://singtown.com/learn/49239/
Tutoriel vidéo 21 - Une voiture chassant d'autres objets : https://singtown.com/learn/50041/

Préparer le matériel

  • Carte OpenMV x1 :\

  • Base de voiture imprimée en 3D :

  • Batterie au lithium 3,7V x1 :

  • Carte de pilotage moteur TB6612 x1 :

  • Roue folle (bull's eye) x2 :

  • Moteur DC N20 x2 (avec support fixe, avec pneu) :

  • Écrou de vis M3*20 x2 :

  • Vis autotaraudeuse M2*4 x2

Connecter le circuit et tester le moteur

Écrire le module de la voiture

Tout d'abord, pourquoi devons-nous écrire un module ? Il n'est pas difficile de piloter directement le moteur. – Parce que c'est la meilleure façon de réutiliser le code, et la logique de contrôle est indépendante de la structure de la voiture. Pour différentes voitures, il suffit de changer le module de la voiture.

car.py

from pyb import Pin, Timer
inverse_left=False  # changez en True pour inverser la roue gauche
inverse_right=False # changez en True pour inverser la roue droite

ain1 =  Pin('P0', Pin.OUT_PP)
ain2 =  Pin('P1', Pin.OUT_PP)
bin1 =  Pin('P2', Pin.OUT_PP)
bin2 =  Pin('P3', Pin.OUT_PP)
ain1.low()
ain2.low()
bin1.low()
bin2.low()

pwma = Pin('P7')
pwmb = Pin('P8')
tim = Timer(4, freq=1000)
ch1 = tim.channel(1, Timer.PWM, pin=pwma)
ch2 = tim.channel(2, Timer.PWM, pin=pwmb)
ch1.pulse_width_percent(0)
ch2.pulse_width_percent(0)

def run(left_speed, right_speed):
    if inverse_left==True:
        left_speed=(-left_speed)
    if inverse_right==True:
        right_speed=(-right_speed)

    if left_speed < 0:
        ain1.low()
        ain2.high()
    else:
        ain1.high()
        ain2.low()
    ch1.pulse_width_percent(int(abs(left_speed)))

    if right_speed < 0:
        bin1.low()
        bin2.high()
    else:
        bin1.high()
        bin2.low()
    ch2.pulse_width_percent(int(abs(right_speed)))

Enregistrez le fichier ci-dessus sous car.py, et enregistrez car.py sur OpenMV selon l'utilisation des modules.

Testez le code dans l'IDE :\ main.py

import car

while True:
    car.run(100,100)

Vérifiez si la voiture avance. Sinon, modifiez inverse_left et inverse_right aux deuxième et troisième lignes pour inverser la roue gauche ou droite afin de garantir que la voiture avance.

car.run(left_speed, right_speed) prend deux paramètres, l'un est la vitesse de la roue gauche et l'autre est la vitesse de la roue droite.

Si le paramètre de vitesse est un nombre positif, la roue tournera vers l'avant, s'il est négatif, elle tournera vers l'arrière. Plus le nombre est grand entre 0 et 100, plus ce sera rapide.

Implémentation de l'algorithme PID

L'algorithme PID est un algorithme très courant utilisé en contrôle, et il existe de nombreux principes sur Internet.\ https://zh.wikipedia.org/wiki/PID控制器\ http://baike.baidu.com/link?url=-obQq78Ur4bTeqA10bIniO6y0euQFcWL9WW18vq2hA3fyHN3rt32o79F2WPE7cK0Di9M6904rlHD9ttvVTySIK\ Le code est très simple. J'ai directement copié le code source d'un contrôleur de vol :\ https://github.com/wagnerc4/flight_controller/blob/master/pid.py\ C'est une copie d'ArduPilot\ https://github.com/ArduPilot/ardupilot

pid.py

from pyb import millis
from math import pi, isnan

class PID:
    _kp = _ki = _kd = _integrator = _imax = 0
    _last_error = _last_derivative = _last_t = 0
    _RC = 1/(2 * pi * 20)
    def __init__(self, p=0, i=0, d=0, imax=0):
        self._kp = float(p)
        self._ki = float(i)
        self._kd = float(d)
        self._imax = abs(imax)
        self._last_derivative = float('nan')

    def get_pid(self, error, scaler):
        tnow = millis()
        dt = tnow - self._last_t
        output = 0
        if self._last_t == 0 or dt > 1000:
            dt = 0
            self.reset_I()
        self._last_t = tnow
        delta_time = float(dt) / float(1000)
        output += error * self._kp
        if abs(self._kd) > 0 and dt > 0:
            if isnan(self._last_derivative):
                derivative = 0
                self._last_derivative = 0
            else:
                derivative = (error - self._last_error) / delta_time
            derivative = self._last_derivative + \
                                     ((delta_time / (self._RC + delta_time)) * \
                                        (derivative - self._last_derivative))
            self._last_error = error
            self._last_derivative = derivative
            output += self._kd * derivative
        output *= scaler
        if abs(self._ki) > 0 and dt > 0:
            self._integrator += (error * self._ki) * scaler * delta_time
            if self._integrator < -self._imax: self._integrator = -self._imax
            elif self._integrator > self._imax: self._integrator = self._imax
            output += self._integrator
        return output
    def reset_I(self):
        self._integrator = 0
        self._last_derivative = float('nan')

Enregistrez également pid.py sur OpenMV selon l'utilisation des modules.

Ajuster les paramètres pour réaliser le suivi

L'essentiel est d'ajuster les deux paramètres de PI, http://blog.csdn.net/zyboy2000/article/details/9418257

# Exemple de détection de blob
#
# Cet exemple montre comment utiliser la fonction find_blobs pour trouver des
# blobs de couleur dans l'image. Cet exemple recherche en particulier des
# objets vert foncé.

import csi, image, time
import car
csi0 = csi.CSI()

from pid import PID

# Vous devrez peut-être ajuster les réglages ci-dessus pour suivre des objets verts...
# Sélectionnez une zone dans le tampon d'image pour copier les réglages de couleur.

csi0.reset() # Initialise le capteur de la caméra.
csi0.pixformat(csi.RGB565) # utilise RGB565.
csi0.framesize(csi.QQVGA) # utilise QQVGA pour la vitesse.
csi0.snapshot(frames=10) # Laisse les nouveaux réglages prendre effet.
csi0.auto_whitebal(False) # désactive ceci.
clock = time.clock() # Suit le FPS.

# Pour que le suivi de couleur fonctionne vraiment bien, vous devriez idéalement
# être dans un environnement très, très, très contrôlé où l'éclairage est constant...
green_threshold   = (76, 96, -110, -30, 8, 66)
size_threshold = 2000
x_pid = PID(p=0.5, i=1, imax=100)
h_pid = PID(p=0.05, i=0.1, imax=50)

def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size:
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob

while(True):
    clock.tick() # Suit les millisecondes écoulées entre les snapshot().
    img = csi0.snapshot() # Prend une photo et renvoie l'image.

    blobs = img.find_blobs([green_threshold])
    if blobs:
        max_blob = find_max(blobs)
        x_error = max_blob[5]-img.width()/2
        h_error = max_blob[2]*max_blob[3]-size_threshold
        print("x error: ", x_error)
        '''
        for b in blobs:
            # Dessine un rectangle autour du blob.
            img.draw_rectangle(b[0:4]) # rect
            img.draw_cross((b[5], b[6])) # cx, cy
        '''
        img.draw_rectangle(max_blob[0:4]) # rect
        img.draw_cross((max_blob[5], max_blob[6])) # cx, cy
        x_output=x_pid.get_pid(x_error,1)
        h_output=h_pid.get_pid(h_error,1)
        print("h_output",h_output)
        car.run(-h_output-x_output,-h_output+x_output)
    else:
        car.run(18,-18)

results matching ""

    No results matching ""