本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

基于M5Stack的BLE智能保温杯

发布时间:2022-05-21
分享到:

基于M5Stack的BLE智能保温杯

发布时间:2022-05-21
分享到:

这个保温瓶可感应内部温度并通过蓝牙将信息发送到接收器。

在本文中,我将向您展示如何通过蓝牙协议在两个 ESP32 板之间传输传感器读数。

你需要的东西:

  • M5Stick C
  • M5Stamp Pico
  • LM35 温度传感器

M5Stick C:

M5StickC是一款迷你 M5Stack,由 ESP32 供电。它是一款便携、易用、开源的物联网开发板。它可以做什么?这个小块能够在很短的时间内实现您的想法,激发您的创造力,并帮助您进行物联网原型设计。它将从开发过程中带走很多痛苦。M5stickC是M5Stack产品系列中的核心设备之一。

电源开关操作:

  • 开机:长按电源键2秒
  • 关机:长按电源键6秒

注意:

  • M5StickC支持的波特率:1200~115200、250K、500K、750K、1500K

产品特点

  • 基于 ESP32
  • 内置6轴IMU
  • 红色 LED
  • 红外线发射器
  • 麦克风
  • 按钮,LCD(0.96英寸)
  • 内置锂电池
  • 可扩展插座
  • 可穿戴和壁挂式

兼容多平台开发:

  • UIFlow
  • 微蟒
  • 阿杜诺
  • .NET 纳米框架

M5Stamp Pico:

STAMP-PICO采用超紧凑设计,在 PCB 上具有两个低功耗接口Xtensa® 32-bit LX6 microprocessors,240MHz像邮票一样小巧精致。低功耗。它非常适合任何空间受限或电池供电的设备,例如可穿戴设备、医疗设备、传感器和其他IoT设备。

  1. MULTIFORM:5种安装方式,意味着无限可能!(SMT、DIP、flywire、grove接口),采用耐高温塑料外壳,3D天线和元器件可以得到更好的保护。
  2. LOW-CODE DEVELOPMENT:STAMP-PICO支持UIFlow图形化编程平台,免脚本,云端推送;全面兼容Arduino、MicroPython、ESP32-IDF等主流开发平台,快速搭建各类应用。
  3. HIGH INTEGRATION:STAMP-PICO包含5V->3.3V DC/DC接口,GPIOx12,可编程RGB灯x1,按键x1,微调射频电路,提供稳定可靠的无线通信。
  4. STRONG EXPANDABILITY:轻松接入M5Stack软硬件生态系统:丰富的传感器、执行器、功能模块、配件可供选择,极速适配。

产品特点:

  • 芯片组:ESP32-PICO-D4(2.4GHz Wi-Fi双模)
  • 支持 UIFlow 图形化编程
  • 多IO引出线,支持多种应用形式(SMT、DIP、fly-by-wire)
  • 集成可编程 RGB LED 和按钮

微型模块

LM35 温度传感器:

LM35 是一款集成模拟温度传感器,其输出与摄氏度成正比。LM35 等传感器无需外部校准或微调即可提供典型精度。LM35 的低输出阻抗、线性输出和精确的固有校准使其特别容易与读数和控制电路连接。

硬件连接:

将 LM35 的输出引脚连接到 M5Stamp 的第 36 引脚,将 LM35 的电源连接到 PICO 的 5 V 和 GND 到 GND。

  • VOUT -> G36
  • 接地 - > 接地
  • VCC - > 5V

对发射器进行编程:

在本文中,M5Stamp pico 将充当发射器,一旦连接发射器,它将向发射器发送温度读数。

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <FastLED.h>

// LED Count
#define NUM_LEDS 1
#define DATA_PIN 27

// Define the array of leds
CRGB leds[NUM_LEDS];

#define Button 39
//BLE server name
#define bleServerName "M5"

//LM35
#define ADC_VREF_mV    3300.0 // in millivolt
#define ADC_RESOLUTION 4096.0
#define PIN_LM35       36 // ESP32 pin GIOP36 (ADC0) connected to LM35

float temp;
float tempF;
float hum;

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

bool deviceConnected = false;

#define SERVICE_UUID "91bad492-b950-4226-aa2b-4ede9fa42f59"

