查看: 1520|回复: 8

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

[复制链接]
  • TA的每日心情
    开心
    2020-11-21 14:04
  • 签到天数: 22 天

    [LV.4]偶尔看看III

    发表于 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, 下载次数: 28

  • TA的每日心情
    无聊
    2020-5-8 13:13
  • 签到天数: 146 天

    [LV.7]常住居民III

    发表于 2020-5-11 19:29 | 显示全部楼层
    这个好,作个记号。有空也玩玩INA266
  • TA的每日心情
    开心
    2020-4-8 14:24
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2020-5-11 22:10 | 显示全部楼层
    这个的确不错
  • TA的每日心情
    开心
    2020-11-21 14:04
  • 签到天数: 22 天

    [LV.4]偶尔看看III

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

    来一起探讨探讨
  • TA的每日心情
    开心
    2020-11-21 14:04
  • 签到天数: 22 天

    [LV.4]偶尔看看III

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

    好东西一起分享

    该用户从未签到

    发表于 2020-10-15 15:45 | 显示全部楼层
    我APP按键没有写错呀,数据同步不到APP里面,求大神教教
  • TA的每日心情
    开心
    2020-10-16 01:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2020-10-19 22:18 | 显示全部楼层
    如果能读取充电协议就更完美了
  • TA的每日心情
    开心
    2020-1-29 12:33
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2020-11-22 17:33 | 显示全部楼层
    INA266 I2C。。哈哈。。还以为是USB协议呢。。哈哈。。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    万万nano不得买山寨版
    万万nano不得买山寨版
    arduino nano板子体积小,方便开发小型机器人。不过山寨版不得买,到时候后悔都来不及
    【干货分享】mega2560原理图PCB图纸altium designer18
    【干货分享】mega2560原理
    分享一下mega2560的板子 AD版本 **** 本内容被作者隐藏 **** ergo
    串口处理字符串输出指定统计信息
    串口处理字符串输出指定统
    设问串口接收一串字符串,要求打印出全部字符串,统计一共有几个整数,找出最大的整数
    【Arduino】168种传感器模块系列实验(104)---MAX30102手腕心率
    【Arduino】168种传感器模
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
    【项目】基于Arduino Nano的多功能桌面感应垃圾桶
    【项目】基于Arduino Nano
    基于Arduino Nano的多功能桌面感应垃圾桶 (不知不觉中,自己已经步入大学第三年的时
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表