EV3 PyBrick question

Discussion and questions about boards that can run MicroPython but don't have a dedicated forum.
Target audience: Everyone interested in running MicroPython on other hardware.
Post Reply
Frank He
Posts: 1
Joined: Fri Oct 30, 2020 4:39 pm

EV3 PyBrick question

Post by Frank He » Fri Oct 30, 2020 4:42 pm

https://stackoverflow.com/questions/645 ... nvironment

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!

Post Reply