-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 67f898e
Showing
34 changed files
with
4,741 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# User added | ||
.pio/* | ||
workspace.code-workspace | ||
.vscode | ||
app/ble/esp-nimble-cpp | ||
|
||
# Prerequisites | ||
*.d | ||
|
||
# Compiled Object files | ||
*.slo | ||
*.lo | ||
*.o | ||
*.obj | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Compiled Dynamic libraries | ||
*.so | ||
*.dylib | ||
*.dll | ||
|
||
# Fortran module files | ||
*.mod | ||
*.smod | ||
|
||
# Compiled Static libraries | ||
*.lai | ||
*.la | ||
*.a | ||
*.lib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "app/ble/esp-nimble-cpp"] | ||
path = app/ble/esp-nimble-cpp | ||
url = https://github.com/h2zero/esp-nimble-cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
cmake_minimum_required(VERSION 3.16.0) | ||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
project(time_tracker_esp32) | ||
|
||
set(CMAKE_CXX_STANDARD 14) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 Maciej Śliwiński | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Cube Time Tracker ESP32 | ||
|
||
**:exclamation: This project is still under heavy development. First release is coming!** | ||
</br> | ||
|
||
![:game_die: tracker](docs/images/cubeDemo.png) | ||
|
||
</br> | ||
|
||
Open source time tracker in a form of cube :game_die: Each wall has a symbol which describes activity you might be doing. Flip the wall and the clock is ticking! Cube pairs with a **desktop app** (under development), which shows you the insights into time you spent on particular activities. | ||
</br> | ||
|
||
|
||
In order to start with your own DIY tracker you will go through these steps: | ||
- :hammer: Obtain and build (esp32 board, accelometer board, battery and enclosure) | ||
- :arrow_double_up: Upload firmware to ESP32 board | ||
- :mag: Connect to tracker with desktop app | ||
- :rocket: Go thru initial configuration process | ||
|
||
# Hardware Build | ||
|
||
![All the elements](docs/images/hwAll.png) | ||
|
||
## Components | ||
|
||
Alright, time to build the tracker :game_die: Here is the list of parts you need :gear: | ||
|
||
- [DFRobot Firebeetle ESP32](https://wiki.dfrobot.com/FireBeetle_Board_ESP32_E_SKU_DFR0654) (currently the only supported board) | ||
|
||
- [MPU6050 Accelometer](https://components101.com/sensors/mpu6050-module) | ||
- Battery (lithium) of your choice, single cell, with the right shape you can fit any up to 1000mAh. Mind that Firebeetle has no any protection circuit | ||
- 3D printed parts (models available in docs/ ) | ||
- Enclosure | ||
- Insert which will hold your electronics | ||
- Two tiny screws | ||
|
||
Equipment you might need for assembly: | ||
- Soldering iron | ||
- Tape (duct or double sided) | ||
- Screwdriver | ||
|
||
## Assembly | ||
|
||
![Steps](docs/images/hwBuild.png) | ||
|
||
- Solder MPU6050 to Firebeetle. Match the pins from MPU :exclamation: Mind that MPU's VCC pin should connect to 3V3 on the beetle | ||
- Take your battery and solder its terminals to pads on the beetle's bottom side | ||
- Attach battery to Firebeetle board (suggestion: tape) | ||
- Put your assembled electronics into the printed insert and thighten screws through the holes in insert | ||
|
||
:checkered_flag: I hope you didn't screw it up (lol you get it, the last step with screws). | ||
</br> | ||
Connect USB-C cable, charge the battery and upload software! | ||
|
||
## Hardware additional info | ||
|
||
### Power consumption | ||
|
||
![Steps](docs/images/consumption.png) | ||
|
||
An average current consumption on FireBeetle is around 1.3 mA (to be improved) Deep sleep consumption is 400uA. Time on battery you can calculate as follows: </br>`90% * capacity[mAh] / avg_consumption[mA] = time[h]`. </br>Other boards might yield different results. When looking for an alternative board pay attention to what components on the board are powered from 3V3 rail, an example is USB to UART converter present on almost every board, they are usually connected to 3V3, so they will drain your battery. Lolin32 Lite seems to be the closest suitable alternative, but since it has no connection from battery to ESP32 you might to hack a resistor divier and connect it to some analog input. | ||
</br> | ||
Cube app will remind you about low battery level. | ||
|
||
# Software Build | ||
|
||
Time to upload software into the tracker. Or you might want to tweak the software a lil bit on your own? | ||
|
||
### Build | ||
Project is build with [PlatformIO](https://platformio.org) framework. | ||
|
||
- Install PlatformIO extension in VSCode | ||
- PIO Home > Platforms > Embedded > Download and install "Espressif 32" **version 6.1.0** (includes ESP-IDF v5.0.1) | ||
- Make sure you cloned/pulled this git repository | ||
- Download submodules `git submodule update --init` </br> NimBLE repo in {project}/app/ble/esp32-nimble-cpp should be downloaded. If not, use `git submodule add https://github.com/h2zero/esp-nimble-cpp` and then update submodule | ||
- Build project and upload binaries using PlatformIO buttons/shortcuts at the bottom status bar | ||
|
||
Off you go! In case of errors - clean and build. | ||
|
||
## Troubleshooting | ||
- Firebeetle board not recognized (OS X): http://www.wch-ic.com/downloads/CH341SER_MAC_ZIP.html | ||
|
||
Otherwise... Plug the cube and run PlatformIO serial monitor, lookup the errors in the console | ||
|
||
## Found a bug? | ||
If you found a :bug: please report it via issues tab | ||
|
||
## Known issues | ||
Time drifts +/- 5%. Changed from RTC clock source from internal RC to internal 8 MHz clock; didn't help |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/** | ||
* @file appManagement.hpp | ||
* @author Maciej Sliwinski | ||
* @brief This file is a part of time_tracker_esp32 project. | ||
* | ||
* The code is distributed under the MIT License. | ||
* See the LICENCE file for more details. | ||
*/ | ||
|
||
#include "imu.hpp" | ||
#include "ble.hpp" | ||
#include "battery.hpp" | ||
#include "dateTime.hpp" | ||
|
||
extern "C" { | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "esp_sleep.h" | ||
#include "soc/rtc.h" | ||
#include "driver/rtc_io.h" | ||
} // extern C close | ||
|
||
#define TASK_STACK_DEPTH_NORMAL (4U * 1024U) | ||
#define TASK_STACK_DEPTH_MORE (6U * 1024U) | ||
#define TASK_PRIORITY_NORMAL (3U) | ||
|
||
//TODO add some info about queues | ||
//TODO simplify queues??? | ||
QueueHandle_t BatteryQueue = xQueueCreate(1, sizeof(int)); | ||
QueueHandle_t ImuReadyQueue = xQueueCreate(1, sizeof(uint8_t)); | ||
QueueHandle_t ImuPositionQueue = xQueueCreate(1, sizeof(IMU::PositionQueueType)); | ||
QueueHandle_t ImuPositionGetQueue = xQueueCreate(1, sizeof(uint8_t)); | ||
QueueHandle_t ImuCalibrationInitQueue = xQueueCreate(1, sizeof(uint8_t)); | ||
QueueHandle_t ImuCalibrationStateQueue = xQueueCreate(1, sizeof("x,xx")); | ||
QueueHandle_t SleepPauseQueue = xQueueCreate(1,16); | ||
QueueHandle_t SleepStartQueue = xQueueCreate(1, sizeof(uint8_t)); | ||
|
||
namespace APP { | ||
|
||
RTC_DATA_ATTR Timestamp lastBle; | ||
|
||
static void sleep(std::chrono::duration<long long, std::micro> duration) { | ||
// Wake up after... | ||
esp_sleep_enable_timer_wakeup(duration.count()); | ||
|
||
// Tasks to do before going to deep sleep! | ||
|
||
rtc_gpio_isolate(GPIO_NUM_2); | ||
rtc_gpio_isolate(GPIO_NUM_12); //TODO idk if it affects anything. brought it cuz of esp-idf reference recommendation | ||
// gpio_reset_pin(GPIO_NUM_0); | ||
// gpio_reset_pin(GPIO_NUM_2); | ||
// gpio_reset_pin(GPIO_NUM_4); | ||
// gpio_reset_pin(GPIO_NUM_12); | ||
// gpio_reset_pin(GPIO_NUM_13); | ||
// gpio_reset_pin(GPIO_NUM_14); | ||
// gpio_reset_pin(GPIO_NUM_15); | ||
// gpio_reset_pin(GPIO_NUM_25); | ||
// gpio_reset_pin(GPIO_NUM_26); | ||
// gpio_reset_pin(GPIO_NUM_27); | ||
// gpio_reset_pin(GPIO_NUM_32); | ||
// gpio_reset_pin(GPIO_NUM_33); | ||
// gpio_reset_pin(GPIO_NUM_34); | ||
// gpio_reset_pin(GPIO_NUM_35); | ||
// gpio_reset_pin(GPIO_NUM_36); | ||
// gpio_reset_pin(GPIO_NUM_37); | ||
// gpio_reset_pin(GPIO_NUM_38); | ||
// gpio_reset_pin(GPIO_NUM_39); | ||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); | ||
// esp_sleep_pd_config(ESP_PD_DOMAIN_RTC8M, ESP_PD_OPTION_ON); | ||
|
||
|
||
if(BLE::Ble::state == BLE::Ble::ConnectionState::CONNECTED) { | ||
BLEDevice::deinit(); | ||
} | ||
|
||
//TODO Firebeetle board deep sleep consumption: 1.6mA. Huge, spent a day trying to fix. | ||
//TODO No signs of possible improvements so far :( | ||
ESP_LOGI(__FILE__, "%s:%d. zzz...", __func__ ,__LINE__); | ||
esp_deep_sleep_start(); | ||
// Remember - after deep sleep whole application CPU will run application from the start | ||
// No memory is retained (except: flash and RTC_DATA_ATTR) | ||
} | ||
|
||
void AppManagementTask(void *pvParameters) { | ||
ESP_LOGI(__FILE__, "%s:%d. Task init", __func__ ,__LINE__); | ||
|
||
TaskHandle_t imuTask; | ||
TaskHandle_t bleTask; | ||
TaskHandle_t batteryTask; | ||
|
||
auto res = xTaskCreate(IMU::ImuTask, "ImuTask", TASK_STACK_DEPTH_NORMAL, NULL, | ||
TASK_PRIORITY_NORMAL, &imuTask); | ||
configASSERT(res); | ||
// vTaskSuspend(imuTask); | ||
|
||
res = xTaskCreate(BATTERY::BatteryTask, "BatteryTask", TASK_STACK_DEPTH_NORMAL, NULL, | ||
TASK_PRIORITY_NORMAL, &batteryTask); | ||
configASSERT(res); | ||
// vTaskSuspend(batteryTask); | ||
|
||
res = xTaskCreate(BLE::BleTask, "BleTask", TASK_STACK_DEPTH_MORE, NULL, | ||
TASK_PRIORITY_NORMAL, &bleTask); | ||
configASSERT(res); | ||
vTaskSuspend(bleTask); | ||
|
||
//TODO check battery level. if below 20% sleep indefinetely/very loong | ||
|
||
// If you want to debug device, see whats going on without it | ||
// going to sleep so quick all the time: increase this cooldown! | ||
// Sleep cooldown is a point in time | ||
Timestamp sleepCooldown = Clock::now() + 200ms; | ||
|
||
for(;;) { | ||
if(BLE::Ble::state == BLE::Ble::ConnectionState::CONNECTED) { | ||
lastBle = Clock::now(); | ||
} | ||
// Last connection with BLE more than 5 min ago? | ||
if(Clock::now() - lastBle > 5min) { | ||
lastBle = Clock::now(); | ||
vTaskResume(bleTask); | ||
// Let the BLE do the stuff | ||
sleepCooldown += 5s; | ||
} | ||
|
||
auto imuReady = 0; | ||
// IMU got new position? | ||
if(xQueueReceive(ImuReadyQueue, &imuReady, 0)) { | ||
vTaskResume(bleTask); | ||
// vTaskResume(batteryTask); | ||
sleepCooldown += 5s; | ||
} | ||
|
||
// Anyone delaying the sleep? | ||
char msg[16] = {0}; | ||
if(xQueueReceive(SleepPauseQueue, msg, 0)) { | ||
std::string message(msg); | ||
ESP_LOGI(__FILE__, "%s:%d. Sleep deferred", __func__ ,__LINE__); | ||
if(message == "imuCalibration") { | ||
sleepCooldown = Clock::now() + 1min; | ||
} | ||
else if(message == "imuSendPosition") { | ||
sleepCooldown = Clock::now() + 1s; | ||
} | ||
else if(message == "otaUpdate") { | ||
sleepCooldown = Clock::now() + 5min; | ||
} | ||
} | ||
|
||
// Someone requested immediate sleep | ||
auto sleepStart = 0; | ||
if(xQueueReceive(SleepStartQueue, &sleepStart, 0)) { | ||
sleepCooldown = Clock::now(); | ||
} | ||
|
||
// Is it the time to sleep? | ||
// WILL SLEEP IMMEDIATELY IF SYSTEM TIME WAS UPDATED! | ||
//TODO fix it? ^ | ||
if(Clock::now() >= sleepCooldown) { | ||
sleep(20s); | ||
} | ||
TaskDelay(10ms); | ||
} | ||
} | ||
|
||
}; // namespace end ------------ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* @file battery.cpp | ||
* @author Maciej Sliwinski | ||
* @brief This file is a part of time_tracker_esp32 project. | ||
* | ||
* The code is distributed under the MIT License. | ||
* See the LICENCE file for more details. | ||
*/ | ||
|
||
#include "battery.hpp" | ||
#include "dateTime.hpp" | ||
|
||
extern "C" { | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/queue.h" | ||
#include "freertos/task.h" | ||
} // extern C close | ||
|
||
using namespace BATTERY; | ||
|
||
extern QueueHandle_t BatteryQueue; | ||
|
||
void BATTERY::BatteryTask(void *pvParameters) { | ||
ESP_LOGI(__FILE__, "%s:%d. Task init", __func__ ,__LINE__); | ||
|
||
// see ADCx_CHANNEL macro description for details | ||
// Battery battery(ADC1_CHANNEL_6); // Lolinlite | ||
|
||
//TODO lolin has no battery read pin | ||
Battery battery(ADC_UNIT_1, ADC_CHANNEL_6); // Firebeetle | ||
|
||
for(;;) { | ||
auto batPercent = battery.GetPercent(); | ||
if(xQueueSend(BatteryQueue, &batPercent, 0) == pdFALSE) { | ||
// overwrite existing value | ||
xQueueOverwrite(BatteryQueue, &batPercent); | ||
} | ||
|
||
TaskDelay(1s); | ||
} | ||
} | ||
|
||
int Battery::GetPercent() { | ||
// theres two stage voltage divider on battery voltage | ||
// 1st *0.5, 2nd *0.3125 | ||
// Vout(@adc_pin) = Vbat * 0.1563 | ||
// Vbat = Vout(@adc_pin) / 0.1563; 1/0.1563 = 6.4 | ||
#ifdef ARDUINO_LOLIN32_LITE | ||
auto voltage = GetAdcVoltage() * 6.4; | ||
#endif | ||
//firebeetle voltage divier: /2 | ||
// #ifdef ARDUINO_FIREBEETLE32 | ||
auto voltage = GetAdcVoltage() * 2; | ||
// #endif | ||
|
||
for (uint8_t i = 0; i < voltageCx.size(); i++) { | ||
if(voltage > voltageCx[i]) { | ||
if(voltage < voltageCx[i + 1]) { | ||
return i * 10; | ||
} | ||
} | ||
} | ||
return 0; | ||
} |
Oops, something went wrong.