226 views|2 replies

280

Posts

7

Resources
The OP
 

[DigiKey Creative Competition] Portable Life Detector 04+ Driving BME680 and Designing UI [Copy link]

 
000

The previous post introduced how to use DMA to increase the frame rate of thermal imaging display. This post first introduces how to drive BME680 and display the detection results on the screen, and then designs an operation interaction interface to realize user operation functions.

1. Drive BME680 and display on the screen

BME680 has two interfaces: SPI and I2C. Since the SPI port of the ESP32-S3 development board I used is connected to the screen and SPI occupies more IO ports, I prefer to use the I2C interface to connect the BME680 board. To save trouble, I hang it and MLX90640 on the same I2C bus. See the figure below.
Then install the Adafruit BME680 Library in PlatformIO, as shown below.
Use the default routine test directly. You don't need to worry about the wheels made by Adafruit. Just flash them into the board and it will be OK. The test code is as follows.
Code 1:
/***************************************************************************
  This is a library for the BME680 gas, humidity, temperature & pressure sensor

  Designed specifically to work with the Adafruit BME680 Breakout
  ----> http://www.adafruit.com/products/3660

  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing products
  from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME680 bme; // I2C
//Adafruit_BME680 bme(BME_CS); // hardware SPI
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println(F("BME680 test"));

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms
}

void loop() {
  if (! bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  Serial.print("Temperature = ");
  Serial.print(bme.temperature);
  Serial.println(" *C");

  Serial.print("Pressure = ");
  Serial.print(bme.pressure / 100.0);
  Serial.println(" hPa");

  Serial.print("Humidity = ");
  Serial.print(bme.humidity);
  Serial.println(" %");

  Serial.print("Gas = ");
  Serial.print(bme.gas_resistance / 1000.0);
  Serial.println(" KOhms");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.println();
  delay(2000);
}

Then consider how to port it to the existing program. The blank area on the right side of the thermal image is prepared for BME680 data. A button is placed in the lower right corner to switch the screen function. The blank display effect is as shown below.
In terms of programming, an independent task is created specifically for BME680, which is set to read data every 2 seconds. The display task updates the screen when the data changes. The actual display effect is shown in the figure below.
Although the entire screen display is realized, I found a problem, that is, every time I read BME680, the thermal image refresh will be stuck, which is a bad experience. The reason is the shared bus. Fortunately, ESP32-S3 has multiple I2Cs and a super awesome GPIO switch matrix, which allows peripherals to use any IO port. So I found two idle IO ports A4 and A5 from the pin allocation table and configured them as I2C buses, as shown below.
Also make appropriate modifications in the program initialization, select I2C1, and call it directly. The code is as follows.
Code 2:
#define SEALEVELPRESSURE_HPA (1019.25)
Adafruit_BME680 bme(&Wire1); // I2C

void Bme680Init(void)
{
    Serial.println(F("BME680 async test"));
    // I2C init
    Wire1.begin(BME_SDA, BME_SCL);

    // bme.Adafruit_BME680(Wire1);

    if (!bme.begin())
    {
        Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
        while (1)
            ;
    }

    // Set up oversampling and filter initialization
    bme.setTemperatureOversampling(BME680_OS_8X);
    bme.setHumidityOversampling(BME680_OS_2X);
    bme.setPressureOversampling(BME680_OS_4X);
    bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
    bme.setGasHeater(320, 150); // 320*C for 150 ms
}

After all the above is done, the screen display becomes smooth. Although it looks a bit crude, it is no problem. The next step is to design the human-computer interaction.

2. Design the operation interface

My expected function is this: this work has two screen interfaces. The first screen interface displays thermal imaging images and environmental information, which is used to find rescued people whose body temperature is higher than the ambient temperature. The above has been done. The second screen interface displays an electrocardiogram, the purpose of which is to immediately perform a rapid electrocardiogram test on the person who is found after a life form is found, to help rescuers formulate the next rescue plan based on the electrocardiogram data.
The designed ECG acquisition interface is shown in the figure below.
The entire screen is partially allocated with a 480x240 dot matrix area for displaying the ECG waveform. The lower left corner is divided into two lines of text, one for lead-off information and one for heart rate. The button in the lower right corner is used to switch between the two interfaces.
ECG data is expected to be received from the serial port. Here I have created a separate task to temporarily generate random numbers to simulate ECG waveforms, heart rate, and lead-off information. By connecting the simulation data with the display task, the various functions of the ECG acquisition interface can be simulated. The simulation data generation code is as follows.
Code 3:
#include <Arduino.h>
#include <ecg.h>
#include <lcd.h>

uint8_t ECG_data = 0;
uint16_t ECG_hr = 0;
bool ECG_lead = true;
bool ECG_flag = true;

float ecg_data = 0;
float ecg_hr = 0;
float ecg_lead = 0;

void task_ecg(void *ptr)
{
    int i = 0;

    while (true)
    {
        vTaskDelay(4);
        ECG_flag = true;
        ECG_data = random(0, 239);
        ECG_hr = random(60, 120);
        if (ECG_hr > 110)
            ECG_lead = true;
        else
            ECG_lead = false;
    }
    vTaskDelete(NULL);
}

The TFT_eSPI library itself supports the touch function. You can directly call the API interface function to implement touch input event parsing. Through the button lock logic, each time you click the lower right button, the interface is switched and the button text changes accordingly. The specific code is as follows.
Code 4:

void LcdScreenSwitch(void)
{
    if (screen_lock == SCREEN_CAM)
    {
        lock_mxl = true;//禁能热成像采集
        screen_lock = SCREEN_ECG;
        tft.fillScreen(TFT_BLACK);
        LcdEcgBar();
        // Serial.println("ECG");
    }
    else
    {
        screen_lock = SCREEN_CAM;
        tft.fillScreen(TFT_BLACK);
        LcdColorBar();
        Bme680Display();
        lock_mxl = false;//使能热成像采集
        // Serial.println("CAM");
    }
}

bool Key_Short = false;
void LcdGetTouch(void)
{
    uint16_t x = 0, y = 0; // To store the touch coordinates

    // Pressed will be set true is there is a valid touch on the screen
    bool pressed = tft.getTouch(&x, &y);
    // Serial.println(pressed);
    // Draw a white spot at the detected coordinates
    if (pressed)
    {
        if ((x > 350) && (y > 260))
        {
            if (Key_Short == false)
            {
                Key_Short = true;
                LcdScreenSwitch(); // 切换屏幕
            }
        }
        else
        {
            Key_Short = false;
        }
    }
    else
    {
        Key_Short = false;
    }
}

At this point, the basic design of the user interface is completed. The specific demonstration effect can be seen in the video at the beginning. The next step is to collect and process the ECG data.

This post is from DigiKey Technology Zone

Latest reply

Every time I read the BME680, the thermal image refresh will freeze. This seems to be a bus problem.   Details Published on 2024-9-23 07:29
 
 

6555

Posts

0

Resources
2
 

Every time I read the BME680, the thermal image refresh will freeze. This seems to be a bus problem.

This post is from DigiKey Technology Zone

Comments

Yes, just change the I2C port. Fortunately, ESP32-S3 has many I2C ports.  Details Published on 2024-9-26 12:19
 
 
 

280

Posts

7

Resources
3
 
Jacktang posted on 2024-9-23 07:29 Every time I read the BME680, the thermal image refresh will freeze. This seems to be a bus problem.

Yes, just change the I2C port. Fortunately, ESP32-S3 has many I2C ports.

This post is from DigiKey Technology Zone
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list