This shows you the differences between two versions of the page.
iothings:proiecte:2025sric:racing-game-simulator [2025/05/28 19:37] ionut_razvan.stan [Hardware] |
iothings:proiecte:2025sric:racing-game-simulator [2025/05/28 20:47] (current) ionut_razvan.stan [System Architecture] |
||
---|---|---|---|
Line 27: | Line 27: | ||
* displays the game and adapts to the inputs given in a concurrently safe way | * displays the game and adapts to the inputs given in a concurrently safe way | ||
+ | |||
+ | The ESP 32 Dev Module is plugged into a breadboard, with the ground pin connected to the power rail, as well as the 5V pin. There are two IR FC-51 Sensors on a smaller breadboard, with the ground pins connected to the ground rail, the VCC pins connected to the 5V rail, and the output of the "left" sensor to the 34th GPIO pin, "right" being pin 35. In addition, two buttons, connected on another breadboard for "forward" and "back". They get ground from the main ground rail, and their other connectors are plugged into pins 27 and 26. | ||
====== Hardware ====== | ====== Hardware ====== | ||
The Hardware is composed of : | The Hardware is composed of : | ||
* ESP32 board | * ESP32 board | ||
+ | |||
* 2x Infrared sensor modules for obstacles | * 2x Infrared sensor modules for obstacles | ||
+ | |||
* Button modules | * Button modules | ||
+ | |||
* Breadboard HQ | * Breadboard HQ | ||
+ | |||
* 2x Mini Breadboard | * 2x Mini Breadboard | ||
+ | |||
* Laptop that can run the video game | * Laptop that can run the video game | ||
====== Software ====== | ====== Software ====== | ||
+ | The ESP32 code uses an HTTP library to send post requests gotten through platformio: | ||
+ | |||
+ | '' | ||
+ | |||
+ | #define DISTANCE_THRESHHOLD 3000 | ||
+ | void loop() { | ||
+ | if ((millis() - lastTime) > timerDelay) { | ||
+ | // Check WiFi connection status | ||
+ | if (WiFi.status() == WL_CONNECTED) { | ||
+ | HTTPClient http; | ||
+ | |||
+ | String serverPath = serverName; // eventually add + "something?=" | ||
+ | |||
+ | http.begin(serverPath.c_str()); | ||
+ | |||
+ | float distanceLeft = analogRead(irSensorPin1); | ||
+ | float distanceRight = analogRead(irSensorPin2); | ||
+ | bool forwardButton = digitalRead(forwardButtonPin) == LOW; | ||
+ | bool backwardButton = digitalRead(backwardButtonPin) == LOW; | ||
+ | |||
+ | String postData = ""; | ||
+ | |||
+ | // if (distanceLeft < 3000 && distanceRight < 3000) | ||
+ | //{ | ||
+ | // Serial.println("FORWARD"); | ||
+ | // postData = "FORWARD"; | ||
+ | // } | ||
+ | if (distanceLeft < DISTANCE_THRESHHOLD) { | ||
+ | // Serial.println("LEFT"); | ||
+ | postData += " LEFT"; | ||
+ | } | ||
+ | if (distanceRight < DISTANCE_THRESHHOLD) { | ||
+ | // Serial.println("RIGHT"); | ||
+ | postData += " RIGHT"; | ||
+ | } | ||
+ | if (forwardButton) { | ||
+ | // Serial.println("FORWARD"); | ||
+ | postData += " FORWARD"; | ||
+ | } | ||
+ | |||
+ | if (backwardButton) { | ||
+ | postData += " BACKWARD"; | ||
+ | } | ||
+ | |||
+ | Serial.println(postData); | ||
+ | |||
+ | int httpResponseCode = http.POST(postData); | ||
+ | |||
+ | if (httpResponseCode > 0) { | ||
+ | Serial.print("HTTP Response code: "); | ||
+ | Serial.println(httpResponseCode); | ||
+ | String payload = http.getString(); | ||
+ | Serial.println(payload); | ||
+ | } else { | ||
+ | Serial.print("Error code: "); | ||
+ | Serial.println(httpResponseCode); | ||
+ | } | ||
+ | // Free resources | ||
+ | http.end(); | ||
+ | } else { | ||
+ | Serial.println("WiFi Disconnected"); | ||
+ | } | ||
+ | lastTime = millis(); | ||
+ | } | ||
+ | }'' | ||
+ | |||
+ | |||
+ | |||
+ | The game frontend uses the standard HTTP library from Golang to listen to HTTP requests at a certain point. It also uses Raylib (through a community made binding module) to render 3D Graphics. | ||
+ | |||
+ | |||
+ | '' | ||
+ | func handler(w http.ResponseWriter, r *http.Request) { | ||
+ | // fmt.Printf("Received a %s request at %s\n", r.Method, r.URL.Path) // Prints for any request | ||
+ | |||
+ | body, _ := io.ReadAll(r.Body) | ||
+ | fmt.Printf("Body: %s \n", body) | ||
+ | bodyStr := string(body) | ||
+ | // bodyStr = strings.ReplaceAll(bodyStr, " ", "") | ||
+ | dirMutex.Lock() | ||
+ | defer dirMutex.Unlock() | ||
+ | |||
+ | directions := strings.Split(bodyStr, " ") | ||
+ | isLeftPressed = false | ||
+ | isRightPressed = false | ||
+ | isUpPressed = false | ||
+ | isDownPressed = false | ||
+ | for _, direction := range directions { | ||
+ | if direction == DIRECTION_LEFT_STR { | ||
+ | isLeftPressed = true | ||
+ | } | ||
+ | if direction == DIRECTION_RIGHT_STR { | ||
+ | isRightPressed = true | ||
+ | } | ||
+ | if direction == DIRECTION_UP_STR { | ||
+ | isUpPressed = true | ||
+ | } | ||
+ | if direction == DIRECTION_DOWN_STR { | ||
+ | isDownPressed = true | ||
+ | } | ||
+ | } | ||
+ | fmt.Fprintf(w, "Request body: %s", bodyStr) | ||
+ | } | ||
+ | |||
+ | func listeningServer() { | ||
+ | http.HandleFunc("/post", handler) // Handles any path after "/" | ||
+ | fmt.Println("Server listening on :8080") | ||
+ | http.ListenAndServe("192.168.1.129:8080", nil) | ||
+ | } | ||
+ | |||
+ | var trackVerticalTexture rl.Texture2D | ||
+ | var trackHorizontalTexture rl.Texture2D | ||
+ | |||
+ | var trackCornerRDTexture rl.Texture2D | ||
+ | var trackCornerDRTexture rl.Texture2D | ||
- | ====== Challenges ====== | + | const CHRONOMETER_MAX_TIME = 120.0 |
+ | func main() { | ||
+ | screenWidth := int32(1600) | ||
+ | screenHeight := int32(900) | ||
+ | // other code | ||
+ | } | ||
+ | '' | ||
- | ====== References ====== |