1 https://github.com/LAPSyLAB/Misko3_Docs_and_Projects
Parts list
- Miško 3 an STM32G474QETx board
Miško 3
Miško 3 is a development board for learning programming on microcontroller. The name stands for Microcontroller Student Kit (MIkrokrmilniški Študentski KOmplet) 3rd generation and it's powerd by STM32G474QETx, an ARM-based 32-bit MCU. It has 12 PWM pins, 4 serial communications (RX, TX), 30 digital pins, 12 analog pins and can supply 3.3V, 5V and 12V.You can learn more about the MCU on https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf .
Before we can use the board, we need to solder on 7 buttons, 8 leds, connector headers and the screen (XPT2046) as well as connect the joystick and srew it in place.
Maze
There are many different types of mazes1: standard, circular, block, number... For this project we'll implement a standard maze without entrance and exit where the goal is to find the shortest path from one position to another. For storing the maze we'll use an array where 1 will be a wall and 0 will be a path.1 https://en.wikipedia.org/wiki/Maze
Generating
There are many different aproches for randomly generating mazes1 such as randomized depth-first search, Kruskal's algorithm, Prim's algorithm... The algorithm that we are going to implement is randomized depth-first search with iterative implementation. Before we implement everything from scratch we should search the web if there is allredy something similar allready made. I found just what we need on Figglewatts's github2 which we'll modifiy to suit our needs.Since iterative implementation of random dept-first search is implemented using a stack, we have to implement it first before we even think of
making algorithm. Stack is an abstract data type which serves as a collection of elements that has two main operations: push (adds element) and pop (removes last added element).
These two operations are implemented as stack_push and stack_pop. Since there is no built-in implementation of array that automatically resizes in C, we use a pointer to allocated space,
which we realocate to double size when it runs out of allocated capacity.
1 https://en.wikipedia.org/wiki/Maze_generation_algorithm
2 https://github.com/Figglewatts/mazegen
After implementation of stack, we can implement a interative random dept-first search. The maze that we're implementing has 2 different axis, x and y axis,
therefore we need 2 stacks to store each axis without over complicating functionality of the stack. For implementation of the algorithm we run a while loop
until one of the stack is empty. Which stack we check is not important since they are always the same size. To make the algorithm random we first shuffle the directions of posible moves in current position.
If the planned direction is at the edge or it is allready a path (zero), nothing happens, otherwise a path is made (zero is written in two next cells on planned directions)
and the position with that direction is pushed to a stack.
Since the above algorithm is just for carving the maze, we also need a function to initialize all variables and allocate enough space for a maze of defined
size and fill it with walls (ones). When the algorithm is done carving the maze, the generated maze is returned to the main program where we implement the logic for
player movement and visualise it.
Visualising
For visualising the maze, we will use μGUI1, a free and open source library for embedded systems. The algorithm used for drawing the walls will draw white lines of defined size withUG_DrawLine
. To optimize the algorithm, the bottom and right edge are drawn outside the double for loops. At the end we draw a target position, a green
rectangle with UG_DrawFrame
which only draws a border, on top right corner.
1 http://embeddedlightning.com/download/reference-guide/
Interactions
The program contains of two main interactive scenes, main menu and maze game, with a posibility to quickly add new types of game and controlls for it.Main menu
Main menu is the first thing that you can see when you power-up the Miško. The main part of the main menu are top text, that says "MENU", and blue rectangles with white arrow on each side of the screen.UG_FillScreen
to make the whole screen black. Then we set a foreground and background color to draw the text
with UG_PutString
and use UG_FillFrame
to draw blue rectangles on each side.
Since there are multiple settings for maze game I implemented "pages" witch contains a rounded square border with some
graphics, title and sequential page number on top left. If you want to add a new page, you simply change the amount of pages in predefined variable "pages"
and add a new case in the switch statement. Bellow function is used for refreshing the contetn of the page, which means changing
sequential number, title, graphics and border. If the page is not defined a default page with a blue border and title "SOON" will be displayed.
We also need to implement menu controlls to switch between the pages. To increment the page we will use right button or move the joystick to the right and
to decrement the page we will use left button or move the joystick to the left. Page selection we will implement by ok button or joystick press, which will
also call a function to draw all the static content of the game page. joystickSensitivity
is used for setting how far you need to move joystick
before action is made.
We can also implemented touch controls, where pressing the left blue rectangle will decrement the page, right blue rectengle will increment the page and anywhere else will select the page.
The touch controlls are not the most accurate on this miško and pressing the touch screen will most likely select the page even if we accurately press the blue rectangles.
This is most likely caused by either slightly damaged screen or poor soldering of the screen connector.
To draw all the static (not changing) content of the games, we can implement a function that will only be called when the page is selected.
Since we allready defined all the maze variables on pages, we can just group the three cases and use the same functionality for drawing the maze.
Maze game
Maze game contains a maze, move counter and a yellow circle which represent current player position.We will implemented three different presets of the maze: easy, normal and hard; which is defined in MainMenuRefresh()
shown above.
Easy dificulty will of size 21x13 and have a cell size of 31, with a (5,43) offset and a player circle radius 7.
Normal dificulty will of size 29x19 and have a cell size of 21, with a (12,40) offset and a player circle radius 5.
Hard dificulty will of size 51x33 and have a cell size of 12, with a (10,40) offset and a player circle radius 2.
Case
Since standalone Miško is not the most comfortable thing to hold in hands I aslo designed a cases for easier useage of it. The cases were designed in blender and you can find them https://github.com/Klemen2/VIN-Projekt/tree/main/case.Version 1
Version 1 of the case has a few flaws. Before printing the case needs to be scaled to match 3D printer tolerances, since it's made for a super tight fit and will need a lot of sanding if you decide not to do so. There are some other areas that needs sanding eaither way such as joystick hole, since it's too small and shifted, holes for the pins on the back, due to one of them being shifted, and the buttons guides, they are way too big. The front buttons are also too small for comfortable use, but it's much better than to use it without a case.If the case doesn't stay toggether you'll also need to widen 3 holes on top and bottom side (the hole next to the reset button does not work well) and use appropiet screws, i'm using 10mm long screws Ø2 that I got from an old Lenovo laptop.
Version 2
In version 2 of the case I fixed issues that I had with the version 1 of the case, such as scaling, bigger hole for pins, bigger front buttons (the back reset button is still a small so you don't press it by accident). I also removed the screw hole next to the reset button since there just isn't enough space for it.The only problem that I had was the same as before where the hole for joystick is too small, even though I made it bigger.
I allready made it bigger in uploaded files, but haven't tested if it's big enough.