Rapid Roads (Racing Game)

by RubenVierstraete in Circuits > Raspberry Pi

65 Views, 1 Favorites, 0 Comments

Rapid Roads (Racing Game)

448268440_984980150015527_6696558228909307599_n.jpg

You all know the big crazy fun arcade racing games you can keep playing just getting that tiny bit closer to the high score every time. Well I have made a compact version of one of these iconic games, so you can compete with you're friends to get the highest score.


all the code:

https://github.com/howest-mct/2023-2024-projectone-mct-VierstraeteRuben

Supplies

8x8display.jpg
MPU.jpg
drukknoppen.jpg
LCD_scherm.jpg
voorlopige_potentiometer.jpg
Hall_sensor.jpg
PCF.jpg
mcp3008.jpg
446079646_1186538462342580_1700118655245420328_n.jpg
raspberry-pi-4b-4gb.jpg

Sensors & Components:

  • Raspberry Pi 4

https://www.kiwi-electronics.com/nl/raspberry-pi-4-model-b-2gb-4267?country=BE&gad_source=1

  • 8x8 LED display

https://www.conrad.be/nl/p/tru-components-tc-9072480-8-x-8-matrix-displaymodule-max7219-voor-arduino-2268120.html?adcampaign=google&tid=16860426636_pla-2268120&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWJvWVZVBWe2zF1OFg3fTD6OyEPq2S_EPUvNeMr0Xsm88Yj7AYsXhehoCA8wQAvD_BwE

  • MPU 6050

https://www.otronic.nl/nl/acceleratie-versnellingsmeter-en-gyroscoop-i2c-mpu.html?source=googlebase&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWI8CgDMpM1Phslt7-T7MPUgbAUR6YMSyCJX53aB2ZjKw3FfI2AgicBoCWJ8QAvD_BwE

  • buttons

https://www.amazon.com.be/-/nl/tijdelijke-drukknopschakelaar-geassorteerde-automatische-mini-schakelaar/dp/B09MBQSM44/ref=sr_1_25?crid=SKLK2QV0CX81&dib=eyJ2IjoiMSJ9.uOoe-7TIeAlB4U2SH1UkuJ2muSiTrUDuCShz_KF_t5EIZ_FWLOVIVoTQ-GbO1GPDxXzayxIlj4OlRqqWu-u_LmLBSgz53aOi7a3Rw8-QrbPFnPHyIof6209Hx_L55F3WFffDYS3AwDQ_eFkkkjifh8NHUCYCUsMs5Nh7RdPm5Aarrk6k5CqlOy1-pNw2JrP3TG32a5gK-wprpWoaWtx-3eqSAQJRTJSIdqR-CJ88HldjbzfdrNTKXed1lRKi5DsJKCsPLa8ZVKtWmy188rXSDmh_e0sfnNvfqpb1MMxi-0A.FwoLCXIuhp_NkWK0ICmAxt3_J9hWETMoOu890FlF-Xw&dib_tag=se&keywords=drukknop%2Barduino&qid=1714027594&sprefix=drukknop%2Barduino%2Caps%2C126&sr=8-25&th=1

  • LCD screen

https://www.digikey.be/nl/products/detail/sunfounder/CN0293/18668626?utm_adgroup=&utm_source=google&utm_medium=cpc&utm_campaign=PMax%20Shopping_Product_Low%20ROAS&utm_term=&productid=18668626&utm_content=&utm_id=go_cmp-20168770009_adg-_ad-__dev-c_ext-_prd-18668626_sig-CjwKCAiAxaCvBhBaEiwAvsLmWLtYK_JK1gb4B76QoiESvUlAH25AC3J_1FBN8C5v3N8Y4aUV6wKgqRoC68wQAvD_BwE&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWLtYK_JK1gb4B76QoiESvUlAH25AC3J_1FBN8C5v3N8Y4aUV6wKgqRoC68wQAvD_BwE

  • RFID reader (and badges)