// Temperature Characteristic and Descriptor
BLECharacteristic bmeTemperatureCelsiusCharacteristics("cba1d466-344c-4be3-ab3f-189f80dd7518", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor bmeTemperatureCelsiusDescriptor(BLEUUID((uint16_t)0x2902));

//Setup callbacks onConnect and onDisconnect
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};


void setup() {
  // Start serial communication
  Serial.begin(115200);

  FastLED.addLeds<SK6812, DATA_PIN, RGB>(leds, NUM_LEDS);

  pinMode(Button, INPUT);

  // Create the BLE Device
  BLEDevice::init(bleServerName);

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *bmeService = pServer->createService(SERVICE_UUID);

  // Create BLE Characteristics and Create a BLE Descriptor
  bmeService->addCharacteristic(&bmeTemperatureCelsiusCharacteristics);
  bmeTemperatureCelsiusDescriptor.setValue("BME temperature Celsius");
  bmeTemperatureCelsiusCharacteristics.addDescriptor(&bmeTemperatureCelsiusDescriptor);


  // Start the service
  bmeService->start();

  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  static bool State;
  State = digitalRead(Button);
  if (State == 0)
  {
    ESP.restart();
  }
  if (deviceConnected) {
    if ((millis() - lastTime) > timerDelay) {

      // Turn the LED on, then pause
      leds[0] = 0xf00000;
      FastLED.show();
      delay(2000);

      // read the ADC value from the temperature sensor
      int adcVal = analogRead(PIN_LM35);
      // convert the ADC value to voltage in millivolt
      float milliVolt = adcVal * (ADC_VREF_mV / ADC_RESOLUTION);
      // convert the voltage to the temperature in °C
      temp = milliVolt / 10;

      static char temperatureCTemp[6];
      dtostrf(temp, 6, 2, temperatureCTemp);
      //Set temperature Characteristic value and notify connected client
      bmeTemperatureCelsiusCharacteristics.setValue(temperatureCTemp);
      bmeTemperatureCelsiusCharacteristics.notify();

      // Now turn the LED off, then pause
      leds[0] = 0x00f000;
      FastLED.show();
      
      Serial.print("Temperature Celsius: ");
      Serial.print(temp);
      Serial.println(" ºC");

      lastTime = millis();
    }
  }

}
在此代码中,如果您需要更改 BLE 服务器名称,请根据需要更改此行:

这行代码包含基本的 LM35 校准读数,不要更改这些。

这是发送器的 BLE 服务 ID:

这是温度数据的服务 ID:

M5Stamp Pico 没有任何重置按钮,但它有一个用户定义的按钮,这里我用那个按钮来重置电路板。

最后,将代码上传到 M5Stamp Pico,确保您选择了正确的板设置:

对接收机编程:

在本文中,M5Stick C 将充当发射器,它将接收来自发射器的温度读数。

#include <M5StickC.h>
#include "BLEDevice.h"

//BLE Server name
#define bleServerName "M5"

/* UUID's of the service, characteristic that we want to read*/
// BLE Service
static BLEUUID bmeServiceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");

//Temperature Celsius Characteristic
static BLEUUID temperatureCharacteristicUUID("cba1d466-344c-4be3-ab3f-189f80dd7518");


//Flags stating if should begin connecting and if the connection is up
static boolean doConnect = false;
static boolean connected = false;

//Address of the peripheral device. Address will be found during scanning...
static BLEAddress *pServerAddress;

//Characteristicd that we want to read
static BLERemoteCharacteristic* temperatureCharacteristic;

//Activate notify
const uint8_t notificationOn[] = {0x1, 0x0};
const uint8_t notificationOff[] = {0x0, 0x0};


//Variables to store temperature and humidity
char* temperatureChar;

//Flags to check whether new temperature and humidity readings are available
boolean newTemperature = false;


//Connect to the BLE Server that has the name, Service, and Characteristics
bool connectToServer(BLEAddress pAddress) {
  BLEClient* pClient = BLEDevice::createClient();

  // Connect to the remove BLE Server.
  pClient->connect(pAddress);
  Serial.println(" - Connected to server");

  // Obtain a reference to the service we are after in the remote BLE server.
  BLERemoteService* pRemoteService = pClient->getService(bmeServiceUUID);
  if (pRemoteService == nullptr) {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(bmeServiceUUID.toString().c_str());
    return (false);
  }

  // Obtain a reference to the characteristics in the service of the remote BLE server.
  temperatureCharacteristic = pRemoteService->getCharacteristic(temperatureCharacteristicUUID);

  if (temperatureCharacteristic == nullptr) {
    Serial.print("Failed to find our characteristic UUID");
    return false;
  }
  Serial.println(" - Found our characteristics");

  //Assign callback functions for the Characteristics
  temperatureCharacteristic->registerForNotify(temperatureNotifyCallback);
  return true;
}

