基于BLINKER的无线USB电压电流表-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 6696|回复: 10

[分享] 基于BLINKER的无线USB电压电流表

[复制链接]
发表于 2020-5-11 14:18 | 显示全部楼层 |阅读模式
本帖最后由 tomy113900173 于 2020-5-11 15:25 编辑

一、方案概述
目前市场上的USB电压电流表很多,但是数据的测量精度和采样频率都是固定的,本着DIY的精神设计了基于BLINKER的无线USB电压电流表,实现电流的精度和采样频率都可调节。
总体方案如下,用ESP8266作为主控芯片,通过IIC跟电压电流传感器INA226进行通信,同时将测量的数据显示在SSD1306上,其中SSD1306通过模拟IIC进行通信,同时将测量的数据通过BLINKER发送到手机APP显示,可以实现远程查看电压、电流、功率、容量。
图片1.png



二、详细方案
2.1电压电流检测
TI INA226是一个具备IIC功能的双向高/低端的电流、功率检测器件,电流检测精度是2.5uV。电路图如右所示,SCL连接到ESP8266D1SDA连接到ESP8266D2,通过设定采样电阻为0.01欧姆则可以检测出1mA的电流。
图片3.png 图片2.png


2.2 SSD1306显示模块
SSD1306通过IO口跟ESP8266D5D6连接,用U8G2显示库驱动

2.3程序设计

#define BLINKER_WIFI
#include <Blinker.h>
char auth[] = "9958e36fd79c";
char ssid[] = "TP-LINK_0430";
char pswd[] = "07743935112";
#define Number_1 "BusVoltage"
#define Number_2 "ShuntCurrent"
#define Number_3 "BusPower"
#define Number_4 "CapaPower"
#define Number_5 "BlinkerTime"


BlinkerNumber Number1(Number_1);
BlinkerNumber Number2(Number_2);
BlinkerNumber Number3(Number_3);
BlinkerNumber Number4(Number_4);
BlinkerNumber Number5(Number_5);
/*****************/
#include <Arduino.h>
#include <INA226.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

    float BusVoltage ;
    float ShuntCurrent ;
    float BusPower ;
    float CapaPower ;
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 14, /* data=*/ 12, /* reset=*/ U8X8_PIN_NONE);   // ESP32 Thing, pure SW emulated I2C
INA226 ina;
void checkConfig()
{
  Serial.print("Mode:                  ");
  switch (ina.getMode())
  {
    case INA226_MODE_POWER_DOWN:      Serial.println("Power-Down"); break;
    case INA226_MODE_SHUNT_TRIG:      Serial.println("Shunt Voltage, Triggered"); break;
    case INA226_MODE_BUS_TRIG:        Serial.println("Bus Voltage, Triggered"); break;
    case INA226_MODE_SHUNT_BUS_TRIG:  Serial.println("Shunt and Bus, Triggered"); break;
    case INA226_MODE_ADC_OFF:         Serial.println("ADC Off"); break;
    case INA226_MODE_SHUNT_CONT:      Serial.println("Shunt Voltage, Continuous"); break;
    case INA226_MODE_BUS_CONT:        Serial.println("Bus Voltage, Continuous"); break;
    case INA226_MODE_SHUNT_BUS_CONT:  Serial.println("Shunt and Bus, Continuous"); break;
    default: Serial.println("unknown");
  }
  Serial.print("Samples average:       ");
  switch (ina.getAverages())
  {
    case INA226_AVERAGES_1:           Serial.println("1 sample"); break;
    case INA226_AVERAGES_4:           Serial.println("4 samples"); break;
    case INA226_AVERAGES_16:          Serial.println("16 samples"); break;
    case INA226_AVERAGES_64:          Serial.println("64 samples"); break;
    case INA226_AVERAGES_128:         Serial.println("128 samples"); break;
    case INA226_AVERAGES_256:         Serial.println("256 samples"); break;
    case INA226_AVERAGES_512:         Serial.println("512 samples"); break;
    case INA226_AVERAGES_1024:        Serial.println("1024 samples"); break;
    default: Serial.println("unknown");
  }
  Serial.print("Bus conversion time:   ");
  switch (ina.getBusConversionTime())
  {
    case INA226_BUS_CONV_TIME_140US:  Serial.println("140uS"); break;
    case INA226_BUS_CONV_TIME_204US:  Serial.println("204uS"); break;
    case INA226_BUS_CONV_TIME_332US:  Serial.println("332uS"); break;
    case INA226_BUS_CONV_TIME_588US:  Serial.println("558uS"); break;
    case INA226_BUS_CONV_TIME_1100US: Serial.println("1.100ms"); break;
    case INA226_BUS_CONV_TIME_2116US: Serial.println("2.116ms"); break;
    case INA226_BUS_CONV_TIME_4156US: Serial.println("4.156ms"); break;
    case INA226_BUS_CONV_TIME_8244US: Serial.println("8.244ms"); break;
    default: Serial.println("unknown");
  }
  Serial.print("Shunt conversion time: ");
  switch (ina.getShuntConversionTime())
  {
    case INA226_SHUNT_CONV_TIME_140US:  Serial.println("140uS"); break;
    case INA226_SHUNT_CONV_TIME_204US:  Serial.println("204uS"); break;
    case INA226_SHUNT_CONV_TIME_332US:  Serial.println("332uS"); break;
    case INA226_SHUNT_CONV_TIME_588US:  Serial.println("558uS"); break;
    case INA226_SHUNT_CONV_TIME_1100US: Serial.println("1.100ms"); break;
    case INA226_SHUNT_CONV_TIME_2116US: Serial.println("2.116ms"); break;
    case INA226_SHUNT_CONV_TIME_4156US: Serial.println("4.156ms"); break;
    case INA226_SHUNT_CONV_TIME_8244US: Serial.println("8.244ms"); break;
    default: Serial.println("unknown");
  }
  Serial.print("Max possible current:  ");
  Serial.print(ina.getMaxPossibleCurrent());
  Serial.println(" A");
  Serial.print("Max current:           ");
  Serial.print(ina.getMaxCurrent());
  Serial.println(" A");
  Serial.print("Max shunt voltage:     ");
  Serial.print(ina.getMaxShuntVoltage());
  Serial.println(" V");
  Serial.print("Max power:             ");
  Serial.print(ina.getMaxPower());
  Serial.println(" W");

}

