El coche persiguiendo la pelota
Vídeo tutorial 9 - Coche persiguiendo la pelota: https://singtown.com/learn/49239/
Vídeo tutorial 21 - Coche persiguiendo otros objetos: https://singtown.com/learn/50041/
preparar materiales
Placa OpenMV x1:\
Suelo de coche impreso en 3D:
- Batería de litio de 3,7 V x1:
- Placa controladora de motor TB6612 x1:
- Rueda de ojo de buey x2:
- Motor N20 DC x2 (incluida base fija, incluidos neumáticos):
- Tuerca de tornillo M3*20 x2:
- M2*4 tornillos autorroscantes x2
Conecte el circuito y pruebe el motor
Escribe el módulo del coche
En primer lugar, debemos responder: ¿por qué necesitamos escribir módulos? No es difícil accionar el motor directamente. – Debido a que el código es más reutilizable de esta manera, la lógica de control es independiente de la estructura del automóvil. Para diferentes coches, simplemente cambia el módulo del coche.
car.py
from pyb import Pin, Timer
inverse_left=False #change it to True to inverse left wheel
inverse_right=False #change it to True to inverse right wheel
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)))
Guarde el archivo anterior como car.py Según Uso del módulo, guarde car.py en OpenMV.
Pruebe el código en el IDE:\ main.py
import car
while True:
car.run(100,100)
Verifique si el automóvil se está moviendo hacia adelante. De lo contrario, cambie la inversa_izquierda y la inversa_derecha de la segunda y tercera líneas para invertir las ruedas izquierda o derecha para asegurarse de que el automóvil se esté moviendo hacia adelante.
car.run(left_speed, right_speed) tiene dos parámetros, uno es la velocidad de la rueda izquierda y el otro es la velocidad de la rueda derecha.
Si el parámetro de velocidad es un número positivo, avanzará. Si es un número negativo, retrocederá. Cuanto mayor sea el número entre 0~100, mayor será la velocidad.
Implementación del algoritmo PID
El algoritmo pid es un algoritmo ampliamente utilizado en el control y existen muchos principios en Internet.\ https://zh.wikipedia.org/wiki/Controlador PID\ http://baike.baidu.com/link?url=-obQq78Ur4bTeqA10bIniO6y0euQFcWL9WW18vq2hA3fyHN3rt32o79F2WPE7cK0Di9M6904rlHD9ttvVTySIK\ El código sigue siendo muy simple. Copié directamente el código fuente de un control de vuelo:\ https://github.com/wagnerc4/flight_controller/blob/master/pid.py\ Es una copia de 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')
Además, de acuerdo con Uso del módulo, guarde pid.py en OpenMV.
Ajuste los parámetros para lograr lo siguiente
Lo principal es ajustar los dos parámetros de PI, http://blog.csdn.net/zyboy2000/article/details/9418257
# Blob Detection Example
#
# This example shows off how to use the find_blobs function to find color
# blobs in the image. This example in particular looks for dark green objects.
import sensor, image, time
import car
from pid import PID
# You may need to tweak the above settings for tracking green things...
# Select an area in the Framebuffer to copy the color settings.
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.
# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is 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() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the 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:
# Draw a rect around the 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)