I have this question post on Stack Overflow. Is there anyone can help us with this question? Thanks.
I installed the Mindstorm EV3 extension in VS Code. We try to import this PID controller into VS Code Mindstorm Extension. How could we do that? We tried "import PID", it doesn't work...We tried to paste the PID.py code into our file, it doesn't work as well. Here is the Github link.
https://github.com/ivmech/ivPID
Code: Select all
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor,
InfraredSensor, UltrasonicSensor, GyroSensor)
from pybricks.parameters import Port, Stop, Direction, Button, Color
from pybricks.tools import wait, StopWatch, DataLog
from pybricks.robotics import DriveBase
from pybricks.media.ev3dev import SoundFile, ImageFile
# This program requires LEGO EV3 MicroPython v2.0 or higher.
# Click "Open user guide" on the EV3 extension tab for more information.
# Variables and constants
ev3 = EV3Brick()
leftMotor = Motor(Port.B, Direction.CLOCKWISE)
rightMotor = Motor(Port.C, Direction.CLOCKWISE)
#left medium motor
mediumMotor = Motor(Port.D, Direction.COUNTERCLOCKWISE)
#right medium motor
mediumMotor2 = Motor(Port.A, Direction.COUNTERCLOCKWISE)
robot = DriveBase(leftMotor, rightMotor, 55.85, 108)
robot.settings(300, 100, 200, 100)
rightcolor = ColorSensor(Port.S1)
leftcolor = ColorSensor(Port.S2)
gyroSensor = GyroSensor(Port.S3)
black = 3
white = 30
import time
def linesquare():
leftblack = leftcolor.reflection() > black - 2 and leftcolor.reflection() < black + 2
rightblack = rightcolor.reflection() > black - 2 and rightcolor.reflection() < black + 2
leftMotor.run(200)
rightMotor.run(200)
while not leftblack or not rightblack:
leftblack = leftcolor.reflection() > black - 2 and leftcolor.reflection() < black + 2
rightblack = rightcolor.reflection() > black - 2 and rightcolor.reflection() < black + 2
if leftblack:
leftMotor.brake()
if rightblack:
rightMotor.brake()
leftrange = leftcolor.reflection() > threshold - 2 and leftcolor.reflection() < threshold + 2
rightrange = rightcolor.reflection() > threshold - 2 and rightcolor.reflection() < threshold + 2
while not leftrange or not rightrange:
leftrange = leftcolor.reflection() > threshold - 2 and leftcolor.reflection() < threshold + 2
rightrange = rightcolor.reflection() > threshold - 2 and rightcolor.reflection() < threshold + 2
if leftrange:
leftMotor.brake()
else:
if leftcolor.reflection() > threshold + 2:
leftMotor.run(50)
else:
leftMotor.run(-50)
if rightrange:
rightMotor.brake()
else:
if rightcolor.reflection() > threshold + 2:
rightMotor.run(50)
else:
rightMotor.run(-50)
class PID:
"""PID Controller
"""
def _init_(self, P=0.2, I=0.0, D=0.0, current_time=None):
self.Kp = P
self.Ki = I
self.Kd = D
self.sample_time = 0.00
self.current_time = current_time if current_time is not None else time.time()
self.last_time = self.current_time
self.clear()
def clear(self):
"""Clears PID computations and coefficients"""
self.SetPoint = 0.0
self.PTerm = 0.0
self.ITerm = 0.0
self.DTerm = 0.0
self.last_error = 0.0
# Windup Guard
self.int_error = 0.0
self.windup_guard = 20.0
self.output = 0.0
def update(self, feedback_value, current_time=None):
"""Calculates PID value for given reference feedback
.. math::
u(t) = K_p e(t) + K_i \int_{0}^{t} e(t)dt + K_d {de}/{dt}
.. figure:: images/pid_1.png
:align: center
Test PID with Kp=1.2, Ki=1, Kd=0.001 (test_pid.py)
"""
error = self.SetPoint - feedback_value
self.current_time = current_time if current_time is not None else time.time()
delta_time = self.current_time - self.last_time
delta_error = error - self.last_error
if (delta_time >= self.sample_time):
self.PTerm = self.Kp * error
self.ITerm += error * delta_time
if (self.ITerm < -self.windup_guard):
self.ITerm = -self.windup_guard
elif (self.ITerm > self.windup_guard):
self.ITerm = self.windup_guard
self.DTerm = 0.0
if delta_time > 0:
self.DTerm = delta_error / delta_time
# Remember last time and last error for next calculation
self.last_time = self.current_time
self.last_error = error
self.output = self.PTerm + (self.Ki * self.ITerm) + (self.Kd * self.DTerm)
def setSampleTime(self, sample_time):
"""PID that should be updated at a regular interval.
Based on a pre-determined sample time, the PID decides if it should compute or return immediately.
"""
self.sample_time = sample_time
#run 1
#robot.straight(610)
#robot.turn(-45)
pid = PID(0.9, 1, 0.001)
pid.setSampleTime(0.01)
pid.SetPoint=(black + white) / 2
feedback = rightcolor.reflection()
#robot.reset()
print(pid.last_time)
print(pid.current_time)
print(time.time())
while robot.distance() < 960:
print(pid.last_time)
print(pid.current_time)
print(time.time())
pid.update(feedback)
robot.drive(200, pid.output)
feedback = rightcolor.reflection()
robot.turn(90)
robot.straight(-500)
linesquare()
robot.straight(1200)
mediumMotor.run_time(300, 3000)
The error we got is that there is no attribute of last time. But it works when it is the test.py
Any idea helps!