基于ESP32-WROOM的新型智能无线蓝牙电压电流表设计

项目需求:

某嵌入式要求设计一个功能类似于微型智能电表的监测小型用电器的模块,连接小型用电器后,能够测量他的电压电流以及功率,并可以通过蓝牙实现远程的断电

项目分析:

这个项目实现的平台是ESP32,由于这款模块,自带了蓝牙功能,所以不用额外购买蓝牙模块;

显示使用的是OLED模块;然后接上电压电流的传感器,去测量用电器的电压和电流,然后,在系统中添加继电器,用来控制用电器的断电和上电,担心这个ESP32的电压不够,则专门使用了ESP32的扩展版给板子进行供电。

使用LED灯或者直流小电机,来模拟用电器

实验平台:

主控MCU:ESP32

购买链接icon-default.png?t=N7T8https://item.taobao.com/item.htm?id=675317800762&skuId=4855638220833

电压电流传感器:

购买链接icon-default.png?t=N7T8https://detail.tmall.com/item.htm?abbucket=11&id=525563678083&ns=1&priceTId=215044ef17168606939193848ee8af&spm=a21n57.1.item.140.6d6c523cbVbYLS

OLED显示屏:

购买链接icon-default.png?t=N7T8https://detail.tmall.com/item.htm?_u=m2ophfao7547&id=42044259331&spm=a1z09.2.0.0.7f452e8d59AvMs&skuId=4285967814255

继电器:

购买链接icon-default.png?t=N7T8https://detail.tmall.com/item.htm?abbucket=11&id=15909056050&ns=1&priceTId=215044ef17168612206748640ee8af&spm=a21n57.1.item.48.3bd5523crodekP&skuId=3931798090624

LED灯:

购买链接icon-default.png?t=N7T8https://item.taobao.com/item.htm?abbucket=11&id=597725910100&ns=1&priceTId=213e38cb17168620151933922e6cd9&spm=a21n57.1.item.141.3bd5523crodekP

直流小电机:

购买链接icon-default.png?t=N7T8https://detail.tmall.com/item.htm?abbucket=11&id=549383498434&ns=1&priceTId=214781e817168667202426632e99e6&skuId=3786596101760&spm=a21n57.1.item.275.3bd5523crodekP

手机蓝牙APP(APP的截图和APK的安装包):

APP的实物图:

APP的百度网盘链接:

通过百度网盘分享的文件:base.apk
链接:https://pan.baidu.com/s/1llxYHOOaDbKY6SHFSPb7ww?pwd=nix1 
提取码:nix1 
--来自百度网盘超级会员V6的分享

硬件连接:

OLED显示屏硬件连接表格:

OLED模块的引脚ESP32 MCU的引脚
SCK18
SDA13
RES15
DC5
CS17

电压电流传感器的硬件连接表格:

INA219模块的引脚

ESP32 MCU的引脚

VCC

5V

GND

GND

SCL

GPIO22

SDA

GPIO21

VIN-

用电器的正极

VIN+

继电器的COM口

继电器的硬件连接表格:

继电器引脚

MCU引脚

用电器引脚(LED或直流电机)

INA219电流表

继电器输出端:

NO

5V

COM

VIN+

NC

GND

用电器负极

继电器输入端:

DC+

5V

DC-

GND

IN

GPIO12

注:

用电器的负极接继电器NC口,然后继电器的NC口又和GND连起来了,所以,用电器的负极就和GND连接起来了。当继电器上电之后,IN引脚输出高电平之后,用电器,就会运行。

软件实现:

这个项目主要是三个部分,然后分别调用Arduino中的第三方库,对三个部分进行实现,具体是实现代码如下:

代码细节:

包含的头文件:

/*蓝牙ble的头文件*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <stdio.h>  //使用sprintf函数

/*OLED相关的头文件*/
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

/*INA219相关的头文件*/
#include <Wire.h>
#include <Adafruit_INA219.h>

各个模块相关的变量及宏定义:

/*电压传感器相关的变量*/
#define VOLT_POT 26
int volt_pot_value = 0;

/*继电器的相关变量*/
#define RELAY_PIN 12


/*INA219相关的变量*/
Adafruit_INA219 ina219;



float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float loadvoltage = 0;
float power_mW = 0;



/*OLED相关的变量*/
#define WIDTH   128   // OLED display width, in pixels
#define HEIGHT  64    // OLED display height, in pixels
// 软件 SPI 总线
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_SCK  18
#define OLED_SDA  13
#define OLED_RES  15
#define OLED_DC   5
#define OLED_CS   17     //因为体重秤已经用了4引脚了,但是3也不能用,因为3是串口
char show_oled[64] = {};
// 构造对象
Adafruit_SSD1306  OLED(WIDTH, HEIGHT, OLED_SDA, OLED_SCK, OLED_DC, OLED_RES, OLED_CS);


/*蓝牙的相关变量*/
#define BLEBUF_LEN   64
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;   //蓝牙设备的连接状态
char BLEbuf[BLEBUF_LEN] = {0};  //用来保存蓝牙将要发送的食物的重量数据
//uint32_t cnt = 0;
int food_kind_flag = 1;
char send_once_flag = 0;    //只发一次的标志位
char weight_start_falg = 1;  //一上电的时候,是有打印输出的
char weight_middle_falg = 0;  
char weight_end_falg = 0;
char get_start_flag = 0;

 
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" // 手机--->模块(交叉)
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" // 模块-->手机

具体的蓝牙处理函数:

/*回调服务函数*/
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      /*串口打印“蓝牙连接成功”*/
      Serial.println("蓝牙连接成功");
    };
 
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      Serial.println("蓝牙断开连接");
    };  //之前是没有分号的
};



