I'm currently working on a project, where i want to measure accelerometer Data while brushing teeth. On a long way of getting used with arduinos and searching for a good low power solution(The toothbrush should last for at least 30 days in standby while measuring 2x3min per day) i created a first prototyp using a ESP32 Wroom and my first custom PCB As i am a mechanical engineer a lot of this was new for me and i think i might not allways choose the best practice solution.
Anyway, the System is built up by the following components:
ESP32 Wroom
CR123a 3V Lithium battery 1600mah
Bosch BMI160 IMU
SD card module
Cupperfoil connected to GPIO for measuring if device is touched
Right now everything works more or less. I was able to push down the consumption to 0.9ma in deep sleep ( need to figure out how to put the BMI160 in suspend mode as well, right now it is consuming almost everything when in deepsleep) and i can write IMU data around 40HZ to the SD card (working on a better way to buffer the data and not sampling it directly to the sd card)
But what i really dont understand is, the problem i have with the touch sensor used for interrrupt. I connected a cupper foil which goes around the toothbrush case for detection of skin. If i do not touch it the capacity value is around 90 and if i touch the divice without pressing to hard it drops to ~40. Thats why i choose a threshold of 80, because a false positive would not be so problematic as missing values in my case.
Everything works fine so far, and im able to measure everything as i wanted. BUT if i just let the toothbrush rest over night and use it the next morning, it doesn't log the data.. If i get the battery out and try it again afterwards it just works fine
I really dont Know, if i did something stupid in the code or if the capacity drifts over time while in battery mode or something else..? For me it is only necessery to turn the esp on when somebody grabs the toothbrush, thats why i thought the touchread() would be easy to use, as i only have a simple detection..
I would be super glad if somebody could help me and maybe sees some bad practice here, which leads to problems..
Here are some pictures of the prototyp and the code:
Code: Select all
#include <DFRobot_BMI160.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#define Threshold 80
DFRobot_BMI160 bmi160;
const int8_t i2c_addr = 0x69;
void callback(){
}
void setupSDCard(){
if(!SD.begin()){
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
return;
}
}
void setupBMI(){
//init the hardware bmin160
if (bmi160.softReset() != BMI160_OK){
while(1);
}
//set and init the bmi160 i2c address
if (bmi160.I2cInit(i2c_addr) != BMI160_OK){
while(1);
}
}
void setupTouch(){
}
void setup(){
Serial.begin(115200);
touch_pad_init();
touch_pad_deinit();
setupSDCard();
setupBMI();
if(!SD.exists("/data.csv")){
File file = SD.open("/data.txt" ,FILE_APPEND);
file.print("Time in millis;Gx;Gy;Gz;X;Y;Z\n");
file.close();
}
}
void loop(){
//bmi160.wakeUp();
int i = 0;
int rslt;
int16_t accelGyro[6]={0};
//get both accel and gyro data from bmi160
//parameter accelGyro is the pointer to store the data
unsigned long check = millis();
File file = SD.open("/data.txt" ,FILE_APPEND);
Serial.println("while");
while(touchRead(T3) < Threshold || millis()-check<5000){
//Setzt den check immer auf aktuell solange Kontakt besteht
if(touchRead(T3) < Threshold){
check = millis();
}
//Gets the data
rslt = bmi160.getAccelGyroData(accelGyro);
if(rslt == 0){
file.print(millis());file.print(";");
file.print(accelGyro[0]*3.14/180.0);file.print(";");
file.print(accelGyro[1]*3.14/180.0);file.print(";");
file.print(accelGyro[2]*3.14/180.0);file.print(";");
file.print(accelGyro[3]/16384.0);file.print(";");
file.print(accelGyro[4]/16384.0);file.print(";");
file.print(accelGyro[5]/16384.0);file.print(";");
file.print(touchRead(T3));file.print(";");
file.print("\n");
}
}
file.print("Aufnahme beendet");
file.close();
Serial.println("Going to sleep");
SD.end();
//bmi160.setLowPower();
touchAttachInterrupt(T3, callback, Threshold);
esp_sleep_enable_touchpad_wakeup();
esp_deep_sleep_start();
}