This tutorial will guide you through the process of developing a simple video player using Python on the UNIHIKER device. The project will utilize the 2x3A DC Motor Driver Carrier Board attached to the UNIHIKER, which provides additional features such as LEDs and an Infrared (IR) receiver. By the end of this tutorial, you will be able to control video playback using a remote control, and the LED status will indicate the playback state.
To complete this tutorial, you will need the following hardware:
- UNIHIKER device from DFRobot
- 2x3A DC Motor Driver Carrier Board for UNIHIKER
- IR remote control
- Necessary cables and connectors
We'll organize our project with the following structure:
The “main.py” script is a Python application that turns a UNIHIKER device into a simple video player. It utilizes the PyGame and OpenCV libraries to handle video playback and display, while interacting with hardware components such as LEDs and an IR receiver.
Key Functionalities:
Video Playback Control: The script plays and stops a video based on input from an IR remote control.
LED Indicators: The LEDs indicate the current playback status, switching between green (playing) and red (stopped).
User Interface: A basic UI is displayed on the screen using PyGame, showing whether the video is playing or stopped.
import pygame
import cv2
from pinpong.board import Board, Pin, IRRecv, NeoPixel
from os.path import dirname, join
from sys import exit
SCREEN_WIDTH: int = 240
SCREEN_HEIGHT: int = 320
FPS: int = 60
FONT_SIZE: int = 32
FONT_COLOR: tuple = (255, 255, 255)
VIDEO_PATH: str = 'demo.mp4'
IR_SIGNAL: hex = '0xff38c7'
LED_GREEN: tuple = (0, 100, 0)
LED_RED: tuple = (100, 0, 0)
def toggle_led_color(status: bool) -> None:
"""
Toggle LED color.
:param status: The status to determine the LED color.
:type status: bool
:return: None
"""
global np
if bool(status):
for led in range(3):
np[led] = LED_GREEN
else:
for led in range(3):
np[led] = LED_RED
def ir_callback(data: int) -> None:
"""
This method is a callback function that is triggered when data is received from an infrared (IR) sensor.
:param data: The data received from the infrared (IR) sensor.
:type data: int
:return: None
"""
global play
print(f'[INFO] IR_SIGNAL: {hex(data)}')
if hex(data) == IR_SIGNAL:
play = not play
toggle_led_color(status=play)
def draw_status(display: pygame.Surface, font_type: pygame.font.Font, status_text: str) -> None:
"""
This function draws the status text on the display.
:param display: The surface on which the status text will be drawn.
:type display: pygame.Surface
:param font_type: The font used to render the status text.
:type font_type: pygame.font.Font
:param status_text: The text to be rendered and displayed as the status.
:type status_text: str
:return: None
"""
status_surface = font_type.render(str(status_text), True, FONT_COLOR)
text_width = status_surface.get_width()
x_pos = (SCREEN_WIDTH - text_width) // 2
y_pos = SCREEN_HEIGHT - FONT_SIZE - 20
display.blit(status_surface, (x_pos, y_pos))
if __name__ == '__main__':
Board().begin()
running = True
play = False
ir = IRRecv(pin_obj=Pin(Pin.P14), callback=ir_callback)
np = NeoPixel(pin_obj=Pin(Pin.P13), num=3)
toggle_led_color(status=play)
current_dir = dirname(__file__)
target_path = join(current_dir, VIDEO_PATH)
cap = cv2.VideoCapture(target_path)
if not cap.isOpened():
print(f'[ERROR] Could not open video file: {VIDEO_PATH}')
exit(1)
pygame.init()
pygame.display.set_caption('Movie Player')
pygame.event.set_allowed(None)
pygame.mouse.set_visible(False)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
font = pygame.font.Font(None, FONT_SIZE)
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((0, 0, 0))
if play:
ret, frame = cap.read()
if not ret:
break
frame = cv2.flip(frame, 1)
frame = cv2.rotate(frame, cv2.ROTATE_90_COUNTERCLOCKWISE)
frame = cv2.resize(frame, (SCREEN_WIDTH, SCREEN_HEIGHT))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame_surface = pygame.surfarray.make_surface(frame)
screen.blit(frame_surface, (0, 0))
draw_status(screen, font, "Video Started")
else:
draw_status(screen, font, "Video Stopped")
pygame.display.flip()
clock.tick(FPS)
cap.release()
cv2.destroyAllWindows()
pygame.quit()
You can upload the project files to the UNIHIKER device using Secure Copy Protocol (SCP) or SMB (Samba). Here's how to do it using SCP:
$ scp -r VideoPlayer [email protected]:/root/
Once the files are uploaded to the UNIHIKER device, you can run the application via touch screen or command-line:
# login to UNIHIKER (via SSH)
$ ssh [email protected]
# change directory
$ cd /root/VideoPlayer/
# run application
$ python3 main.py
Note: The remote control codes are displayed in the terminal. You can adjust this in the constant “IR_SIGNAL”.
What More Ideas Can Be Developed:
Extended Remote Control Functions: Add more buttons on the remote to control functionalities like fast-forward, rewind, and volume control.
Multiple Video Playback: Implement a feature to select and play different videos.
Enhanced UI: Improve the user interface with more interactive elements and better visuals.
Status Indicators: Use the LEDs to indicate different statuses like buffering, error states, etc.
Audio Support: Integrate audio playback alongside the video.