version 2.0

This commit is contained in:
StuckAtPrototype
2024-10-14 22:33:43 -05:00
commit 4110b70152
57 changed files with 649250 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
build/
dependencies.lock
.idea/
cmake-build-debug/
sdkconfig.old
sdkconfig
venv/

100
README.md Normal file
View File

@@ -0,0 +1,100 @@
# Micro Racer Car - StuckAtPrototype
## Youtube Video
A bit of a back-story of how this project came to be.
[![My Kickstarter failed, so I open sourced it](https://img.youtube.com/vi/6jzG-BMannc/0.jpg)](https://www.youtube.com/watch?v=6jzG-BMannc)
Sub if you like what you see.
*Some pictures of the project*
![Picture of PCB car](project_pictures/242A0548.png)
![Picture of PCB car](project_pictures/242A1274.png)
## Hardware Remote for this car
https://github.com/StuckAtPrototype/Thumbtroller
## Project Structure
The project consists of
1. Firmware
2. Hardware
3. Mechanical
4. Scripts
These are structured into their own files. I could have used submodules, but decided against it.
### 1. Firmware
Code for the little car. This lives on the ESP32
#### Requirements
- ESP32 IDF version 5.3.1
- USB to Serial dongle
- Target set to ESP32-H2
### 2. Hardware
#### Schematic
PDF schematic included for your viewing pleasure.
#### PCBs
All the gerber files you'd need to send to a fab house.
#### Kicad
All the files you'd need to expand and work on this further. If you'd like.
### 3. Mechanical
#### Enclosure
All the step files you need to make one of these. Extrusion printer works well for this part.
#### Wheels
A bit of caution on this one.. you'll need an SLA printer.
### 4. Scripts
Did anyone say neural networks?
This folder has all the python code you'd need to train up your own neural network for the car. It also consists scripts that let you drive it using a keyboard -- just in case you dont want to make a physical controller.
#### Requirements
- Python 3
- You'll need to install a bunch of pip modules
#### Training the neural network
Training the neural network is as simple as running the training script with the data in the `color_data.txt` file. For data format see the sample data in the file. You need to stick to the formatting.
To train run `python trainer.py`
#### Keyboard controller
To run the script `python controller.py`
Use `w` `s` `a` `d` for control. Modify the script for different speeds, etc
*Protocol for motor control*
60,1,60,1,5 -- translates to:
motor side A: speed 60, direction forward
motor side B: speed 60, direction forward
500 miliseconds run time
See firmware file `motor.c` if you need more details
## What the project could use
1. Cleanup, but thats true for almost anything out there
2. Some fun code that makes the little car drive using the color sensor -- think very fancy line follower
3. LLM integration -- ChatGPT driving a physical little robot? anyone? :)
## If you take it further
Let me know if you ever make one of these, I'd love to see it. Seriously, that'd be exciting and inspiring to keep making my projects open source!
---
## License
### Apache 2.0 -- i.e. use as you'd like
http://www.apache.org/licenses/LICENSE-2.0
---
## Special Thanks
Thanks to Michael Angerer for his open sourced `esp32_ble_ota` project. I used it to get BLE running in this project. His blog post and github repo are a great resource. Check it out. https://github.com/michael-angerer/esp32_ble_ota

6
firmware/CMakeLists.txt Normal file
View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)

View File

@@ -0,0 +1,4 @@
idf_component_register(SRCS "main.c" "gap.c" "gatt_svr.c" "motor.c"
"controller.c" "led.c" "battery.c" "gpio_interrupt.c" "i2c_config.c"
"opt4060.c" "color_predictor.c"
INCLUDE_DIRS ".")

52
firmware/main/battery.c Normal file
View File

@@ -0,0 +1,52 @@
#include "battery.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_log.h"
static const char *TAG = "BATTERY";
#define ADC_UNIT ADC_UNIT_1
#define ADC_CHANNEL ADC_CHANNEL_2 // GPIO2 is ADC1_CHANNEL_2
#define ADC_ATTEN ADC_ATTEN_DB_12
#define ADC_BITWIDTH ADC_BITWIDTH_DEFAULT
static adc_oneshot_unit_handle_t adc1_handle;
esp_err_t battery_init(void) {
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT,
.ulp_mode = ADC_ULP_MODE_DISABLE,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
adc_oneshot_chan_cfg_t config = {
.atten = ADC_ATTEN,
.bitwidth = ADC_BITWIDTH,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL, &config));
return ESP_OK;
}
esp_err_t battery_read_voltage(float *voltage) {
int raw;
esp_err_t ret = adc_oneshot_read(adc1_handle, ADC_CHANNEL, &raw);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to read ADC value");
return ret;
}
// Convert raw ADC value to voltage
// *voltage = (float)raw / (float)(1 << ADC_BITWIDTH) * 3.3f; // Assuming 0-3.3V range
*voltage = (float)raw;
// 3300 == 2556
// 3700 == 2865
// 4000 == 3025
// correct the voltage readings
// this is due to us reading through a 10k resistor instead of direct
// this in turn creates a small voltage divider with the resistors inside the esp body
*voltage = (1.4925f * raw - 511.83f) / 1000.0f;
return ESP_OK;
}

12
firmware/main/battery.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef BATTERY_H
#define BATTERY_H
#include "esp_err.h"
// Initializes the ADC for battery voltage measurement
esp_err_t battery_init(void);
// Reads the battery voltage
esp_err_t battery_read_voltage(float *voltage);
#endif // BATTERY_H

View File

@@ -0,0 +1,169 @@
#include <string.h>
#include <math.h>
#include "esp_log.h"
#include "color_predictor.h"
static const char *TAG = "ColorPredictor";
static float relu(float x) {
return (x > 0) ? x : 0;
}
static void softmax(float* input, int size) {
float max = input[0];
for (int i = 1; i < size; i++) {
if (input[i] > max) {
max = input[i];
}
}
float sum = 0;
for (int i = 0; i < size; i++) {
input[i] = expf(input[i] - max);
sum += input[i];
}
for (int i = 0; i < size; i++) {
input[i] /= sum;
}
}
static void forward(NeuralNetwork* nn, float* input, float* output) {
float hidden1[HIDDEN_SIZE1];
float hidden2[HIDDEN_SIZE2];
// Input to first hidden layer
for (int i = 0; i < HIDDEN_SIZE1; i++) {
hidden1[i] = 0;
for (int j = 0; j < INPUT_SIZE; j++) {
hidden1[i] += input[j] * nn->input_weights[j][i];
}
hidden1[i] = relu(hidden1[i] + nn->hidden_bias1[i]);
}
// First hidden layer to second hidden layer
for (int i = 0; i < HIDDEN_SIZE2; i++) {
hidden2[i] = 0;
for (int j = 0; j < HIDDEN_SIZE1; j++) {
hidden2[i] += hidden1[j] * nn->hidden_weights1[j][i];
}
hidden2[i] = relu(hidden2[i] + nn->hidden_bias2[i]);
}
// Second hidden layer to output
for (int i = 0; i < OUTPUT_SIZE; i++) {
output[i] = 0;
for (int j = 0; j < HIDDEN_SIZE2; j++) {
output[i] += hidden2[j] * nn->hidden_weights2[j][i];
}
output[i] += nn->output_bias[i];
}
// Apply softmax to output
softmax(output, OUTPUT_SIZE);
}
uint32_t predict_color(NeuralNetwork* nn, float red, float green, float blue, float clear) {
float input[INPUT_SIZE] = {red / 2048.0f, green / 2048.0f, blue / 2048.0f, clear / 2048.0f};
float output[OUTPUT_SIZE];
forward(nn, input, output);
ESP_LOGD(TAG, "Predicted color probabilities:");
ESP_LOGD(TAG, "Red: %.2f", output[0]);
ESP_LOGD(TAG, "Black: %.2f", output[1]);
ESP_LOGD(TAG, "Green: %.2f", output[2]);
ESP_LOGD(TAG, "White: %.2f", output[3]);
const char* color_names[] = {"Red", "Black", "Green", "White"};
uint32_t max_index = 0;
for (int i = 1; i < OUTPUT_SIZE; i++) {
if (output[i] > output[max_index]) {
max_index = i;
}
}
ESP_LOGW(TAG, "Predicted color: %s", color_names[max_index]);
return max_index;
}
void initialize_neural_network(NeuralNetwork* nn) {
// Replace these placeholder values with the actual values generated by the Python script
uint32_t input_weights[INPUT_SIZE][HIDDEN_SIZE1] = {
{0x3dce7ff6, 0x401e01c2, 0x3f459587, 0x400acd7e, 0xbf93b293, 0x3f2cf3d9, 0x3dbe0fee, 0xbe966725, 0xbe3eca2c, 0xbfb2791a, 0xbd73893e, 0xc00ff0f9, 0x3e6a0ceb, 0x3f3c1ffe, 0x3f152aea, 0xbe1e4345},
{0xbe871da1, 0xbfa83525, 0x3ff85ca0, 0x3ee6bebb, 0x3e3af972, 0xbe95efb6, 0x3f06985c, 0x3fd70757, 0xbf87f079, 0x3f106880, 0x3fa1f1f0, 0x3f40f90e, 0xbfc2e236, 0x3bf3808c, 0xc00b8537, 0xbfc3463b},
{0x3e4727eb, 0x3fb70b61, 0x3f187bcc, 0x3f89ce30, 0xbf77adbf, 0x3fd85ae7, 0xbc9ef28e, 0x3f915603, 0xbedd5458, 0xbd7e8b58, 0xbf76fde8, 0xbf8105a0, 0xbfa62a86, 0xbd80ff74, 0xbfbf5b8a, 0xbf8c73c0},
{0xbeb4bb83, 0x3e755932, 0xbda6a6a8, 0xbca989d1, 0xbdcd8bf7, 0x3e90b015, 0xbf4f5c9b, 0x3f2422c6, 0x3f038e7b, 0x3faccd13, 0x3e0d272d, 0x3ff347d2, 0xbf0afc03, 0xbf162bd6, 0x3f8f54f9, 0xbee48cae},
};
uint32_t hidden_weights1[HIDDEN_SIZE1][HIDDEN_SIZE2] = {
{0xbeddbd91, 0x3f6c2506, 0xbd911552, 0xbe76f383, 0x3ed556cd, 0x3da8e90b, 0x3e49ea95, 0xbeb2d561},
{0xbf1a278d, 0x3ca261d7, 0x3fedee4f, 0xbfb821c0, 0xbe097b23, 0xbe7e2793, 0x3fab0160, 0xbee746cd},
{0x3f8c4ec1, 0xbede6a3f, 0x3fc49ba2, 0x3e48b249, 0x3ebb0e0d, 0x3f37e7e8, 0xbf485926, 0x3e7d986a},
{0xbecc1e5e, 0x3cb84720, 0x3fd03b59, 0xbf795731, 0x3f3fdb72, 0x3edd316c, 0xbe94472d, 0xbe02ab59},
{0xbe5c034e, 0x3f404120, 0x3f1605c2, 0x3e5eb4f7, 0xbe289aa5, 0x3c2ddfd5, 0xbe87485e, 0xbf22705f},
{0xbed082a6, 0x3ec899c8, 0x3f5cc247, 0xbdefa97d, 0x3f34ec47, 0xbec36f74, 0xbed7b3cc, 0x3c916d35},
{0xbdf4806f, 0xbecec7c0, 0xbc73454b, 0x3dfdec3e, 0x3ead244d, 0x3dbaa0f1, 0x3f4ed45e, 0xbdfef530},
{0x3fd68018, 0xbcb75ceb, 0x3f8dee75, 0xbae6561d, 0xbd807fb9, 0x3df4d7c4, 0xbee11a0a, 0xbdaf9fda},
{0xbf336719, 0x3c49d37b, 0xbf2c21c1, 0x3e81ad0b, 0x3ddc0c19, 0xbec2aa5b, 0x3f29ba8d, 0xbda87acc},
{0x3f3f73a8, 0xbf4b89b5, 0xbd185663, 0x3f686f07, 0xbe27f74f, 0xbe28d1fd, 0x3cb4593c, 0x3e810361},
{0x3f3eef19, 0x3f34aac4, 0x3de40d11, 0xbd210d3d, 0x3c3d2d8a, 0x3e374f9b, 0xbe94b745, 0x3c7a17ab},
{0x3fc60b9a, 0xbe8e5dd0, 0xbf5e80ec, 0x3f803072, 0xbde40889, 0xbd405f1b, 0x3e839d7f, 0xbe986ca2},
{0x3e5a3297, 0xbeebd1e2, 0xbd293f51, 0x3e872d1e, 0x3f46442f, 0x3f5b6e08, 0x3f0ba50d, 0x3e823e3c},
{0x3ee984dd, 0x3db408e0, 0x3e809863, 0xbe9ccc61, 0xbea47da9, 0x3e63df62, 0x3f27a76d, 0xba9d4194},
{0xbfd16413, 0xbd3cc8e7, 0xbe818b79, 0xbe8174c0, 0xbe35a6aa, 0x3e5ae9db, 0x4006262e, 0xbdb2febc},
{0x3df66350, 0xbe836eca, 0xbe5d5139, 0xbd7b160e, 0xbbf3ebbc, 0xbf4f0ecc, 0x3e8ccde4, 0x3d26607e},
};
uint32_t hidden_weights2[HIDDEN_SIZE2][OUTPUT_SIZE] = {
{0xbec535c5, 0xc0175ba4, 0x400e5d6e, 0xbf832f19},
{0x3eda3cf3, 0xbd8a0d44, 0xbf0ae5c1, 0x3ef72346},
{0x3fa4f9a5, 0xc00bb0ce, 0xbfdd5d0a, 0x3ff993c4},
{0xbfb11a1a, 0x3e412ab1, 0x3fc9744c, 0xbe8ab1d8},
{0xbdfd7557, 0xbf07ad4e, 0xbf8cc4c5, 0x3f319475},
{0x3f255c30, 0xbf4fbc1d, 0x3ed62111, 0x3e0a3a56},
{0x3f405f36, 0x401f25bd, 0xbf9aabb0, 0xbf78920d},
{0x3ef9266c, 0xbf11d1bb, 0x3f25a439, 0xbe24bc17},
};
uint32_t hidden_bias1[HIDDEN_SIZE1] = {0x0, 0x3d26afd5, 0xbee89e2a, 0xbec19fae, 0x0, 0xbe98e479, 0x0, 0xbe172c28,
0x3ea6bccb, 0x3d61e7b9, 0xbdb4ef70, 0x3ebe1c6d, 0x0, 0xbd7032e0, 0x3f8e17ec, 0x0};
uint32_t hidden_bias2[HIDDEN_SIZE2] = {0x3e2b2fc8, 0x3c82fd64, 0x3f4c8c0c, 0xbf009713, 0xbd5baff6, 0x3dc2def8, 0x3f7d654f, 0x0};
uint32_t output_bias[OUTPUT_SIZE] = {0x3f1e3c58, 0xbd665b7d, 0x3def0633, 0xbf2db793};
// Copy the values to the neural network structure
for (int i = 0; i < INPUT_SIZE; i++) {
for (int j = 0; j < HIDDEN_SIZE1; j++) {
nn->input_weights[i][j] = *(float*)&input_weights[i][j];
}
}
for (int i = 0; i < HIDDEN_SIZE1; i++) {
for (int j = 0; j < HIDDEN_SIZE2; j++) {
nn->hidden_weights1[i][j] = *(float*)&hidden_weights1[i][j];
}
}
for (int i = 0; i < HIDDEN_SIZE2; i++) {
for (int j = 0; j < OUTPUT_SIZE; j++) {
nn->hidden_weights2[i][j] = *(float*)&hidden_weights2[i][j];
}
}
for (int i = 0; i < HIDDEN_SIZE1; i++) {
nn->hidden_bias1[i] = *(float*)&hidden_bias1[i];
}
for (int i = 0; i < HIDDEN_SIZE2; i++) {
nn->hidden_bias2[i] = *(float*)&hidden_bias2[i];
}
for (int i = 0; i < OUTPUT_SIZE; i++) {
nn->output_bias[i] = *(float*)&output_bias[i];
}
}

View File

@@ -0,0 +1,23 @@
#ifndef COLOR_PREDICTOR_H
#define COLOR_PREDICTOR_H
#include <stdint.h>
#define INPUT_SIZE 4
#define HIDDEN_SIZE1 16
#define HIDDEN_SIZE2 8
#define OUTPUT_SIZE 4
typedef struct {
float input_weights[INPUT_SIZE][HIDDEN_SIZE1];
float hidden_weights1[HIDDEN_SIZE1][HIDDEN_SIZE2];
float hidden_weights2[HIDDEN_SIZE2][OUTPUT_SIZE];
float hidden_bias1[HIDDEN_SIZE1];
float hidden_bias2[HIDDEN_SIZE2];
float output_bias[OUTPUT_SIZE];
} NeuralNetwork;
uint32_t predict_color(NeuralNetwork* nn, float red, float green, float blue, float clear);
void initialize_neural_network(NeuralNetwork* nn);
#endif // COLOR_PREDICTOR_H

232
firmware/main/controller.c Normal file
View File