https://www.conrad.be/nl/p/joy-it-sbc-rfid-rc522-rfid-chip-rfid-set-1-stuk-s-1503746.html?adcampaign=google&tid=16860426636_pla-1503746&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWN25lgaS1V0mY8oELSowjGpl9-0WIb9fpwk28G3EN3_DOzztut06fRoCMb8QAvD_BwE

  • MCP

https://www.distrelec.be/nl/mcp3008-kanaals-10-bits-adc-met-spi-interface-adafruit-856/p/30139253?ext_cid=shgooaqbenl-P-Shopping-PMax&cq_src=google_ads&cq_cmp=17730351004&cq_con=&cq_term=&cq_med=pla&cq_plac=&cq_net=x&cq_pos=&cq_plt=gp&gad_source=1&gclid=Cj0KCQjwsaqzBhDdARIsAK2gqnfWo5WgRJpd6FjnJgo6aSV63aNmwdbRpy5yRXedIQbqSl-xuSJYu8kaAgS0EALw_wcB&gclsrc=aw.ds

  • PCF

https://www.digikey.be/nl/products/detail/texas-instruments/PCF8574AN/484958?utm_adgroup=&utm_source=google&utm_medium=cpc&utm_campaign=PMax%20Shopping_Product_Low%20ROAS&utm_term=&productid=484958&utm_content=&utm_id=go_cmp-20168770009_adg-_ad-__dev-c_ext-_prd-484958_sig-Cj0KCQjwsaqzBhDdARIsAK2gqnfZQp6Haz16ivxo9L89P5RFiMp3ylHjm6r-2sIsNDfeGktQiPNJbR8aAqZVEALw_wcB&gad_source=1&gclid=Cj0KCQjwsaqzBhDdARIsAK2gqnfZQp6Haz16ivxo9L89P5RFiMp3ylHjm6r-2sIsNDfeGktQiPNJbR8aAqZVEALw_wcB

  • Potentiometer

https://www.allekabels.be/potmeter/11469/1066233/potmeter.html?mc=nl-be&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWDEVZAYKFeETR539dNpimSSs144TkA-MYVI4gGa4E720mbKii8wd_RoCN64QAvD_BwE&lang=nl-be

  • Hall Sensor

https://www.amazon.nl/AZDelivery-Magnetische-Hallsensormodule-compatibel-Inclusief/dp/B07ZZ8N4VC?th=1

  • Cables

https://www.amazon.com.be/-/nl/Breadboard-kabels-mannelijk-vrouwelijk-stekker-testplaat/dp/B01JD5WCG2/ref=asc_df_B01JD5WCG2/?tag=begogshpadd0d-21&linkCode=df0&hvadid=633391988539&hvpos=&hvnetw=g&hvrand=11645996038449690857&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1001270&hvtargid=pla-1940049636127&psc=1&mcid=79a0b16f093f3d598cd94cc6c34adbaf

  • nylon bolts and screws

https://www.amazon.com.be/-/nl/schroeven-waterdicht-elektrische-mechanische-apparatuur/dp/B07LD6G622/ref=asc_df_B07LD6G622/?tag=begogshpadd0d-21&linkCode=df0&hvadid=632929277223&hvpos=&hvnetw=g&hvrand=17296251334319963104&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1001270&hvtargid=pla-635055483275&psc=1&mcid=998c78fb03ee3657b24f24b2383ec22f

  • Pi power supply

https://www.sossolutions.nl/originele-raspberry-pi-foundation-usbc-3a-voeding-zwart?gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWPC8594y4N0PCTAJCFqhyGUIUaBYqXX-6U_IdfBGWS4LF0844Ow40RoCYvkQAvD_BwE

  • SD 16GB

https://www.bol.com/nl/nl/p/sandisk-micro-sd-16gb-geheugenkaart-class-10/9200000084792189/?Referrer=ADVNLGOO002020-S--9200000084792189&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWNkA31Ns3mQVjDqfFnytRY-B5ZGKABk8zXsDOsjFXEcULnBIoxkJbhoCm1MQAvD_BwE

  • Raspberry PI GPIO extension board T 

&hvpos=&hvnetw=g&hvrand=8201943129760031346&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1001259&hvtargid=pla-681507229800&psc=1&mcid=aa595e2a0f993fb49a21ad84aa91780d

  • external source

