xdd44, Nov. 27, 2024
In my childhood I played this toy where I tilt the board to roll the mable ball, so that it avoids the holes and gets to the destiny. I actually played it on my Dad's phone, which I guess embedded an accelerometer so that the phone knew how I tilted it.
I planned to implement this toy, while using phone as a controller instead of a physical nob. Therefore, this week I tested how frequent my phone can communicate with a chip.
Original Toy
I used an ESP32C3 in the inventory to set up a server, so that I can send request from my device under same WiFi. The orientation itself is just a vector, i.e. three float values, so I just formatted a GET request: http://<ip address>/vector?x=1.23&y=4.56&z=7.89
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "MIT";
const char* password = "&YbtLSS$C8";
WebServer server(80);
float vector[3] = {0.0, 0.0, 0.0};
void setup() {
Serial.begin(115200);
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, handleRoot);
server.on("/vector", HTTP_GET, handleGetVector);
server.on("/vector", HTTP_OPTIONS, handleOptions);
server.begin();
Serial.println("Server started");
}
void loop() {
server.handleClient();
}
void handleRoot() {
server.send(200, "text/plain", "ESP32C3 is running!");
}
void handleGetVector() {
if (server.hasArg("x") && server.hasArg("y") && server.hasArg("z")) {
vector[0] = server.arg("x").toFloat();
vector[1] = server.arg("y").toFloat();
vector[2] = server.arg("z").toFloat();
Serial.printf("Vector received: [%.2f, %.2f, %.2f]\n", vector[0], vector[1], vector[2]);
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", "Vector received successfully");
} else {
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(400, "text/plain", "Missing parameters. Please provide x, y, and z.");
}
}
void handleOptions() {
server.sendHeader("Access-Control-Allow-Origin", "*");
server.sendHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
server.sendHeader("Access-Control-Allow-Headers", "Content-Type");
server.send(204);
}
It's worth noting that there is an annoying "Access-Control" stuff from handleOptions()
function, to prevent browser from blocking request with "No 'Access-Control-Allow-Origin' header is present on the requested resource".
However, eventually I still gave up on using browser and javascript, since phone browsers block users from sending requests to http server, while it is even harder to set up https server on ESP32C3.
Eventually found out why it didn't work on phone through Safari developer monitor
I'm quite familiar with Unity and I noticed Unity can optionally allow http requests. Therefore I quickly implemented an app to display orientation vector and send to my ESP32C3.
Successful sync through Unity
The code is also simple:
private IEnumerator SendOrientationToServer() {
string url = string.Format("{0}?x={1}&y={2}&z={3}",
ServerUrl,
Input.acceleration.x.ToString("F2"),
Input.acceleration.y.ToString("F2"),
Input.acceleration.z.ToString("F2"));
UnityWebRequest request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success) {
Debug.Log("Data sent successfully: " + url);
}
else {
Debug.LogError("Failed to send data: " + request.error);
}
}