@@ -0,0 +1,232 @@
#include "controller.h"
#include "motor.h"
#include <stdio.h>
#include "esp_log.h"
static MotorCommand current_command;
static SemaphoreHandle_t command_mutex;
static TaskHandle_t controller_task_handle = NULL;
static TimerHandle_t command_timer;
static TimerHandle_t command_game_timer;
// game state
game_status state;
// we need to make sure to give immunity for 10 seconds after we have a hit an obstacle
static TickType_t cooldown_end = 0;
void command_set_game_status(uint32_t status){
if(state == GAME_OFF){
// set the game state
state = status;
uint32_t period = 0;
TickType_t current_time = xTaskGetTickCount();
// set the timer period
switch (status) {
case GAME_GREEN:
if(current_time < cooldown_end){
ESP_LOGW("controller", "Cooldown. Ignoring.");
period = 0;
// turn off the game effect
state = GAME_OFF;
} else{
ESP_LOGW("controller", "Set GREEN");
led_set_flash_mode(LED_FLASH_ALL);
period = 1000; // 1 second
cooldown_end = current_time + pdMS_TO_TICKS(5000); // 5 second cool down
}
break;
case GAME_RED:
period = 1000; // 1 second
ESP_LOGW("controller", "Set RED");
break;
case GAME_WHITE:
period = 10000; // 10 seconds
ESP_LOGW("controller", "Set WHITE");
led_set_flash_mode(LED_FLASH_FRONT_ALTERNATE);
break;
case GAME_BLACK:
period = 10000; // 10 seconds
ESP_LOGW("controller", "Set BLACK");
led_set_flash_mode(LED_FLASH_BACK);
break;
case GAME_YELLOW:
period = 1000; // 1 second
ESP_LOGW("controller", "Set YELLOW");
break;
default:
period = 0;
break;
}
// start the timer
if (xTimerIsTimerActive(command_game_timer) == pdFALSE && period != 0) {
ESP_LOGW("controller", "Starting game timer");
xTimerChangePeriod(command_game_timer, pdMS_TO_TICKS(period), 0);
xTimerStart(command_game_timer, 0);
}
}
}
void command_timer_callback(TimerHandle_t xTimer)
{
ESP_LOGI("controller", "Timer expired, stopping motors");
// Set motor speeds to 0 when the timer expires
MotorUpdate update_a = {0, 0, 0};
MotorUpdate update_b = {1, 0, 0};
BaseType_t xStatus;
xStatus = xQueueSend(motor_queue[0], &update_a, 0);
if (xStatus != pdPASS) {
ESP_LOGE("controller","Failed to send stop update for Motor A");
}
xStatus = xQueueSend(motor_queue[1], &update_b, 0);
if (xStatus != pdPASS) {
ESP_LOGE("controller","Failed to send stop update for Motor B");
}
}
void command_game_timer_callback(TimerHandle_t xTimer)
{
ESP_LOGW("controller", "Game timer expired");
state = GAME_OFF;
led_set_flash_mode(LED_CONST);
}
#define SPEEDUP 10
#define SLOWDOWN 10
#define SPINOUT_SPEED 60
void set_motor_command(MotorCommand command)
{
// modify the command based on the game state
switch (state) {
case GAME_GREEN: // spin out for now
// trying to detect if we are moving forward or not
command.MotorASpeed = SPINOUT_SPEED;
command.MotorADirection = 1;
command.MotorBSpeed = SPINOUT_SPEED;
command.MotorBDirection = 0;
command.seconds = 10;
break;
case GAME_RED: // speed up
// trying to detect if we are moving forward or not
if(command.MotorASpeed < SPEEDUP && command.MotorBSpeed > SPEEDUP){
command.MotorASpeed += SPEEDUP;
command.MotorBSpeed += SPEEDUP;
}
break;
case GAME_WHITE: // speed up
// trying to detect if we are moving forward or not
if(command.MotorASpeed > SPEEDUP && command.MotorBSpeed > SPEEDUP){
ESP_LOGW("controller", "speeding up!");
command.MotorASpeed += SPEEDUP;
command.MotorBSpeed += SPEEDUP;
}
break;
case GAME_BLACK: // slow down
if(command.MotorASpeed > SLOWDOWN && command.MotorBSpeed > SLOWDOWN){
command.MotorASpeed -= SLOWDOWN;
command.MotorBSpeed -= SLOWDOWN;
}
break;
case GAME_YELLOW: // spin out
break;
default:
break;
}
if (xTimerIsTimerActive(command_timer) == pdFALSE) {
ESP_LOGI("controller", "Starting timer");
xTimerChangePeriod(command_timer, pdMS_TO_TICKS(command.seconds * 100), 0);
xTimerStart(command_timer, 0);
} else
{
ESP_LOGI("controller", "Resetting timer");
xTimerReset(command_timer, 0);
xTimerStart(command_timer, 0);
}
current_command = command;
if (controller_task_handle != NULL) {
// Notify the controller task to process the new command
xTaskNotifyGive(controller_task_handle);
}
ESP_LOGI("controller"," set_motor_command: Timer set for %lu S", command.seconds);
}
void controller_task(void *pvParameters)
{
while (1) {
// Wait for a notification to process the command
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
MotorCommand command = current_command;
// Send motor updates to the queue
MotorUpdate update_a = {0, command.MotorASpeed, command.MotorADirection};
MotorUpdate update_b = {1, command.MotorBSpeed, command.MotorBDirection};
BaseType_t xStatus;
xStatus = xQueueSend(motor_queue[0], &update_a, 0);
if (xStatus != pdPASS) {
ESP_LOGE("controller", "Failed to send update for Motor A");
}
xStatus = xQueueSend(motor_queue[1], &update_b, 0);
if (xStatus != pdPASS) {
ESP_LOGE("controller","Failed to send update for Motor B");
}
ESP_LOGI("controller","Motor 0 set to speed %d%%, direction %s", command.MotorASpeed,
command.MotorADirection == 0 ? "FORWARD" : "BACKWARD");
ESP_LOGI("controller","Motor 1 set to speed %d%% , direction %s", command.MotorBSpeed,
command.MotorBDirection == 0 ? "FORWARD" : "BACKWARD");
ESP_LOGI("controller","set motor speeds via controller");
}
}
void controller_init()
{
command_mutex = xSemaphoreCreateMutex();
if (command_mutex == NULL) {
ESP_LOGE("controller","Failed to create command mutex");
return;
}
command_timer = xTimerCreate("CommandTimer", pdMS_TO_TICKS(1000), pdFALSE, (void *)0, command_timer_callback);
if (command_timer == NULL) {
ESP_LOGE("controller","Failed to create command timer");
return;
}
command_game_timer = xTimerCreate("CommandGameTimer", pdMS_TO_TICKS(1000),
pdFALSE, (void *)0, command_game_timer_callback);
if (command_game_timer == NULL) {
ESP_LOGE("controller","Failed to create command timer");
return;
}
xTaskCreate(controller_task, "controller_task", 2048, NULL, 5, &controller_task_handle);
// set the game state to GAME_OFF
state = GAME_OFF;
}

View File

@@ -0,0 +1,36 @@
// controller.h
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "led.h"
// Define the MotorCommand structure
typedef struct {
int MotorASpeed;
int MotorADirection;
int MotorBSpeed;
int MotorBDirection;
uint32_t seconds;
} MotorCommand;
// game states
typedef enum {
GAME_RED = 0,
GAME_BLACK,
GAME_GREEN,
GAME_WHITE,
GAME_YELLOW,
GAME_OFF
} game_status;
void command_set_game_status(uint32_t status);
void set_motor_command(MotorCommand command);
void controller_init(void);
#endif // CONTROLLER_H

115
firmware/main/gap.c Normal file
View File

@@ -0,0 +1,115 @@
#include "gap.h"
#include "led.h"
uint8_t addr_type;
int gap_event_handler(struct ble_gap_event *event, void *arg);
void advertise() {
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields;
int rc;
memset(&fields, 0, sizeof(fields));
// flags: discoverability + BLE only
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
// include power levels
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
// include device name
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
rc = ble_gap_adv_set_fields(&fields);
if (rc != 0) {
ESP_LOGE(LOG_TAG_GAP, "Error setting advertisement data: rc=%d", rc);
return;
}
// start advertising
memset(&adv_params, 0, sizeof(adv_params));
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
rc = ble_gap_adv_start(addr_type, NULL, BLE_HS_FOREVER, &adv_params,
gap_event_handler, NULL);
if (rc != 0) {
ESP_LOGE(LOG_TAG_GAP, "Error enabling advertisement data: rc=%d", rc);
return;
}
}
void reset_cb(int reason) {
ESP_LOGE(LOG_TAG_GAP, "BLE reset: reason = %d", reason);
}
void sync_cb(void) {
// determine best adress type
ble_hs_id_infer_auto(0, &addr_type);
// start avertising
advertise();
}
int gap_event_handler(struct ble_gap_event *event, void *arg) {
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
// A new connection was established or a connection attempt failed
ESP_LOGI(LOG_TAG_GAP, "GAP: Connection %s: status=%d",
event->connect.status == 0 ? "established" : "failed",
event->connect.status);
// turn on the front LEDS
set_led(3,true);
set_led(2,true);
break;
case BLE_GAP_EVENT_DISCONNECT:
ESP_LOGD(LOG_TAG_GAP, "GAP: Disconnect: reason=%d\n",
event->disconnect.reason);
// turn off the front LEDS
set_led(3,false);
set_led(2,false);
set_led(1,true);
set_led(0,true);
// Connection terminated; resume advertising
advertise();
break;
case BLE_GAP_EVENT_ADV_COMPLETE:
ESP_LOGI(LOG_TAG_GAP, "GAP: adv complete");
advertise();
break;
case BLE_GAP_EVENT_SUBSCRIBE:
ESP_LOGI(LOG_TAG_GAP, "GAP: Subscribe: conn_handle=%d",
event->connect.conn_handle);
// turn on the front headlines
set_led(0,true);
set_led(1,true);
set_led(2,true);
set_led(3,true);
break;
case BLE_GAP_EVENT_MTU:
ESP_LOGI(LOG_TAG_GAP, "GAP: MTU update: conn_handle=%d, mtu=%d",
event->mtu.conn_handle, event->mtu.value);
break;
}
return 0;
}
void host_task(void *param) {
// returns only when nimble_port_stop() is executed
nimble_port_run();
nimble_port_freertos_deinit();
}

16
firmware/main/gap.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#include "esp_log.h"
#include "host/ble_hs.h"
#include "nimble/ble.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#define LOG_TAG_GAP "gap"
static const char device_name[] = "Racer3";
void advertise();
void reset_cb(int reason);
void sync_cb(void);
void host_task(void *param);

260
firmware/main/gatt_svr.c Normal file
View File

@@ -0,0 +1,260 @@
#include "gatt_svr.h"
#include "mbedtls/aes.h"
#include <string.h>
#include "controller.h"
uint8_t gatt_svr_chr_ota_control_val;
uint8_t gatt_svr_chr_ota_data_val[128];
uint16_t ota_control_val_handle;
uint16_t ota_data_val_handle;
uint16_t num_pkgs_received = 0;
uint16_t packet_size = 0;
static const char *manuf_name = "DreamNight LLC";
static const char *model_num = "Racer3";
static int gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len,
uint16_t max_len, void *dst, uint16_t *len);
static int gatt_svr_chr_ota_control_cb(uint16_t conn_handle,
uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg);
static int gatt_svr_chr_ota_data_cb(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg);
static int gatt_svr_chr_access_device_info(uint16_t conn_handle,
uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg);
static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
{// Service: Device Information
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(GATT_DEVICE_INFO_UUID),
.characteristics =
(struct ble_gatt_chr_def[]) {
{
// Characteristic: Manufacturer Name
.uuid = BLE_UUID16_DECLARE(GATT_MANUFACTURER_NAME_UUID),
.access_cb = gatt_svr_chr_access_device_info,
.flags = BLE_GATT_CHR_F_READ,
},
{
// Characteristic: Model Number
.uuid = BLE_UUID16_DECLARE(GATT_MODEL_NUMBER_UUID),
.access_cb = gatt_svr_chr_access_device_info,
.flags = BLE_GATT_CHR_F_READ,
},
{
0,
},
}},
{
// service: OTA Service
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &gatt_svr_svc_ota_uuid.u,
.characteristics =
(struct ble_gatt_chr_def[]) {
{
// characteristic: OTA control
.uuid = &gatt_svr_chr_ota_control_uuid.u,
.access_cb = gatt_svr_chr_ota_control_cb,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE |
BLE_GATT_CHR_F_NOTIFY,
.val_handle = &ota_control_val_handle,
},
{
// characteristic: OTA data
.uuid = &gatt_svr_chr_ota_data_uuid.u,
.access_cb = gatt_svr_chr_ota_data_cb,
.flags = BLE_GATT_CHR_F_WRITE,
.val_handle = &ota_data_val_handle,
},
{
0,
}},
},
{
0,
},
};
static int gatt_svr_chr_access_device_info(uint16_t conn_handle,
uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg) {
uint16_t uuid;
int rc;
uuid = ble_uuid_u16(ctxt->chr->uuid);
if (uuid == GATT_MODEL_NUMBER_UUID) {
rc = os_mbuf_append(ctxt->om, model_num, strlen(model_num));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
if (uuid == GATT_MANUFACTURER_NAME_UUID) {
rc = os_mbuf_append(ctxt->om, manuf_name, strlen(manuf_name));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
assert(0);
return BLE_ATT_ERR_UNLIKELY;
}
static int gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len,
uint16_t max_len, void *dst, uint16_t *len) {
uint16_t om_len;
int rc;
om_len = OS_MBUF_PKTLEN(om);
if (om_len < min_len || om_len > max_len) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
if (rc != 0) {
return BLE_ATT_ERR_UNLIKELY;
}
return 0;
}
static void update_ota_control(uint16_t conn_handle) {
struct os_mbuf *om;
esp_err_t err;
// check which value has been received
switch (gatt_svr_chr_ota_control_val) {
case SVR_CHR_OTA_CONTROL_REQUEST:
// OTA request
ESP_LOGD(LOG_TAG_GATT_SVR, "OTA has been requested via BLE.");
// is this only the initial request, or does this happen on every transaction?
// this is saying back to the other device that we are good to go
gatt_svr_chr_ota_control_val = SVR_CHR_OTA_CONTROL_REQUEST_ACK;
// this would say that we are not good to go
// gatt_svr_chr_ota_control_val = SVR_CHR_OTA_CONTROL_REQUEST_NAK;
// retrieve the packet size from OTA data
packet_size =
(gatt_svr_chr_ota_data_val[1] << 8) + gatt_svr_chr_ota_data_val[0];
ESP_LOGI(LOG_TAG_GATT_SVR, "Packet size is: %d", packet_size);
// clear the var
num_pkgs_received = 0;
// notify the client via BLE that the OTA has been acknowledged (or not)
om = ble_hs_mbuf_from_flat(&gatt_svr_chr_ota_control_val,
sizeof(gatt_svr_chr_ota_control_val));
ble_gattc_notify_custom(conn_handle, ota_control_val_handle, om);
ESP_LOGD(LOG_TAG_GATT_SVR, "OTA request acknowledgement has been sent.");
break;
// this case is saying we are done with the comms and are closing the channel
case SVR_CHR_OTA_CONTROL_DONE:
// if needed, we can run checks of any kind here before telling the
// other device if we are ok to terminate the channel
// i.e. turn off all motors before closing connection
gatt_svr_chr_ota_control_val = SVR_CHR_OTA_CONTROL_DONE_ACK;
// or
// gatt_svr_chr_ota_control_val = SVR_CHR_OTA_CONTROL_DONE_NAK;
// notify the client via BLE that DONE has been acknowledged
om = ble_hs_mbuf_from_flat(&gatt_svr_chr_ota_control_val,
sizeof(gatt_svr_chr_ota_control_val));
ble_gattc_notify_custom(conn_handle, ota_control_val_handle, om);
ESP_LOGD(LOG_TAG_GATT_SVR, "OTA DONE acknowledgement has been sent.");
break;
default:
break;
}
}
static int gatt_svr_chr_ota_control_cb(uint16_t conn_handle,
uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg) {
int rc;
uint8_t length = sizeof(gatt_svr_chr_ota_control_val);
switch (ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR:
// a client is reading the current value of ota control
rc = os_mbuf_append(ctxt->om, &gatt_svr_chr_ota_control_val, length);
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
break;
case BLE_GATT_ACCESS_OP_WRITE_CHR:
// a client is writing a value to ota control
rc = gatt_svr_chr_write(ctxt->om, 1, length,
&gatt_svr_chr_ota_control_val, NULL);
// write the new value control:
update_ota_control(conn_handle);
return rc;
break;
default:
break;
}
// this shouldn't happen
assert(0);
return BLE_ATT_ERR_UNLIKELY;
}
// this is where we will recieve the actual data over characteristic OTA Data
static int gatt_svr_chr_ota_data_cb(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg) {
int rc;
esp_err_t err;
// store the received data into gatt_svr_chr_ota_data_val
rc = gatt_svr_chr_write(ctxt->om, 1, sizeof(gatt_svr_chr_ota_data_val),
gatt_svr_chr_ota_data_val, NULL);
ESP_LOGI(LOG_TAG_GATT_SVR, "Received packet data:%i, %i, %i, %i, %i", gatt_svr_chr_ota_data_val[0],
gatt_svr_chr_ota_data_val[1], gatt_svr_chr_ota_data_val[2], gatt_svr_chr_ota_data_val[3],
gatt_svr_chr_ota_data_val[4]);
// Example command to set motor speeds and direction for 10 seconds
MotorCommand command = {gatt_svr_chr_ota_data_val[0], gatt_svr_chr_ota_data_val[1],
gatt_svr_chr_ota_data_val[2], gatt_svr_chr_ota_data_val[3],
gatt_svr_chr_ota_data_val[4]};
set_motor_command(command);
num_pkgs_received++;
ESP_LOGI(LOG_TAG_GATT_SVR, "Received packet %d", num_pkgs_received);
return rc;
}
void gatt_svr_init() {
ble_svc_gap_init();
ble_svc_gatt_init();
ble_gatts_count_cfg(gatt_svr_svcs);
ble_gatts_add_svcs(gatt_svr_svcs);
}

46
firmware/main/gatt_svr.h Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include "esp_ota_ops.h"
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#define LOG_TAG_GATT_SVR "gatt_svr"
#define REBOOT_DEEP_SLEEP_TIMEOUT 500
#define GATT_DEVICE_INFO_UUID 0x180A
#define GATT_MANUFACTURER_NAME_UUID 0x2A29
#define GATT_MODEL_NUMBER_UUID 0x2A24
typedef enum {
SVR_CHR_OTA_CONTROL_NOP,
SVR_CHR_OTA_CONTROL_REQUEST,
SVR_CHR_OTA_CONTROL_REQUEST_ACK,
SVR_CHR_OTA_CONTROL_REQUEST_NAK,
SVR_CHR_OTA_CONTROL_DONE,
SVR_CHR_OTA_CONTROL_DONE_ACK,
SVR_CHR_OTA_CONTROL_DONE_NAK,
} svr_chr_ota_control_val_t;
// service: OTA Service
// d6f1d96d-594c-4c53-b1c6-244a1dfde6d8
static const ble_uuid128_t gatt_svr_svc_ota_uuid =
BLE_UUID128_INIT(0xd8, 0xe6, 0xfd, 0x1d, 0x4a, 024, 0xc6, 0xb1, 0x53, 0x4c,
0x4c, 0x59, 0x6d, 0xd9, 0xf1, 0xd6);
// characteristic: OTA Control
// 7ad671aa-21c0-46a4-b722-270e3ae3d830
static const ble_uuid128_t gatt_svr_chr_ota_control_uuid =
BLE_UUID128_INIT(0x30, 0xd8, 0xe3, 0x3a, 0x0e, 0x27, 0x22, 0xb7, 0xa4, 0x46,
0xc0, 0x21, 0xaa, 0x71, 0xd6, 0x7a);
// characteristic: OTA Data
// 23408888-1f40-4cd8-9b89-ca8d45f8a5b0
static const ble_uuid128_t gatt_svr_chr_ota_data_uuid =
BLE_UUID128_INIT(0xb0, 0xa5, 0xf8, 0x45, 0x8d, 0xca, 0x89, 0x9b, 0xd8, 0x4c,
0x40, 0x1f, 0x88, 0x88, 0x40, 0x23);
void gatt_svr_init();

View File

@@ -0,0 +1,54 @@
#include "gpio_interrupt.h"
#include <stdio.h>
#include "freertos/task.h"
#include "driver/gpio.h"
#define GPIO_QUEUE_LENGTH 10
#define GPIO_QUEUE_ITEM_SIZE sizeof(uint32_t)
#define DEBOUNCE_TIME_MS 200
QueueHandle_t gpio_evt_queue = NULL;
QueueHandle_t gpio_interrupt_get_evt_queue(void){
return gpio_evt_queue;
}
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
static uint32_t last_interrupt_time = 0;
uint32_t interrupt_time = xTaskGetTickCountFromISR();
uint32_t gpio_num = (uint32_t) arg;
// Check if it's a falling edge
if (gpio_get_level(gpio_num) == 0) {
// Debounce mechanism
if (interrupt_time - last_interrupt_time > pdMS_TO_TICKS(DEBOUNCE_TIME_MS)) {
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
last_interrupt_time = interrupt_time;
}
}
}
void configure_gpio_interrupt(void)
{
// Create a queue to handle GPIO event from ISR
gpio_evt_queue = xQueueCreate(GPIO_QUEUE_LENGTH, GPIO_QUEUE_ITEM_SIZE);
// Configure the GPIO pin
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_NEGEDGE; // Interrupt on falling edge only
io_conf.pin_bit_mask = (1ULL << INTERRUPT_PIN); // Bit mask of the pin
io_conf.mode = GPIO_MODE_INPUT; // Set as input
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; // Enable pull-up resistor
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; // Disable pull-down resistor
gpio_config(&io_conf);
// Install GPIO ISR service
gpio_install_isr_service(0);
// Attach the interrupt service routine
gpio_isr_handler_add(INTERRUPT_PIN, gpio_isr_handler, (void*) INTERRUPT_PIN);
printf("GPIO %d configured for interrupt on falling edge only with pull-up enabled and %d ms debounce\n", INTERRUPT_PIN, DEBOUNCE_TIME_MS);
}