https://www.temu.com/ul/kuiper/un9.html?subj=coupon-un&_bg_fs=1&_p_jump_id=895&_x_vst_scene=adg&goods_id=601099522152697&sku_id=17592240489685&adg_ctx=a-a90ad0f7~c-7dd19b44~f-50e0726a&_x_ads_sub_channel=shopping&_p_rfs=1&_x_ns_prz_type=-1&_x_ns_sku_id=17592240489685&mrk_rec=1&_x_ads_channel=google&_x_gmc_account=760631223&_x_login_type=Google&_x_ads_account=9370551288&_x_ads_set=20727373909&_x_ads_id=154927248653&_x_ads_creative_id=678767718393&_x_ns_source=g&_x_ns_gclid=CjwKCAiAxaCvBhBaEiwAvsLmWLyk4PiGnBAhENpOHMRz-6pDDd66Jq-T28ThdNgzOKZZiS7u4Q6NkhoCd-gQAvD_BwE&_x_ns_placement=&_x_ns_match_type=&_x_ns_ad_position=&_x_ns_product_id=760631223-en-17592240489685&_x_ns_target=&_x_ns_devicemodel=&_x_ns_wbraid=Cj4KCAiAopuvBhADEi4A5iS5mgTbbo7FX1yXfuO5c4fShwBB1owYd_A1wQW4wiaCfs4t3mdu5sSk1KC9GgLhEQ&_x_ns_gbraid=0AAAAAo4mICF0vDWatMJkJb3vA8IUYeP7p&_x_ns_targetid=pla-2233208089375&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWLyk4PiGnBAhENpOHMRz-6pDDd66Jq-T28ThdNgzOKZZiS7u4Q6NkhoCd-gQAvD_BwE

  • external source adapter

https://www.bax-shop.be/nl/voedingen/devine-ad-03-adapter-voor-diverse-casio-keyboards?gclsrc=aw.ds&utm_source=google&utm_medium=cpc&utm_campaign=18344795213&utm_term=&adgroup=&creative=&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWHK5amJYsM_l08sX0M4yBk9mIxgz3eP3ji_O-_7Rk0xAlsyfIEq7wRoC5-EQAvD_BwE

  • wood rod (2 pieces with a diameter of 48 mm and a length of 125 mm, and 2 pieces with a diameter of 8 mm, one with a length of about 30 mm and the other with a length of around 75-100 mm)

https://www.gamma.be/nl/assortiment/ronde-stok-grenen-45-mm-270-cm/p/B509776

  • ball bearing (2)

https://www.temu.com/ul/kuiper/un9.html?subj=coupon-un&_bg_fs=1&_p_jump_id=895&_x_vst_scene=adg&goods_id=601099518459656&sku_id=17592224352186&adg_ctx=a-f0daf8ba~c-13a617a7~f-50e0726a&_x_ads_sub_channel=shopping&_p_rfs=1&_x_ns_prz_type=-1&_x_ns_sku_id=17592224352186&mrk_rec=1&_x_ads_channel=google&_x_gmc_account=760631223&_x_login_type=Google&_x_ads_account=9370551288&_x_ads_set=20842663190&_x_ads_id=159466397987&_x_ads_creative_id=683739518761&_x_ns_source=g&_x_ns_gclid=CjwKCAiAxaCvBhBaEiwAvsLmWHRFSA3l-bq8FgzoAFUQOTvacGTwxzV63Y6bGyayySmadPR5-1AOBBoCG9MQAvD_BwE&_x_ns_placement=&_x_ns_match_type=&_x_ns_ad_position=&_x_ns_product_id=760631223-nl-17592224352186&_x_ns_target=&_x_ns_devicemodel=&_x_ns_wbraid=Cj4KCAiAopuvBhADEi4A5iS5mrezlrKBCSLjfe0K_FATF7FgqT9pJfvhSMpdzEcZgzMGpflmVjAyRFFfGgLNFA&_x_ns_gbraid=0AAAAAo4mICHivJm9rJeA8kXpuK9jx7X1M&_x_ns_targetid=pla-2279904018156&gad_source=1&gclid=CjwKCAiAxaCvBhBaEiwAvsLmWHRFSA3l-bq8FgzoAFUQOTvacGTwxzV63Y6bGyayySmadPR5-1AOBBoCG9MQAvD_BwE&fbclid=IwAR1IaF4nN9R_lFM3PVmVxrJTDWbKG7i9dOY5PWgVxQo0ezFl-_uF5N-4KUU

  • lasercutted exterior (illustrator and dfx files included)

