diff options
author | kartofen <mladenovnasko0@gmail.com> | 2023-12-25 01:45:05 +0200 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2023-12-25 01:45:05 +0200 |
commit | 4b0fdca8673c76cb2305db301a3b36e9e3822e02 (patch) | |
tree | bbcf1c6364baba0afe9a2a595f4a579ad0946188 |
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Makefile | 35 | ||||
-rw-r--r-- | README.md | 30 | ||||
-rw-r--r-- | include/rctp.h | 50 | ||||
-rw-r--r-- | kociemba/Makefile | 44 | ||||
-rw-r--r-- | kociemba/README.md | 0 | ||||
-rw-r--r-- | master/CMakeLists.txt | 8 | ||||
-rw-r--r-- | master/README.md | 0 | ||||
-rw-r--r-- | master/main/CMakeLists.txt | 2 | ||||
-rw-r--r-- | master/main/main.c | 34 | ||||
-rw-r--r-- | slave/Makefile | 0 | ||||
-rw-r--r-- | slave/README.md | 0 |
12 files changed, 207 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c29eb74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +**/bin/ +**/obj/ +**/build/ +**/sdkconfig
\ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be34b04 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +PORT ?= ttyUSB0 + +ifeq ($(origin IDF_PATH),undefined) +IDF_ENV=0 +else +IDF_ENV=1 +endif + +all: kociemba master slave + +kociemba slave: + $(MAKE) -C $(shell pwd)/$@ all PROD=1 + +master: +ifeq ($(IDF_ENV), 1) + cd $(shell pwd)/$@ && PATH=$(PATH) idf.py build +else + @echo "FAILED: ESP-IDF export script is not sourced!" + @echo -e "\t(use 'source <esp-idf path>/export.sh')" + @exit 1 +endif + +run: kociemba slave master +ifeq ($(FLASH),1) +ifeq ($(IDF_ENV),1) + cd $(shell pwd)/master && idf.py flash -p $(PORT) +else + @echo "FAILED: FLASH is set to 1 but ESP-IDS export script is not sourced!" + @exit 1 +endif +endif + $(MAKE) -C $(shell pwd)/kociemba run + + +.PHONY: all kociemba slave master run diff --git a/README.md b/README.md new file mode 100644 index 0000000..3898a1f --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +### Rubik's Cube Solving Robot + +This repository is for a robot that solves the rubik's cube. The idea is that after a scrambled rubik's cube has been places in the robot, an ESP32 (master) gets the cube's state (using 2 cameras, looking at opposite corners, each seeing 3 faces). The data is then sent to a more powerful computer (slave) which puts the data through [kociemba's algorithm](http://kociemba.org/cube.htm). The solution is then sent back to the master for servos to execute and (hopefully) solve the cube. + +#### Master-Slave Relationship + +The data is sent through the default UART connection between the master and the slave in the simple RCTP protocol (Rubik's Cube Transfer Protocol) (see `include/rctp.h`) (Note that both machines have to have the same endianess since the protocol is binary) + +### Building + +The projects can all be built separately, but only the implementation of kociemba's algorithm (`kociemba/`) can be useful on its own. + +- **`kociemba/`:** built using `GNU make` (`kociemba/README.md` for more details) + +- **`slave/`:** built using `GNU make` (`slave/README.md` for more details) + + - **`master/`:** in contrast with the other parts, the master is built using`esp-idf`'s build system (`master/README.md` for more details) + +The Makfile in the root of this repo is a wrapper around the other build systems, so just use: + +- **`make all/kociemba/slave/master`** to build all or a single one (with nondebug flags) + +- **`make run [FLASH=1] [PORT=ttyUSBn]`** to build and run the slave, and when `FLASH` is set the master program is flashed, and when `PORT` is set, the given port is tried instead of the default `ttyUSB0` + +Note that building `master/` using the wrapper requires the `esp-idf` export script to be sourced. + +### References + +- <http://kociemba.org/cube.htm> +- <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/index.html> diff --git a/include/rctp.h b/include/rctp.h new file mode 100644 index 0000000..71aa812 --- /dev/null +++ b/include/rctp.h @@ -0,0 +1,50 @@ +#ifndef RCTP_H +#define RCTP_H + +typedef unsigned char rctp_byte; + +typedef struct request rctp_req_t; +typedef struct response rctp_res_t; + +typedef enum { + RCTP_OK = 0, + RCTP_ERROR, // unknown error + + RCTP_UNKNOWN_METHOD, + RCTP_UNKNOWN_STATUS, + + RCTP_INVALID_STRING, +} RCTP_STAT; + +#define RCTP_METHODS(X) \ + X(PING) \ + +#define RCTP_STATUSES(X) \ + X(PONG) \ + +#define TO_ENUM(s) s, +#define TO_STR(s) #s, + +enum rctp_method { + RCTP_METHODS(TO_ENUM) +} __attribute__((packed)); + +enum rctp_status { + RCTP_STATUSES(TO_ENUM) +} __attribute__((packed)); + +struct request { + enum rctp_req method; + union { + /* ... */ + }; +} __attribute__((packed)); + +struct response { + enum rctp_res status; + union { + /* ... */ + }; +} __attribute__((packed)); + +#endif diff --git a/kociemba/Makefile b/kociemba/Makefile new file mode 100644 index 0000000..61fa1aa --- /dev/null +++ b/kociemba/Makefile @@ -0,0 +1,44 @@ +CC := gcc +AR := ar + +ifeq ($(PROD),1) +CFLAGS := -std=c99 -O2 # production flags +else +CFLAGS := -std=c99 -Wall -Wextra -Wpedantic -g -DDEBUG # debug flags +endif + +SRCD := src +OBJD := obj +BIND := bin + +FILES = $(shell find $(SRCD)/ -type f 2> /dev/null) +CSRCS = $(filter %.c, $(FILES)) +COBJS = $(CSRCS:$(SRCD)/%.c=$(OBJD)/%.o) + +CDEPS = $(COBJS:%.o=%.d) +-include $(CDEPS) + +NAME := kociemba + +all: standalone lib + +standalone $(NAME): $(BIND)/$(NAME) +static $(NAME).a: $(BIND)/$(NAME).a + +clean: + rm -rf $(OBJD) + rm -rf $(BIND) + +$(OBJD)/%.o: $(SRCD)/%.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -c $< -o $@ + +$(BIND)/$(NAME): $(COBJS) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $^ -o $@ + +$(BIND)/$(NAME).a: $(COBJS) + @mkdir -p $(dir $@) + $(AR) rsc $@ $^ + +.PHONY: all standalone lib clean $(NAME) $(NAME).a diff --git a/kociemba/README.md b/kociemba/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/kociemba/README.md diff --git a/master/CMakeLists.txt b/master/CMakeLists.txt new file mode 100644 index 0000000..664d458 --- /dev/null +++ b/master/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five 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(main) diff --git a/master/README.md b/master/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/master/README.md diff --git a/master/main/CMakeLists.txt b/master/main/CMakeLists.txt new file mode 100644 index 0000000..cf2c455 --- /dev/null +++ b/master/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/master/main/main.c b/master/main/main.c new file mode 100644 index 0000000..ee170bc --- /dev/null +++ b/master/main/main.c @@ -0,0 +1,34 @@ +#include <stdio.h> +#include "driver/uart.h" + +#define ECHECK(...) ESP_ERROR_CHECK(__VA_ARGS__) + +QueueHandle_t uart_queue; + +void uart_setup(void); + +void app_main(void) +{ + uart_setup(); + + char message[] = "Hello World\n"; + uart_write_bytes(UART_NUM_0, message, sizeof(message)); +} + +void uart_setup(void) +{ + // stty -F /dev/ttyUSB0 cs8 -parenb -crtscts -cstopb + uart_config_t uart_config = { + .baud_rate = 9600, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_DEFAULT, + }; + + #define UART_BUFFER_SIZE 2048 + ECHECK(uart_param_config(UART_NUM_0, &uart_config)); + ECHECK(uart_driver_install(UART_NUM_0, UART_BUFFER_SIZE, UART_BUFFER_SIZE, 10, &uart_queue, 0)); +} + diff --git a/slave/Makefile b/slave/Makefile new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/slave/Makefile diff --git a/slave/README.md b/slave/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/slave/README.md |