View File

@@ -0,0 +1,19 @@
#ifndef GPIO_INTERRUPT_H
#define GPIO_INTERRUPT_H
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
// Define the interrupt pin
#define INTERRUPT_PIN 10
// Function prototypes
QueueHandle_t gpio_interrupt_get_evt_queue(void);
void configure_gpio_interrupt(void);
void start_gpio_interrupt_task(void);
// Declare the queue handle as extern so it can be accessed from main.c
extern QueueHandle_t gpio_evt_queue;
#endif // GPIO_INTERRUPT_H

View File

@@ -0,0 +1,32 @@
#include "i2c_config.h"
#include "esp_log.h"
static const char *TAG = "i2c_config";
esp_err_t i2c_master_init(void)
{
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = I2C_MASTER_SCL_IO,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
esp_err_t err = i2c_param_config(i2c_master_port, &conf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "I2C parameter configuration failed. Error: %s", esp_err_to_name(err));
return err;
}
err = i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "I2C driver installation failed. Error: %s", esp_err_to_name(err));
return err;
}
ESP_LOGI(TAG, "I2C master initialized successfully");
return ESP_OK;
}

View File

@@ -0,0 +1,17 @@
#ifndef I2C_CONFIG_H
#define I2C_CONFIG_H
#include "driver/i2c.h"
// I2C configuration
#define I2C_MASTER_SCL_IO 0 // GPIO number for I2C master clock (IO0)
#define I2C_MASTER_SDA_IO 1 // GPIO number for I2C master data (IO1)
#define I2C_MASTER_NUM 0 // I2C master i2c port number
#define I2C_MASTER_FREQ_HZ 400000 // I2C master clock frequency (400 kHz)
#define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master doesn't need buffer
#define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master doesn't need buffer
// Function prototypes
esp_err_t i2c_master_init(void);
#endif // I2C_CONFIG_H

142
firmware/main/led.c Normal file
View File

@@ -0,0 +1,142 @@
// led.c
#include "led.h"
#include "driver/gpio.h"
#include <stdio.h>
// Shared configuration structure
led_config_t led_config = {
.mode = LED_CONST,
.flash_period = pdMS_TO_TICKS(500), // Default 500ms
.led_state = {false, false, false, false}
};
static const int led_gpios[NUM_LEDS] = {LED_1_GPIO, LED_2_GPIO, LED_3_GPIO, LED_4_GPIO};
static int get_gpio_num(int led_index)
{
if (led_index >= 0 && led_index < NUM_LEDS) {
return led_gpios[led_index];
}
return -1;
}
static void led_task(void *pvParameters)
{
TickType_t xLastWakeTime = xTaskGetTickCount();
bool toggle = false;
while (1) {
switch (led_config.mode) {
case LED_CONST:
// Apply current LED states
for (int i = 0; i < NUM_LEDS; i++) {
gpio_set_level(led_gpios[i], led_config.led_state[i] ? 1 : 0);
}
vTaskDelay(led_config.flash_period);
break;
case LED_FLASH_ALL:
for (int i = 0; i < NUM_LEDS; i++) {
gpio_set_level(led_gpios[i], toggle ? 1 : 0);
}
toggle = !toggle;
vTaskDelayUntil(&xLastWakeTime, led_config.flash_period);
break;
case LED_FLASH_BACK:
gpio_set_level(led_gpios[0], toggle ? 1 : 0);
gpio_set_level(led_gpios[1], toggle ? 1 : 0);
toggle = !toggle;
vTaskDelayUntil(&xLastWakeTime, led_config.flash_period);
break;
case LED_FLASH_FRONT:
gpio_set_level(led_gpios[2], toggle ? 1 : 0);
gpio_set_level(led_gpios[3], toggle ? 1 : 0);
toggle = !toggle;
vTaskDelayUntil(&xLastWakeTime, led_config.flash_period);
break;
case LED_FLASH_FRONT_ALTERNATE:
gpio_set_level(led_gpios[2], toggle ? 1 : 0);
gpio_set_level(led_gpios[3], toggle ? 0 : 1);
toggle = !toggle;
vTaskDelayUntil(&xLastWakeTime, led_config.flash_period);
break;
}
}
}
static void configure_led(int gpio)
{
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL << gpio),
.pull_down_en = 0,
.pull_up_en = 0
};
gpio_config(&io_conf);
}
void led_init(void)
{
for (int i = 0; i < NUM_LEDS; i++) {
configure_led(led_gpios[i]);
}
xTaskCreate(led_task, "led_task", 2048, NULL, 10, NULL);
}
void set_led(int led_index, bool state)
{
if (led_index < 0 || led_index >= NUM_LEDS) {
printf("Invalid LED index\n");
return;
}
led_config.led_state[led_index] = state;
if (led_config.mode == LED_CONST) {
gpio_set_level(led_gpios[led_index], state ? 1 : 0);
}
printf("LED %d (GPIO %d) set to %s\n", led_index, led_gpios[led_index], state ? "ON" : "OFF");
}
void led_set_flash_mode(led_flash mode)
{
led_config.mode = mode;
printf("LED flash mode set to %d\n", mode);
}
void led_set_flash_period(TickType_t period)
{
led_config.flash_period = period;
printf("LED flash period set to %u ticks\n", (unsigned int)period);
}
void led_all_on(void)
{
for (int i = 0; i < NUM_LEDS; i++) {
set_led(i, true);
}
led_set_flash_mode(LED_CONST);
}
void led_all_off(void)
{
for (int i = 0; i < NUM_LEDS; i++) {
set_led(i, false);
}
led_set_flash_mode(LED_CONST);
}
void led_front_on(void)
{
set_led(0, true);
set_led(1, true);
led_set_flash_mode(LED_CONST);
}
void led_back_on(void)
{
set_led(2, true);
set_led(3, true);
led_set_flash_mode(LED_CONST);
}

47
firmware/main/led.h Normal file
View File

@@ -0,0 +1,47 @@
// led.h
#ifndef LED_H
#define LED_H
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define NUM_LEDS 4
#define LED_1_GPIO 27
#define LED_2_GPIO 26
#define LED_3_GPIO 25
#define LED_4_GPIO 22
// LED states
typedef enum {
LED_CONST = 0,
LED_FLASH_ALL,
LED_FLASH_BACK,
LED_FLASH_FRONT,
LED_FLASH_FRONT_ALTERNATE
} led_flash;
typedef struct {
led_flash mode;
TickType_t flash_period;
bool led_state[NUM_LEDS];
} led_config_t;
// Extern declaration of the shared configuration
extern led_config_t led_config;
// Original function prototypes
void led_init(void);
void set_led(int led_index, bool state);
// New function prototypes
void led_set_flash_mode(led_flash mode);
void led_set_flash_period(TickType_t period);
void led_all_on(void);
void led_all_off(void);
void led_front_on(void);
void led_back_on(void);
#endif // LED_H

176
firmware/main/main.c Normal file
View File

@@ -0,0 +1,176 @@
// main.c
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/ledc.h"
#include "driver/gpio.h"
#include "motor.h"
// BLE
#include "gap.h"
#include "gatt_svr.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "controller.h"
#include "led.h"
// battery
#include "battery.h"
// interrupt on gpio
#include "gpio_interrupt.h"
// i2c config for the color sensor
#include "i2c_config.h"
#include "opt4060.h"
#include "color_predictor.h"
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_DUTY_RES LEDC_TIMER_10_BIT // Set duty resolution to 13 bits
#define LEDC_FREQUENCY (15000) // Frequency in Hertz. Set frequency at 15 kHz
#define MOTOR_A_FWD_GPIO 13
#define MOTOR_A_BWD_GPIO 14
#define MOTOR_B_FWD_GPIO 4
#define MOTOR_B_BWD_GPIO 5
// Global variables
static bool motor_direction[NUM_MOTORS] = {true, true}; // true for forward, false for backward
QueueHandle_t gpio_intr_evt_queue = NULL;
NeuralNetwork nn;
void gpio_interrupt_task(void *pvParameters)
{
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_intr_evt_queue, &io_num, portMAX_DELAY)) {
printf("GPIO[%lu] interrupt occurred (falling edge)!\n", io_num);
uint16_t red, green, blue, clear;
opt4060_read_color(&red, &green, &blue, &clear);
ESP_LOGD("main", "Color values - Red: %d, Green: %d, Blue: %d, Clear: %d, Color: White", red, green, blue, clear);
if (gpio_get_level(INTERRUPT_PIN) == 0) {
uint32_t color = predict_color(&nn, red, green, blue, clear);
command_set_game_status(color);
}
}
}
}
void app_main(void)
{
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_MODE,
.timer_num = LEDC_TIMER,
.duty_resolution = LEDC_DUTY_RES,
.freq_hz = LEDC_FREQUENCY,
.clk_cfg = LEDC_AUTO_CLK
};
esp_err_t err = ledc_timer_config(&ledc_timer);
if (err != ESP_OK) {
printf("LEDC Timer Config failed: %s\n", esp_err_to_name(err));
return;
}
// Initialize LEDs
led_init();
// set the blink rate to 100ms
led_set_flash_period(pdMS_TO_TICKS(100));
// Configure Motors
configure_motor_pwm(MOTOR_A_FWD_GPIO, LEDC_CHANNEL_0);
configure_motor_pwm(MOTOR_A_BWD_GPIO, LEDC_CHANNEL_1);
configure_motor_pwm(MOTOR_B_FWD_GPIO, LEDC_CHANNEL_2);
configure_motor_pwm(MOTOR_B_BWD_GPIO, LEDC_CHANNEL_3);
// Create motor queue
motor_queue[0] = xQueueCreate(MOTOR_QUEUE_SIZE, sizeof(MotorUpdate));
if (motor_queue[0] == NULL) {
printf("Failed to create motor queue\n");
return;
}
motor_queue[1] = xQueueCreate(MOTOR_QUEUE_SIZE, sizeof(MotorUpdate));
if (motor_queue[1] == NULL) {
printf("Failed to create motor queue\n");
return;
}
// Create semaphore for synchronizing motor start
motor_start_semaphore = xSemaphoreCreateCounting(4,0);
if (motor_start_semaphore == NULL) {
printf("Failed to create motor start semaphore\n");
return;
}
// Create motor tasks for Motor A and Motor B
xTaskCreate(motor_task, "motor_task_A", 2048, (void *)0, 1, NULL);
xTaskCreate(motor_task, "motor_task_B", 2048, (void *)1, 1, NULL);
// Turn on all LEDs
for (int i = 0; i < NUM_LEDS; i++) {
set_led(i, true);
}
set_led(3,false);
set_led(2,false);
set_led(1,true);
set_led(0,true);
// BLE Setup -------------------
nimble_port_init();
ble_hs_cfg.sync_cb = sync_cb;
ble_hs_cfg.reset_cb = reset_cb;
gatt_svr_init();
ble_svc_gap_device_name_set(device_name);
nimble_port_freertos_init(host_task);
// Initialize the motor controller
controller_init();
esp_err_t ret = battery_init();
if (ret != ESP_OK) {
ESP_LOGE("main", "Battery initialization failed");
return;
}
initialize_neural_network(&nn);
// initilize interrupt for HAL
configure_gpio_interrupt();
gpio_intr_evt_queue = gpio_interrupt_get_evt_queue();
xTaskCreate(gpio_interrupt_task, "gpio_interrupt_task", 2048, NULL, 10, NULL);
// color sensor
opt4060_init();
while (1) {
// // uncomment this for training data collection
// uint16_t red, green, blue, clear;
// opt4060_read_color(&red, &green, &blue, &clear);
// // NOTE "Color: White" is hardcoded -- rename this to the color you are training for
// ESP_LOGI("main", "Color values - Red: %d, Green: %d, Blue: %d, Clear: %d, Color: Black", red, green, blue, clear);
vTaskDelay(100 / portTICK_PERIOD_MS); // Delay
}
}

122
firmware/main/motor.c Normal file
View File

@@ -0,0 +1,122 @@
#include "motor.h"
#include <stdio.h>
#include "esp_log.h"
QueueHandle_t motor_queue[2];
SemaphoreHandle_t motor_start_semaphore;
void configure_motor_pwm(int gpio, ledc_channel_t channel)
{
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = channel,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = gpio,
.duty = 0,
.hpoint = 0
};
esp_err_t err = ledc_channel_config(&ledc_channel);
if (err != ESP_OK) {
ESP_LOGE("motor","LEDC Channel Config failed for GPIO %d: %s", gpio, esp_err_to_name(err));
}
}
void set_motor_speed(int motor_index, int speed_percent, bool direction)
{
if (motor_index < 0 || motor_index >= NUM_MOTORS) {
ESP_LOGE("motor","Invalid motor index");
return;
}
// Ensure speed_percent is between MIN_SPEED_PERCENT and 100
speed_percent = (speed_percent < MIN_SPEED_PERCENT) ? 0 : (speed_percent > 100) ? 100 : speed_percent;
// Map MIN_SPEED_PERCENT-100 to MIN_DUTY-MAX_DUTY
int duty;
if (speed_percent == 0) {
duty = 0;
} else {
int min_duty = (MIN_SPEED_PERCENT * MAX_DUTY) / 100;
duty = min_duty + ((speed_percent - MIN_SPEED_PERCENT) * (MAX_DUTY - min_duty)) / (100 - MIN_SPEED_PERCENT);
}
ledc_channel_t fwd_channel = (ledc_channel_t)(motor_index * 2);
ledc_channel_t bwd_channel = (ledc_channel_t)(motor_index * 2 + 1);
ledc_set_duty(LEDC_LOW_SPEED_MODE, fwd_channel, direction ? duty : 0);
ledc_set_duty(LEDC_LOW_SPEED_MODE, bwd_channel, direction ? 0 : duty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, fwd_channel);
ledc_update_duty(LEDC_LOW_SPEED_MODE, bwd_channel);
ESP_LOGD("motor","Motor %d set to speed %d%% (duty %d), direction %s",
motor_index, speed_percent, duty, direction ? "FORWARD" : "BACKWARD");
}
void soft_start_motor(int motor_index, int target_speed, bool target_direction)
{
static int current_speed[NUM_MOTORS] = {0};
static bool current_direction[NUM_MOTORS] = {true, true};
int start_speed = current_speed[motor_index];
bool start_direction = current_direction[motor_index];
// If direction is changing, first slow down to 0
if (start_direction != target_direction && start_speed > 0) {
ESP_LOGD("motor","slow stopping motor %i", motor_index);
for (int speed = start_speed; speed >= MIN_SPEED_PERCENT; speed--) {
set_motor_speed(motor_index, speed, start_direction);
vTaskDelay(SOFT_START_DELAY_MS / portTICK_PERIOD_MS);
}
set_motor_speed(motor_index, 0, start_direction);
start_speed = 0;
}
// Now ramp up to target speed in the correct direction
if (target_speed > 0) {
ESP_LOGD("motor","ramping up motor %i", motor_index);
if (start_speed == 0) {
ESP_LOGD("motor","initial speed was 0 %i", motor_index);
set_motor_speed(motor_index, MIN_SPEED_PERCENT, target_direction);
vTaskDelay(SOFT_START_DELAY_MS * 2 / portTICK_PERIOD_MS); // Longer delay for initial start
start_speed = MIN_SPEED_PERCENT;
}
int step = (target_speed > start_speed) ? 1 : -1;
for (int speed = start_speed; speed != target_speed; speed += step) {
set_motor_speed(motor_index, speed, target_direction);
vTaskDelay(SOFT_START_DELAY_MS / portTICK_PERIOD_MS);
}
} else {
ESP_LOGD("motor","direct set on motor %i", motor_index);
set_motor_speed(motor_index, 0, target_direction);
}
// Ensure we reach exactly the target speed
set_motor_speed(motor_index, target_speed, target_direction);
// Update current speed and direction
current_speed[motor_index] = target_speed;
current_direction[motor_index] = target_direction;
ESP_LOGD("motor","done with motor %i", motor_index);
}
void motor_task(void *pvParameters)
{
int motor_index = (int)pvParameters;
MotorUpdate update;
while (1) {
if (xQueueReceive(motor_queue[0], &update, pdMS_TO_TICKS(10)) == pdTRUE) {
ESP_LOGI("Motor", "motor index %i speed %i direction %i", update.motor_index, update.speed_percent,
update.direction);
set_motor_speed(update.motor_index, update.speed_percent, update.direction);
}
if (xQueueReceive(motor_queue[1], &update, pdMS_TO_TICKS(10)) == pdTRUE) {
ESP_LOGI("Motor", "motor index %i speed %i direction %i", update.motor_index, update.speed_percent,
update.direction);
set_motor_speed(update.motor_index, update.speed_percent, update.direction);
}
}
}

31
firmware/main/motor.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef MOTOR_H
#define MOTOR_H
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/ledc.h"
#define NUM_MOTORS 2
#define MIN_SPEED_PERCENT 15 // Minimum speed percentage
#define MAX_DUTY ((1 << LEDC_TIMER_10_BIT) - 1) // Max duty cycle for 10-bit resolution
#define MOTOR_QUEUE_SIZE 10
#define SOFT_START_DELAY_MS 30 // Adjust this value to change the softness of the start
// Motor speed update structure
typedef struct {
int motor_index;
int speed_percent;
bool direction;
} MotorUpdate;
void configure_motor_pwm(int gpio, ledc_channel_t channel);
void set_motor_speed(int motor_index, int speed_percent, bool direction);
void soft_start_motor(int motor_index, int target_speed, bool target_direction);
void motor_task(void *pvParameters);
extern QueueHandle_t motor_queue[2];
extern SemaphoreHandle_t motor_start_semaphore;
#endif // MOTOR_H

200
firmware/main/opt4060.c Normal file
View File

