feat(hardware): initial hardware documentation, 3D models, and ESP32 client code

- Add initial versions of hardware bills of materials (BOM v1-v4), shopping lists, plan, and assembly guides.
- Add STL models for 3D-printing the 1/27 scale OpenRC F1 car parts.
- Add Blender 3D project files (.blend) and camera renders of the car design iterations.
- Add ESP32 client firmware source (client.ino) for handling video streaming and car controls.
- Ignore Blender backup files (*.blend1, *.blend2) and IDE directories.
This commit is contained in:
x0gp
2026-07-06 12:41:04 +04:00
parent 49351b4928
commit 76e33cfe62
73 changed files with 2353 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
#include "esp_camera.h"
#include <WiFi.h>
#include <WiFiUdp.h>
// Конфигурация пинов (пример для Seeed Studio XIAO ESP32S3 Sense)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 10
#define SIOD_GPIO_NUM 40
#define SIOC_GPIO_NUM 39
#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 47
#define Y7_GPIO_NUM 13
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 12
#define Y4_GPIO_NUM 11
#define Y3_GPIO_NUM 17
#define Y2_GPIO_NUM 16
#define VSYNC_GPIO_NUM 41
#define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 37
const char* ssid = "RT-WiFi-1712";
const char* password = "yt3xihY2Ci";
const char* serverIP = "192.168.0.11";
const int serverPort = 9999;
const int localPort = 8888;
// !!! УНИКАЛЬНЫЙ ID ДЛЯ КАЖДОЙ ПЛАТЫ (например, 1 для первой, 2 для второй и т.д.)
const uint8_t DEVICE_ID = 1;
WiFiUDP udpVideo;
WiFiUDP udpCmd;
camera_config_t config;
void setup() {
Serial.begin(115200);
// Настройка камеры (QVGA для стабильности)
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_QVGA;
config.pixel_format = PIXFORMAT_JPEG;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_count = 2;
esp_camera_init(&config);
// Подключение к Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.println("Wi-Fi подключен!");
// Запуск прослушивания порта для команд
udpCmd.begin(localPort);
Serial.print("Ожидание команд на порту: ");
Serial.println(localPort);
}
void checkIncomingCommands() {
int packetSize = udpCmd.parsePacket();
if (packetSize > 0) {
char packetBuffer[255];
int len = udpCmd.read(packetBuffer, 255);
if (len > 0) { packetBuffer[len] = 0; }
String command = String(packetBuffer);
command.trim();
Serial.print("Получена команда: ");
Serial.println(command);
Serial.print("Получена команда: ");
Serial.println(command);
// Логика управления
if (command == "left") {
// Ваш код поворота налево
} else if (command == "right") {
// Ваш код поворота направо
} else if (command == "start") {
// Ваш код запуска моторов / логики
} else if (command == "stop") {
// Ваш код остановки
}
}
}
void loop() {
checkIncomingCommands();
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) return;
size_t bufferSize = fb->len;
uint8_t * buf = fb->buf;
// Размер куска данных уменьшаем до 1023, чтобы вместе с 1 байтом ID пакет был 1024 байта
size_t chunkSize = 1023;
uint8_t packetBuffer[1024];
for (size_t i = 0; i < bufferSize; i += chunkSize) {
size_t sendSize = chunkSize;
if (i + chunkSize > bufferSize) {
sendSize = bufferSize - i;
}
// Формируем пакет: первый байт — ID, дальше — видеоданные
packetBuffer[0] = DEVICE_ID;
memcpy(packetBuffer + 1, buf + i, sendSize);
udpVideo.beginPacket(serverIP, serverPort);
udpVideo.write(packetBuffer, sendSize + 1); // Отправляем данные вместе с ID
udpVideo.endPacket();
}
esp_camera_fb_return(fb);
delay(10);
}