/*****************/

void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    Blinker.vibrate();
    uint32_t BlinkerTime = millis();  
   
    Blinker.print("V", BusVoltage);
    Number1.icon("icon_1");
    Number1.color("#FFFFFF");
    Number1.unit("mV");
    Number1.print(BusVoltage*1000);

    Blinker.print("A", ShuntCurrent);
    Number2.icon("icon_1");
    Number2.color("#FFFFFF");
    Number2.unit("mA");
    Number2.print(ShuntCurrent*1000);

    Blinker.print("W", BusPower);
    Number3.icon("icon_1");
    Number3.color("#FFFFFF");
    Number3.unit("W");
    Number3.print(BusPower);

    Blinker.print("mAh", CapaPower);
    Number4.icon("icon_1");
    Number4.color("#FFFFFF");
    Number4.unit("mAh");
    Number4.print(CapaPower);

    Blinker.print("millis", BlinkerTime);
    Number5.icon("icon_1");
    Number5.color("#FFFFFF");
    Number5.unit("minute");
    Number5.print(BlinkerTime/1000/60);
   
   
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void setup()
{
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);
    Blinker.attachData(dataRead);
    Blinker.begin(auth, ssid, pswd);
    delay(500);
   
/*****************************************************/
    Serial.println("Initialize INA226");
    Serial.println("-----------------------------------------------");
    // Default INA226 address is 0x40
    ina.begin();
    // Configure INA226
    ina.configure(INA226_AVERAGES_128, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
    // Calibrate INA226. Rshunt = 0.01 ohm, Max excepted current = 4A
    ina.calibrate(0.01, 3);
    // Display configuration
    checkConfig();
    Serial.println("-----------------------------------------------");

    u8g2.begin();
    u8g2.setFont(u8g2_font_ncenB14_tf ); // choose a suitable font   

/*****************************************************/

   
}
void loop()
{
    Blinker.run();
  /******************************************/
    static unsigned long time1 = millis();
    static unsigned long time3 = millis();
    static unsigned long time2 = 0, time4 = 0;
    time2 = millis();
    if ((time2 - time1) >= 10)//10m测量一次参数,并进行容量测量
    {
      BusVoltage = ina.readBusVoltage();
      ShuntCurrent = ina.readShuntCurrent();
      BusPower = ina.readBusPower();
      CapaPower
+
= ShuntCurrent * (time2 - time1) / 3600;
      time1 = time2;
    }
    time4 = millis();
    if ((time4 - time3) >= 500)//50mS刷新一次SSD1306
    {

      time3 = time4;
      u8g2.clearBuffer();         // clear the internal memory
      u8g2.setCursor(108, 14);         
      u8g2.print(" V");
      u8g2.setCursor(113, 30);
      u8g2.print("A");
      u8g2.setCursor(110, 46);
      u8g2.print("W");
      u8g2.setCursor(83, 64);
      u8g2.print("mAh");

      u8g2.setCursor(0, 14);
      u8g2.print(BusVoltage, 3);

      u8g2.setCursor(0, 30);
      u8g2.print(ShuntCurrent, 3);

      u8g2.setCursor(0, 46);
      u8g2.print(BusPower, 3);
      u8g2.setCursor(0, 64);
      u8g2.print(CapaPower);

      u8g2.sendBuffer();

       digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

  }

}