@@ -0,0 +1,200 @@
#include "opt4060.h"
#include "driver/i2c.h"
#include "esp_log.h"
// math
#include <stdio.h>
#include <math.h>
static const char *TAG = "OPT4060";
static esp_err_t i2c_master_init(void)
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
esp_err_t err = i2c_param_config(I2C_MASTER_NUM, &conf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "I2C parameter configuration failed: %s", esp_err_to_name(err));
return err;
}
err = i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0);
if (err != ESP_OK) {
if (err == ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "I2C driver already installed, attempting to use existing installation");
return ESP_OK;
}
ESP_LOGE(TAG, "I2C driver installation failed: %s", esp_err_to_name(err));
return err;
}
return ESP_OK;
}
esp_err_t opt4060_init(void)
{
esp_err_t ret = i2c_master_init();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize I2C: %s", esp_err_to_name(ret));
return ret;
}
// set the chip to continuous conversion at 1ms
// 0x30, 0x78 - write to 0x0A
uint8_t write_data[3] = {0x0A, 0x30, 0x78};
ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT4060_SENSOR_ADDR, write_data,
3, pdMS_TO_TICKS(1000));
if (ret == ESP_OK)
ESP_LOGI(TAG, "OPT4060 initialized successfully");
else
ESP_LOGE(TAG, "failed to init OPT4060");
return ESP_OK;
}
void determineColor(uint16_t red, uint16_t green, uint16_t blue, uint16_t clear) {
// // Normalize the values
// float r = (float)red / clear;
// float g = (float)green / clear;
// float b = (float)blue / clear;
//
// // Define color thresholds
// float threshold = 0.2;
// float white_threshold = 0.9;
// float black_threshold = 0.1;
//
// // Determine the color
// if (r < black_threshold && g < black_threshold && b < black_threshold) {
// printf("Black\n");
// } else if (r > white_threshold && g > white_threshold && b > white_threshold) {
// printf("White\n");
// } else if (r > threshold && r > g && r > b) {
// printf("Red\n");
// } else if (g > threshold && g > r && g > b) {
// printf("Green\n");
// } else if (b > threshold && b > r && b > g) {
// printf("Blue\n");
// } else if (r > threshold && g > threshold && r > b && g > b) {
// printf("Yellow\n");
// } else if (r > threshold && b > threshold && r > g && b > g) {
// printf("Magenta\n");
// } else if (g > threshold && b > threshold && g > r && b > r) {
// printf("Cyan\n");
// } else {
// printf("Unknown\n");
// }
// Define thresholds based on the provided examples
const uint16_t GREEN_THRESHOLD = 1000;
const uint16_t BLACK_THRESHOLD = 300;
const uint16_t WHITE_THRESHOLD = 1000;
const uint16_t CLEAR_THRESHOLD = 3000;
// Calculate ratios for more accurate color detection
float red_ratio = (float)red / (red + green + blue);
float green_ratio = (float)green / (red + green + blue);
float blue_ratio = (float)blue / (red + green + blue);
// Check for green
if (green > GREEN_THRESHOLD && green_ratio > 0.4) {
ESP_LOGW("opt4060", "Green");
}
// Check for black
else if (red < BLACK_THRESHOLD && green < BLACK_THRESHOLD && blue < BLACK_THRESHOLD) {
ESP_LOGW("opt4060", "Black");
}
// Check for white
else if (red > WHITE_THRESHOLD && green > WHITE_THRESHOLD && blue > WHITE_THRESHOLD && clear > CLEAR_THRESHOLD) {
ESP_LOGW("opt4060", "White");
}
// Check for red
else if (red_ratio > 0.35 && red > green && red > blue) {
ESP_LOGW("opt4060", "Red");
}
// Check for blue
else if (blue_ratio > 0.35 && blue > red && blue > green) {
ESP_LOGW("opt4060", "Blue");
}
// If no specific color is detected
else {
ESP_LOGW("opt4060", "Unknown");
}
}
void classify_color(double X, double Y, double Z, double LUX) {
// Convert XYZ to RGB
double R = 3.2404542 * X - 1.5371385 * Y - 0.4985314 * Z;
double G = -0.9692660 * X + 1.8760108 * Y + 0.0415560 * Z;
double B = 0.0556434 * X - 0.2040259 * Y + 1.0572252 * Z;
// Normalize RGB values
R = fmax(0, fmin(1, R));
G = fmax(0, fmin(1, G));
B = fmax(0, fmin(1, B));
// Define thresholds
const double COLOR_THRESHOLD = 0.5;
const double BLACK_THRESHOLD = 0.1;
const double WHITE_THRESHOLD = 0.9;
// Check for black and white first
if (LUX < BLACK_THRESHOLD) {
ESP_LOGW(TAG, "Classified color: Black");
} else if (LUX > WHITE_THRESHOLD && R > WHITE_THRESHOLD && G > WHITE_THRESHOLD && B > WHITE_THRESHOLD) {
ESP_LOGW(TAG, "Classified color: White");
}
// Classify based on dominant color
else if (R > COLOR_THRESHOLD && R > G && R > B) {
ESP_LOGW(TAG, "Classified color: Red");
} else if (G > COLOR_THRESHOLD && G > R && G > B) {
ESP_LOGW(TAG, "Classified color: Green");
} else if (B > COLOR_THRESHOLD && B > R && B > G) {
ESP_LOGW(TAG, "Classified color: Blue");
}
// Default case
else {
ESP_LOGW(TAG, "Classified color: Unclassified");
}
}
esp_err_t opt4060_read_color(uint16_t *red, uint16_t *green, uint16_t *blue, uint16_t *clear)
{
uint8_t data[16];
esp_err_t ret;
uint8_t address[1] = {0};
ret = i2c_master_write_read_device(I2C_MASTER_NUM, OPT4060_SENSOR_ADDR, address, 1, data,
16, pdMS_TO_TICKS(1000));
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to read color data: %s", esp_err_to_name(ret));
return ret;
}
// Convert the read data to color values
// *red = (data[1] << 8) | data[0];
// *green = (data[3] << 8) | data[2];
// *blue = (data[5] << 8) | data[4];
// *clear = (data[7] << 8) | data[6];
*red = ((data[0] & 0xF) << 8) | data[1];
*green = ((data[4] & 0xF) << 8) | data[5];
*blue = ((data[8] & 0xF) << 8) | data[9];
*clear = ((data[12] & 0xF) << 8) | data[13];
return ESP_OK;
}

20
firmware/main/opt4060.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef OPT4060_H
#define OPT4060_H
#include <stdint.h>
#include "esp_err.h"
#define I2C_MASTER_SCL_IO 0 // GPIO number for I2C master clock
#define I2C_MASTER_SDA_IO 1 // GPIO number for I2C master data
#define I2C_MASTER_NUM 0 // I2C master i2c port number
#define I2C_MASTER_FREQ_HZ 100000 // I2C master clock frequency
#define OPT4060_SENSOR_ADDR 0x44 // OPT4060 I2C address (1000100 in binary)
#define OPT4060_REG_COLOR 0x00 // Register address for color data
esp_err_t opt4060_init(void);
void determineColor(uint16_t red, uint16_t green, uint16_t blue, uint16_t clear);
void classify_color(double X, double Y, double Z, double LUX);
esp_err_t opt4060_read_color(uint16_t *red, uint16_t *green, uint16_t *blue, uint16_t *clear);
#endif // OPT4060_H

0
firmware/sdkconfig.ci Normal file
View File

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
{
"board": {
"active_layer": 36,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": false,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36,
39,
40
],
"visible_layers": "ffcffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "sensors.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@@ -0,0 +1,602 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.05,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.1,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.1,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.2032
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.1524,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.1524,
"min_hole_to_hole": 0.127,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 1,
"min_silk_clearance": 0.0,
"min_text_height": 0.508,
"min_text_thickness": 0.127,
"min_through_hole_diameter": 0.254,
"min_track_width": 0.1524,
"min_via_annular_width": 0.127,
"min_via_diameter": 0.508,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.1524,
0.2032,
0.3048
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 0.508,
"drill": 0.254
}
],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "sensors.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "gerbers/",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"name": "Grouped By Value",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"ec97f746-e716-4c2a-b33e-ac66d59ccd45",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

96636
hardware/racer/fp-info-cache Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

28662
hardware/racer/racer.kicad_pcb Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
{
"board": {
"active_layer": 40,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": false,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36,
39,
40
],
"visible_layers": "ff4ffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "tank.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@@ -0,0 +1,635 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.1,
"copper_line_width": 0.1016,
"copper_text_italic": false,
"copper_text_size_h": 0.508,
"copper_text_size_v": 0.508,
"copper_text_thickness": 0.1016,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1016,
"fab_text_italic": false,
"fab_text_size_h": 0.508,
"fab_text_size_v": 0.508,
"fab_text_thickness": 0.1016,
"fab_text_upright": false,
"other_line_width": 0.1016,
"other_text_italic": false,
"other_text_size_h": 0.508,
"other_text_size_v": 0.508,
"other_text_thickness": 0.1016,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.1016,
"silk_text_italic": false,
"silk_text_size_h": 0.508,
"silk_text_size_v": 0.508,
"silk_text_thickness": 0.1016,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [
"footprint_type_mismatch|175732800|109995000|a0accbaf-4c88-4d9b-a33b-483c8d6cf345|00000000-0000-0000-0000-000000000000",
"footprint_type_mismatch|176670200|131877200|b4d11d8a-6823-4555-afb5-e281dbb73ef6|00000000-0000-0000-0000-000000000000",
"footprint_type_mismatch|177258000|92155200|893b6f4d-ca29-4cfc-8e28-ec17db2b8cb3|00000000-0000-0000-0000-000000000000",
"footprint_type_mismatch|184912000|124750600|85739941-68b4-452d-b206-1e220b27ffbb|00000000-0000-0000-0000-000000000000",
"footprint_type_mismatch|192337400|92063000|901525e1-5d10-4132-adb7-46ad328f0aa2|00000000-0000-0000-0000-000000000000",
"footprint_type_mismatch|193090800|131914200|6309729c-b0eb-45b6-9068-ab82c3edf66f|00000000-0000-0000-0000-000000000000",
"footprint_type_mismatch|198720200|102158800|3b30881e-2389-484b-b281-97faee83cbc6|00000000-0000-0000-0000-000000000000",
"lib_footprint_mismatch|184886600|133985000|d29dc366-5f2a-4c5e-ae46-a25d45e2eb0e|00000000-0000-0000-0000-000000000000",
"lib_footprint_mismatch|184886600|89382600|3494d978-8306-4ce5-b4ee-dea6fb601383|00000000-0000-0000-0000-000000000000"
],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "ignore",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.14986,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.1524,
"min_hole_to_hole": 0.127,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 1,
"min_silk_clearance": 0.0,
"min_text_height": 0.508,
"min_text_thickness": 0.0762,
"min_through_hole_diameter": 0.254,
"min_track_width": 0.1524,
"min_via_annular_width": 0.127,
"min_via_diameter": 0.4572,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.1524,
0.2032,
0.254,
0.3048,
0.4572,
0.762,
1.016,
1.27
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 0.508,
"drill": 0.254
}
],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "tank.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.1524,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2032,
"via_diameter": 0.508,
"via_drill": 0.254,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "gerbers",
"pos_files": "./",
"specctra_dsn": "",
"step": "tank.step",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": false,
"label": "#",
"name": "${ITEM_NUMBER}",
"show": false
},
{
"group_by": false,
"label": "MANUFACTURER",
"name": "MANUFACTURER",
"show": false
},
{
"group_by": false,
"label": "Description",
"name": "Description",
"show": false
}
],
"filter_string": "",
"group_symbols": true,
"name": "",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"11c7bd96-786c-4c10-b71b-7b198cc052d5",
"Root"
]
],
"text_variables": {}
}

20353
hardware/racer/racer.kicad_sch Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
Ref,Val,Package,PosX,PosY,Rot,Side
"D1","LED","C_0603_1608Metric",4.267200,42.062400,180.000000,bottom
"D2","LED","C_0603_1608Metric",4.267200,38.252400,180.000000,bottom
"D3","LED","C_0603_1608Metric",4.267200,34.442400,180.000000,bottom
"S2","TL4100AF240QG_","SW_PTS810_SJM_250_SMTR_LFS",15.029000,20.421600,180.000000,bottom
"S3","TL4100AF240QG_","SW_PTS810_SJM_250_SMTR_LFS",15.036800,10.718800,180.000000,bottom
"S5","TL4100AF240QG_","SW_PTS810_SJM_250_SMTR_LFS",20.599400,15.560900,-90.000000,bottom
"S6","TL4100AF240QG_","SW_PTS810_SJM_250_SMTR_LFS",9.440600,15.552600,90.000000,bottom
1 Ref Val Package PosX PosY Rot Side
2 D1 LED C_0603_1608Metric 4.267200 42.062400 180.000000 bottom
3 D2 LED C_0603_1608Metric 4.267200 38.252400 180.000000 bottom
4 D3 LED C_0603_1608Metric 4.267200 34.442400 180.000000 bottom
5 S2 TL4100AF240QG_ SW_PTS810_SJM_250_SMTR_LFS 15.029000 20.421600 180.000000 bottom
6 S3 TL4100AF240QG_ SW_PTS810_SJM_250_SMTR_LFS 15.036800 10.718800 180.000000 bottom
7 S5 TL4100AF240QG_ SW_PTS810_SJM_250_SMTR_LFS 20.599400 15.560900 -90.000000 bottom
8 S6 TL4100AF240QG_ SW_PTS810_SJM_250_SMTR_LFS 9.440600 15.552600 90.000000 bottom

View File

@@ -0,0 +1,36 @@
Ref,Val,Package,PosX,PosY,Rot,Side,
C1,1uF 25V,C_0603_1608Metric,2.93,37.62,180,top,270
C2,1uF 25V,C_0603_1608Metric,2.93,36.07,180,top,270
C3,1uF 25V,C_0603_1608Metric,2.96,32.97,180,top,270
C4,1uF 25V,C_0603_1608Metric,2.96,29.87,180,top,270
C10,1uF 25V,C_0603_1608Metric,3.00,48.67,180,top,270
C11,0.1uF,C_0603_1608Metric,19.99,46.89,0,top,90
C12,0.1uF,C_0603_1608Metric,6.33,48.62,0,top,90
C13,0.1uF,C_0603_1608Metric,9.96,41.71,90,top,180
C14,2.2uF,C_0603_1608Metric,19.29,16.02,0,top,90
C15,10uF,C_0603_1608Metric,19.54,22.52,0,top,90
C16,10uF,C_0603_1608Metric,3.54,16.02,180,top,270
C17,22uF,C_0603_1608Metric,3.43,7.95,-90,top,0
R1,200,R_0603_1608Metric,2.74,42.57,0,top,90
R2,10k,R_0603_1608Metric,6.06,37.62,0,top,90
R3,100k,R_0603_1608Metric,2.93,39.18,180,top,270
R4,10k,R_0603_1608Metric,6.07,34.52,0,top,90
R5,100k,R_0603_1608Metric,2.96,34.52,180,top,270
R6,10k,R_0603_1608Metric,6.03,31.42,0,top,90
R7,100k,R_0603_1608Metric,2.95,31.42,180,top,270
R8,10k,R_0603_1608Metric,6.07,28.32,0,top,90
R9,10k,R_0603_1608Metric,6.30,46.89,180,top,270
R10,10k,R_0603_1608Metric,4.52,26.06,180,top,270
R11,10k,R_0603_1608Metric,9.80,35.00,180,top,270
R12,200,R_0603_1608Metric,2.74,46.13,0,top,90
R13,200,R_0603_1608Metric,2.74,44.35,0,top,90
R14,100k,R_0603_1608Metric,2.98,28.32,180,top,270
R16,1M,R_0603_1608Metric,16.71,10.03,90,top,180
R17,5k1,R_0603_1608Metric,25.58,12.19,90,top,180
R18,5k1,R_0603_1608Metric,23.93,12.19,90,top,180
R20,470,R_0603_1608Metric,11.68,17.55,180,top,270
R21,470,R_0603_1608Metric,11.66,15.42,180,top,270
R22,1.43K,R_0603_1608Metric,1.73,7.95,-90,top,0
R23,1.43K,R_0603_1608Metric,8.54,9.52,180,top,270
R24,75K,R_0603_1608Metric,11.54,11.02,180,top,270
R25,200,R_0603_1608Metric,15.57,5.49,90,top,180
1 Ref Val Package PosX PosY Rot Side
2 C1 1uF 25V C_0603_1608Metric 2.93 37.62 180 top 270
3 C2 1uF 25V C_0603_1608Metric 2.93 36.07 180 top 270
4 C3 1uF 25V C_0603_1608Metric 2.96 32.97 180 top 270
5 C4 1uF 25V C_0603_1608Metric 2.96 29.87 180 top 270
6 C10 1uF 25V C_0603_1608Metric 3.00 48.67 180 top 270
7 C11 0.1uF C_0603_1608Metric 19.99 46.89 0 top 90
8 C12 0.1uF C_0603_1608Metric 6.33 48.62 0 top 90
9 C13 0.1uF C_0603_1608Metric 9.96 41.71 90 top 180
10 C14 2.2uF C_0603_1608Metric 19.29 16.02 0 top 90
11 C15 10uF C_0603_1608Metric 19.54 22.52 0 top 90
12 C16 10uF C_0603_1608Metric 3.54 16.02 180 top 270
13 C17 22uF C_0603_1608Metric 3.43 7.95 -90 top 0
14 R1 200 R_0603_1608Metric 2.74 42.57 0 top 90
15 R2 10k R_0603_1608Metric 6.06 37.62 0 top 90
16 R3 100k R_0603_1608Metric 2.93 39.18 180 top 270
17 R4 10k R_0603_1608Metric 6.07 34.52 0 top 90
18 R5 100k R_0603_1608Metric 2.96 34.52 180 top 270
19 R6 10k R_0603_1608Metric 6.03 31.42 0 top 90
20 R7 100k R_0603_1608Metric 2.95 31.42 180 top 270
21 R8 10k R_0603_1608Metric 6.07 28.32 0 top 90
22 R9 10k R_0603_1608Metric 6.30 46.89 180 top 270
23 R10 10k R_0603_1608Metric 4.52 26.06 180 top 270
24 R11 10k R_0603_1608Metric 9.80 35.00 180 top 270
25 R12 200 R_0603_1608Metric 2.74 46.13 0 top 90
26 R13 200 R_0603_1608Metric 2.74 44.35 0 top 90
27 R14 100k R_0603_1608Metric 2.98 28.32 180 top 270
28 R16 1M R_0603_1608Metric 16.71 10.03 90 top 180
29 R17 5k1 R_0603_1608Metric 25.58 12.19 90 top 180
30 R18 5k1 R_0603_1608Metric 23.93 12.19 90 top 180
31 R20 470 R_0603_1608Metric 11.68 17.55 180 top 270
32 R21 470 R_0603_1608Metric 11.66 15.42 180 top 270
33 R22 1.43K R_0603_1608Metric 1.73 7.95 -90 top 0
34 R23 1.43K R_0603_1608Metric 8.54 9.52 180 top 270
35 R24 75K R_0603_1608Metric 11.54 11.02 180 top 270
36 R25 200 R_0603_1608Metric 15.57 5.49 90 top 180

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": false,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36,
39,
40
],
"visible_layers": "ff4ffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "controller.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@@ -0,0 +1,625 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.1,
"copper_line_width": 0.1016,
"copper_text_italic": false,
"copper_text_size_h": 0.508,
"copper_text_size_v": 0.508,
"copper_text_thickness": 0.1016,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1016,
"fab_text_italic": false,
"fab_text_size_h": 0.508,
"fab_text_size_v": 0.508,
"fab_text_thickness": 0.1016,
"fab_text_upright": false,
"other_line_width": 0.1016,
"other_text_italic": false,
"other_text_size_h": 0.508,
"other_text_size_v": 0.508,
"other_text_thickness": 0.1016,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.1016,
"silk_text_italic": false,
"silk_text_size_h": 0.508,
"silk_text_size_v": 0.508,
"silk_text_thickness": 0.1016,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.0
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "ignore",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "warning",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.14986,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.1524,
"min_hole_to_hole": 0.127,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 1,
"min_silk_clearance": 0.0,
"min_text_height": 0.508,
"min_text_thickness": 0.127,
"min_through_hole_diameter": 0.254,
"min_track_width": 0.1524,
"min_via_annular_width": 0.127,
"min_via_diameter": 0.4572,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.1524,
0.2032,
0.254,
0.3048,
0.4572,
0.762,
1.016,
1.27
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 0.508,
"drill": 0.254
}
],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "controller.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.1524,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2032,
"via_diameter": 0.508,
"via_drill": 0.254,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "gerbers/",
"pos_files": "./",
"specctra_dsn": "",
"step": "controller-pcb.step",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": false,
"label": "#",
"name": "${ITEM_NUMBER}",
"show": false
},
{
"group_by": false,
"label": "MANUFACTURER",
"name": "MANUFACTURER",
"show": false
},
{
"group_by": false,
"label": "Description",
"name": "Description",
"show": false
}
],
"filter_string": "",
"group_symbols": true,
"name": "",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"11c7bd96-786c-4c10-b71b-7b198cc052d5",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3129
mechanical/wheel.step Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

