[ev3dev × Python] Gyro sensor

This article is for anyone who wants to work with ev3 in Python. This time, I would like to perform various operations using the gyro sensor.

table of contents

  1. What to prepare
  2. Gyro sensor program

0. What to prepare

◯ ev3 (tank) and gyro sensor ◯ Personal computer (VS Code) ◯ bluetooth ◯ microSD ◯ Material (It is recommended to proceed while watching this.)

1. Gyro sensor program (Document p.36)

1-0. Program that changes direction by a specified angle ①

gyrosensor00.py


#!/usr/bin/env python3
from ev3dev2.sensor.lego import GyroSensor
from ev3dev2.display import Display
from time import sleep

#Instance generation
dsp = Display()
gy = GyroSensor()

#Repeat 4 times
for i in range(4):
    #Go straight two turns
    tank_drive.on_for_rotations(10,10,2)
    #Set the value of the gyro sensor to 0
    gy.reset()
    #Continue to change direction until the value of the gyro sensor changes by 90 degrees.
    tank_drive.on(5,0)
    gy.wait_until_angle_changed_by(90)
exit()

** Point **: A program that repeats going straight and turning 90 degrees four times.

Point : wait_until_angle_changed_by(delta,direction_sensitive=False)

A function that waits until it changes by the specified angle. Enter the width of change (displacement) in the first argument. direction_sensitive can determine whether to distinguish the direction of rotation.

For example, if delta = -90, If direction_sensitive = True, wait until the gyro sensor value reaches -90. (Distinguish the direction of rotation) If direction_sensitive = False, wait until the gyro sensor value reaches 90 or -90. (Do not distinguish the direction of rotation)

1-1. Program that changes direction by a specified angle ②

gyrosensor01.py


#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_A, OUTPUT_B, MoveTank, SpeedPercent
from ev3dev2.sensor.lego import GyroSensor

#Instance generation
tank = MoveTank(OUTPUT_A, OUTPUT_B)
#Assign an instance of the gyro sensor to the variable gyro in the class MoveTank
tank.gyro = GyroSensor()
#Set the current gyro sensor value to 0
tank.gyro.calibrate()

#Rotate 30 degrees
tank.turn_degrees(
speed=SpeedPercent(5),
target_angle=30
)

** Point **: A program that turns 30 degrees

Point : turn_degrees(speed, target_angle, brake=True, error_margin=2, sleep_time=0.01) → This is a tank-specific function that uses a gyro sensor to wait until the angle direction is changed as specified on the spot. error_margin can determine how much error is allowed between the target_angle and the actual turn.

1-2. Program to display the angle

gyrosensor02.py


#!/usr/bin/env python3
from ev3dev2.display import Display
from ev3dev2.sensor.lego import GyroSensor
from time import sleep

dsp = Display()
gy = GyroSensor()

#infinite loop
while True:
    dsp.update()
    #Because I always want to get the value of the gyro sensor
    #The variable ang is created in a loop.
    ang = gy.angle
    #Convert the angle of the gyro sensor to characters and display it with the unit
    dsp.text_pixels(str(ang) + 'cm',True,0,52,font = 'helvB' + '24')
    #Get characters at intervals to make processing lighter
    sleep(0.1)

** Point **: A program that displays the value of the gyro sensor

Point : angle A variable that stores the numerical value of the gyro sensor.

1-3. Parallel processing program

gyrosensor03.py


#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_A,OUTPUT_B,MoveTank
from ev3dev2.display import Display
from ev3dev2.sensor.lego import GyroSensor
from time import sleep
from threading import Thread

#Instance generation
tank_drive = MoveTank(OUTPUT_A,OUTPUT_B)
dsp = Display()
gy = GyroSensor()

#Create your own function(Define)
def angle_display():
    # loop =Repeated while True
    #Program to display the angle
    while loop:
        dsp.update()
        gy = gy.angle
        dsp.text_pixels(str(angle) + 'cm',True,0,52,font = 'helvB' + '24')
        sleep(0.1)

#Keep loop true
loop = True
#Create an instance t of class Thread
#Select which thread to start
t = Thread(target = angle_display)
#Start a thread with an instance
t.start()

#Repeat 4 times
for i in range(4):
    #Go straight two turns
    tank_drive.on_for_rotations(10,10,2)
    #Set the value of the gyro sensor to 0
    gy.reset()
    #Continue to change direction until the value of the gyro sensor changes by 90 degrees.
    tank_drive.on(5,0)
    gy.wait_until_angle_changed_by(90)
tank_drive.stop()
#End the thread by setting loop to False
loop = False

Point : A program that repeats going straight and turning 90 degrees four times Then, the value of the gyro sensor is displayed at the same time as running.