2.4调试
串口结果如下面所示证明esp8266已经跟INA226通信成功而且已经连接上网络了,网址是192.168.1.103,good news!!!
QQ截图20200511144431.png

再看看SSD1306显示,good news again!因为显示屏尺寸比较小,现在只显示了电压、电流、功率、容量这几个参数,后面再考虑分屏显示!!!目前看到的这个图片内容是USB风扇作为负载的数据!!!
微信图片_20200511145559.png


2.5 手机APP设计
打开“点灯BLINKER”app,简单几个拖拽就可以设计好符合自己的APP了,这点要为点灯科技点32个赞:D :D :D
微信图片_20200511150400.jpg
我的这个界面显示接单了点,没有做优化~~~,点击一下刷新一下数据,比SSD1306显示的内容多了一个运行的时间!!!

三、未来展望
  到目前为止,已基本完成了本项目的设定目标了!!!
  但是我们要不断前进!前进!前进!
  后面再考虑给这个项目添加新能的功能,比如加大数据采集的频率,然后再讲数据保存到U盘或者SD卡,就是一个简单的数据记录仪了!
  好吧,YY太多了,到这里为止吧!!!

PS:INA226的驱动我也是网上找的,忘了在哪里下载了,对于原作者说声SORRY!!!
另外可以调节到采样电阻可以实现采样微安级别的电流,有需要的可以自行调节!!!
电流和容量的精度也不做保证,误差肯定有的,因为采样电阻也是有一定的误差的!!!


Arduino-INA226-master.rar

18.81 KB, 下载次数: 88

发表于 2020-5-11 19:29 | 显示全部楼层
这个好,作个记号。有空也玩玩INA266
发表于 2020-5-11 22:10 | 显示全部楼层
这个的确不错
 楼主| 发表于 2020-5-12 08:45 | 显示全部楼层
47okey 发表于 2020-5-11 19:29
这个好,作个记号。有空也玩玩INA266

来一起探讨探讨
 楼主| 发表于 2020-5-12 08:46 | 显示全部楼层
47okey 发表于 2020-5-11 19:29
这个好,作个记号。有空也玩玩INA266

好东西一起分享
发表于 2020-10-15 15:45 | 显示全部楼层
我APP按键没有写错呀,数据同步不到APP里面,求大神教教
发表于 2020-10-19 22:18 | 显示全部楼层
如果能读取充电协议就更完美了
发表于 2020-11-22 17:33 | 显示全部楼层
INA266 I2C。。哈哈。。还以为是USB协议呢。。哈哈。。
发表于 2020-12-23 23:31 | 显示全部楼层
该方案,我已成功搞出实物。文中附的程序漏了void heartbeat(),因而APP上无法获取到数据。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 15:56 , Processed in 0.112242 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表