25
scripts/README.md Normal file
View File

@@ -0,0 +1,25 @@
## trainer.py
#### to run, simply call `python trainer.py`
trainer.py is the training algorithm for the neural network embedded within the Racer.
To use, `trainer.py` ensure you have classified data in `color_data.txt`
Here is the format:
```
W (17447) main: Color values - Red: 1822, Green: 2184, Blue: 1762, Clear: 2008, Color: White
W (9847) main: Color values - Red: 220, Green: 472, Blue: 124, Clear: 1780, Color: Black
W (16447) main: Color values - Red: 488, Green: 748, Blue: 196, Clear: 1620, Color: Red
W (19947) main: Color values - Red: 428, Green: 1368, Blue: 336, Clear: 2148, Color: Green
```
it requires all colors to be present to train. 200 samples of each color seems to be ok.
## controller.py
controller.py is a simple BLE script that accepts keyboard input and relays it to the Racer. Its great for debugging.
#### to run, simply call `python controller.py`

View File

@@ -0,0 +1 @@
{"ble_address": "74:4D:BD:61:A7:B3"}

615
scripts/color_data.txt Normal file
View File

@@ -0,0 +1,615 @@
W (647) main: Color values - Red: 440, Green: 1378, Blue: 328, Clear: 1060, Color: Green
W (747) main: Color values - Red: 428, Green: 1376, Blue: 324, Clear: 1060, Color: Green
W (847) main: Color values - Red: 432, Green: 1384, Blue: 332, Clear: 1064, Color: Green
W (947) main: Color values - Red: 436, Green: 1380, Blue: 336, Clear: 1060, Color: Green
W (1047) main: Color values - Red: 432, Green: 1380, Blue: 336, Clear: 1060, Color: Green
W (1147) main: Color values - Red: 432, Green: 1380, Blue: 336, Clear: 1064, Color: Green
W (1247) main: Color values - Red: 428, Green: 1376, Blue: 332, Clear: 1064, Color: Green
W (1347) main: Color values - Red: 436, Green: 1376, Blue: 328, Clear: 1068, Color: Green
W (1447) main: Color values - Red: 436, Green: 1376, Blue: 332, Clear: 2156, Color: Green
W (1547) main: Color values - Red: 440, Green: 1388, Blue: 328, Clear: 2156, Color: Green
W (1647) main: Color values - Red: 436, Green: 1384, Blue: 328, Clear: 2144, Color: Green
W (1747) main: Color values - Red: 440, Green: 1360, Blue: 332, Clear: 2144, Color: Green
W (1847) main: Color values - Red: 436, Green: 1380, Blue: 330, Clear: 2152, Color: Green
W (1947) main: Color values - Red: 436, Green: 1372, Blue: 332, Clear: 2160, Color: Green
W (2047) main: Color values - Red: 432, Green: 1368, Blue: 332, Clear: 2156, Color: Green
W (2147) main: Color values - Red: 428, Green: 1368, Blue: 320, Clear: 2144, Color: Green
W (2247) main: Color values - Red: 428, Green: 1364, Blue: 320, Clear: 2136, Color: Green
W (2347) main: Color values - Red: 436, Green: 1356, Blue: 324, Clear: 2132, Color: Green
W (2447) main: Color values - Red: 432, Green: 1352, Blue: 316, Clear: 2160, Color: Green
W (2547) main: Color values - Red: 432, Green: 1352, Blue: 328, Clear: 2140, Color: Green
W (2647) main: Color values - Red: 440, Green: 1384, Blue: 336, Clear: 2180, Color: Green
W (2747) main: Color values - Red: 440, Green: 1404, Blue: 348, Clear: 2216, Color: Green
W (2847) main: Color values - Red: 440, Green: 1384, Blue: 328, Clear: 2156, Color: Green
W (2947) main: Color values - Red: 440, Green: 1400, Blue: 282, Clear: 2192, Color: Green
W (3047) main: Color values - Red: 436, Green: 1408, Blue: 332, Clear: 2180, Color: Green
W (3147) main: Color values - Red: 440, Green: 1376, Blue: 328, Clear: 2184, Color: Green
W (3247) main: Color values - Red: 448, Green: 1408, Blue: 344, Clear: 2212, Color: Green
W (3347) main: Color values - Red: 440, Green: 1404, Blue: 336, Clear: 2180, Color: Green
W (3447) main: Color values - Red: 440, Green: 1396, Blue: 332, Clear: 2152, Color: Green
W (3547) main: Color values - Red: 444, Green: 1404, Blue: 336, Clear: 2172, Color: Green
W (3647) main: Color values - Red: 444, Green: 1404, Blue: 332, Clear: 2184, Color: Green
W (3747) main: Color values - Red: 448, Green: 1378, Blue: 328, Clear: 2188, Color: Green
W (3847) main: Color values - Red: 428, Green: 1368, Blue: 328, Clear: 2140, Color: Green
W (3947) main: Color values - Red: 428, Green: 1368, Blue: 320, Clear: 2132, Color: Green
W (4047) main: Color values - Red: 398, Green: 1264, Blue: 320, Clear: 2112, Color: Green
W (4147) main: Color values - Red: 432, Green: 1380, Blue: 328, Clear: 2128, Color: Green
W (4247) main: Color values - Red: 428, Green: 1368, Blue: 320, Clear: 2136, Color: Green
W (4347) main: Color values - Red: 440, Green: 1352, Blue: 324, Clear: 2152, Color: Green
W (4447) main: Color values - Red: 424, Green: 1372, Blue: 324, Clear: 2156, Color: Green
W (4547) main: Color values - Red: 432, Green: 1376, Blue: 328, Clear: 2152, Color: Green
W (4647) main: Color values - Red: 432, Green: 1384, Blue: 320, Clear: 2100, Color: Green
W (4747) main: Color values - Red: 440, Green: 1388, Blue: 328, Clear: 2164, Color: Green
W (4847) main: Color values - Red: 436, Green: 1388, Blue: 324, Clear: 2164, Color: Green
W (4947) main: Color values - Red: 436, Green: 1368, Blue: 328, Clear: 2172, Color: Green
W (5047) main: Color values - Red: 448, Green: 1412, Blue: 336, Clear: 2216, Color: Green
W (5147) main: Color values - Red: 448, Green: 1392, Blue: 336, Clear: 2176, Color: Green
W (5247) main: Color values - Red: 448, Green: 1420, Blue: 340, Clear: 2192, Color: Green
W (5347) main: Color values - Red: 440, Green: 1384, Blue: 326, Clear: 2184, Color: Green
W (5447) main: Color values - Red: 432, Green: 1380, Blue: 340, Clear: 2180, Color: Green
W (5547) main: Color values - Red: 444, Green: 1396, Blue: 334, Clear: 2192, Color: Green
W (5647) main: Color values - Red: 440, Green: 1388, Blue: 340, Clear: 2184, Color: Green
W (5747) main: Color values - Red: 432, Green: 1380, Blue: 332, Clear: 2144, Color: Green
W (5847) main: Color values - Red: 436, Green: 1364, Blue: 324, Clear: 2128, Color: Green
W (5947) main: Color values - Red: 424, Green: 1352, Blue: 260, Clear: 2132, Color: Green
W (6047) main: Color values - Red: 428, Green: 1360, Blue: 336, Clear: 2144, Color: Green
W (6147) main: Color values - Red: 440, Green: 1388, Blue: 328, Clear: 2164, Color: Green
W (6247) main: Color values - Red: 432, Green: 1368, Blue: 328, Clear: 2152, Color: Green
W (6347) main: Color values - Red: 436, Green: 1382, Blue: 328, Clear: 2152, Color: Green
W (6447) main: Color values - Red: 448, Green: 1384, Blue: 332, Clear: 2156, Color: Green
W (6547) main: Color values - Red: 432, Green: 1380, Blue: 324, Clear: 2160, Color: Green
W (6647) main: Color values - Red: 432, Green: 1360, Blue: 324, Clear: 2140, Color: Green
W (6747) main: Color values - Red: 436, Green: 1376, Blue: 324, Clear: 2152, Color: Green
W (6847) main: Color values - Red: 436, Green: 1376, Blue: 328, Clear: 2156, Color: Green
W (6947) main: Color values - Red: 432, Green: 1368, Blue: 324, Clear: 2124, Color: Green
W (7047) main: Color values - Red: 436, Green: 1364, Blue: 332, Clear: 1898, Color: Green
W (7147) main: Color values - Red: 348, Green: 1100, Blue: 260, Clear: 1740, Color: Green
W (7247) main: Color values - Red: 396, Green: 1240, Blue: 308, Clear: 1968, Color: Green
W (7347) main: Color values - Red: 344, Green: 1064, Blue: 260, Clear: 1700, Color: Green
W (7447) main: Color values - Red: 304, Green: 916, Blue: 224, Clear: 1464, Color: Green
W (7547) main: Color values - Red: 256, Green: 760, Blue: 184, Clear: 1236, Color: Green
W (7647) main: Color values - Red: 232, Green: 652, Blue: 148, Clear: 1072, Color: Green
W (7747) main: Color values - Red: 220, Green: 556, Blue: 132, Clear: 1952, Color: Green
W (7847) main: Color values - Red: 264, Green: 776, Blue: 188, Clear: 2560, Color: Green
W (7947) main: Color values - Red: 332, Green: 1048, Blue: 256, Clear: 1664, Color: Green
W (8047) main: Color values - Red: 408, Green: 1280, Blue: 312, Clear: 2020, Color: Green
W (8147) main: Color values - Red: 440, Green: 1384, Blue: 324, Clear: 2164, Color: Green
W (8247) main: Color values - Red: 436, Green: 1368, Blue: 336, Clear: 2164, Color: Green
W (8347) main: Color values - Red: 440, Green: 1380, Blue: 332, Clear: 2164, Color: Green
W (8447) main: Color values - Red: 432, Green: 1364, Blue: 332, Clear: 2152, Color: Green
W (8547) main: Color values - Red: 436, Green: 1372, Blue: 328, Clear: 2140, Color: Green
W (8647) main: Color values - Red: 432, Green: 1364, Blue: 336, Clear: 2140, Color: Green
W (8747) main: Color values - Red: 432, Green: 1388, Blue: 332, Clear: 2176, Color: Green
W (8847) main: Color values - Red: 436, Green: 1390, Blue: 340, Clear: 2168, Color: Green
W (8947) main: Color values - Red: 444, Green: 1376, Blue: 310, Clear: 2044, Color: Green
W (9047) main: Color values - Red: 428, Green: 1368, Blue: 328, Clear: 2140, Color: Green
W (9147) main: Color values - Red: 432, Green: 1348, Blue: 320, Clear: 2120, Color: Green
W (9247) main: Color values - Red: 432, Green: 1376, Blue: 324, Clear: 2156, Color: Green
W (9347) main: Color values - Red: 388, Green: 1232, Blue: 288, Clear: 1916, Color: Green
W (9447) main: Color values - Red: 432, Green: 1380, Blue: 332, Clear: 2156, Color: Green
W (9547) main: Color values - Red: 436, Green: 1360, Blue: 328, Clear: 2140, Color: Green
W (9647) main: Color values - Red: 360, Green: 1252, Blue: 300, Clear: 1908, Color: Green
W (9747) main: Color values - Red: 432, Green: 1396, Blue: 332, Clear: 2168, Color: Green
W (9847) main: Color values - Red: 432, Green: 1376, Blue: 332, Clear: 2144, Color: Green
W (9947) main: Color values - Red: 432, Green: 1384, Blue: 324, Clear: 2168, Color: Green
W (10047) main: Color values - Red: 432, Green: 1364, Blue: 320, Clear: 2136, Color: Green
W (10147) main: Color values - Red: 436, Green: 1376, Blue: 336, Clear: 2160, Color: Green
W (10247) main: Color values - Red: 432, Green: 1372, Blue: 328, Clear: 2136, Color: Green
W (10347) main: Color values - Red: 384, Green: 1216, Blue: 278, Clear: 1788, Color: Green
W (10447) main: Color values - Red: 428, Green: 1348, Blue: 324, Clear: 2088, Color: Green
W (10547) main: Color values - Red: 428, Green: 1364, Blue: 318, Clear: 1956, Color: Green
W (10647) main: Color values - Red: 424, Green: 1352, Blue: 328, Clear: 2132, Color: Green
W (10747) main: Color values - Red: 440, Green: 1462, Blue: 344, Clear: 2188, Color: Green
W (10847) main: Color values - Red: 428, Green: 1376, Blue: 320, Clear: 2168, Color: Green
W (10947) main: Color values - Red: 436, Green: 1228, Blue: 324, Clear: 2156, Color: Green
W (11047) main: Color values - Red: 440, Green: 1376, Blue: 324, Clear: 2116, Color: Green
W (11147) main: Color values - Red: 424, Green: 1372, Blue: 318, Clear: 2148, Color: Green
W (11247) main: Color values - Red: 424, Green: 1364, Blue: 312, Clear: 2148, Color: Green
W (11347) main: Color values - Red: 428, Green: 1352, Blue: 324, Clear: 2156, Color: Green
W (11447) main: Color values - Red: 436, Green: 1376, Blue: 332, Clear: 2172, Color: Green
W (11547) main: Color values - Red: 440, Green: 1380, Blue: 332, Clear: 2188, Color: Green
W (11647) main: Color values - Red: 448, Green: 1410, Blue: 344, Clear: 2196, Color: Green
W (11747) main: Color values - Red: 456, Green: 1432, Blue: 336, Clear: 2220, Color: Green
W (11847) main: Color values - Red: 444, Green: 1392, Blue: 332, Clear: 2212, Color: Green
W (11947) main: Color values - Red: 456, Green: 1420, Blue: 340, Clear: 2236, Color: Green
W (12047) main: Color values - Red: 448, Green: 1432, Blue: 344, Clear: 2232, Color: Green
W (12147) main: Color values - Red: 456, Green: 1448, Blue: 348, Clear: 2236, Color: Green
W (12247) main: Color values - Red: 460, Green: 1460, Blue: 344, Clear: 2264, Color: Green
W (12347) main: Color values - Red: 452, Green: 1424, Blue: 340, Clear: 2244, Color: Green
W (12447) main: Color values - Red: 448, Green: 1424, Blue: 340, Clear: 2196, Color: Green
W (12547) main: Color values - Red: 436, Green: 1372, Blue: 328, Clear: 2140, Color: Green
W (12647) main: Color values - Red: 372, Green: 1132, Blue: 264, Clear: 1716, Color: Green
W (12747) main: Color values - Red: 392, Green: 1188, Blue: 292, Clear: 1836, Color: Green
W (12847) main: Color values - Red: 420, Green: 1304, Blue: 320, Clear: 2028, Color: Green
W (12947) main: Color values - Red: 428, Green: 1368, Blue: 332, Clear: 2140, Color: Green
W (13047) main: Color values - Red: 436, Green: 1364, Blue: 328, Clear: 2152, Color: Green
W (13147) main: Color values - Red: 428, Green: 1376, Blue: 332, Clear: 2144, Color: Green
W (13247) main: Color values - Red: 440, Green: 1392, Blue: 328, Clear: 2156, Color: Green
W (13347) main: Color values - Red: 436, Green: 1376, Blue: 340, Clear: 2168, Color: Green
W (13447) main: Color values - Red: 432, Green: 1368, Blue: 320, Clear: 2160, Color: Green
W (13547) main: Color values - Red: 428, Green: 1360, Blue: 324, Clear: 2140, Color: Green
W (13647) main: Color values - Red: 432, Green: 1368, Blue: 328, Clear: 2132, Color: Green
W (13747) main: Color values - Red: 428, Green: 1376, Blue: 320, Clear: 2132, Color: Green
W (13847) main: Color values - Red: 440, Green: 1400, Blue: 336, Clear: 2184, Color: Green
W (13947) main: Color values - Red: 440, Green: 1388, Blue: 340, Clear: 2204, Color: Green
W (14047) main: Color values - Red: 440, Green: 1400, Blue: 332, Clear: 2188, Color: Green
W (14147) main: Color values - Red: 444, Green: 1408, Blue: 336, Clear: 2208, Color: Green
W (14247) main: Color values - Red: 452, Green: 1420, Blue: 336, Clear: 2228, Color: Green
W (14347) main: Color values - Red: 456, Green: 1436, Blue: 340, Clear: 2240, Color: Green
W (14447) main: Color values - Red: 448, Green: 1404, Blue: 340, Clear: 2184, Color: Green
W (14547) main: Color values - Red: 432, Green: 1360, Blue: 324, Clear: 2124, Color: Green
W (14647) main: Color values - Red: 344, Green: 1020, Blue: 240, Clear: 1604, Color: Green
W (14747) main: Color values - Red: 336, Green: 912, Blue: 208, Clear: 1424, Color: Green
W (14847) main: Color values - Red: 328, Green: 880, Blue: 216, Clear: 1440, Color: Green
W (14947) main: Color values - Red: 328, Green: 864, Blue: 196, Clear: 1352, Color: Green
W (15047) main: Color values - Red: 342, Green: 1000, Blue: 236, Clear: 1548, Color: Green
W (15147) main: Color values - Red: 440, Green: 1372, Blue: 328, Clear: 2148, Color: Green
W (15247) main: Color values - Red: 444, Green: 1416, Blue: 340, Clear: 2200, Color: Green
W (15347) main: Color values - Red: 448, Green: 1410, Blue: 344, Clear: 2192, Color: Green
W (15447) main: Color values - Red: 368, Green: 1152, Blue: 280, Clear: 1864, Color: Green
W (15547) main: Color values - Red: 336, Green: 1036, Blue: 244, Clear: 1644, Color: Green
W (15647) main: Color values - Red: 360, Green: 1140, Blue: 272, Clear: 1764, Color: Green
W (15747) main: Color values - Red: 440, Green: 1384, Blue: 320, Clear: 2164, Color: Green
W (15847) main: Color values - Red: 448, Green: 1416, Blue: 340, Clear: 2204, Color: Green
W (15947) main: Color values - Red: 440, Green: 1396, Blue: 332, Clear: 2204, Color: Green
W (16047) main: Color values - Red: 444, Green: 1392, Blue: 336, Clear: 2192, Color: Green
W (16147) main: Color values - Red: 440, Green: 1384, Blue: 324, Clear: 2168, Color: Green
W (16247) main: Color values - Red: 444, Green: 1376, Blue: 332, Clear: 2164, Color: Green
W (16347) main: Color values - Red: 436, Green: 1376, Blue: 324, Clear: 2160, Color: Green
W (16447) main: Color values - Red: 428, Green: 1364, Blue: 324, Clear: 2120, Color: Green
W (16547) main: Color values - Red: 436, Green: 1372, Blue: 336, Clear: 2156, Color: Green
W (16647) main: Color values - Red: 436, Green: 1376, Blue: 324, Clear: 2144, Color: Green
W (16747) main: Color values - Red: 432, Green: 1352, Blue: 320, Clear: 2140, Color: Green
W (16847) main: Color values - Red: 424, Green: 1356, Blue: 322, Clear: 2104, Color: Green
W (16947) main: Color values - Red: 432, Green: 1368, Blue: 278, Clear: 2188, Color: Green
W (17047) main: Color values - Red: 424, Green: 1344, Blue: 316, Clear: 2084, Color: Green
W (17147) main: Color values - Red: 432, Green: 1372, Blue: 328, Clear: 2104, Color: Green
W (17247) main: Color values - Red: 424, Green: 1340, Blue: 316, Clear: 2100, Color: Green
W (17347) main: Color values - Red: 432, Green: 1372, Blue: 328, Clear: 2180, Color: Green
W (17447) main: Color values - Red: 436, Green: 1312, Blue: 324, Clear: 2160, Color: Green
W (17547) main: Color values - Red: 416, Green: 1340, Blue: 316, Clear: 2096, Color: Green
W (17647) main: Color values - Red: 416, Green: 1316, Blue: 304, Clear: 2060, Color: Green
W (17747) main: Color values - Red: 428, Green: 1368, Blue: 328, Clear: 2072, Color: Green
W (17847) main: Color values - Red: 412, Green: 1320, Blue: 312, Clear: 2076, Color: Green
W (17947) main: Color values - Red: 416, Green: 1316, Blue: 302, Clear: 2068, Color: Green
W (18047) main: Color values - Red: 424, Green: 1352, Blue: 284, Clear: 2120, Color: Green
W (18147) main: Color values - Red: 416, Green: 1336, Blue: 320, Clear: 2088, Color: Green
W (18247) main: Color values - Red: 404, Green: 1316, Blue: 312, Clear: 1772, Color: Green
W (18347) main: Color values - Red: 416, Green: 1320, Blue: 320, Clear: 2072, Color: Green
W (18447) main: Color values - Red: 436, Green: 1380, Blue: 328, Clear: 2136, Color: Green
W (18547) main: Color values - Red: 432, Green: 1372, Blue: 322, Clear: 2152, Color: Green
W (18647) main: Color values - Red: 440, Green: 1372, Blue: 328, Clear: 2152, Color: Green
W (18747) main: Color values - Red: 436, Green: 1364, Blue: 332, Clear: 2152, Color: Green
W (18847) main: Color values - Red: 432, Green: 1376, Blue: 328, Clear: 2148, Color: Green
W (18947) main: Color values - Red: 432, Green: 1372, Blue: 332, Clear: 2144, Color: Green
W (19047) main: Color values - Red: 432, Green: 1372, Blue: 336, Clear: 2148, Color: Green
W (19147) main: Color values - Red: 436, Green: 1332, Blue: 324, Clear: 2148, Color: Green
W (19247) main: Color values - Red: 428, Green: 1368, Blue: 332, Clear: 2140, Color: Green
W (19347) main: Color values - Red: 436, Green: 1364, Blue: 328, Clear: 2148, Color: Green
W (19447) main: Color values - Red: 432, Green: 1372, Blue: 332, Clear: 2148, Color: Green
W (19547) main: Color values - Red: 428, Green: 1376, Blue: 332, Clear: 2132, Color: Green
W (19647) main: Color values - Red: 432, Green: 1372, Blue: 324, Clear: 2148, Color: Green
W (19747) main: Color values - Red: 440, Green: 1368, Blue: 332, Clear: 2140, Color: Green
W (19847) main: Color values - Red: 432, Green: 1372, Blue: 324, Clear: 2156, Color: Green
W (19947) main: Color values - Red: 428, Green: 1368, Blue: 336, Clear: 2148, Color: Green
W (647) main: Color values - Red: 484, Green: 720, Blue: 188, Clear: 1596, Color: Red
W (747) main: Color values - Red: 480, Green: 716, Blue: 192, Clear: 1600, Color: Red
W (847) main: Color values - Red: 488, Green: 728, Blue: 192, Clear: 1604, Color: Red
W (947) main: Color values - Red: 484, Green: 716, Blue: 188, Clear: 1608, Color: Red
W (1047) main: Color values - Red: 488, Green: 724, Blue: 184, Clear: 1608, Color: Red
W (1147) main: Color values - Red: 488, Green: 728, Blue: 188, Clear: 1600, Color: Red
W (1247) main: Color values - Red: 488, Green: 732, Blue: 188, Clear: 1604, Color: Red
W (1347) main: Color values - Red: 488, Green: 720, Blue: 192, Clear: 1608, Color: Red
W (1447) main: Color values - Red: 488, Green: 724, Blue: 192, Clear: 1604, Color: Red
W (1547) main: Color values - Red: 488, Green: 724, Blue: 184, Clear: 1600, Color: Red
W (1647) main: Color values - Red: 484, Green: 716, Blue: 188, Clear: 1604, Color: Red
W (1747) main: Color values - Red: 480, Green: 728, Blue: 182, Clear: 1596, Color: Red
W (1847) main: Color values - Red: 484, Green: 732, Blue: 188, Clear: 1608, Color: Red
W (1947) main: Color values - Red: 480, Green: 728, Blue: 184, Clear: 1596, Color: Red
W (2047) main: Color values - Red: 488, Green: 724, Blue: 184, Clear: 1596, Color: Red
W (2147) main: Color values - Red: 488, Green: 724, Blue: 192, Clear: 1600, Color: Red
W (2247) main: Color values - Red: 484, Green: 720, Blue: 188, Clear: 1604, Color: Red
W (2347) main: Color values - Red: 484, Green: 724, Blue: 188, Clear: 1600, Color: Red
W (2447) main: Color values - Red: 480, Green: 724, Blue: 196, Clear: 1608, Color: Red
W (2547) main: Color values - Red: 484, Green: 716, Blue: 188, Clear: 1600, Color: Red
W (2647) main: Color values - Red: 488, Green: 724, Blue: 188, Clear: 1604, Color: Red
W (2747) main: Color values - Red: 488, Green: 720, Blue: 192, Clear: 1596, Color: Red
W (2847) main: Color values - Red: 488, Green: 720, Blue: 188, Clear: 1600, Color: Red
W (2947) main: Color values - Red: 488, Green: 716, Blue: 188, Clear: 1604, Color: Red
W (3047) main: Color values - Red: 488, Green: 716, Blue: 192, Clear: 1600, Color: Red
W (3147) main: Color values - Red: 488, Green: 724, Blue: 184, Clear: 1604, Color: Red
W (3247) main: Color values - Red: 484, Green: 724, Blue: 188, Clear: 1600, Color: Red
W (3347) main: Color values - Red: 488, Green: 724, Blue: 184, Clear: 1604, Color: Red
W (3447) main: Color values - Red: 488, Green: 724, Blue: 184, Clear: 1608, Color: Red
W (3547) main: Color values - Red: 484, Green: 724, Blue: 196, Clear: 1612, Color: Red
W (3647) main: Color values - Red: 488, Green: 712, Blue: 192, Clear: 1596, Color: Red
W (3747) main: Color values - Red: 480, Green: 716, Blue: 192, Clear: 1604, Color: Red
W (3847) main: Color values - Red: 480, Green: 716, Blue: 188, Clear: 1604, Color: Red
W (3947) main: Color values - Red: 484, Green: 720, Blue: 184, Clear: 1600, Color: Red
W (4047) main: Color values - Red: 490, Green: 728, Blue: 192, Clear: 1592, Color: Red
W (4147) main: Color values - Red: 492, Green: 724, Blue: 192, Clear: 1604, Color: Red
W (4247) main: Color values - Red: 484, Green: 720, Blue: 188, Clear: 1600, Color: Red
W (4347) main: Color values - Red: 480, Green: 720, Blue: 188, Clear: 1596, Color: Red
W (4447) main: Color values - Red: 480, Green: 720, Blue: 192, Clear: 1604, Color: Red
W (4547) main: Color values - Red: 488, Green: 728, Blue: 188, Clear: 1604, Color: Red
W (4647) main: Color values - Red: 488, Green: 724, Blue: 180, Clear: 1600, Color: Red
W (4747) main: Color values - Red: 484, Green: 720, Blue: 184, Clear: 1600, Color: Red
W (4847) main: Color values - Red: 488, Green: 720, Blue: 188, Clear: 1604, Color: Red
W (4947) main: Color values - Red: 488, Green: 724, Blue: 182, Clear: 1604, Color: Red
W (5047) main: Color values - Red: 480, Green: 720, Blue: 180, Clear: 1580, Color: Red
W (5147) main: Color values - Red: 492, Green: 764, Blue: 200, Clear: 1616, Color: Red
W (5247) main: Color values - Red: 452, Green: 684, Blue: 168, Clear: 1432, Color: Red
W (5347) main: Color values - Red: 480, Green: 724, Blue: 180, Clear: 1592, Color: Red
W (5447) main: Color values - Red: 476, Green: 708, Blue: 188, Clear: 1548, Color: Red
W (5547) main: Color values - Red: 472, Green: 716, Blue: 192, Clear: 1576, Color: Red
W (5647) main: Color values - Red: 476, Green: 716, Blue: 184, Clear: 1580, Color: Red
W (5747) main: Color values - Red: 480, Green: 716, Blue: 184, Clear: 1564, Color: Red
W (5847) main: Color values - Red: 488, Green: 728, Blue: 188, Clear: 1612, Color: Red
W (5947) main: Color values - Red: 488, Green: 740, Blue: 192, Clear: 1604, Color: Red
W (6047) main: Color values - Red: 492, Green: 732, Blue: 196, Clear: 1632, Color: Red
W (6147) main: Color values - Red: 484, Green: 740, Blue: 188, Clear: 1588, Color: Red
W (6247) main: Color values - Red: 488, Green: 736, Blue: 192, Clear: 1628, Color: Red
W (6347) main: Color values - Red: 496, Green: 732, Blue: 192, Clear: 1592, Color: Red
W (6447) main: Color values - Red: 488, Green: 732, Blue: 196, Clear: 1604, Color: Red
W (6547) main: Color values - Red: 460, Green: 688, Blue: 180, Clear: 1516, Color: Red
W (6647) main: Color values - Red: 484, Green: 716, Blue: 200, Clear: 1596, Color: Red
W (6747) main: Color values - Red: 452, Green: 668, Blue: 180, Clear: 1472, Color: Red
W (6847) main: Color values - Red: 484, Green: 724, Blue: 188, Clear: 1584, Color: Red
W (6947) main: Color values - Red: 476, Green: 712, Blue: 180, Clear: 1588, Color: Red
W (7047) main: Color values - Red: 492, Green: 732, Blue: 188, Clear: 1588, Color: Red
W (7147) main: Color values - Red: 488, Green: 728, Blue: 188, Clear: 1600, Color: Red
W (7247) main: Color values - Red: 488, Green: 728, Blue: 188, Clear: 1596, Color: Red
W (7347) main: Color values - Red: 488, Green: 740, Blue: 188, Clear: 1612, Color: Red
W (7447) main: Color values - Red: 480, Green: 724, Blue: 184, Clear: 1604, Color: Red
W (7547) main: Color values - Red: 484, Green: 736, Blue: 192, Clear: 1612, Color: Red
W (7647) main: Color values - Red: 488, Green: 728, Blue: 184, Clear: 1612, Color: Red
W (7747) main: Color values - Red: 484, Green: 724, Blue: 188, Clear: 1612, Color: Red
W (7847) main: Color values - Red: 480, Green: 716, Blue: 184, Clear: 1556, Color: Red
W (7947) main: Color values - Red: 464, Green: 696, Blue: 180, Clear: 1508, Color: Red
W (8047) main: Color values - Red: 460, Green: 668, Blue: 164, Clear: 1516, Color: Red
W (8147) main: Color values - Red: 488, Green: 726, Blue: 188, Clear: 1620, Color: Red
W (8247) main: Color values - Red: 484, Green: 732, Blue: 188, Clear: 1600, Color: Red
W (8347) main: Color values - Red: 480, Green: 728, Blue: 184, Clear: 1604, Color: Red
W (8447) main: Color values - Red: 488, Green: 736, Blue: 188, Clear: 1612, Color: Red
W (8547) main: Color values - Red: 476, Green: 728, Blue: 200, Clear: 1576, Color: Red
W (8647) main: Color values - Red: 480, Green: 732, Blue: 196, Clear: 1584, Color: Red
W (8747) main: Color values - Red: 480, Green: 736, Blue: 200, Clear: 1604, Color: Red
W (8847) main: Color values - Red: 488, Green: 736, Blue: 200, Clear: 1624, Color: Red
W (8947) main: Color values - Red: 488, Green: 728, Blue: 188, Clear: 1600, Color: Red
W (9047) main: Color values - Red: 488, Green: 736, Blue: 188, Clear: 1608, Color: Red
W (9147) main: Color values - Red: 488, Green: 732, Blue: 184, Clear: 1596, Color: Red
W (9247) main: Color values - Red: 480, Green: 732, Blue: 188, Clear: 1604, Color: Red
W (9347) main: Color values - Red: 484, Green: 724, Blue: 196, Clear: 1612, Color: Red
W (9447) main: Color values - Red: 484, Green: 732, Blue: 192, Clear: 1600, Color: Red
W (9547) main: Color values - Red: 492, Green: 732, Blue: 192, Clear: 1604, Color: Red
W (9647) main: Color values - Red: 486, Green: 740, Blue: 188, Clear: 1628, Color: Red
W (9747) main: Color values - Red: 488, Green: 732, Blue: 188, Clear: 1616, Color: Red
W (9847) main: Color values - Red: 492, Green: 732, Blue: 188, Clear: 1620, Color: Red
W (9947) main: Color values - Red: 488, Green: 732, Blue: 192, Clear: 1620, Color: Red
W (10047) main: Color values - Red: 480, Green: 732, Blue: 192, Clear: 1608, Color: Red
W (10147) main: Color values - Red: 488, Green: 728, Blue: 192, Clear: 1612, Color: Red
W (10247) main: Color values - Red: 492, Green: 728, Blue: 188, Clear: 1616, Color: Red
W (10347) main: Color values - Red: 488, Green: 724, Blue: 192, Clear: 1616, Color: Red
W (10447) main: Color values - Red: 488, Green: 732, Blue: 188, Clear: 1616, Color: Red
W (10547) main: Color values - Red: 484, Green: 728, Blue: 192, Clear: 1608, Color: Red
W (10647) main: Color values - Red: 476, Green: 716, Blue: 188, Clear: 1600, Color: Red
W (10747) main: Color values - Red: 432, Green: 636, Blue: 168, Clear: 1404, Color: Red
W (10847) main: Color values - Red: 476, Green: 708, Blue: 180, Clear: 1540, Color: Red
W (10947) main: Color values - Red: 484, Green: 720, Blue: 188, Clear: 1584, Color: Red
W (11047) main: Color values - Red: 488, Green: 724, Blue: 180, Clear: 1596, Color: Red
W (11147) main: Color values - Red: 456, Green: 688, Blue: 184, Clear: 1484, Color: Red
W (11247) main: Color values - Red: 480, Green: 712, Blue: 184, Clear: 1572, Color: Red
W (11347) main: Color values - Red: 480, Green: 724, Blue: 188, Clear: 1596, Color: Red
W (11447) main: Color values - Red: 484, Green: 728, Blue: 196, Clear: 1608, Color: Red
W (11547) main: Color values - Red: 484, Green: 720, Blue: 196, Clear: 1588, Color: Red
W (11647) main: Color values - Red: 484, Green: 716, Blue: 180, Clear: 1564, Color: Red
W (11747) main: Color values - Red: 484, Green: 736, Blue: 196, Clear: 1604, Color: Red
W (11847) main: Color values - Red: 488, Green: 744, Blue: 196, Clear: 1616, Color: Red
W (11947) main: Color values - Red: 484, Green: 720, Blue: 188, Clear: 1600, Color: Red
W (12047) main: Color values - Red: 492, Green: 730, Blue: 192, Clear: 1620, Color: Red
W (12147) main: Color values - Red: 496, Green: 728, Blue: 196, Clear: 1608, Color: Red
W (12247) main: Color values - Red: 484, Green: 740, Blue: 200, Clear: 1612, Color: Red
W (12347) main: Color values - Red: 484, Green: 736, Blue: 192, Clear: 1608, Color: Red
W (12447) main: Color values - Red: 488, Green: 728, Blue: 192, Clear: 1612, Color: Red
W (12547) main: Color values - Red: 480, Green: 728, Blue: 200, Clear: 1584, Color: Red
W (12647) main: Color values - Red: 472, Green: 712, Blue: 188, Clear: 1548, Color: Red
W (12747) main: Color values - Red: 476, Green: 716, Blue: 192, Clear: 1572, Color: Red
W (12847) main: Color values - Red: 488, Green: 690, Blue: 160, Clear: 1592, Color: Red
W (12947) main: Color values - Red: 500, Green: 748, Blue: 212, Clear: 1704, Color: Red
W (13047) main: Color values - Red: 472, Green: 656, Blue: 156, Clear: 1536, Color: Red
W (13147) main: Color values - Red: 464, Green: 696, Blue: 172, Clear: 1544, Color: Red
W (13247) main: Color values - Red: 472, Green: 692, Blue: 184, Clear: 1552, Color: Red
W (13347) main: Color values - Red: 464, Green: 692, Blue: 176, Clear: 1520, Color: Red
W (13447) main: Color values - Red: 480, Green: 720, Blue: 184, Clear: 1564, Color: Red
W (13547) main: Color values - Red: 484, Green: 736, Blue: 196, Clear: 1612, Color: Red
W (13647) main: Color values - Red: 486, Green: 732, Blue: 192, Clear: 1616, Color: Red
W (13747) main: Color values - Red: 488, Green: 736, Blue: 188, Clear: 1628, Color: Red
W (13847) main: Color values - Red: 492, Green: 732, Blue: 196, Clear: 1632, Color: Red
W (13947) main: Color values - Red: 492, Green: 736, Blue: 188, Clear: 1624, Color: Red
W (14047) main: Color values - Red: 496, Green: 740, Blue: 192, Clear: 1620, Color: Red
W (14147) main: Color values - Red: 492, Green: 740, Blue: 200, Clear: 1628, Color: Red
W (14247) main: Color values - Red: 496, Green: 740, Blue: 196, Clear: 1620, Color: Red
W (14347) main: Color values - Red: 488, Green: 740, Blue: 196, Clear: 1624, Color: Red
W (14447) main: Color values - Red: 496, Green: 740, Blue: 180, Clear: 1628, Color: Red
W (14547) main: Color values - Red: 492, Green: 744, Blue: 196, Clear: 1628, Color: Red
W (14647) main: Color values - Red: 492, Green: 740, Blue: 192, Clear: 1628, Color: Red
W (14747) main: Color values - Red: 496, Green: 740, Blue: 192, Clear: 1632, Color: Red
W (14847) main: Color values - Red: 492, Green: 744, Blue: 192, Clear: 1624, Color: Red
W (14947) main: Color values - Red: 496, Green: 736, Blue: 188, Clear: 1620, Color: Red
W (15047) main: Color values - Red: 492, Green: 740, Blue: 188, Clear: 1620, Color: Red
W (15147) main: Color values - Red: 492, Green: 740, Blue: 200, Clear: 1620, Color: Red
W (15247) main: Color values - Red: 484, Green: 744, Blue: 196, Clear: 1616, Color: Red
W (15347) main: Color values - Red: 496, Green: 744, Blue: 192, Clear: 1620, Color: Red
W (15447) main: Color values - Red: 484, Green: 744, Blue: 200, Clear: 1628, Color: Red
W (15547) main: Color values - Red: 496, Green: 736, Blue: 192, Clear: 1620, Color: Red
W (15647) main: Color values - Red: 492, Green: 744, Blue: 192, Clear: 1624, Color: Red
W (15747) main: Color values - Red: 488, Green: 732, Blue: 196, Clear: 1632, Color: Red
W (15847) main: Color values - Red: 492, Green: 740, Blue: 188, Clear: 1628, Color: Red
W (15947) main: Color values - Red: 500, Green: 732, Blue: 192, Clear: 1620, Color: Red
W (16047) main: Color values - Red: 496, Green: 736, Blue: 192, Clear: 1632, Color: Red
W (16147) main: Color values - Red: 492, Green: 740, Blue: 192, Clear: 1632, Color: Red
W (16247) main: Color values - Red: 500, Green: 744, Blue: 188, Clear: 1624, Color: Red
W (16347) main: Color values - Red: 488, Green: 744, Blue: 196, Clear: 1624, Color: Red
W (16447) main: Color values - Red: 488, Green: 748, Blue: 196, Clear: 1620, Color: Red
W (647) main: Color values - Red: 224, Green: 448, Blue: 132, Clear: 1780, Color: Black
W (747) main: Color values - Red: 224, Green: 456, Blue: 132, Clear: 1780, Color: Black
W (847) main: Color values - Red: 220, Green: 456, Blue: 124, Clear: 1772, Color: Black
W (947) main: Color values - Red: 216, Green: 460, Blue: 120, Clear: 1788, Color: Black
W (1047) main: Color values - Red: 212, Green: 456, Blue: 128, Clear: 1748, Color: Black
W (1147) main: Color values - Red: 220, Green: 450, Blue: 120, Clear: 1784, Color: Black
W (1247) main: Color values - Red: 216, Green: 456, Blue: 132, Clear: 1772, Color: Black
W (1347) main: Color values - Red: 216, Green: 452, Blue: 132, Clear: 1776, Color: Black
W (1447) main: Color values - Red: 224, Green: 456, Blue: 128, Clear: 1780, Color: Black
W (1547) main: Color values - Red: 216, Green: 460, Blue: 128, Clear: 1772, Color: Black
W (1647) main: Color values - Red: 224, Green: 456, Blue: 136, Clear: 1780, Color: Black
W (1747) main: Color values - Red: 212, Green: 456, Blue: 128, Clear: 1776, Color: Black
W (1847) main: Color values - Red: 224, Green: 456, Blue: 124, Clear: 1760, Color: Black
W (1947) main: Color values - Red: 224, Green: 460, Blue: 124, Clear: 1764, Color: Black
W (2047) main: Color values - Red: 216, Green: 452, Blue: 128, Clear: 1780, Color: Black
W (2147) main: Color values - Red: 220, Green: 456, Blue: 132, Clear: 1772, Color: Black
W (2247) main: Color values - Red: 216, Green: 456, Blue: 124, Clear: 1772, Color: Black
W (2347) main: Color values - Red: 220, Green: 456, Blue: 124, Clear: 1764, Color: Black
W (2447) main: Color values - Red: 224, Green: 464, Blue: 124, Clear: 1766, Color: Black
W (2547) main: Color values - Red: 220, Green: 460, Blue: 132, Clear: 1776, Color: Black
W (2647) main: Color values - Red: 216, Green: 456, Blue: 136, Clear: 1760, Color: Black
W (2747) main: Color values - Red: 224, Green: 464, Blue: 128, Clear: 1780, Color: Black
W (2847) main: Color values - Red: 224, Green: 464, Blue: 132, Clear: 1784, Color: Black
W (2947) main: Color values - Red: 224, Green: 456, Blue: 128, Clear: 1752, Color: Black
W (3047) main: Color values - Red: 220, Green: 460, Blue: 128, Clear: 1796, Color: Black
W (3147) main: Color values - Red: 216, Green: 464, Blue: 136, Clear: 1776, Color: Black
W (3247) main: Color values - Red: 220, Green: 472, Blue: 132, Clear: 1828, Color: Black
W (3347) main: Color values - Red: 224, Green: 460, Blue: 128, Clear: 1784, Color: Black
W (3447) main: Color values - Red: 220, Green: 464, Blue: 124, Clear: 1776, Color: Black
W (3547) main: Color values - Red: 220, Green: 456, Blue: 130, Clear: 1762, Color: Black
W (3647) main: Color values - Red: 216, Green: 456, Blue: 124, Clear: 1768, Color: Black
W (3747) main: Color values - Red: 216, Green: 460, Blue: 120, Clear: 1752, Color: Black
W (3847) main: Color values - Red: 214, Green: 456, Blue: 124, Clear: 1764, Color: Black
W (3947) main: Color values - Red: 228, Green: 464, Blue: 132, Clear: 1796, Color: Black
W (4047) main: Color values - Red: 220, Green: 468, Blue: 132, Clear: 1796, Color: Black
W (4147) main: Color values - Red: 220, Green: 456, Blue: 128, Clear: 1760, Color: Black
W (4247) main: Color values - Red: 224, Green: 452, Blue: 124, Clear: 1756, Color: Black
W (4347) main: Color values - Red: 224, Green: 464, Blue: 128, Clear: 1780, Color: Black
W (4447) main: Color values - Red: 216, Green: 460, Blue: 132, Clear: 1772, Color: Black
W (4547) main: Color values - Red: 212, Green: 460, Blue: 124, Clear: 1756, Color: Black
W (4647) main: Color values - Red: 224, Green: 460, Blue: 124, Clear: 1776, Color: Black
W (4747) main: Color values - Red: 216, Green: 464, Blue: 136, Clear: 1792, Color: Black
W (4847) main: Color values - Red: 228, Green: 464, Blue: 132, Clear: 1808, Color: Black
W (4947) main: Color values - Red: 228, Green: 472, Blue: 140, Clear: 1828, Color: Black
W (5047) main: Color values - Red: 228, Green: 476, Blue: 124, Clear: 1788, Color: Black
W (5147) main: Color values - Red: 224, Green: 452, Blue: 128, Clear: 1772, Color: Black
W (5247) main: Color values - Red: 224, Green: 456, Blue: 128, Clear: 1768, Color: Black
W (5347) main: Color values - Red: 224, Green: 464, Blue: 136, Clear: 1794, Color: Black
W (5447) main: Color values - Red: 216, Green: 460, Blue: 128, Clear: 1776, Color: Black
W (5547) main: Color values - Red: 228, Green: 472, Blue: 132, Clear: 1792, Color: Black
W (5647) main: Color values - Red: 216, Green: 464, Blue: 124, Clear: 1784, Color: Black
W (5747) main: Color values - Red: 232, Green: 464, Blue: 132, Clear: 1784, Color: Black
W (5847) main: Color values - Red: 214, Green: 460, Blue: 128, Clear: 1768, Color: Black
W (5947) main: Color values - Red: 220, Green: 464, Blue: 128, Clear: 1804, Color: Black
W (6047) main: Color values - Red: 224, Green: 460, Blue: 128, Clear: 1772, Color: Black
W (6147) main: Color values - Red: 220, Green: 468, Blue: 128, Clear: 1788, Color: Black
W (6247) main: Color values - Red: 220, Green: 460, Blue: 132, Clear: 1792, Color: Black
W (6347) main: Color values - Red: 216, Green: 456, Blue: 124, Clear: 1742, Color: Black
W (6447) main: Color values - Red: 216, Green: 456, Blue: 120, Clear: 1768, Color: Black
W (6547) main: Color values - Red: 220, Green: 448, Blue: 124, Clear: 1776, Color: Black
W (6647) main: Color values - Red: 212, Green: 448, Blue: 124, Clear: 1756, Color: Black
W (6747) main: Color values - Red: 216, Green: 456, Blue: 124, Clear: 1748, Color: Black
W (6847) main: Color values - Red: 220, Green: 476, Blue: 136, Clear: 1784, Color: Black
W (6947) main: Color values - Red: 220, Green: 460, Blue: 128, Clear: 1792, Color: Black
W (7047) main: Color values - Red: 228, Green: 460, Blue: 124, Clear: 1792, Color: Black
W (7147) main: Color values - Red: 220, Green: 468, Blue: 132, Clear: 1804, Color: Black
W (7247) main: Color values - Red: 224, Green: 464, Blue: 136, Clear: 1820, Color: Black
W (7347) main: Color values - Red: 228, Green: 472, Blue: 132, Clear: 1804, Color: Black
W (7447) main: Color values - Red: 228, Green: 472, Blue: 132, Clear: 1804, Color: Black
W (7547) main: Color values - Red: 224, Green: 472, Blue: 132, Clear: 1796, Color: Black
W (7647) main: Color values - Red: 220, Green: 472, Blue: 128, Clear: 1794, Color: Black
W (7747) main: Color values - Red: 216, Green: 468, Blue: 132, Clear: 1804, Color: Black
W (7847) main: Color values - Red: 228, Green: 468, Blue: 132, Clear: 1804, Color: Black
W (7947) main: Color values - Red: 228, Green: 468, Blue: 132, Clear: 1808, Color: Black
W (8047) main: Color values - Red: 220, Green: 468, Blue: 136, Clear: 1812, Color: Black
W (8147) main: Color values - Red: 220, Green: 472, Blue: 132, Clear: 1800, Color: Black
W (8247) main: Color values - Red: 224, Green: 472, Blue: 124, Clear: 1792, Color: Black
W (8347) main: Color values - Red: 220, Green: 468, Blue: 124, Clear: 1804, Color: Black
W (8447) main: Color values - Red: 220, Green: 464, Blue: 132, Clear: 1796, Color: Black
W (8547) main: Color values - Red: 224, Green: 464, Blue: 128, Clear: 1796, Color: Black
W (8647) main: Color values - Red: 224, Green: 468, Blue: 136, Clear: 1800, Color: Black
W (8747) main: Color values - Red: 220, Green: 468, Blue: 132, Clear: 1808, Color: Black
W (8847) main: Color values - Red: 216, Green: 464, Blue: 128, Clear: 1804, Color: Black
W (8947) main: Color values - Red: 220, Green: 464, Blue: 132, Clear: 1800, Color: Black
W (9047) main: Color values - Red: 224, Green: 468, Blue: 132, Clear: 1804, Color: Black
W (9147) main: Color values - Red: 224, Green: 464, Blue: 128, Clear: 1768, Color: Black
W (9247) main: Color values - Red: 228, Green: 464, Blue: 128, Clear: 1804, Color: Black
W (9347) main: Color values - Red: 228, Green: 476, Blue: 132, Clear: 1812, Color: Black
W (9447) main: Color values - Red: 224, Green: 476, Blue: 136, Clear: 1804, Color: Black
W (9547) main: Color values - Red: 220, Green: 464, Blue: 136, Clear: 1800, Color: Black
W (9647) main: Color values - Red: 228, Green: 468, Blue: 128, Clear: 1808, Color: Black
W (9747) main: Color values - Red: 232, Green: 472, Blue: 124, Clear: 1804, Color: Black
W (9847) main: Color values - Red: 220, Green: 472, Blue: 124, Clear: 1780, Color: Black
W (647) main: Color values - Red: 1842, Green: 1100, Blue: 1782, Clear: 1016, Color: White
W (747) main: Color values - Red: 1838, Green: 1088, Blue: 1762, Clear: 2008, Color: White
W (847) main: Color values - Red: 1836, Green: 1088, Blue: 1758, Clear: 2012, Color: White
W (947) main: Color values - Red: 1832, Green: 1088, Blue: 1772, Clear: 2016, Color: White
W (1047) main: Color values - Red: 1828, Green: 1084, Blue: 1766, Clear: 2020, Color: White
W (1147) main: Color values - Red: 1828, Green: 1088, Blue: 1766, Clear: 2020, Color: White
W (1247) main: Color values - Red: 1832, Green: 1084, Blue: 1770, Clear: 2012, Color: White
W (1347) main: Color values - Red: 1834, Green: 1088, Blue: 1736, Clear: 2016, Color: White
W (1447) main: Color values - Red: 1834, Green: 1084, Blue: 1776, Clear: 2012, Color: White
W (1547) main: Color values - Red: 1832, Green: 1084, Blue: 1762, Clear: 2020, Color: White
W (1647) main: Color values - Red: 1836, Green: 1092, Blue: 1762, Clear: 2016, Color: White
W (1747) main: Color values - Red: 1838, Green: 1084, Blue: 1768, Clear: 2020, Color: White
W (1847) main: Color values - Red: 1830, Green: 1088, Blue: 1760, Clear: 2016, Color: White
W (1947) main: Color values - Red: 1832, Green: 1088, Blue: 1760, Clear: 2016, Color: White
W (2047) main: Color values - Red: 1832, Green: 1088, Blue: 1772, Clear: 2016, Color: White
W (2147) main: Color values - Red: 1830, Green: 1080, Blue: 1736, Clear: 2016, Color: White
W (2247) main: Color values - Red: 1828, Green: 1084, Blue: 1756, Clear: 2016, Color: White
W (2347) main: Color values - Red: 1836, Green: 1088, Blue: 1764, Clear: 2016, Color: White
W (2447) main: Color values - Red: 1830, Green: 1084, Blue: 1776, Clear: 2016, Color: White
W (2547) main: Color values - Red: 1834, Green: 1084, Blue: 1758, Clear: 2016, Color: White
W (2647) main: Color values - Red: 1826, Green: 1084, Blue: 1766, Clear: 2012, Color: White
W (2747) main: Color values - Red: 1834, Green: 1088, Blue: 1756, Clear: 2016, Color: White
W (2847) main: Color values - Red: 1834, Green: 1088, Blue: 1772, Clear: 2016, Color: White
W (2947) main: Color values - Red: 1838, Green: 1084, Blue: 1746, Clear: 2016, Color: White
W (3047) main: Color values - Red: 1824, Green: 1088, Blue: 1768, Clear: 2016, Color: White
W (3147) main: Color values - Red: 1838, Green: 1084, Blue: 1762, Clear: 2020, Color: White
W (3247) main: Color values - Red: 1824, Green: 1092, Blue: 1772, Clear: 2016, Color: White
W (3347) main: Color values - Red: 1832, Green: 1088, Blue: 1728, Clear: 2020, Color: White
W (3447) main: Color values - Red: 1834, Green: 1084, Blue: 1770, Clear: 2016, Color: White
W (3547) main: Color values - Red: 1826, Green: 1084, Blue: 1760, Clear: 2012, Color: White
W (3647) main: Color values - Red: 1830, Green: 1080, Blue: 1736, Clear: 2012, Color: White
W (3747) main: Color values - Red: 1806, Green: 1084, Blue: 1754, Clear: 2000, Color: White
W (3847) main: Color values - Red: 1826, Green: 1088, Blue: 1760, Clear: 2012, Color: White
W (3947) main: Color values - Red: 1834, Green: 1088, Blue: 1758, Clear: 2016, Color: White
W (4047) main: Color values - Red: 1826, Green: 1084, Blue: 1760, Clear: 2020, Color: White
W (4147) main: Color values - Red: 1842, Green: 1092, Blue: 1760, Clear: 2016, Color: White
W (4247) main: Color values - Red: 1826, Green: 1088, Blue: 1756, Clear: 2012, Color: White
W (4347) main: Color values - Red: 1828, Green: 1088, Blue: 1770, Clear: 2016, Color: White
W (4447) main: Color values - Red: 1842, Green: 1088, Blue: 1774, Clear: 2012, Color: White
W (4547) main: Color values - Red: 1820, Green: 1088, Blue: 1764, Clear: 2016, Color: White
W (4647) main: Color values - Red: 1834, Green: 1084, Blue: 1764, Clear: 2016, Color: White
W (4747) main: Color values - Red: 1826, Green: 1088, Blue: 1770, Clear: 2016, Color: White
W (4847) main: Color values - Red: 1830, Green: 1084, Blue: 1768, Clear: 2012, Color: White
W (4947) main: Color values - Red: 1840, Green: 1088, Blue: 1756, Clear: 2020, Color: White
W (5047) main: Color values - Red: 1830, Green: 1088, Blue: 1760, Clear: 2012, Color: White
W (5147) main: Color values - Red: 1828, Green: 1092, Blue: 1760, Clear: 2016, Color: White
W (5247) main: Color values - Red: 1844, Green: 1084, Blue: 1770, Clear: 2016, Color: White
W (5347) main: Color values - Red: 1830, Green: 1084, Blue: 1770, Clear: 2016, Color: White
W (5447) main: Color values - Red: 1830, Green: 1076, Blue: 1734, Clear: 2016, Color: White
W (5547) main: Color values - Red: 1828, Green: 1084, Blue: 1762, Clear: 2016, Color: White
W (5647) main: Color values - Red: 1834, Green: 1088, Blue: 1756, Clear: 2016, Color: White
W (5747) main: Color values - Red: 1714, Green: 2044, Blue: 1650, Clear: 1856, Color: White
W (5847) main: Color values - Red: 1826, Green: 2196, Blue: 1766, Clear: 2016, Color: White
W (5947) main: Color values - Red: 1864, Green: 2224, Blue: 1788, Clear: 2044, Color: White
W (6047) main: Color values - Red: 1868, Green: 2252, Blue: 1806, Clear: 2064, Color: White
W (6147) main: Color values - Red: 1906, Green: 2288, Blue: 1838, Clear: 2100, Color: White
W (6247) main: Color values - Red: 1844, Green: 2208, Blue: 1778, Clear: 2032, Color: White
W (6347) main: Color values - Red: 1852, Green: 2220, Blue: 1782, Clear: 2040, Color: White
W (6447) main: Color values - Red: 1932, Green: 2324, Blue: 1846, Clear: 2132, Color: White
W (6547) main: Color values - Red: 1986, Green: 2384, Blue: 1896, Clear: 2192, Color: White
W (6647) main: Color values - Red: 2076, Green: 2476, Blue: 1932, Clear: 2276, Color: White
W (6747) main: Color values - Red: 2070, Green: 2468, Blue: 1964, Clear: 2272, Color: White
W (6847) main: Color values - Red: 2046, Green: 2432, Blue: 1938, Clear: 2244, Color: White
W (6947) main: Color values - Red: 2006, Green: 2412, Blue: 1884, Clear: 2212, Color: White
W (7047) main: Color values - Red: 1978, Green: 2350, Blue: 1860, Clear: 2172, Color: White
W (7147) main: Color values - Red: 1948, Green: 2332, Blue: 1852, Clear: 2144, Color: White
W (7247) main: Color values - Red: 1914, Green: 2296, Blue: 1830, Clear: 2112, Color: White
W (7347) main: Color values - Red: 1966, Green: 2356, Blue: 1858, Clear: 2156, Color: White
W (7447) main: Color values - Red: 2094, Green: 2492, Blue: 1936, Clear: 2280, Color: White
W (7547) main: Color values - Red: 2246, Green: 2668, Blue: 2070, Clear: 2456, Color: White
W (7647) main: Color values - Red: 2270, Green: 2700, Blue: 2102, Clear: 2496, Color: White
W (7747) main: Color values - Red: 2302, Green: 2728, Blue: 2128, Clear: 2524, Color: White
W (7847) main: Color values - Red: 2288, Green: 2712, Blue: 2118, Clear: 2520, Color: White
W (7947) main: Color values - Red: 2288, Green: 2710, Blue: 2120, Clear: 2516, Color: White
W (8047) main: Color values - Red: 2300, Green: 2712, Blue: 2102, Clear: 2516, Color: White
W (8147) main: Color values - Red: 2250, Green: 2648, Blue: 2060, Clear: 2444, Color: White
W (8247) main: Color values - Red: 2084, Green: 2468, Blue: 1932, Clear: 2260, Color: White
W (8347) main: Color values - Red: 1918, Green: 2292, Blue: 1822, Clear: 2092, Color: White
W (8447) main: Color values - Red: 1836, Green: 2188, Blue: 1754, Clear: 2008, Color: White
W (8547) main: Color values - Red: 1826, Green: 2192, Blue: 1766, Clear: 2012, Color: White
W (8647) main: Color values - Red: 1972, Green: 2404, Blue: 1894, Clear: 2204, Color: White
W (8747) main: Color values - Red: 2136, Green: 2548, Blue: 1992, Clear: 2356, Color: White
W (8847) main: Color values - Red: 2114, Green: 2548, Blue: 1970, Clear: 2352, Color: White
W (8947) main: Color values - Red: 2170, Green: 2596, Blue: 2036, Clear: 2388, Color: White
W (9047) main: Color values - Red: 2210, Green: 2620, Blue: 2072, Clear: 2420, Color: White
W (9147) main: Color values - Red: 2154, Green: 2572, Blue: 2032, Clear: 2384, Color: White
W (9247) main: Color values - Red: 2186, Green: 2604, Blue: 2062, Clear: 2412, Color: White
W (9347) main: Color values - Red: 2252, Green: 2664, Blue: 2086, Clear: 2480, Color: White
W (9447) main: Color values - Red: 2138, Green: 2556, Blue: 2016, Clear: 2356, Color: White
W (9547) main: Color values - Red: 1910, Green: 2272, Blue: 1822, Clear: 2096, Color: White
W (9647) main: Color values - Red: 1886, Green: 2252, Blue: 1802, Clear: 2068, Color: White
W (9747) main: Color values - Red: 1924, Green: 2304, Blue: 1826, Clear: 2104, Color: White
W (9847) main: Color values - Red: 2038, Green: 2440, Blue: 1912, Clear: 2232, Color: White
W (9947) main: Color values - Red: 2076, Green: 2468, Blue: 1900, Clear: 2264, Color: White
W (10047) main: Color values - Red: 2058, Green: 2452, Blue: 1892, Clear: 2244, Color: White
W (10147) main: Color values - Red: 1998, Green: 2376, Blue: 1878, Clear: 2176, Color: White
W (10247) main: Color values - Red: 1914, Green: 2296, Blue: 1828, Clear: 2100, Color: White
W (10347) main: Color values - Red: 1818, Green: 2196, Blue: 1758, Clear: 2008, Color: White
W (10447) main: Color values - Red: 1838, Green: 2224, Blue: 1774, Clear: 2036, Color: White
W (10547) main: Color values - Red: 1926, Green: 2316, Blue: 1830, Clear: 2120, Color: White
W (10647) main: Color values - Red: 2148, Green: 2568, Blue: 2000, Clear: 2352, Color: White
W (10747) main: Color values - Red: 2202, Green: 2620, Blue: 2042, Clear: 2416, Color: White
W (10847) main: Color values - Red: 2044, Green: 2456, Blue: 1912, Clear: 2236, Color: White
W (10947) main: Color values - Red: 1732, Green: 2092, Blue: 1694, Clear: 1920, Color: White
W (11047) main: Color values - Red: 1790, Green: 2148, Blue: 1726, Clear: 1972, Color: White
W (11147) main: Color values - Red: 1894, Green: 2256, Blue: 1816, Clear: 2080, Color: White
W (11247) main: Color values - Red: 1924, Green: 2304, Blue: 1812, Clear: 2112, Color: White
W (11347) main: Color values - Red: 1904, Green: 2296, Blue: 1830, Clear: 2108, Color: White
W (11447) main: Color values - Red: 1918, Green: 2300, Blue: 1832, Clear: 2100, Color: White
W (11547) main: Color values - Red: 1886, Green: 2252, Blue: 1808, Clear: 2072, Color: White
W (11647) main: Color values - Red: 1866, Green: 2240, Blue: 1802, Clear: 2064, Color: White
W (11747) main: Color values - Red: 1856, Green: 2220, Blue: 1792, Clear: 2040, Color: White
W (11847) main: Color values - Red: 1766, Green: 2136, Blue: 1732, Clear: 1964, Color: White
W (11947) main: Color values - Red: 1770, Green: 2120, Blue: 1718, Clear: 1944, Color: White
W (12047) main: Color values - Red: 1908, Green: 2288, Blue: 1822, Clear: 2100, Color: White
W (12147) main: Color values - Red: 2042, Green: 2434, Blue: 1924, Clear: 2240, Color: White
W (12247) main: Color values - Red: 2022, Green: 2444, Blue: 1922, Clear: 2244, Color: White
W (12347) main: Color values - Red: 2170, Green: 2584, Blue: 2036, Clear: 2388, Color: White
W (12447) main: Color values - Red: 2244, Green: 2660, Blue: 2072, Clear: 2460, Color: White
W (12547) main: Color values - Red: 2300, Green: 2712, Blue: 2112, Clear: 2516, Color: White
W (12647) main: Color values - Red: 2372, Green: 2792, Blue: 2156, Clear: 2592, Color: White
W (12747) main: Color values - Red: 2388, Green: 2824, Blue: 2176, Clear: 2620, Color: White
W (12847) main: Color values - Red: 2362, Green: 2792, Blue: 2170, Clear: 2588, Color: White
W (12947) main: Color values - Red: 2220, Green: 2632, Blue: 2070, Clear: 2432, Color: White
W (13047) main: Color values - Red: 2156, Green: 2576, Blue: 2012, Clear: 2356, Color: White
W (13147) main: Color values - Red: 2028, Green: 2412, Blue: 1892, Clear: 2212, Color: White
W (13247) main: Color values - Red: 1896, Green: 2280, Blue: 1792, Clear: 2080, Color: White
W (13347) main: Color values - Red: 1876, Green: 2264, Blue: 1810, Clear: 2068, Color: White
W (13447) main: Color values - Red: 2054, Green: 2448, Blue: 1940, Clear: 2264, Color: White
W (13547) main: Color values - Red: 2080, Green: 2478, Blue: 1972, Clear: 2280, Color: White
W (13647) main: Color values - Red: 2086, Green: 2488, Blue: 1976, Clear: 2292, Color: White
W (13747) main: Color values - Red: 2054, Green: 2460, Blue: 1948, Clear: 2268, Color: White
W (13847) main: Color values - Red: 1862, Green: 2232, Blue: 1790, Clear: 2052, Color: White
W (13947) main: Color values - Red: 1874, Green: 2256, Blue: 1828, Clear: 2076, Color: White
W (14047) main: Color values - Red: 1938, Green: 2344, Blue: 1874, Clear: 2152, Color: White
W (14147) main: Color values - Red: 2018, Green: 2416, Blue: 1912, Clear: 2220, Color: White
W (14247) main: Color values - Red: 1872, Green: 2240, Blue: 1816, Clear: 2076, Color: White
W (14347) main: Color values - Red: 1722, Green: 2056, Blue: 1678, Clear: 1896, Color: White
W (14447) main: Color values - Red: 1708, Green: 2044, Blue: 1668, Clear: 1880, Color: White
W (14547) main: Color values - Red: 1724, Green: 2060, Blue: 1656, Clear: 1892, Color: White
W (14647) main: Color values - Red: 1712, Green: 2068, Blue: 1664, Clear: 1892, Color: White
W (14747) main: Color values - Red: 1732, Green: 2084, Blue: 1672, Clear: 1916, Color: White
W (14847) main: Color values - Red: 1898, Green: 2270, Blue: 1834, Clear: 2100, Color: White
W (14947) main: Color values - Red: 2048, Green: 2444, Blue: 1936, Clear: 2252, Color: White
W (15047) main: Color values - Red: 2014, Green: 2416, Blue: 1908, Clear: 2216, Color: White
W (15147) main: Color values - Red: 1890, Green: 2256, Blue: 1808, Clear: 2080, Color: White
W (15247) main: Color values - Red: 1888, Green: 2264, Blue: 1818, Clear: 2084, Color: White
W (15347) main: Color values - Red: 1878, Green: 2248, Blue: 1786, Clear: 2068, Color: White
W (15447) main: Color values - Red: 1870, Green: 2236, Blue: 1788, Clear: 2060, Color: White
W (15547) main: Color values - Red: 1852, Green: 2236, Blue: 1798, Clear: 2048, Color: White
W (15647) main: Color values - Red: 1856, Green: 2228, Blue: 1798, Clear: 2044, Color: White
W (15747) main: Color values - Red: 1854, Green: 2220, Blue: 1776, Clear: 2040, Color: White
W (15847) main: Color values - Red: 1852, Green: 2208, Blue: 1784, Clear: 2040, Color: White
W (15947) main: Color values - Red: 1838, Green: 2208, Blue: 1748, Clear: 2036, Color: White
W (16047) main: Color values - Red: 1838, Green: 2216, Blue: 1778, Clear: 2032, Color: White
W (16147) main: Color values - Red: 1844, Green: 2192, Blue: 1774, Clear: 2028, Color: White
W (16247) main: Color values - Red: 1844, Green: 2204, Blue: 1762, Clear: 2024, Color: White
W (16347) main: Color values - Red: 1832, Green: 2204, Blue: 1764, Clear: 2028, Color: White
W (16447) main: Color values - Red: 1840, Green: 2204, Blue: 1766, Clear: 2024, Color: White
W (16547) main: Color values - Red: 1838, Green: 2204, Blue: 1764, Clear: 2020, Color: White
W (16647) main: Color values - Red: 1826, Green: 2186, Blue: 1736, Clear: 2020, Color: White
W (16747) main: Color values - Red: 1830, Green: 2204, Blue: 1762, Clear: 2016, Color: White
W (16847) main: Color values - Red: 1834, Green: 2200, Blue: 1762, Clear: 2016, Color: White
W (16947) main: Color values - Red: 1838, Green: 2192, Blue: 1778, Clear: 2016, Color: White
W (17047) main: Color values - Red: 1822, Green: 2192, Blue: 1762, Clear: 2012, Color: White
W (17147) main: Color values - Red: 1822, Green: 2192, Blue: 1752, Clear: 2012, Color: White
W (17247) main: Color values - Red: 1816, Green: 2188, Blue: 1756, Clear: 2008, Color: White
W (17347) main: Color values - Red: 1824, Green: 2180, Blue: 1758, Clear: 2008, Color: White
W (17447) main: Color values - Red: 1822, Green: 2184, Blue: 1762, Clear: 2008, Color: White