** Point **: Reference article on parallel processing Multithreading [Implement in thread](https://qiita.com/tchnkmr/items/b05f321fa315bbce4f77#:~:text=%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89 % E3% 81% A8% E3% 81% AF,% E3% 82% 92% E8% A1% 8C% E3% 81% 86% E3% 81% 93% E3% 81% A8% E3% 81% 8C% E3% 81% A7% E3% 81% 8D% E3% 81% BE% E3% 81% 9B% E3% 82% 93% E3% 80% 82 & text =% E3% 81% 9D% E3% 81% AE% E4 % B8% A6% E5% 88% 97% E5% 87% A6% E7% 90% 86% E3% 82% 92% E8% A1% 8C% E3% 81% 86,% E3% 81% AE% E4% BD% BF% E7% 94% A8% E3% 81% AB% E3% 81% AA% E3% 82% 8A% E3% 81% BE% E3% 81% 99% E3% 80% 82)

** Point **: Reference article about functions Define / call a function in Python (def, return)

1-4. Concurrent processing program

main.py


#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_A,OUTPUT_B,MoveTank
from ev3dev2.sensor.lego import GyroSensor
import subprocess

#Instance generation
tank_drive = MoveTank(OUTPUT_A,OUTPUT_B)
gy = GyroSensor()

#Run the child program in a new process
subprocess.Popen(['python3','sub.py'])

for i in range(4):
    #Go straight two turns
    tank_drive.on_for_rotations(10,10,2)
    #Set the value of the gyro sensor to 0
    gy.reset()
    #Continue to change direction until the value of the gyro sensor changes by 90 degrees.
    tank_drive.on(5,0)
    gy.wait_until_angle_changed_by(90)
#Create an instance proc of Popen class
proc = subprocess.Popen(['python3','sub.py'])
#Kill the child process using proc
proc.kill()
exit()

sub.py


from ev3dev2.sensor.lego import GyroSensor
from ev3dev2.display import Display
from time import sleep

dsp = Display()
us = GyroSensor()

#infinite loop
while True:
    dsp.update()
    #Because I always want to get the value of the gyro sensor
    #The variable ang is created in a loop.
    ang = gy.angle
    #Convert the angle of the gyro sensor to characters and display it with the unit
    dsp.text_pixels(str(ang) + 'cm',True,0,52,font = 'helvB' + '24')
    #Get characters at intervals to make processing lighter
    sleep(0.1)

** Point **: A program that repeats going straight and turning 90 degrees four times. Then, the value of the gyro sensor is displayed at the same time as running.

** Point **: A program that calls sub.py from main.py for parallel processing. (Processing is heavy) Point : subprocess.Popen() Just spawn a process, don't wait for it to finish → Start and leave Popen.terminate() Stop the child process. Popen.kill() Kill the child process.

** Point **: Reference article on concurrency Introduction to Concurrency Programming in Python [Deeper about subprocess (3 series, updated version)] (https://qiita.com/HidKamiya/items/e192a55371a2961ca8a4#subprocesspopen%E3%81%AB%E3%82%88%E3%82%8B%E8%87%AA%E7%94%B1%E5%BA%A6%E3%81%AE%E9%AB%98%E3%81%84%E5%87%A6%E7%90%86) [17.5. Subprocess — Subprocess Management (Official)] (https://docs.python.org/ja/3.5/library/subprocess.html)

1-5. A program that runs using PID control

gyrosensor05.py


from ev3dev2.motor import OUTPUT_A, OUTPUT_B, MoveTank, SpeedPercent, follow_for_ms
from ev3dev2.sensor.lego import GyroSensor

#Instance generation
tank = MoveTank(OUTPUT_A, OUTPUT_B)
#Assign an instance of class GyroSensor to the variable gyro in class MoveTank
tank.gyro = GyroSensor()
#Set the current gyro sensor value to 0
tank.gyro.calibrate()

try:
#4500ms(4.5 seconds)Only during
#The value of the gyro sensor is always the target value(0 in this case)Start running so that
    tank.follow_gyro_angle(
    kp=11.3, ki=0.05, kd=3.2,
    speed=SpeedPercent(30),
    target_angle=0,
    follow_for=follow_for_ms,
    ms=4500
    )
#Decide what to do if an exception occurs
except FollowGyroAngleErrorTooFast:
    tank.stop()
    raise

** Point **: A program that runs while trying to keep the angle at 0 no matter what Use PID control to try to bring the gyro sensor value closer to the target value.

Point : follow_gyro_angle(kp, ki, kd, speed, target_angle=0, sleep_time=0.01, follow_for=, **kwargs)

kp, ki, kd are PID constants. speed is the speed of the robot target_angle is the angle you want to keep

** Point **: Reference article about PID control

PID control of line trace car

** Point **: Reference article about python exception handling

Python exception handling (try, except, else, finally)

Finally

Thank you for reading! !! Next time I would like to write about ssh control!

I want to make a better article ◯ This is easier to understand ◯ This is difficult to understand ◯ This is wrong ◯ I want you to explain more here We appreciate your opinions and suggestions.

Recommended Posts

[ev3dev × Python] Gyro sensor
[ev3dev × Python] Ultrasonic sensor
[ev3dev × Python] Touch sensor
[ev3dev × Python] Color sensor
[ev3dev × Python] Intelligent block button
[ev3dev × Python] Build ev3dev development environment
[ev3dev × Python] Single motor control
[ev3dev × Python] Control of multiple motors
Python
[ev3dev × Python] Display, audio, LED control
Get keystrokes from / dev / input (python evdev)
[ev3dev × Python] SSH Control (remote control with keyboard)