INA226-USB電壓電流表 設計可行性資料,親測可用
- /*
- 程序完善中,我自己本身也沒學過C/C++,完全就是靠感覺寫的代碼,若有BUG屬正常現象
- V1.0版本視頻鏈接https://www.bilibili.com/video/BV1Ev411k7jA
- V3.0版本視頻鏈接https://www.bilibili.com/video/BV1Ea411w7dj
- V5.0版本視頻鏈接https://www.bilibili.com/video/BV11a411F7mX
- 自2020.12.9開始記錄更新歷史
- 2020.12.9-----添加低電流關閉屏幕按鍵代碼并掉電保存狀態
- 2020.12.24----平安夜快樂!優化三個按鍵EEPROM保存部分代碼,避免新的328P芯片第一次上電EEPROM數據問題
- */
- #include <Wire.h>
- #include <INA226.h>
- #include <Adafruit_SSD1306.h>
- #include <EEPROM.h>
- #define SCREEN_WIDTH 128
- #define SCREEN_HEIGHT 32
- #define OLED_RESET -1
- Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
- #define NUMFLAKES
- static const uint8_t PROGMEM qidong[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xE0,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x02,0x00,0xE0,0x00,0x03,0x00,0x00,0x03,0x80,0xE0,0x3E,0x0F,0xE0,0x00,0x0C,0x00,0x07,0x00,0x60,0x00,0x03,0x00,0x00,0x03,0x80,0xE0,0xFF,0x0F,0xF8,0x00,0x0C,0x00,0x03,0xFF,0xFF,0x87,0xFF,0xFF,0x80,0x03,0x80,0xE1,0xC1,0x0E,0x3C,0x0F,0xFF,0xF8,0x01,0xBF,0xFF,0x87,0xFF,0xFF,0x80,0x03,0x80,0xE3,0x80,0x0E,0x0E,0x0F,0xFF,0xF8,0x00,0x81,0x00,0x00,0x03,0x00,0x00,0x03,0x80,0xE3,0x80,0x0E,0x0E,0x0C,0x0C,0x18,0x00,0x03,0x98,0x00,0x03,0x00,0x00,0x03,0x80,0xE3,0x80,0x0E,0x0E,0x0C,0x0C,0x18,0x0C,0x06,0x0C,0x01,0xFF,0xFF,0x00,0x03,0x80,0xE3,0xC0,0x0E,0x0C,0x0C,0x0C,0x18,0x0F,0xAC,0x1E,0x01,0xFF,0xFF,0x00,0x03,0x80,0xE1,0xE0,0x0E,0x1C,0x0F,0xFF,0xF8,0x03,0x1F,0xFF,0x80,0x03,0x00,0x00,0x03,0x80,0xE0,0xF8,0x0F,0xF8,0x0F,0xFF,0xF8,0x01,0x1C,0x01,0x0F,0xFF,0xFF,0xC0,0x03,0x80,0xE0,0x7E,0x0F,0xFC,0x0C,0x0C,0x18,0x00,0x00,0x08,0x0F,0xFF,0xFF,0xC0,0x03,0x80,0xE0,0x1F,0x0E,0x1E,0x0C,0x0C,0x18,0x00,0x0C,0xCC,0x00,0x0E,0x00,0x00,0x03,0x80,0xE0,0x07,0x0E,0x0F,0x0C,0x0C,0x18,0x01,0x0C,0xCC,0x00,0x1D,0x82,0x00,0x03,0x80,0xE0,0x03,0x8E,0x07,0x0F,0xFF,0xF8,0x03,0x8C,0xCC,0x00,0x39,0x87,0x80,0x03,0x80,0xE0,0x03,0x8E,0x07,0x0F,0xFF,0xF8,0x03,0x0C,0xCC,0x00,0x70,0xCE,0x00,0x03,0x80,0xC0,0x03,0x8E,0x07,0x0C,0x0C,0x18,0x03,0x0C,0xCC,0x01,0xF0,0xF8,0x00,0x01,0xC1,0xC0,0x03,0x8E,0x0E,0x0C,0x0C,0x02,0x07,0x0C,0xCC,0x0F,0xB0,0x70,0x00,0x01,0xE3,0x83,0x0F,0x0E,0x1E,0x00,0x0C,0x01,0x86,0x18,0xCC,0x87,0x30,0x38,0x00,0x00,0xFF,0x03,0xFE,0x0F,0xFC,0x00,0x0C,0x03,0x8E,0x38,0xCC,0xC4,0x31,0x1E,0x00,0x00,0x3C,0x00,0xF8,0x0F,0xE0,0x00,0x0F,0xFF,0x0E,0xF0,0xCF,0xC0,0x3F,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFE,0x02,0x60,0xCF,0x80,0x7E,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
- INA226 ina;
- unsigned long previousMillis = 0;
- unsigned long interval = 50;
- float shuntvoltage = 0;
- float busvoltage = 0;
- float current_mA = 0;
- float loadvoltage = 0;
- int SECONDS;
- int MINUTES;
- int HOURS;
- char flag1=1;
- char flag2=1;
- char flag3=1;
- bool temp1=0;
- bool temp2=0;
- double lasttime;
- double mah = 0;
- double mwh = 0;
- bool screen = 1;
- double screentime;
- bool state = 0;
- int page = 0;
- bool eeprom = 0;
- bool AlwayOn =0;
- int ShuaXinShiJian = 0;
- void setup() {
- int value;
- int address = 0;
- // EEPROM.get(512,value);
- value = EEPROM.read(512);
- if (value ==255){
- Serial.print(value);Serial.println("test");
- while(address<=512)
- {
- EEPROM.write(address,0);
- address++;
- }
- }
-
- display.begin(SSD1306_SWITCHCAPVCC, 0x3C, false, false);
- EEPROM.get(0,temp1);
- EEPROM.get(2,temp2);
- EEPROM.get(4,AlwayOn);
-
- pinMode(A0,INPUT);
- pinMode(A1,INPUT);
- //********************啟動畫面***********************
- setContrast (&display, 0);
- display.clearDisplay();
- display.drawBitmap(0,0,qidong,128,62,WHITE);
- display.drawRect(0,0,128,32,WHITE);
- display.display();
- delay(1000);
- //**************************************************
- Serial.begin(115200);
- ina.begin();
- ina.configure(INA226_AVERAGES_1, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
- ina.calibrate(0.01, 4);
- ina.enableOverPowerLimitAlert();
- ina.setPowerLimit(0.130);
- ina.setAlertLatch(true);
- }
- //--------------主循環函數----------------
- void loop() {
- unsigned long currentMillis = millis();
- if (currentMillis - previousMillis >= interval)
- {
- previousMillis = currentMillis;
- ina226values();
- displaydata();
- }
- SECONDS = (millis () / 1000) % 60;
- MINUTES = (millis () / 1000) % 3600/60;
- HOURS = (millis () / 1000) % (24*3600)/3600;
- setbright();
- Page();
- SAOn();
- if (AlwayOn){
- screenstate();
- }
-
- // Serial.print(" ");
- // Serial.print(millis() - screentime);
- // Serial.print(" ");
- // Serial.print(current_mA);
- // Serial.print(" ");
- // Serial.print(screen);
- // Serial.print(" ");
- // Serial.println(state);
- // Serial.println(" ");
-
- }
- //-------------------屏幕顯示部分------------------
- void displaydata() {
- if (screen){
- display.clearDisplay();
- display.setTextSize(2);
- display.setTextColor(SSD1306_WHITE);
- if (loadvoltage < 10){
- display.setCursor(0,0);
- display.print(loadvoltage ,3);
- display.println("V");
- }
- else {
- display.setCursor(0,0);
- display.print(loadvoltage);
- display.println("V");
- }
-
- display.setCursor(0, 18);
- display.print(current_mA / 1000,3);
- display.println("A");
- display.setTextSize(1);
- display.setTextColor(SSD1306_WHITE);
-
- display.setCursor(74, 0);
- display.print(loadvoltage * current_mA / 1000,4);
- display.println("W");
- if (!AlwayOn){
- display.drawLine(0,15,69,15,WHITE);
- }
- //———————————————————————————————
- if (page==0){
- if (mah < 100){
- display.setCursor(74, 8);
- display.print(mah,2);
- display.println("mAh");
- }
- else if (mah < 1000){
- display.setCursor(74, 8);
- display.print(mah,1);
- display.println("mAh");
- }
- else {
- display.setCursor(74, 8);
- display.print(mah / 1000,3);
- display.println("Ah");
- }
-
-
- if (mwh < 100){
- display.setCursor(74, 16);
- display.print(mwh,2);
- display.println("mWh");
- }
- else if (mwh < 1000){
- display.setCursor(74, 16);
- display.print(mwh ,1);
- display.println("mWh");
- }
- else {
- display.setCursor(74, 16);
- display.print(mwh / 1000 ,3);
- display.println("Wh");
- }
- }
- else {
- display.setCursor(74, 8);
- display.print("D+:");
- int V1 = analogRead(A0);
- float vol1 = V1*(3.966 / 1023.0);
- display.print(vol1);
- display.println("V");
- Serial.println(digitalRead(A0));
- display.setCursor(74, 16);
- display.print("D-:");
- int V2 = analogRead(A1);
- float vol2 = V2*(3.966 / 1023.0);
- display.print(vol2);
- display.println("V");
- }
- //----------------運行時間顯示----------------
- display.setCursor(74, 24);
-
- if (HOURS < 10){
- display.print("0");
- display.print(HOURS);
- }
- else{display.print(HOURS);}
- display.print(":");
- if (MINUTES < 10){
- display.print("0");
- display.print(MINUTES);
- }
- else{display.print(MINUTES);}
- display.print(":");
- if (SECONDS < 10){
- display.print("0");
- display.print(SECONDS);
- }
- else{display.print(SECONDS);}
-
-
- display.display();
-
- }
- else {
- display.clearDisplay();
- display.display();
- }
- }
- //--------------------數據計算---------------------
- void ina226values() {
- shuntvoltage = ina.readShuntVoltage();
- busvoltage = ina.readBusVoltage();
- current_mA = ina.readShuntCurrent() * 1000;
- loadvoltage = busvoltage + (shuntvoltage / 1000);
- if (loadvoltage < 0){
- loadvoltage = - loadvoltage;
- }
- if (current_mA < 0){
- current_mA = -current_mA;
- }
- if (millis() - lasttime >= 500 ){
- if ((current_mA >= 5)){
- mah = mah + (current_mA * ((millis() - lasttime)) / 1000)/3600;
- mwh = mwh +(loadvoltage * ((current_mA * ((millis() - lasttime)) / 1000)/3600));
- lasttime = millis();
-
- }
- }
- }
- void setContrast(Adafruit_SSD1306 *display, uint8_t contrast) {
- display->ssd1306_command(SSD1306_SETCONTRAST);
- display->ssd1306_command(contrast);
- }
- //---------------屏幕亮度按鍵控制--------------
- void setbright(){
- if(digitalRead(8)==0&&flag1==1)
- {
- delay(5);flag1=0;
- if(digitalRead(8)==0){
- temp1=!temp1;
- EEPROM.put(0,temp1);
- }
- }
- else if(digitalRead(8)==1){
- flag1=1;
- }
- switch (temp1){
- case 1:setContrast (&display, 255);break;
- case 0:setContrast (&display, 0);break;
- }
- }
- //-----------------頁面切換------------------
- void Page(){
- if(digitalRead(9)==0&&flag2==1)
- {
- delay(5);flag2=0;
- if(digitalRead(9)==0){
- temp2=!temp2;
- EEPROM.put(2,temp2);
- }
- }
- else if(digitalRead(9)==1){
- flag2=1;
- }
- switch (temp2){
- case 0:page=0;break;
- case 1:page=1;break;
- }
- }
- //-------------按鍵切換是否開啟低電流屏幕保護-------------
- void SAOn(){
- if(digitalRead(10)==0&&flag3==1)
- {
- delay(5);flag3=0;
- if(digitalRead(10)==0){
- AlwayOn=!AlwayOn;
- screen = 1;
- screentime = millis();
- EEPROM.put(4,AlwayOn);
- }
- }
- else if(digitalRead(10)==1){
- flag3=1;
- }
- switch (AlwayOn){
- case 0:;break;
- case 1:;break;
- }
- }
- //-------------電流低于5mA 5s后關閉屏幕-------------
- void screenstate(){
- if (current_mA <= 5){
- if (millis() - screentime > 5000){
- screen = 0;
- }
- if (state){
- screentime = millis();
- state = 0;
- }
- if (millis() - screentime < 5000){
- screen = 1;
- }
- }
- else {
- screen = 1;
- state = 1;
- }
- }
復制代碼
|