We were so excited that we finished our first volunteer teaching class in our community, shared with a group of 6 kids aged 11 – 12. Introduced them to the world of Arduino by making simple LED circuity.
I feel like I have learned a lot while teaching the students, I have learned how to teach people clearly and how to make them understand how to write the program and create the circuit. This lesson also proved that I can teach people programming and circuitry. I think I can have a better time management skill the next time I teach the kids. I want to have better time management skill because we didn’t have enough time to make other light patterns. – Alex
I have learnt a lot from this teaching experience. My programming skills may not be as good as Alex, but I was a good supporter. When Alex is teaching the class, I guided Alex to bring up different topics to make his teaching more fascinating. I also guided the students to have a better understanding of the program. From this teaching lesson, I have learnt that being a good supporter can help make big difference in how the students think and how the teacher speak. Because I forgot most of the programming techniques, so I took this lesson for granted and I managed to recover most of the techniques. Without this lesson, I don’t think I would even remember how to turn on a led. For this time’s lesson, I am very satisfied in the result, so I would like to continue teaching the kids or other kids! – Mountain
Since ev3dev is Linux based, when PS4 controller connected to the EV3 Brick via Bluetooth, we can identify the handler from a directory call /dev/input. As shown below, event2, event3 and event4 are created when the PS4 controller is connected.
When we looked into the device detail from /proc/bus/input/devices, we can get the following details,
We are going to use the Wireless Controller to control the Dog, event4 is the target handler to get all inputs information. Based on the information we reviewed, we learnt that event4 contains 16 bytes of data as shown below,
tv_sec (long unsigned value) : Time in seconds since epoch at which event occurred.
tv_usec (long unsigned value) : Microsecond portion of the timestamp.
ev_type (unsigned short) : Event type
code (unsigned short) : Event code
value (signed long) : Event value
We are using ev_type, code and value to monitor the PS4 controller inputs. It updates real time for any status change, such as button press, button release, joystick movement. Keep in mind, if a button is being held, it will generate a value ‘1’ for once but no additional update until the button is released, then a value ‘0’ will be generated.
[This part was created by Adam]
PS4 Controller mapping with EV3DEV
# Open the PS4 Controller file at /dev/input/event4 in binary mode
infile_path = "/dev/input/event4"
in_file = open(infile_path, "rb")
# Format of the event contains - unsigned long int, unsigned long int,
# unsigned short, unsigned short, signed int, i.e. LLHHi
FORMAT = 'LLHHi'
EVENT_SIZE = struct.calcsize(FORMAT)
.
.
.
# Read from the file and unpack into five variable based on the format
event = in_file.read(EVENT_SIZE)
(tv_sec, tv_usec, ev_type, code, value) = struct.unpack(FORMAT, event)
This part is to open the file event4 to import the PS4 Controller values into 5 variables based on the predefined format – ‘LLHHi’. We use ev_type, code and value to identify the action from PS4 Controller.
ev_type : There are two main type, type 1 = buttons, type 3 = joystick, dpad and analog trigger
code : Which button or joystick being pressed / moved
value : The action done, button pressed = 1, released = 0, or analog value from joystick and analog trigger
So, we wrote a small program to identify each codes and values from the PS4 Controller. The result is shown below,
Key mapping as shown below
Type = 1, code & possible value
L1 - 310 (0,1)
L2 - 312 (0,1)
L3 - 317 (0,1)
R1 - 311 (0,1)
R2 - 313 (0,1)
R3 - 318 (0,1)
Triangle - 307 (0,1)
Square - 308 (0,1)
Cross - 304 (0,1)
Circle - 305 (0,1)
Share - 314 (0,1)
Option - 315 (0,1)
PS - 316 (0,1)
Type = 3, code & possible value
Left Stick Y - 1 (Up 0 - Down 255)
Left Stick X - 0 (Left 0 - Right 255)
Right Stick Y - 4 (Up 0 - Down 255)
Right Stick X - 3 (Left 0 - Right 255)
L2 - 2 (0 - 255)
R2 - 5 (0 - 255)
dpad Up & Down - 17 (-1, 0, 1)
dpad Left & Right- 16 (-1, 0, 1)
How does the program work
def PS4_Controller():
global pressed
global trigger_dog
global speed
global speed_backwards
global speed_forwards
global turning
global out
while True:
# Read from the file and unpack into five variable based on the format
event = in_file.read(EVENT_SIZE)
(tv_sec, tv_usec, ev_type, code, value) = struct.unpack(FORMAT, event)
if ev_type == 1 and code == 311 and value == 1:
trigger_dog = 45
out = 1
if ev_type == 1 and code == 311 and value == 0:
trigger_dog = 0
out = 0
if ev_type == 1 and code == 310 and value == 1 and out == 0:
trigger_dog = 35
if ev_type == 1 and code == 310 and value == 0 and out == 0:
trigger_dog = 0
if ev_type == 1 and code == 305 and value == 1:
pressed = True
if ev_type == 1 and code == 305 and value == 0:
pressed = False
if ev_type == 3 and code == 5:
speed_forwards = value * 6
elif ev_type == 3 and code == 2:
speed_backwards = value * -6
if ev_type == 3 and code == 0:
turning = (value*360-(180*255))/255
PS4_Controller_Thread = threading.Thread(target = PS4_Controller)
PS4_Controller_Thread.setDaemon = True
PS4_Controller_Thread.start()
bite = 0
while True:
speed = speed_forwards + speed_backwards
print(speed)
combo(pressed)
forward(speed,turning)
bite = Dog_bite(trigger_dog, bite)
in_file.close()
Basic Idea
Since we didn’t want to change the program of ‘the Dog’, we replaced the LEGO Controller part, i.e. receiving LEGO Controller result, with a new function to detect the action from the PS4 Controller buttons and joysticks. When corresponding action done on the PS4 Controller, the function will update the variable for ‘the Dog’ to action.
For example, when we press the circle, the function will detect a value of ev_type = 1 , code = 305 and value = 1. Then, it changes the variable ‘Pressed ‘ to True so that ‘the Dog’ will do combo. If we keep pressing the button, the variable ‘Pressed’ will stay True until we released the button.
Parallel Processing
We made the function parallel processing because it can detect all the status changes from the PS4 Controller. If we use normal function, the function will only read the latest actions from the controller that may result missing some of the actions. Especially, if we want to detect button pressed or released.
Global Variable
When we use global variable, the variable change by the parallel progressing function can be read by the program outside. For the PS4_Controller function detects any actions from the controller, it will change the corresponding variable for ‘the Dog’ to respond, just like the LEGO Controller sending message to ‘the Dog’.
Build instruction and the program
We created the program from scratch without referring any example, you can download from below.