Skip to content

Instantly share code, notes, and snippets.

@kylejohnson
Last active February 15, 2021 16:56

Revisions

  1. kylejohnson revised this gist Feb 15, 2021. 1 changed file with 128 additions and 208 deletions.
    336 changes: 128 additions & 208 deletions pulse.ino
    Original file line number Diff line number Diff line change
    @@ -1,248 +1,168 @@
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    #include <SparkFun_Bio_Sensor_Hub_Library.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>

    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

    const char ssid[] = "skynet_";
    const char pass[] = "fubar";
    const byte resPin = 14;
    const byte mfioPin = 12;
    const int MPU_ADDR = 0x68;

    SparkFun_Bio_Sensor_Hub bioHub(resPin, mfioPin);
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
    bioData body;
    WiFiUDP udp;


    void setup_wifi(){
    WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
    Serial.println();
    Serial.print("Connected! IP address: ");
    Serial.println(WiFi.localIP());
    }


    void setup_lcd(){
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
    delay(2000);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println("Starting up!");
    display.display();
    }


    void setup_bio(){
    int result = bioHub.begin();
    if (result == 0) // Zero errors!
    Serial.println("Sensor started!");
    else
    Serial.println("Could not communicate with the sensor!!!");

    Serial.println("Configuring Sensor....");
    int error = bioHub.configBpm(MODE_ONE); // Configuring just the BPM settings.
    if(error == 0){ // Zero errors!
    Serial.println("Sensor configured.");
    }
    else {
    Serial.println("Error configuring sensor.");
    Serial.print("Error: ");
    Serial.println(error);
    }

    Serial.println("Loading up the buffer with data....");
    delay(4000);
    }


    void setup_mpu(){
    Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
    Wire.write(0x6B); // PWR_MGMT_1 register
    Wire.write(0); // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);
    }
    #include <SPI.h>
    #if defined(ESP32)
    #include <WiFi.h>
    #elif defined(ESP8266)
    #include <ESP8266WiFi.h>
    #else
    #error "Only ESP32 and ESP8266 are supported!"
    #endif
    #include <WiFiUdp.h>
    #include "pulse.h"


    void setup(){
    Serial.begin(115200);
    Wire.begin();
    delay(500);

    setup_mpu();
    setup_wifi();
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
    setup_lcd();
    setup_bio();
    setup_mpu();
    }

    delay(500);
    }

    void write_led(byte oxygen, byte heartrate, byte sts, char* msg) {
    display.clearDisplay();
    delay(100);

    display.setTextColor(WHITE);
    display.setTextSize(1);

    if (sts == 0) {
    display.setCursor(15, 0);
    display.print("No object detected");
    } else if (sts == 1) {
    display.setCursor(15, 0);
    display.print("Object detected");
    } else if (sts == 2) {
    display.setCursor(15, 0);
    display.print("Non-finger detected");
    } else if (sts == 3) {
    display.setCursor(15, 0);
    display.print("sP02");

    display.setCursor(50, 0);
    display.print("BPM");

    display.setCursor(85, 0);
    display.print("Sending");


    display.setCursor(17, 17);
    display.print(oxygen);
    display.print("%");

    display.setCursor(52, 17);
    display.print(heartrate);

    display.setCursor(87, 17);
    display.print(msg);
    }

    display.display();
    void loop(){
    do_bpm();
    delay(10);
    }


    void send_to_influxdb(byte bheartrate, byte bconfidence, byte boxygen, byte bsts){
    char heartrate[4];
    itoa(bheartrate, heartrate, 10);

    char confidence[4];
    itoa(bconfidence, confidence, 10);

    char oxygen[4];
    itoa(boxygen, oxygen, 10);

    char sts[2];
    itoa(bsts, sts, 10);

    Serial.println("Sending Bio data to InfluxDB.");
    char line[64];
    sprintf(line, "bpm,confidence=%s,status=%d heartrate=%di,oxygen=%di", confidence, bsts, bheartrate, boxygen);
    void send_udp(char line[64]) {
    Serial.println(line);

    udp.beginPacket("192.168.1.158", 8089);
    udp.write(line);
    udp.endPacket();
    // udp.beginPacket(influxHost, influxPort);
    // udp.write(line);
    // udp.endPacket();
    }


    void do_mpu(){
    Wire.beginTransmission(MPU_ADDR);
    Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
    Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
    Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_addr,6); // request a total of 14 registers
    int16_t ax,ay,az,gx,gy,gz;


    int16_t ax, ay, az; // variables for accelerometer raw data
    int16_t gx, gy, gz; // variables for gyro raw data
    int16_t temperature; // variables for temperature data
    char tmp_str[7]; // temporary variable used in convert function

    // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
    ax = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
    ay = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
    az = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
    temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
    gx = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
    gy = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
    gz = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)

    Serial.println("Sending MPU data to InfluxDB.");
    char line[64];
    sprintf(line, "mpu ax=%di,ay=%di,az=%di,gx=%di,gy=%di,gz=%di", ax, ay, az, gx, gy, gz);
    Serial.println(line);
    ax=Wire.read()<<8|Wire.read() / 16384; // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    ay=Wire.read()<<8|Wire.read() / 16384; // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    az=Wire.read()<<8|Wire.read() / 16384; // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

    udp.beginPacket("192.168.1.158", 8089);
    udp.write(line);
    udp.endPacket();
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x43); // Gyro data first register address 0x43
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_addr,6);
    gx=Wire.read()<<8|Wire.read() / 131; // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    gy=Wire.read()<<8|Wire.read() / 131; // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    gz=Wire.read()<<8|Wire.read() / 131; // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)


    char mpu_line[64];
    sprintf(mpu_line, "mpu ax=%di,ay=%di,az=%di,gx=%di,gy=%di,gz=%di",
    ax,
    ay,
    az,
    gx,
    gy,
    gz
    );

    send_udp(mpu_line);
    }


    void loop(){
    // uint16_t heartrate; // LSB = 0.1bpm
    // uint8_t confidence; // 0-100% LSB = 1%
    // uint16_t oxygen; // 0-100% LSB = 1%
    // uint8_t sts; // 0: Success, 1: Not Ready, 2: Object Detectected, 3: Finger Detected

    void do_bpm() {
    uint16_t t = millis();
    static uint16_t t_old = 0;
    int16_t t_diff;
    uint8_t samples = bioHub.numSamplesOutFifo();
    static uint16_t t_old = t;
    uint16_t t_diff;

    uint8_t samples = bioHub.numSamplesOutFifo();

    //read all samples in fifo and use most recent one
    while(samples){
    body = bioHub.readBpm();
    samples--;
    while(samples){
    body = bioHub.readSensorBpm();
    samples--;
    }

    t_diff = t - t_old;
    if(t_diff>=1000){

    if (t_diff >= 1000) {
    byte heartrate, confidence, oxygen, sts;
    char bpm_line[64];

    t_old += 1000;

    byte bheartrate = body.heartRate;
    byte bconfidence = body.confidence;
    byte boxygen = body.oxygen;
    byte bsts = body.status;
    body = bioHub.readSensorBpm();
    heartrate = body.heartRate;
    confidence = body.confidence;
    oxygen = body.oxygen;
    sts = body.status;

    Serial.printf("Heartrate: %d\n", bheartrate);
    Serial.printf("Confidence: %d\n", bconfidence);
    Serial.printf("Oxygen: %d\n", boxygen);
    Serial.printf("Status: %d\n", bsts);
    Serial.println();

    if (bsts == 3 && boxygen > 10 && bheartrate > 10) {
    send_to_influxdb(bheartrate, bconfidence, boxygen, bsts);
    write_led(boxygen, bheartrate, bsts, "Yes");
    } else {
    write_led(boxygen, bheartrate, bsts, "No");
    }
    // Serial.printf("Heartrate: %d, Confidence: %d, Oxygen: %d, Status: %d\n", heartrate, confidence, oxygen, sts);
    sprintf(bpm_line, "bpm,confidence=%d,status=%d heartrate=%di,oxygen=%di", confidence, sts, heartrate, oxygen);
    send_udp(bpm_line);

    do_mpu();

    samples = bioHub.numSamplesOutFifo();
    Serial.println();
    }
    do_mpu();
    }

    //clear fifo before delay
    while(samples){
    body = bioHub.readBpm();
    samples--;
    body = bioHub.readSensorBpm();
    samples--;
    }
    }

    delay(10);
    void setup_wifi(){
    WiFi.begin(ssid, pass);
    Serial.print("Connecting to wifi...");
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
    Serial.print(" Connected! IP address: ");
    Serial.println(WiFi.localIP());
    }


    void setup_bio(){
    uint8_t result = bioHub.begin();
    if (result == 0) {
    Serial.println("Sensor started!");

    Serial.print("Configuring Sensor... ");
    uint8_t error = bioHub.configSensorBpm(MODE_ONE);

    if (error == 0) {
    Serial.println("Done!");

    error = bioHub.setPulseWidth(width);
    if (error == 0){
    Serial.printf("Pulse Width set to %d.\n", bioHub.readPulseWidth());
    } else {
    Serial.printf("Could not set Pulse Width! Error: %d\n", error);
    }

    error = bioHub.setSampleRate(samples);
    if (error == 0){
    Serial.printf("Sample Rate set to %d.\n", bioHub.readSampleRate());
    } else {
    Serial.printf("Could not set Sample Rate! Error: %d\n", error);
    }

    } else {
    Serial.printf("Error configuring sensor! Error: %d\n", error);
    }

    } else {
    Serial.printf("Could not start sensor! Error: %d\n", result);
    }
    }


    void setup_mpu(){
    Wire.begin();
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x6B);
    Wire.write(0x00);
    Wire.endTransmission(true);
    }
  2. kylejohnson created this gist Feb 6, 2021.
    248 changes: 248 additions & 0 deletions pulse.ino
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,248 @@
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    #include <SparkFun_Bio_Sensor_Hub_Library.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>

    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

    const char ssid[] = "skynet_";
    const char pass[] = "fubar";
    const byte resPin = 14;
    const byte mfioPin = 12;
    const int MPU_ADDR = 0x68;

    SparkFun_Bio_Sensor_Hub bioHub(resPin, mfioPin);
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
    bioData body;
    WiFiUDP udp;


    void setup_wifi(){
    WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
    Serial.println();
    Serial.print("Connected! IP address: ");
    Serial.println(WiFi.localIP());
    }


    void setup_lcd(){
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
    delay(2000);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println("Starting up!");
    display.display();
    }


    void setup_bio(){
    int result = bioHub.begin();
    if (result == 0) // Zero errors!
    Serial.println("Sensor started!");
    else
    Serial.println("Could not communicate with the sensor!!!");

    Serial.println("Configuring Sensor....");
    int error = bioHub.configBpm(MODE_ONE); // Configuring just the BPM settings.
    if(error == 0){ // Zero errors!
    Serial.println("Sensor configured.");
    }
    else {
    Serial.println("Error configuring sensor.");
    Serial.print("Error: ");
    Serial.println(error);
    }

    Serial.println("Loading up the buffer with data....");
    delay(4000);
    }


    void setup_mpu(){
    Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
    Wire.write(0x6B); // PWR_MGMT_1 register
    Wire.write(0); // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);
    }


    void setup(){
    Serial.begin(115200);
    Wire.begin();

    setup_wifi();
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
    setup_lcd();
    setup_bio();
    setup_mpu();
    }


    void write_led(byte oxygen, byte heartrate, byte sts, char* msg) {
    display.clearDisplay();
    delay(100);

    display.setTextColor(WHITE);
    display.setTextSize(1);

    if (sts == 0) {
    display.setCursor(15, 0);
    display.print("No object detected");
    } else if (sts == 1) {
    display.setCursor(15, 0);
    display.print("Object detected");
    } else if (sts == 2) {
    display.setCursor(15, 0);
    display.print("Non-finger detected");
    } else if (sts == 3) {
    display.setCursor(15, 0);
    display.print("sP02");

    display.setCursor(50, 0);
    display.print("BPM");

    display.setCursor(85, 0);
    display.print("Sending");


    display.setCursor(17, 17);
    display.print(oxygen);
    display.print("%");

    display.setCursor(52, 17);
    display.print(heartrate);

    display.setCursor(87, 17);
    display.print(msg);
    }

    display.display();
    }


    void send_to_influxdb(byte bheartrate, byte bconfidence, byte boxygen, byte bsts){
    char heartrate[4];
    itoa(bheartrate, heartrate, 10);

    char confidence[4];
    itoa(bconfidence, confidence, 10);

    char oxygen[4];
    itoa(boxygen, oxygen, 10);

    char sts[2];
    itoa(bsts, sts, 10);

    Serial.println("Sending Bio data to InfluxDB.");
    char line[64];
    sprintf(line, "bpm,confidence=%s,status=%d heartrate=%di,oxygen=%di", confidence, bsts, bheartrate, boxygen);
    Serial.println(line);

    udp.beginPacket("192.168.1.158", 8089);
    udp.write(line);
    udp.endPacket();
    }


    void do_mpu(){
    Wire.beginTransmission(MPU_ADDR);
    Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
    Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
    Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers


    int16_t ax, ay, az; // variables for accelerometer raw data
    int16_t gx, gy, gz; // variables for gyro raw data
    int16_t temperature; // variables for temperature data
    char tmp_str[7]; // temporary variable used in convert function

    // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
    ax = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
    ay = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
    az = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
    temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
    gx = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
    gy = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
    gz = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)

    Serial.println("Sending MPU data to InfluxDB.");
    char line[64];
    sprintf(line, "mpu ax=%di,ay=%di,az=%di,gx=%di,gy=%di,gz=%di", ax, ay, az, gx, gy, gz);
    Serial.println(line);

    udp.beginPacket("192.168.1.158", 8089);
    udp.write(line);
    udp.endPacket();
    }


    void loop(){
    // uint16_t heartrate; // LSB = 0.1bpm
    // uint8_t confidence; // 0-100% LSB = 1%
    // uint16_t oxygen; // 0-100% LSB = 1%
    // uint8_t sts; // 0: Success, 1: Not Ready, 2: Object Detectected, 3: Finger Detected

    uint16_t t = millis();
    static uint16_t t_old = 0;
    int16_t t_diff;
    uint8_t samples = bioHub.numSamplesOutFifo();

    //read all samples in fifo and use most recent one
    while(samples){
    body = bioHub.readBpm();
    samples--;
    }

    t_diff = t - t_old;
    if(t_diff>=1000){
    t_old += 1000;

    byte bheartrate = body.heartRate;
    byte bconfidence = body.confidence;
    byte boxygen = body.oxygen;
    byte bsts = body.status;

    Serial.printf("Heartrate: %d\n", bheartrate);
    Serial.printf("Confidence: %d\n", bconfidence);
    Serial.printf("Oxygen: %d\n", boxygen);
    Serial.printf("Status: %d\n", bsts);
    Serial.println();

    if (bsts == 3 && boxygen > 10 && bheartrate > 10) {
    send_to_influxdb(bheartrate, bconfidence, boxygen, bsts);
    write_led(boxygen, bheartrate, bsts, "Yes");
    } else {
    write_led(boxygen, bheartrate, bsts, "No");
    }

    do_mpu();

    samples = bioHub.numSamplesOutFifo();
    Serial.println();
    }

    //clear fifo before delay
    while(samples){
    body = bioHub.readBpm();
    samples--;
    }

    delay(10);
    }