├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── ci └── build_all_projects.sh ├── gpio_interrupts ├── CMakeLists.txt ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.c └── requirements.txt ├── image_part ├── CMakeLists.txt ├── README.md ├── README.zh-CN.md ├── main.py ├── main │ ├── CMakeLists.txt │ ├── app_main.cpp │ └── component.mk └── requirements.txt ├── jpeg_demo ├── CMakeLists.txt ├── README.md ├── README.zh-CN.md ├── main.py ├── main │ ├── CMakeLists.txt │ ├── app_main.cpp │ └── component.mk └── requirements.txt ├── jpeg_webserver_demo ├── CMakeLists.txt ├── README.md ├── main │ ├── CMakeLists.txt │ ├── favicon.ico │ ├── file_server.cpp │ ├── main.cpp │ ├── main.hpp │ └── upload_script.html ├── partitions_example.csv ├── requirements.txt └── sdkconfig.defaults ├── mjpeg_streaming_wifi ├── CMakeLists.txt ├── README.md ├── main.py ├── main │ ├── CMakeLists.txt │ ├── favicon.ico │ ├── file_server.cpp │ ├── main.cpp │ └── main.hpp ├── main_lightweight.py ├── partitions_example.csv ├── requirements.txt ├── sdkconfig.defaults └── sdkconfig.old ├── mobilenet_raw ├── CMakeLists.txt ├── README.md ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt ├── parse_meta ├── CMakeLists.txt ├── README.md ├── README.zh-CN.md ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt ├── people_tracker ├── CMakeLists.txt ├── README.md └── main │ ├── CMakeLists.txt │ └── app_main.cpp ├── script_node_communication ├── CMakeLists.txt ├── README.md ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt ├── spatial_image_detections ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── app_main.cpp ├── spatial_location_calculator ├── CMakeLists.txt └── main │ ├── CMakeLists.txt │ └── app_main.cpp ├── speed_benchmark ├── CMakeLists.txt ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt ├── spi_in_landmark ├── CMakeLists.txt ├── README.md ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt ├── spi_in_passthrough ├── CMakeLists.txt ├── README.md ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt ├── two_streams ├── CMakeLists.txt ├── README.md ├── main.py ├── main │ ├── CMakeLists.txt │ └── app_main.cpp └── requirements.txt └── uart_echo ├── CMakeLists.txt ├── README.md ├── main.py ├── main ├── CMakeLists.txt ├── Kconfig.projbuild └── uart_echo_example_main.c ├── requirements.txt └── sdkconfig.old /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: ESP32 CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | builder: 7 | name: Build ESP32 projects 8 | runs-on: ubuntu-20.04 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | submodules: 'recursive' 14 | 15 | - name: Install ESP-IDF 16 | uses: CalinRadoni/esp-idf-v4-action@v2 17 | with: 18 | esp_idf_version: 'v4.1' 19 | 20 | - name: Build 21 | run: | 22 | source ~/esp/esp-idf/export.sh 23 | ci/build_all_projects.sh 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sdkconfig 2 | CMakeOutput.log 3 | .vscode/ 4 | */build/ 5 | build 6 | sdkconfig 7 | CMakeOutput.log 8 | main/build/* 9 | .vscode/ 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "components/depthai-spi-api"] 2 | path = components/depthai-spi-api 3 | url = https://github.com/luxonis/depthai-spi-api.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Luxonis Holding Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## NOTE! 3 | 4 | OAK IoT series and this repository is **community supported only**, and is **provided as-is**. We most likely **won't update it** and **we don't provide support** for it (Discord, forums, email...). 5 | 6 | # Demo 7 | 8 | See below for this running on the [BW1092](https://shop.luxonis.com/collections/all/products/bw1092): 9 | 10 | [![SPI ESP32 Interface with DepthAI](https://user-images.githubusercontent.com/32992551/102835329-9bfa2100-43b3-11eb-8cce-ce65cb8e600d.png)](https://www.youtube.com/watch?v=S2xYcVoyPxk "Embedded UseCase of DepthAI") 11 | 12 | ## Building 13 | 14 | The first time you build, the repository submodules need be initialized: 15 | ``` 16 | git submodule update --init --recursive 17 | 18 | # Tip: You can ask Git to do that automatically: 19 | git config submodule.recurse true 20 | ``` 21 | 22 | Later submodules also need to be updated. To build an example, you will need to use [ESP-IDF](https://www.espressif.com/en/products/sdks/esp-idf)'s `idf.py`. **Examples here were only tested with ESP-IDF version 4.1** and we encourage you to use the same version as well. 23 | 24 | # SPI Protocol 25 | 26 | SPI messaging is currently arranged in 2 layers. The first is the spi protocol. The spi protocol is the lowest level. It defines a standard packet for all SPI communication. It is a 256 byte packet arranged in the following manner: 27 | 28 | ``` 29 | typedef struct { 30 | uint8_t start; 31 | uint8_t data[SPI_PROTOCOL_PAYLOAD_SIZE]; 32 | uint8_t crc[2]; 33 | uint8_t end; 34 | } SpiProtocolPacket; 35 | ``` 36 | start and end are constant bytes to mark the beginning and end of packets. 37 | ``` 38 | static const uint8_t START_BYTE_MAGIC = 0b10101010; 39 | static const uint8_t END_BYTE_MAGIC = 0b00000000; 40 | ``` 41 | # SPI Messaging 42 | On top of this we have a layer called SPI messaging. This code defines the following: 43 | * A list of a supported commands, 44 | * A way to encapsulate commands going to the MyriadX over SPI. 45 | * A way to receive and parse command responses. 46 | * We’ll go into greater depth as to how exactly to use this in the SPI Messaging Example. 47 | -------------------------------------------------------------------------------- /ci/build_all_projects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit if any subsequent commands fail 4 | set -e 5 | 6 | # Source folder of this script 7 | SCRIPT_PATH=$(realpath $0) 8 | echo $SCRIPT_PATH 9 | SOURCE_DIR=$(dirname $SCRIPT_PATH) 10 | echo $SOURCE_DIR 11 | ROOT_DIR="$SOURCE_DIR/../" 12 | echo $ROOT_DIR 13 | 14 | ### Projects 15 | 16 | PROJECTS=( 17 | gpio_interrupts image_part jpeg_demo jpeg_webserver_demo mjpeg_streaming_wifi 18 | mobilenet_raw parse_meta people_tracker script_node_communication spatial_image_detections 19 | spatial_location_calculator speed_benchmark spi_in_landmark spi_in_passthrough two_streams 20 | uart_echo 21 | ) 22 | 23 | for project in "${PROJECTS[@]}"; do 24 | cd "$ROOT_DIR/$project" 25 | idf.py build 26 | done 27 | -------------------------------------------------------------------------------- /gpio_interrupts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's CMakeLists 2 | # in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | # Set C++14 required by DepthAI shared 6 | set(CMAKE_CXX_STANDARD 14) 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | 9 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 10 | 11 | set(EXTRA_COMPONENT_DIRS 12 | ../components 13 | ) 14 | 15 | project(gpio-interrupts) 16 | -------------------------------------------------------------------------------- /gpio_interrupts/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import time 3 | import depthai as dai 4 | 5 | # Start defining a pipeline 6 | pipeline = dai.Pipeline() 7 | 8 | # Script node 9 | script = pipeline.create(dai.node.Script) 10 | script.setScript(""" 11 | import time 12 | import GPIO 13 | # Pin 34, highCount (clock cycles), lowCount (clock cycles) 14 | ret = GPIO.setup(34, GPIO.OUT) 15 | node.warn(f'gpio 34 init ret: {ret}') 16 | node.warn(f'gpio 34 val: {GPIO.read(34)}') 17 | GPIO.setPwm(34, 100000000, 100000000) 18 | GPIO.enablePwm(34, 1) 19 | time.sleep(1) 20 | GPIO.enablePwm(34, 0) 21 | 22 | # Interrupts 23 | cb = lambda gpio : node.warn(f'Rising edge interrupted GPIO{gpio}') 24 | # Default - input, no pull up/down, shared 25 | node.warn(f'setup ret: {GPIO.setup(32)}') 26 | node.warn(f'setInterrupt ret: {GPIO.setInterrupt(32, GPIO.RISING, 100, cb)}') 27 | while True: 28 | time.sleep(1) 29 | """) 30 | 31 | # Connect to device with pipeline 32 | with dai.Device(pipeline) as device: 33 | while not device.isClosed(): 34 | time.sleep(1) 35 | -------------------------------------------------------------------------------- /gpio_interrupts/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Create application 2 | set(SOURCES 3 | app_main.c 4 | ) 5 | 6 | set(INCLUDE_DIRS 7 | . 8 | ) 9 | 10 | idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${INCLUDE_DIRS} REQUIRES depthai-spi-api) 11 | -------------------------------------------------------------------------------- /gpio_interrupts/main/app_main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "freertos/FreeRTOS.h" 5 | #include "freertos/task.h" 6 | #include "freertos/queue.h" 7 | #include "driver/gpio.h" 8 | 9 | /** 10 | * Brief: 11 | * This shows interrupts between DepthAI<->ESP32 12 | * 13 | * GPIO status: 14 | * ESP32_GPIO13 -> DEPTHAI_GPIO32 15 | * DEPTHAI_GPIO34 -> ESP32_GPIO2 16 | * 17 | */ 18 | #define GPIO_OUTPUT_IO_0 13 19 | #define GPIO_OUTPUT_PIN_SEL ((1ULL< ENCODER -> SPI OUT") 14 | pipeline = dai.Pipeline() 15 | 16 | cam_color = pipeline.createColorCamera() 17 | spiout_preview = pipeline.createSPIOut() 18 | videnc = pipeline.createVideoEncoder() 19 | 20 | # set up color camera 21 | cam_color.setPreviewSize(300, 300); 22 | cam_color.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P); 23 | cam_color.setInterleaved(False); 24 | cam_color.setColorOrder(dai.ColorCameraProperties.ColorOrder.BGR); 25 | 26 | # Link plugins CAM -> ENCODER -> SPI OUT 27 | spiout_preview.setStreamName("spipreview"); 28 | spiout_preview.setBusId(0); 29 | cam_color.preview.link(spiout_preview.input); 30 | 31 | with dai.Device(pipeline) as device: 32 | while not device.isClosed(): 33 | time.sleep(1) 34 | 35 | -------------------------------------------------------------------------------- /image_part/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Create library 2 | set(SOURCES 3 | app_main.cpp 4 | ) 5 | 6 | set(INCLUDE_DIRS 7 | . 8 | ) 9 | 10 | idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${INCLUDE_DIRS} REQUIRES depthai-spi-api) 11 | -------------------------------------------------------------------------------- /image_part/main/app_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "esp32_spi_impl.h" 7 | 8 | #include "spi_api.hpp" 9 | 10 | static const char* PREVIEWSTREAM = "spipreview"; 11 | 12 | extern "C" { 13 | void app_main(); 14 | } 15 | 16 | void run_demo(){ 17 | uint8_t req_success = 0; 18 | 19 | dai::SpiApi mySpiApi; 20 | mySpiApi.set_send_spi_impl(&esp32_send_spi); 21 | mySpiApi.set_recv_spi_impl(&esp32_recv_spi); 22 | 23 | int newlineiter = 0; 24 | int newlinemod = 20; 25 | int offset = 269900; 26 | int dataSize = 100; 27 | while(1) { 28 | dai::Data received_data; 29 | req_success = mySpiApi.req_data_partial(&received_data, PREVIEWSTREAM, offset, dataSize); 30 | if(req_success){ 31 | newlineiter = 0; 32 | for(int i=0; i