/*接收数据的函数*/ 
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();
      if (rxValue.length() > 0) {
        send_once_flag = 1;   //将只发一次的标志位设置为1,为了在loop中发一次
        Serial.print("------>Received Value: ");
        /*将接收到的数据全部打印出来*/
        for (int i = 0; i < rxValue.length(); i++) {
          Serial.print(rxValue[i]);
        }
        Serial.println(); //打印换行
        /*寻找特殊的字符,使用rxValue.find()*/
        if(rxValue.find("断电") != -1)  //收到断电字符
        {
            /*串口打印上电,同时,将继电器的引脚拉高*/
            Serial.println("断电");
            digitalWrite(RELAY_PIN, LOW);

        }
        else if(rxValue.find("上电") != -1)  //收到上电字符
        {
            /*串口打印上电,同时,将继电器的引脚拉高*/
            Serial.println("上电");
            digitalWrite(RELAY_PIN, HIGH);
        }


      }
    }
};

setup函数:


void setup() {


  
  /***********串口初始化***********/
  Serial.begin(115200);           //串口的波特率是115200

  /*INA219初始化*/
  if (! ina219.begin()) 
  {
    Serial.println("Failed to find INA219 chip");
  }
  /*校准*/
  ina219.setCalibration_16V_400mA();
  
  /*电压传感器的初始化*/
  pinMode(VOLT_POT, INPUT);

  /*继电器的初始化*/
  pinMode(RELAY_PIN, OUTPUT);



  /**********OLED的初始化**********/
  /*经过测试打印,在字号为0时,可以打印最多7行,最多打印20列*/
  // OLED初始化
  if(!OLED.begin())
  {
    // 初始化失败
    Serial.println("OLED初始化失败");
  }

  // OLED清除显示
  OLED.clearDisplay();
  // 设置光标位置
  OLED.setCursor(1, 1);
  // 设置文本颜色
  OLED.setTextColor(SSD1306_WHITE);
  // 设置字体大小
  OLED.setTextSize(0);//原来的值是2,字号0-9  
  // 显示字符(经过测试打印,在字号为0时,可以打印最多7行,最多打印20列)
  sprintf(show_oled,"init_ok\r\n");   
  OLED.println(show_oled);   
  // 显示内容
  OLED.display();    
  
  /***********蓝牙的初始化***********/
  //Create the BLE Device
  BLEDevice::init("ESP32 BLE Test"); 
  // 创建蓝牙服务器
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  // 创建广播服务的UUID
  BLEService *pService = pServer->createService(SERVICE_UUID);
  //创建广播服务的UUID
  pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);            
  pCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
  pCharacteristic->setCallbacks(new MyCallbacks());
  // 开始蓝牙服务
  pService->start();
  // 开始广播
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");  

  
  }

loop函数:

 
void loop() {
  if (deviceConnected) {//设备连接后,每秒钟发送txValue。 

    #if 0
      /*采集电压的值*/
      volt_pot_value = analogReadMilliVolts(VOLT_POT);

      /*将电压值算出来*/
      volt_pot_value = volt_pot_value * 5 / 1024 * 100;   //算出来的值扩大100倍
      /*将电压的值打印出来*/
      Serial.println(volt_pot_value);    
    #endif 

    /*采集电压和电流的值*/
    shuntvoltage = ina219.getShuntVoltage_mV();
    busvoltage = ina219.getBusVoltage_V();
    current_mA = ina219.getCurrent_mA();
    power_mW = ina219.getPower_mW();
    loadvoltage = busvoltage + (shuntvoltage / 1000);
    
    /*将电流的值打印出来*/
    // Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
    // Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
    Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
    Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
    Serial.print("Power:         "); Serial.print(power_mW); Serial.println(" mW");
    Serial.println("");

    /*将电压电流的值通过OLED显示出来*/
    // OLED清除显示
    OLED.clearDisplay();
    // 设置光标位置
    OLED.setCursor(1, 1);      
    // 显示字符(经过测试打印,在字号为0时,可以打印最多7行,最多打印20列)
    sprintf(show_oled,"Volt = %.2f, Cur = %.2f,Pow = %.2f \r\n",loadvoltage,current_mA,power_mW);   
    OLED.println(show_oled);   
    // 显示内容
    OLED.display();    


    /*将电压电流的值通过蓝牙发送出来*/
    pCharacteristic->setValue((uint8_t *)show_oled,strlen(show_oled));  //将BLEbuf数组里面的数据保存到pCharacteristic中    
    pCharacteristic->notify();          // Send the value to the app! 这句代码就是将数据通过蓝牙发送出去

  }
  delay(1000);
}

调试细节:

直接问GPT,然后它有一条说,是我没有校准,所以按照它的思路来,确实可行。

实验平台实物图:

实验效果图:

参考文章:

基于ESP-01S的USB电压电流表:

https://blog.csdn.net/qq_35042880/article/details/123518816?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171803672616800213089603%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=171803672616800213089603&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-10-123518816-null-null.142^v100^pc_search_result_base9&utm_term=%20ESP32%E5%BC%80%E5%8F%91%20ina219%20i2c%20%E6%A8%A1%E5%9D%97&spm=1018.2226.3001.4187

INA219电压电流计:

https://blog.csdn.net/HaaSTech/article/details/124375577?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171803664116800178517970%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171803664116800178517970&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-124375577-null-null.142^v100^pc_search_result_base9&utm_term=ina219%20i2c%20%E6%A8%A1%E5%9D%97&spm=1018.2226.3001.4187

联系方式:(需要源代码的可以联系我)

实在复现不出来,可以联系我要源代码!!!

        微信号:   15052687571

        网易邮箱:15052687571@163.com

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值