99
scripts/controller.py Normal file
View File

@@ -0,0 +1,99 @@
import asyncio
import os
import json
from bleak import BleakClient, BleakScanner
import keyboard
CONFIG_FILE = "ble_device_config.json"
CHARACTERISTIC_UUID = "23408888-1f40-4cd8-9b89-ca8d45f8a5b0" # Replace with your characteristic UUID
async def send_command(client, speedA, speedB, directionA, directionB, duration):
command = bytearray([speedA, speedB, directionA, directionB, duration])
await client.write_gatt_char(CHARACTERISTIC_UUID, command)
async def select_device():
devices = await BleakScanner.discover()
if not devices:
print("No BLE devices found.")
return None
print("Available BLE devices:")
for i, device in enumerate(devices):
print(f"{i}: {device.name} - {device.address}")
while True:
try:
selection = int(input("Select device by number: "))
if 0 <= selection < len(devices):
return devices[selection].address
else:
print("Invalid selection. Please try again.")
except ValueError:
print("Please enter a valid number.")
def load_config():
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
return json.load(f)
return {}
def save_config(config):
with open(CONFIG_FILE, "w") as f:
json.dump(config, f)
async def get_ble_address():
config = load_config()
saved_address = config.get("ble_address")
if saved_address:
print(f"Previously connected to device with address: {saved_address}")
choice = input("Do you want to connect to the same device? (y/n): ").lower()
if choice == 'y':
return saved_address
new_address = await select_device()
if new_address:
config["ble_address"] = new_address
save_config(config)
return new_address
async def handle_key_press(client):
# motor A speed, motor A dir, motor B speed, motor B dir, time 50 == 5.0 seconds
if keyboard.is_pressed('w'):
await send_command(client, 60,1,60,1,5)
print(f"Forward")
elif keyboard.is_pressed('s'):
await send_command(client, 50,0,50,0,5)
print(f"Backwards")
elif keyboard.is_pressed('d'):
await send_command(client, 40,1,40,0,3)
print(f"Right")
elif keyboard.is_pressed('a'):
await send_command(client, 40,0,40,1,3)
print(f"Left")
async def main():
global motor_speed
ble_address = await get_ble_address()
if not ble_address:
print("No device selected. Exiting.")
return
print(f"Connecting to device: {ble_address}")
async with BleakClient(ble_address) as client:
print(f"Connected: {await client.is_connected()}")
print("Press 'w' to speed up, 's' to slow down, or 'q' to quit.")
while True:
await handle_key_press(client)
if keyboard.is_pressed('q'):
print("Quitting...")
break
if __name__ == "__main__":
asyncio.run(main())

