mirror of
https://github.com/StuckAtPrototype/Racer.git
synced 2024-10-20 22:49:48 +03:00
version 2.0
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
build/
|
||||
dependencies.lock
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
sdkconfig.old
|
||||
sdkconfig
|
||||
venv/
|
||||
100
README.md
Normal file
100
README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Micro Racer Car - StuckAtPrototype
|
||||
|
||||
## Youtube Video
|
||||
A bit of a back-story of how this project came to be.
|
||||
|
||||
[](https://www.youtube.com/watch?v=6jzG-BMannc)
|
||||
|
||||
Sub if you like what you see.
|
||||
|
||||
*Some pictures of the project*
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 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
6
firmware/CMakeLists.txt
Normal 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)
|
||||
4
firmware/main/CMakeLists.txt
Normal file
4
firmware/main/CMakeLists.txt
Normal 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
52
firmware/main/battery.c
Normal 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
12
firmware/main/battery.h
Normal 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
|
||||
169
firmware/main/color_predictor.c
Normal file
169
firmware/main/color_predictor.c
Normal 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];
|
||||
}
|
||||
}
|
||||
|
||||
23
firmware/main/color_predictor.h
Normal file
23
firmware/main/color_predictor.h
Normal 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
232
firmware/main/controller.c
Normal 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;
|
||||
}
|
||||
36
firmware/main/controller.h
Normal file
36
firmware/main/controller.h
Normal 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
115
firmware/main/gap.c
Normal 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
16
firmware/main/gap.h
Normal 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
260
firmware/main/gatt_svr.c
Normal 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
46
firmware/main/gatt_svr.h
Normal 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();
|
||||
54
firmware/main/gpio_interrupt.c
Normal file
54
firmware/main/gpio_interrupt.c
Normal 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);
|
||||
}
|
||||
|
||||
19
firmware/main/gpio_interrupt.h
Normal file
19
firmware/main/gpio_interrupt.h
Normal 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
|
||||
32
firmware/main/i2c_config.c
Normal file
32
firmware/main/i2c_config.c
Normal 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;
|
||||
}
|
||||
17
firmware/main/i2c_config.h
Normal file
17
firmware/main/i2c_config.h
Normal 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
142
firmware/main/led.c
Normal 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
47
firmware/main/led.h
Normal 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
176
firmware/main/main.c
Normal 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
122
firmware/main/motor.c
Normal 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
31
firmware/main/motor.h
Normal 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
200
firmware/main/opt4060.c
Normal 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
20
firmware/main/opt4060.h
Normal 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
0
firmware/sdkconfig.ci
Normal file
96566
hardware/racer-sensors/fp-info-cache
Normal file
96566
hardware/racer-sensors/fp-info-cache
Normal file
File diff suppressed because it is too large
Load Diff
BIN
hardware/racer-sensors/racer-sensors-v0.1.zip
Normal file
BIN
hardware/racer-sensors/racer-sensors-v0.1.zip
Normal file
Binary file not shown.
5091
hardware/racer-sensors/sensors.kicad_pcb
Normal file
5091
hardware/racer-sensors/sensors.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
83
hardware/racer-sensors/sensors.kicad_prl
Normal file
83
hardware/racer-sensors/sensors.kicad_prl
Normal 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": []
|
||||
}
|
||||
}
|
||||
602
hardware/racer-sensors/sensors.kicad_pro
Normal file
602
hardware/racer-sensors/sensors.kicad_pro
Normal 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": {}
|
||||
}
|
||||
4180
hardware/racer-sensors/sensors.kicad_sch
Normal file
4180
hardware/racer-sensors/sensors.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
96636
hardware/racer/fp-info-cache
Normal file
96636
hardware/racer/fp-info-cache
Normal file
File diff suppressed because it is too large
Load Diff
BIN
hardware/racer/racer-v0.2.zip
Normal file
BIN
hardware/racer/racer-v0.2.zip
Normal file
Binary file not shown.
28662
hardware/racer/racer.kicad_pcb
Normal file
28662
hardware/racer/racer.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
83
hardware/racer/racer.kicad_prl
Normal file
83
hardware/racer/racer.kicad_prl
Normal 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": []
|
||||
}
|
||||
}
|
||||
635
hardware/racer/racer.kicad_pro
Normal file
635
hardware/racer/racer.kicad_pro
Normal 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
20353
hardware/racer/racer.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
8
hardware/thumbtroller/controller-bottom-pos.csv
Normal file
8
hardware/thumbtroller/controller-bottom-pos.csv
Normal 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
|
||||
|
36
hardware/thumbtroller/controller-top-pos.csv
Normal file
36
hardware/thumbtroller/controller-top-pos.csv
Normal 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
|
||||
|
25481
hardware/thumbtroller/controller.kicad_pcb
Normal file
25481
hardware/thumbtroller/controller.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
83
hardware/thumbtroller/controller.kicad_prl
Normal file
83
hardware/thumbtroller/controller.kicad_prl
Normal 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": []
|
||||
}
|
||||
}
|
||||
625
hardware/thumbtroller/controller.kicad_pro
Normal file
625
hardware/thumbtroller/controller.kicad_pro
Normal 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": {}
|
||||
}
|
||||
17467
hardware/thumbtroller/controller.kicad_sch
Normal file
17467
hardware/thumbtroller/controller.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
BIN
hardware/thumbtroller/thumbtroller-v0.2.zip
Normal file
BIN
hardware/thumbtroller/thumbtroller-v0.2.zip
Normal file
Binary file not shown.
339490
mechanical/Racer-entire-car.step
Normal file
339490
mechanical/Racer-entire-car.step
Normal file
File diff suppressed because it is too large
Load Diff
2341
mechanical/main-enclosure.step
Normal file
2341
mechanical/main-enclosure.step
Normal file
File diff suppressed because it is too large
Load Diff
4859
mechanical/top-enclosure.step
Normal file
4859
mechanical/top-enclosure.step
Normal file
File diff suppressed because it is too large
Load Diff
3129
mechanical/wheel.step
Normal file
3129
mechanical/wheel.step
Normal file
File diff suppressed because it is too large
Load Diff
BIN
project_pictures/242A0548.png
Normal file
BIN
project_pictures/242A0548.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 488 KiB |
BIN
project_pictures/242A1274.png
Normal file
BIN
project_pictures/242A1274.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 371 KiB |
25
scripts/README.md
Normal file
25
scripts/README.md
Normal 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`
|
||||
1
scripts/ble_device_config.json
Normal file
1
scripts/ble_device_config.json
Normal file
@@ -0,0 +1 @@
|
||||
{"ble_address": "74:4D:BD:61:A7:B3"}
|
||||
615
scripts/color_data.txt
Normal file
615
scripts/color_data.txt
Normal 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
99
scripts/controller.py
Normal 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
BIN
scripts/nn_model.bin
Normal file
Binary file not shown.
162
scripts/trainer.py
Normal file
162
scripts/trainer.py
Normal 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)])
|
||||
Reference in New Issue
Block a user