Testing Sensors & Components

The first thing I did for my project was testing each sensor individually.

I started with the sensors I was familiar with namely: the potentiometer and hall sensor witch are attached to a MCP, a MPU6050, a RFID scanner and some buttons.

I also tested other components like: a LCD screen wich is attached to a PCF and a 8x8 LED display wich displays a simple game.

MCP (hall sensor & potentiometer):

To use this Micro controller I imported the library spidev in python, with this library we can use the SPI pins on the PI. (because I'm using 3 components that need SPI I changed the pinning of my PI to use SPI 1, the pin nummering can be found on this site: https://pinout.xyz/)

Now by connecting the MCP like on the scheme (see step 3 Making A Full Circuit to see the full circuit) we can use the command .xfer2(bytes to send to mcp) with bytes to send to mcp = [0b00000001,(0b10000000 | (ch<<4)), 0b00000000] and ch is the channel we want to read (0 = potentiometer and 1 = hall sensor)

MPU:

For this sensor I also imported something, SMbus from smbus. With this we can communicate with the I2C bus on the Pi, for this we will need the address of the MPU. Normally this is 68 but to check this you can run this command: 'i2cdetect -y 1' in the terminal of your Pi.

The mpu has multiple things it can measure, for this project I only needed the accelero measurments wich shows how much g's on each axis there is. This is a value between -1 and 1. I used the y axis because of how the MPU was positioned in the steering wheel. then if it read more towards the -1 that means the wheel was turned to one side, if it read close to 0 then it was balanced and if it read more towards the 1 it would be turned to the other side.

We can use the SMbus.read_i2c_block_data(address, channel, amount) to read the values of the accelero of each axis. the address as previously mentioned is most liky 68, the first channel for accelero is 0x3B and the amount means how many channels it needs to read (this is beacause the values are stored throughout multiple channels).

the value we get from this fuction than has to be processed to be something we can interpreted. I made a function that does this.

8x8 display:

This component also uses the SPI bus, the important thing about using multiple SPI busses is to connect each one to a different chip select. Then to use multiple ones in one single code you simply open a SPI bus of the needed chip select en then when you did everything you needed with that one you immediately close it.

To use this display we need to first run some setup code (you can find this exact code in the class 8x8 display code). In this class you will see that i have made a function to show a 8x8 matrix on the screen. To set the matrix correct we have to send per line of the display the right byte.

RFID:

For this sensor I imported a library, the MRFC522 library, I used the SimpleRFID as I don't need to do difficult things with the RFID reader. I did change these libraries a tiny bit, I added in the SimplRFID a function that closed the SPI bus, and I changed it to use SPI 1 and also witch chip select it uses.

Now with this library using the RFID reader is very easy, you have a read and write function, both are very straight forward. The read function waits until a badge is in range of the reader, then it reads the RFID number and the data on it (in my case the data is just the name of the user). The write function takes one argument, a string, it waits until a badge is in range of the reader, then it chages the data on it to the string you give it.

LCD screen (with PCF in 4 bits mode):

The LCD screen has 2 modes 8 bits and 4 bits, I used the 4bits mode because this uses less pins. I also connected it with a PCF, the reason for this is because a PCF only uses 2 pins on the Pi, the SDA and SCL, we can then connect the pins of our LCD to the PCF and save a lot of pins on our Pi.

We can send a byte to the PCF and the corresponding pins will be put high on it. Now we can by sening the wright byte to our pcf and putting the right pins high on our LCD screen write stuff on it.

Test code for the game loop:

The last test code I made was the first iteration of the game.By using all the code I made for each component separate, and combining it I have made something that runs 1 game. Now I can use this code in my backend so that the game can be played while the website is also running.

Making a Database

EER_database.png

The second step is to make a database where all the data will be stored. The stored data will be used to show certain things on the website like tables with all the games played and their measurements of the sensors. In this database there will also be games stored, so all the games that were played are stored with who played it, the score and date.

All the data of the badges is also stored in this database, data like high scores and total amount of games played is not stored here because these things are easily calculated.

There are also relations between some tables, like between the table Badges and Games. This links a Badge to one or more games. There are also relations between Games and Measurements, and Measurements and Sensors. These relations connect the data together.

Making a Full Circuit

Now i made the whole circuit, i connected everything together to make a beginning of the game. I used 2 breadboards in total and a external source.

the important thing is that I changed the SPI bus that my Pi uses, its normally using 0 but I changed it to 1. The reason for this is because the 1 bus has 3 chip selects and the 0 only has 2, and I have 3 components that use SPU.

There are pdf's that show how to connect everything, one for with a breadboard like I did, and one that just shows the connections.

Making a Website

I also needed to make a website witch is connected to my project, I decided to go with a website that has 3 pages: one for all info during the game, one with all the historic data of the games and one with info about the users/badges.

info about pages

The page with info is named Racing Game, here there is a small tutorial of how to start and play the game. On this page there are also a picture of the steering wheel witch shows the directions the wheel is turned and a speedometer witch shows how "fast" you are going. The 8x8 led display is also shown on this page and the last 3 measurements of the current game are also shown (of each sensor 1).

In the page Historic Data there are 4 tables of data shown. The first table is the one with the 3 highest scores and who has that score. The second table shows all the info over the sensors, there are 3 sensors: Potentiometer this one is used to measure how far the gas handle has been turned, a hall sensor witch measures how for the break is from the grip (this works because there is a magnet in the break and a hall sensor measures magnetic fields) and the last sensor is the MPU witch measures the gravity of the steering wheel witch is used to decide witch way the steering wheel is turned.

The third table of the page historic data has all the games with their data in it, this data includes: the game number, who played it, the score and how many seconds the game lasted. Each record in this table also has a button that when pressed fills the fourth table with all the measurements that were recorded during this game. The data of each record of the fourth table are: the measurements number, witch sensor it belongs to, the value of the measurement and the timestamp of when it was measured.

The last page with user info has 1 table, a table with all the info of the badges and their user. This table shows the name, high score, amount of games played and their ID's. Each record of this table has a button, when pressed this will show 2 graphs. One with the time of per game and the other one shows the score per game.

making a working backend and frontend

To make the website get all the right data and display it in the right way I needed to make a backend file (coded in python) and a frontend file for each html page (coded in javascript). The backend runs all the code for the sensors and components and also makes the frontend be able to get the data of the sensors and the data that is stored in the database.

The backend uses API routes and socketio to talk to the frontend, the frontend also sends messages via socketio to the backend.

The frontend of each page makes it so that the right data is displayed at the right place, it also makes the buttons work and other things like displaying the graphs on the user info age.

styling the website

The last step of making the website was styling it, I used SCSS code that I then converted to CSS with an extesion in visual studio code (I used Live SASS Compiler). I chose to make a simple styling that is user friendly, my main color is a light blue (RGB: 116 143 252) and the other colors I used are a few grey values and a blue and red for the graphs.

Apache:

To make it so that when you surf my IP address (witch is displayed on the LCD screen) that you get on the website I needed to change some things in a config file on my Pi.

The file i needed to edit was: /etc/apache2/apache2.conf, I needed to change the following lines:

<Directory />

    Options FollowSymLinks

    AllowOverride All

    Require all denied

</Directory>

to this:

<Directory />

    Options Indexes FollowSymLinks Includes ExecCGI

    AllowOverride All

    Require all granted

</Directory>

I edited this in nano so to save this I had to do ctrl + x and then y. Then I had to set the permission good, this can be done with a few commands:

sudo chmod o+x /home/user/<name of github repo>

sudo chmod o+x /home/user/<name of github repo>/front


Then I restarted apache with the following command: service apache2 restart. You can check the apache with the command: service apache2 status, if everything works you should see active (running) somewhere.

Making a Case

448234077_327834453720049_3074468256679278637_n.jpg
446007115_470617708849514_5846968608320303478_n.jpg
448538677_1647623325989410_6186752990900273540_n (1).jpg
448538677_1647623325989410_6186752990900273540_n.jpg
448314118_794056372818086_6419214457562655689_n.jpg
448228157_476936744844941_2925761623013946423_n.jpg
448228157_3276710912636929_2357803049744284172_n.jpg
448544539_937825241423708_7664871341162389590_n.jpg
448239842_450388221038129_4949175362332725414_n.jpg
448268440_984980150015527_6696558228909307599_n.jpg
447910738_1795886580903228_5027070011973598827_n.jpg
447701629_1114136866355167_1363222954812650740_n.jpg
446057558_3716735225214680_182114724839998552_n.jpg
448383221_982122173559586_9134731246544783008_n.jpg
448472504_996536708281574_9030036494388960903_n.jpg
448597327_2796519170516302_2728035766082281269_n.jpg
448542869_1616869802443576_7545171473095779370_n.jpg
447889247_503111995479378_1170183907258860739_n.jpg
441535514_792336359531944_2832195231486626225_n.jpg
441879113_7828585740529194_4785447185869850403_n.jpg
441930507_1018256252975957_2099493106772841426_n.jpg
442713396_2179627235721556_5529838077436038235_n.jpg
445976428_1025665952449132_5642725633109093249_n.jpg
445378666_7754206157973476_7179559863610610959_n.jpg
445981376_1023152078658665_3242232292352119245_n.jpg
445377165_982840473330268_290962294417130543_n.jpg

To fit all the electronics togheter I laser cutted a case I drew in solid egde. The dxf en illustrator files can be found in supplies.


I used edge joints and some glue to fix everything together. To make the steering wheel be able to turn i used 2 bearings with a metal pipe to connect the case and bearings. I then bolted the bearings to a leftover sheet from the laser cutting to act like a support

i made various hales in the case to bolt components and sensor to with nylon bolts, I used nylon bolts because metal ones can conduct electricity witch can be dangerous with components because it could conduct a signal and short circuit the component.

The last thing I added where 2 supporting beams that are connected to the base with a hinge, this makes them able to move. I bolted them to the base with the hinge positioned so that they can stand up just under the grips of the steering wheel, and when moved they are laying out of the way of the steering wheel. The reason I added these supports is to have a nice way to display the steering wheel without it turned all the way to one side because its very top heavy.

Automatically Starting the Backend

The last thing I needed to do was make it so that when the Pi starts up it needs to run the backend by itself. Now you need to manually start the backend by making a SSH connection with a laptop and opening the code and run it.

You can make this do it automatically by adding a file and enabling this. The first to do is make a new .service file in /etc/systemd/system/, in this file the following lines have to be in there:

[Unit]

Description=ProjectOne Project

After=network.target

[Service]

ExecStart=/home/user/<name of github repo>/<name of virtual envirement>/bin/python -u /home/user/<name of github repo>/backend/app.py

WorkingDirectory=/home/user/<name of github repo>/backend

StandardOutput=inherit

StandardError=inherit

Restart=always

User=user

CPUSchedulingPolicy=rr

CPUSchedulingPriority=99

[Install]

WantedBy=multi-user.target


When this file is made in the right place you can test it with the following commands:

sudo systemctl start <name file>.service this will start the backend

sudo systemctl stop <name file>.service this will stop the backend


When this wroks you can make it start the backend automatically by enabling this file, this can be done with the following command:

sudo systemctl enable <name file>.service


Now when you start up the Pi the backend will also start up, you can check the status of this file or look at the journal with following commands:

sudo service <name file> status

sudo journalctl -u <name file>


You can also disable the file so that the backend doesn't start automatically, you can do this with the following command:

sudo systemctl disable<name file>.service