initial commit
This commit is contained in:
commit
5e172c05ef
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# SyncGrips Firmware
|
||||
## BLE-enabled Pushup Parallettes
|
||||
|
||||
|
||||
## Display Library Configuration for TTGO Dev Board
|
||||
|
||||
To config the [TFT eSPI library](https://github.com/Bodmer/TFT_eSPI), you have to edit `User_Setup_Select.h` in the library location.
|
||||
Comment out `#include <User_Setup.h>` and uncomment `#include <User_Setups/Setup25_TTGO_T_Display.h>`.
|
||||
|
||||
|
||||
506
SyncGrips/SyncGrips.ino
Normal file
506
SyncGrips/SyncGrips.ino
Normal file
@ -0,0 +1,506 @@
|
||||
#define ESP32
|
||||
//#define LEFT_DEVICE
|
||||
#define DEBUG_SAMPLING
|
||||
|
||||
|
||||
#include "Wire.h"
|
||||
#include "HX711.h"
|
||||
//Libraries for OLED Display
|
||||
#include <TFT_eSPI.h>
|
||||
#include <SPI.h>
|
||||
#include "esp_timer.h"
|
||||
#include <Preferences.h>
|
||||
|
||||
#ifdef CORE_DEBUG_LEVEL
|
||||
#undef CORE_DEBUG_LEVEL
|
||||
#endif
|
||||
|
||||
#define CORE_DEBUG_LEVEL 2
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
|
||||
|
||||
#include "esp_log.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEServer.h>
|
||||
#include <BLEUtils.h>
|
||||
|
||||
#ifndef TFT_DISPOFF
|
||||
#define TFT_DISPOFF 0x28
|
||||
#endif
|
||||
|
||||
#ifndef TFT_SLPIN
|
||||
#define TFT_SLPIN 0x10
|
||||
#endif
|
||||
// PIN DEFINITIONS
|
||||
#define TFT_MOSI 19
|
||||
#define TFT_SCLK 18
|
||||
#define TFT_CS 5
|
||||
#define TFT_DC 16
|
||||
#define TFT_RST 23
|
||||
|
||||
#define TFT_BL 4 // Display backlight control pin
|
||||
#define ADC_EN 14 // ADC_EN is the ADC detection enable port
|
||||
#define ADC_PIN 34
|
||||
#define ADC_POWER 34
|
||||
|
||||
#ifdef DEBUG_SAMPLING
|
||||
#define SAMPLE_INDICATOR 27
|
||||
#define SAMPLE_INDICATOR_1 26
|
||||
#endif
|
||||
|
||||
#ifdef LEFT_DEVICE
|
||||
static const char* TAG = "SyncGrip L";
|
||||
#define BUTTON_1 (gpio_num_t)35
|
||||
#define BUTTON_2 (gpio_num_t)0
|
||||
#else
|
||||
static const char* TAG = "SyncGrip R";
|
||||
#define BUTTON_1 (gpio_num_t)35
|
||||
#define BUTTON_2 (gpio_num_t)0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
|
||||
|
||||
Preferences preferences;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define THRESHOLD 40 /* Greater the value, more the sensitivity */
|
||||
#else //ESP32-S2 and ESP32-S3 + default for other chips (to be adjusted) */
|
||||
#define THRESHOLD 5000 /* Lower the value, more the sensitivity */
|
||||
#endif
|
||||
|
||||
RTC_DATA_ATTR int bootCount = 0;
|
||||
touch_pad_t touchPin;
|
||||
|
||||
#define SDA_1 21
|
||||
#define SCL_1 22
|
||||
|
||||
// Module connection pins (Digital Pins)
|
||||
#define CLK 22
|
||||
#define DIO 21
|
||||
|
||||
enum DeviceState {UNCONNECTED, CONNECTED, CALIBRATE};
|
||||
enum DeviceState state = UNCONNECTED;
|
||||
|
||||
int old_btn_state =1 ;
|
||||
int btn_state = 0;
|
||||
|
||||
float reading;
|
||||
float maxReading;
|
||||
|
||||
|
||||
uint64_t nLoopRuns = 0;
|
||||
uint64_t nSamples = 0 ;
|
||||
int missedSamples =0;
|
||||
|
||||
HX711 scale;
|
||||
|
||||
uint32_t scaleOffset;
|
||||
float scaleScaler;
|
||||
|
||||
// TIME SECTION
|
||||
int64_t time_since_boot;
|
||||
esp_timer_handle_t button_timer;
|
||||
esp_timer_handle_t sampling_timer;
|
||||
|
||||
static void button_timer_callback(void* arg);
|
||||
static void sampling_timer_callback(void* arg);
|
||||
|
||||
|
||||
// BLE SECTION
|
||||
BLEServer *pServer = NULL;
|
||||
|
||||
BLECharacteristic *sensor_val_characteristic = NULL;
|
||||
BLECharacteristic *bat_val_characteristic = NULL;
|
||||
BLECharacteristic *sync_characteristic = NULL;
|
||||
BLECharacteristic *calibrate_characteristic = NULL;
|
||||
|
||||
// See the following for generating UUIDs:
|
||||
// https://www.uuidgenerator.net/
|
||||
|
||||
#define SERVICE_UUID "00567f83-72b0-4f28-b7ef-1fce18766da6"
|
||||
#define SENSOR_VAL_CHARACTERISTIC_UUID "082c9546-6a26-4230-a7b2-8d13fa96da55"
|
||||
#define BAT_VAL_CHARACTERISTIC_UUID "53aec279-cf8f-423f-bf13-38f778696fa0"
|
||||
#define SYNC_CHARACTERISTIC_UUID "f1a13d24-57f0-4264-96bf-2c97c8a37561"
|
||||
#define CALIBRATE_CHARACTERISTIC_UUID "89cc5093-096a-4d3e-b7db-18a979bb81fb"
|
||||
|
||||
// TIMERS
|
||||
void initButtonTimer(){
|
||||
const esp_timer_create_args_t button_timer_args = {
|
||||
.callback = &button_timer_callback,
|
||||
/* name is optional, but may help identify the timer when debugging */
|
||||
.name = "buttonpoll"
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&button_timer_args, &button_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(button_timer, 100000));//every 100ms
|
||||
}
|
||||
|
||||
void initSamplingTimer(){
|
||||
const esp_timer_create_args_t sampling_timer_args = {
|
||||
.callback = &sampling_timer_callback,
|
||||
.name = "sampling"
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&sampling_timer_args, &sampling_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(sampling_timer, 105000));//every 105ms
|
||||
}
|
||||
|
||||
// BLE CALLBACKS
|
||||
class MyServerCallbacks : public BLEServerCallbacks
|
||||
{
|
||||
void onConnect(BLEServer *pServer)
|
||||
{
|
||||
Serial.println("Connected");
|
||||
state = CONNECTED;
|
||||
};
|
||||
|
||||
void onDisconnect(BLEServer *pServer)
|
||||
{
|
||||
state = UNCONNECTED;
|
||||
Serial.println("Disconnected, starting advertising again...");
|
||||
// Start advertising
|
||||
pServer->getAdvertising()->start();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
float measureBattery(){
|
||||
// measures with 12 bit ADC on a voltage divider with 3.3V power supply
|
||||
uint16_t readVal = analogRead(ADC_POWER);
|
||||
float vBat = 2.*3.3*((0.0+readVal) / 4096.0);
|
||||
ESP_LOGE(TAG, "Measure BAT: %d %fV", readVal, vBat);
|
||||
return vBat;
|
||||
}
|
||||
|
||||
int batteryPercent(float vBat){
|
||||
return int(100*(vBat-3.3)/(4.2-3.3));
|
||||
}
|
||||
|
||||
bool screenon = true;
|
||||
|
||||
void toggleScreen(){
|
||||
screenon = !screenon;
|
||||
if (screenon){
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
||||
}
|
||||
else {
|
||||
digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
void tare(){
|
||||
state = CALIBRATE;
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.drawString("TARE", 120,32);
|
||||
scale.tare(20);
|
||||
uint32_t offset = scale.get_offset();
|
||||
preferences.begin("calibration", false); //false for r/w mode instead of just r
|
||||
preferences.putULong("offset", offset);
|
||||
preferences.end();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.drawString("DONE", 120,32);
|
||||
delay(500);
|
||||
state = CONNECTED;
|
||||
Serial.println("DONE TARE");
|
||||
}
|
||||
|
||||
void calibrate(int weightGrams){
|
||||
state = CALIBRATE;
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.drawString("calibrate", 120,32);
|
||||
scale.calibrate_scale(weightGrams, 20);
|
||||
float scaler = scale.get_scale();
|
||||
preferences.begin("calibration", false); //false for r/w mode instead of just r
|
||||
preferences.putFloat("scale", scaler);
|
||||
preferences.end();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.drawString("DONE", 120,32);
|
||||
delay(500);
|
||||
state = CONNECTED;
|
||||
}
|
||||
|
||||
class BatteryCharacteristicCallbacks: public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic *pCharacteristic) {
|
||||
float batVal = measureBattery();
|
||||
int batPercent = batteryPercent(batVal);
|
||||
bat_val_characteristic->setValue(String(batPercent).c_str());
|
||||
bat_val_characteristic->notify();
|
||||
}
|
||||
};
|
||||
|
||||
class SyncCharacteristicCallbacks: public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic *pCharacteristic) {
|
||||
// TODO handle SYNC event
|
||||
std::string value = pCharacteristic->getValue();
|
||||
uint32_t int_val = (uint32_t) value.c_str();
|
||||
state = CALIBRATE;
|
||||
ESP_ERROR_CHECK(esp_timer_stop(sampling_timer));
|
||||
#ifdef LEFT_DEVICE
|
||||
delay(1000);
|
||||
#else
|
||||
delay(532); // measured 32ms offset
|
||||
#endif
|
||||
tft.fillScreen(TFT_RED);
|
||||
delay(200);
|
||||
nSamples = 0;
|
||||
missedSamples = 0;
|
||||
state = CONNECTED;
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(sampling_timer, 105000));//every 105ms
|
||||
}
|
||||
};
|
||||
|
||||
class CalibrateCharacteristicCallbacks: public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic *pCharacteristic) {
|
||||
state = CALIBRATE;
|
||||
Serial.println("SHOW ME THE CALIBRATE");
|
||||
tft.fillScreen(TFT_RED);
|
||||
delay(200);
|
||||
int nGrams = atoi(pCharacteristic->getValue().c_str());
|
||||
if(nGrams == 0) {
|
||||
tare();
|
||||
}
|
||||
if(nGrams > 0) {
|
||||
calibrate(nGrams);
|
||||
}
|
||||
state=CONNECTED;
|
||||
}
|
||||
};
|
||||
|
||||
class CharacteristicsCallbacks : public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic *pCharacteristic) {
|
||||
std::string value = pCharacteristic->getValue();
|
||||
uint32_t int_val = (uint32_t) value.c_str();
|
||||
Serial.println("some value arrived");
|
||||
tft.fillScreen(TFT_RED);
|
||||
delay(2000);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void drawReading(float reading, float maxReading) {
|
||||
String out = String(reading<0?0:reading)+"kg";
|
||||
String out1 = String(maxReading)+"kg";
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.drawString(out, 120, 32);
|
||||
tft.drawString(out1, 120, 84);
|
||||
}
|
||||
|
||||
void drawDebugReading(float reading, int missedCount) {
|
||||
String out = String(reading<0?0:reading)+"kg";
|
||||
String out1 = String(missedCount)+" "+ (state==UNCONNECTED ? "NC": "C");
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.drawString(out, 120, 32);
|
||||
tft.drawString(out1, 120, 84);
|
||||
}
|
||||
|
||||
|
||||
void initScale(){
|
||||
scale.begin(DIO, CLK);
|
||||
preferences.begin("calibration", false); //false for r/w mode instead of just r
|
||||
float scaler = preferences.getFloat("scale", -26.326582);
|
||||
uint32_t offset = preferences.getULong("offset", 4294856599);
|
||||
preferences.end();
|
||||
|
||||
scale.set_offset(offset);
|
||||
scale.set_scale(scaler);
|
||||
}
|
||||
|
||||
|
||||
void initTFT(){
|
||||
tft.init();
|
||||
tft.setTextSize(5);
|
||||
|
||||
if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
|
||||
pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
|
||||
}
|
||||
#ifdef LEFT_DEVICE
|
||||
tft.setRotation(1);
|
||||
#else
|
||||
tft.setRotation(3);
|
||||
#endif
|
||||
tft.fillScreen(TFT_RED);
|
||||
delay(20);
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
delay(20);
|
||||
tft.fillScreen(TFT_GREEN);
|
||||
delay(20);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
|
||||
tft.drawString("Hello!", tft.width() / 2, tft.height() / 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t currentReadingTimestamp;
|
||||
int64_t readingStartTimestamp;
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
initTFT();
|
||||
//Increment boot number and print it every reboot
|
||||
++bootCount;
|
||||
Serial.println("Boot number: " + String(bootCount));
|
||||
|
||||
// TOGGLE Pin for sampling timing mesurements
|
||||
#ifdef DEBUG_SAMPLING
|
||||
pinMode(SAMPLE_INDICATOR, OUTPUT);
|
||||
pinMode(SAMPLE_INDICATOR_1, OUTPUT);
|
||||
#endif
|
||||
|
||||
initScale();
|
||||
|
||||
|
||||
pinMode(BUTTON_1, INPUT);
|
||||
pinMode(BUTTON_2, INPUT);
|
||||
|
||||
BLEDevice::init(TAG);
|
||||
// Create the BLE Server
|
||||
pServer = BLEDevice::createServer();
|
||||
pServer->setCallbacks(new MyServerCallbacks());
|
||||
// Create the BLE Service
|
||||
BLEService *pService = pServer->createService(SERVICE_UUID);
|
||||
delay(100);
|
||||
|
||||
uint32_t props = BLECharacteristic::PROPERTY_READ |
|
||||
BLECharacteristic::PROPERTY_WRITE |
|
||||
BLECharacteristic::PROPERTY_NOTIFY |
|
||||
BLECharacteristic::PROPERTY_INDICATE;
|
||||
|
||||
// Create BLE Characteristics
|
||||
sensor_val_characteristic = pService->createCharacteristic(
|
||||
SENSOR_VAL_CHARACTERISTIC_UUID,
|
||||
props);
|
||||
|
||||
bat_val_characteristic = pService->createCharacteristic(
|
||||
BAT_VAL_CHARACTERISTIC_UUID,
|
||||
props);
|
||||
|
||||
sync_characteristic = pService->createCharacteristic(
|
||||
SYNC_CHARACTERISTIC_UUID,
|
||||
props);
|
||||
|
||||
calibrate_characteristic = pService->createCharacteristic(
|
||||
CALIBRATE_CHARACTERISTIC_UUID,
|
||||
props);
|
||||
|
||||
|
||||
sensor_val_characteristic->setValue("0.0 0");
|
||||
|
||||
float vBat = measureBattery();
|
||||
int batPercent = batteryPercent(vBat);
|
||||
/* Serial.println("VBAT: "+ String(vBat)+", "+String(batPercent)+"%"); */
|
||||
bat_val_characteristic->setValue(String(batPercent).c_str());
|
||||
//#ifdef LEFT_DEVICE
|
||||
//bat_val_characteristic->setValue("7");
|
||||
//#else
|
||||
//bat_val_characteristic->setValue("99");
|
||||
//#endif
|
||||
|
||||
bat_val_characteristic->setCallbacks(new CharacteristicsCallbacks());
|
||||
sensor_val_characteristic->setCallbacks(new CharacteristicsCallbacks());
|
||||
sync_characteristic->setCallbacks(new SyncCharacteristicCallbacks());
|
||||
calibrate_characteristic->setCallbacks(new CalibrateCharacteristicCallbacks());
|
||||
|
||||
|
||||
// Start the BLE service
|
||||
pService->start();
|
||||
|
||||
// Start advertising
|
||||
pServer->getAdvertising()->start();
|
||||
|
||||
|
||||
Serial.println("Waiting for a client connection to notify...");
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
//esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0);
|
||||
esp_sleep_enable_ext0_wakeup(BUTTON_1, 0);
|
||||
|
||||
initButtonTimer();
|
||||
initSamplingTimer();
|
||||
time_since_boot = esp_timer_get_time();
|
||||
readingStartTimestamp = esp_timer_get_time();
|
||||
ESP_LOGI(TAG, "startup finished, time since boot: %lld us", time_since_boot);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
nLoopRuns++;
|
||||
|
||||
//time_since_boot = esp_timer_get_time();
|
||||
//ESP_LOGI(TAG, "loop called, time since boot: %lld us", time_since_boot);
|
||||
|
||||
float vBat = measureBattery();
|
||||
int batPercent = batteryPercent(vBat);
|
||||
//Serial.println("VBAT: "+ String(vBat)+", "+String(batPercent)+"%");
|
||||
bat_val_characteristic->setValue(String(batPercent).c_str());
|
||||
bat_val_characteristic->notify();
|
||||
delay(20000);
|
||||
}
|
||||
|
||||
|
||||
static void sampling_timer_callback(void* arg){
|
||||
digitalWrite(SAMPLE_INDICATOR, HIGH);
|
||||
int64_t localTimestamp;
|
||||
char valuesOut[20];
|
||||
|
||||
if (state == CALIBRATE) {
|
||||
return;
|
||||
}
|
||||
nSamples = (nSamples + 1) % 3000;
|
||||
|
||||
scale.wait_ready();
|
||||
if (scale.is_ready()) {
|
||||
digitalWrite(SAMPLE_INDICATOR_1, HIGH);
|
||||
reading = scale.get_units()/1000;
|
||||
reading = reading <0 ? 0:reading;
|
||||
//currentReadingTimestamp = esp_timer_get_time();
|
||||
//localTimestamp = currentReadingTimestamp - readingStartTimestamp;
|
||||
sprintf(valuesOut, "%.2f %d", reading, nSamples);// localTimestamp);
|
||||
// sending reading via BLE
|
||||
if(state == CONNECTED){
|
||||
sensor_val_characteristic->setValue(valuesOut);
|
||||
#ifdef LEFT_DEVICE
|
||||
delay(10);
|
||||
#endif
|
||||
sensor_val_characteristic->notify();
|
||||
}
|
||||
if (reading > maxReading){ maxReading=reading;}
|
||||
digitalWrite(SAMPLE_INDICATOR_1, LOW);
|
||||
if(screenon){
|
||||
//drawReading(reading, maxReading);
|
||||
drawDebugReading(reading, missedSamples);
|
||||
}
|
||||
/* ESP_LOGI(TAG, "scale was ready, time since last reading: %lld us", localTimestamp); */
|
||||
} else {
|
||||
missedSamples++;
|
||||
drawDebugReading(reading, missedSamples);
|
||||
}
|
||||
digitalWrite(SAMPLE_INDICATOR, LOW);
|
||||
}
|
||||
|
||||
static void button_timer_callback(void* arg){
|
||||
btn_state = digitalRead(BUTTON_1);
|
||||
if(btn_state && !old_btn_state){
|
||||
ESP_ERROR_CHECK(esp_timer_stop(button_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_delete(button_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_stop(sampling_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_delete(sampling_timer));
|
||||
Serial.println("pressed sleep button");
|
||||
maxReading=0;
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.drawString("Bye...", tft.width() / 2, tft.height() / 2);
|
||||
delay(500);
|
||||
esp_deep_sleep_start();
|
||||
//toggleScreen();
|
||||
}
|
||||
old_btn_state = btn_state;
|
||||
//Serial.println(nLoopRuns);
|
||||
// nLoopRuns = 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user