//Callback function that gets called, when another device's advertisement has been received
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      if (advertisedDevice.getName() == bleServerName) { //Check if the name of the advertiser matches
        advertisedDevice.getScan()->stop(); //Scan can be stopped, we found what we are looking for
        pServerAddress = new BLEAddress(advertisedDevice.getAddress()); //Address of advertiser is the one we need
        doConnect = true; //Set indicator, stating that we are ready to connect
        Serial.println("Device found. Connecting!");
      }
    }
};

//When the BLE Server sends a new temperature reading with the notify property
static void temperatureNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,
                                      uint8_t* pData, size_t length, bool isNotify) {
  //store temperature value
  temperatureChar = (char*)pData;
  newTemperature = true;
}


//function that prints the latest sensor readings in the OLED display
void printReadings() {
  M5.update();

  //Erase the previous contents in the display
  M5.Lcd.fillScreen(BLACK);

  M5.Lcd.setTextColor(RED);
  M5.Lcd.setCursor(20, 18);
  M5.Lcd.setTextSize(1.8);
  M5.Lcd.print("[ ");
  M5.Lcd.setTextColor(GREEN);
  M5.Lcd.print("BLE Smart Flask");
  M5.Lcd.setTextColor(RED);
  M5.Lcd.print(" ]");
  M5.Lcd.setCursor(18, 40);
  M5.Lcd.setTextColor(GREEN);
  Serial.print("Temperature:");
  M5.Lcd.print("Temperature: ");
  Serial.println(temperatureChar);
  M5.Lcd.print(temperatureChar);
  M5.Lcd.print(" C");

  M5.Lcd.setCursor(15, 55);
  M5.Lcd.setTextColor(RED);
  M5.Lcd.print("---------------------");

  float x = atof(temperatureChar);
  if (x >= 35.0)
  {
    Serial.println("It may be a over heat");
    M5.Lcd.setCursor(15, 65);
    M5.Lcd.setTextColor(RED);

    M5.Lcd.print("It's may be over heat");
  }
  else {
    Serial.println("It's ok to drink");
    M5.Lcd.setCursor(30, 65);
    M5.Lcd.setTextColor(GREEN);
    M5.Lcd.print("It's ok to drink");
  }

  M5.Lcd.setCursor(15, 75);
  M5.Lcd.setTextColor(RED);
  M5.Lcd.print("---------------------");
}
void setup() {

  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Axp.ScreenBreath(10);
  M5.Lcd.setTextColor(RED);
  M5.Lcd.setCursor(10, 35);
  M5.Lcd.setTextSize(1.8);

  //Start serial communication
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");

  //Init BLE device
  BLEDevice::init("");

  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);
}

void loop() {
   
  if (doConnect == true) {
    if (connectToServer(*pServerAddress)) {
      Serial.println("We are now connected to the BLE Server.");
      M5.Lcd.print("Connected to BLE Server");
      //Activate the Notify property of each Characteristic
      temperatureCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);
      connected = true;
    } else {
      Serial.println("We have failed to connect to the server; Restart your device to scan for nearby BLE server again.");
      M5.Lcd.print("Not Connected");
    }
    doConnect = false;
  }
  //if new temperature readings are available, print in the OLED
  if (newTemperature) {
    newTemperature = false;
    printReadings();
  }
}
在此代码中,将变送器名称重命名为与您相同的名称,并确保设备服务 ID 和温度数据 ID 与变送器匹配。

我添加了一些代码行来显示温度读数到 TFT 显示器。

完成后,进行所需的更改,将代码上传到 M5Stick C。

上传一次代码后,就可以按下发射器和接收器上的休息按钮并监控串行输出。

如果您对此项目有任何想法、意见或问题,请在下方留言。

以上内容翻译自网络,原作者:Pradeep,如涉及侵权,可联系删除。

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论