BIN
scripts/nn_model.bin Normal file

Binary file not shown.

162
scripts/trainer.py Normal file
View File

@@ -0,0 +1,162 @@
import numpy as np
import re
import struct
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split
class NeuralNetwork:
def __init__(self, input_size, hidden_size1, hidden_size2, output_size):
self.input_size = input_size
self.hidden_size1 = hidden_size1
self.hidden_size2 = hidden_size2
self.output_size = output_size
self.input_weights = np.random.randn(input_size, hidden_size1).astype(np.float32) * np.sqrt(2.0/input_size)
self.hidden_weights1 = np.random.randn(hidden_size1, hidden_size2).astype(np.float32) * np.sqrt(2.0/hidden_size1)
self.hidden_weights2 = np.random.randn(hidden_size2, output_size).astype(np.float32) * np.sqrt(2.0/hidden_size2)
self.hidden_bias1 = np.zeros((1, hidden_size1), dtype=np.float32)
self.hidden_bias2 = np.zeros((1, hidden_size2), dtype=np.float32)
self.output_bias = np.zeros((1, output_size), dtype=np.float32)
def relu(self, x):
return np.maximum(0, x)
def relu_derivative(self, x):
return np.where(x > 0, 1, 0)
def softmax(self, x):
exp_x = np.exp(x - np.max(x, axis=1, keepdims=True))
return exp_x / np.sum(exp_x, axis=1, keepdims=True)
def forward(self, X):
self.hidden1 = self.relu(np.dot(X, self.input_weights) + self.hidden_bias1)
self.hidden2 = self.relu(np.dot(self.hidden1, self.hidden_weights1) + self.hidden_bias2)
self.output = self.softmax(np.dot(self.hidden2, self.hidden_weights2) + self.output_bias)
return self.output
def backward(self, X, y, output, learning_rate):
output_error = y - output
hidden2_error = np.dot(output_error, self.hidden_weights2.T)
hidden1_error = np.dot(hidden2_error, self.hidden_weights1.T)
hidden2_delta = hidden2_error * self.relu_derivative(self.hidden2)
hidden1_delta = hidden1_error * self.relu_derivative(self.hidden1)
self.hidden_weights2 += learning_rate * np.dot(self.hidden2.T, output_error)
self.hidden_weights1 += learning_rate * np.dot(self.hidden1.T, hidden2_delta)
self.input_weights += learning_rate * np.dot(X.T, hidden1_delta)
self.output_bias += learning_rate * np.sum(output_error, axis=0, keepdims=True)
self.hidden_bias2 += learning_rate * np.sum(hidden2_delta, axis=0, keepdims=True)
self.hidden_bias1 += learning_rate * np.sum(hidden1_delta, axis=0, keepdims=True)
def train(self, X, y, X_val, y_val, epochs, learning_rate, batch_size=32, patience=50):
best_val_loss = float('inf')
patience_counter = 0
for epoch in range(epochs):
epoch_loss = 0
for i in range(0, len(X), batch_size):
batch_X = X[i:i+batch_size]
batch_y = y[i:i+batch_size]
output = self.forward(batch_X)
self.backward(batch_X, batch_y, output, learning_rate)
epoch_loss += np.mean(np.square(batch_y - output))
val_output = self.forward(X_val)
val_loss = np.mean(np.square(y_val - val_output))
if epoch % 100 == 0:
print(f"Epoch {epoch}, Loss: {epoch_loss/len(X)}, Val Loss: {val_loss}")
if val_loss < best_val_loss:
best_val_loss = val_loss
patience_counter = 0
else:
patience_counter += 1
if patience_counter >= patience:
print(f"Early stopping at epoch {epoch}")
break
def parse_input(file_path):
data = []
labels = []
with open(file_path, 'r') as file:
for line in file:
match = re.search(r'Red: (\d+), Green: (\d+), Blue: (\d+), Clear: (\d+), Color: (\w+)', line)
if match:
r, g, b, c, color = match.groups()
data.append([int(r), int(g), int(b), int(c)])
labels.append(color)
return np.array(data), np.array(labels)
def normalize_data(data):
return data / np.array([2048, 2048, 2048, 2048])
def one_hot_encode(labels):
unique_labels = np.array(['Red', 'Black', 'Green', 'White'])
label_dict = {label: i for i, label in enumerate(unique_labels)}
encoded = np.zeros((len(labels), len(unique_labels)))
for i, label in enumerate(labels):
encoded[i, label_dict[label]] = 1
return encoded, unique_labels
def float_to_hex(f):
return hex(struct.unpack('<I', struct.pack('<f', f))[0])
# Prepare training data
input_data, labels = parse_input('color_data.txt')
X = normalize_data(input_data)
y, unique_labels = one_hot_encode(labels)
# Split data into train and validation sets
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# Create and train the neural network
nn = NeuralNetwork(input_size=4, hidden_size1=16, hidden_size2=8, output_size=4)
nn.train(X_train, y_train, X_val, y_val, epochs=10000, learning_rate=0.001, batch_size=32, patience=50)
# Print C-compatible array initializers
print("\nC-compatible array initializers:")
print("uint32_t input_weights[INPUT_SIZE][HIDDEN_SIZE1] = {")
for row in nn.input_weights:
print(" {" + ", ".join(float_to_hex(x) for x in row) + "},")
print("};")
print("\nuint32_t hidden_weights1[HIDDEN_SIZE1][HIDDEN_SIZE2] = {")
for row in nn.hidden_weights1:
print(" {" + ", ".join(float_to_hex(x) for x in row) + "},")
print("};")
print("\nuint32_t hidden_weights2[HIDDEN_SIZE2][OUTPUT_SIZE] = {")
for row in nn.hidden_weights2:
print(" {" + ", ".join(float_to_hex(x) for x in row) + "},")
print("};")
print("\nuint32_t hidden_bias1[HIDDEN_SIZE1] = {" + ", ".join(float_to_hex(x) for x in nn.hidden_bias1.flatten()) + "};")
print("\nuint32_t hidden_bias2[HIDDEN_SIZE2] = {" + ", ".join(float_to_hex(x) for x in nn.hidden_bias2.flatten()) + "};")
print("\nuint32_t output_bias[OUTPUT_SIZE] = {" + ", ".join(float_to_hex(x) for x in nn.output_bias.flatten()) + "};")
# Debug information
print("\nSample predictions from Python:")
for i in range(min(5, len(X))): # Print predictions for up to 5 samples
sample_output = nn.forward(X[i:i+1])
print(f"Input: {input_data[i]}, True label: {labels[i]}")
print(f"Output: {sample_output[0]}")
print(f"Predicted: {unique_labels[np.argmax(sample_output)]}\n")
print("Sample weight values:")
print("Input weights (first few):", nn.input_weights[:2, :2])
print("Hidden weights1 (first few):", nn.hidden_weights1[:2, :2])
print("Hidden weights2 (first few):", nn.hidden_weights2[:2, :2])
print("Hidden bias1 (first few):", nn.hidden_bias1[0, :2])
print("Hidden bias2 (first few):", nn.hidden_bias2[0, :2])
print("Output bias (all):", nn.output_bias[0])
# Test with a specific input
test_input = np.array([[1794, 2164, 1742, 1996]]) # Example for white
test_input_normalized = normalize_data(test_input)
test_output = nn.forward(test_input_normalized)
print("\nTest prediction:")
print("Input:", test_input[0])
print("Output:", test_output[0])
print("Predicted color:", unique_labels[np.argmax(test_output)])