KyleLiuCat
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 電池管理系統(Power Memage Unit) ***說明:用MCU做鋰電池狀態監控,同時控制其他DC電源系統的開關*** ###### tags: `省電` `Arduino' 'Arduino Pro Mini` `I2C` ## 材料 1. MCU:[Arduino Mini Pro(8Mhz 3.3V)](https://www.sparkfun.com/products/11114) 2. Module: * 電源監控:INA219 * DC迴路開關控制:n-MOSFet ## 架構 ### Arduino Pro Mini 的功能 1. 控制某個mcu的電源迴路:使用MOSFet(p-chennel of n-chennel) 2. 提供I2C介面讓MCU來查詢/設定下列功能(以library形式打包): * 設定I2C Address * 設定下次喚醒間隔??秒 * 是否進入睡眠 * 是否監控電池電壓:電池電壓太低時延長喚醒週期 * 設定啟動腳位 * 設定INA219的Address 3. 控制流程(Ver 1.0) 1. 不同階段閃爍不同的LED燈 (P13,6.5mA) * I2C Master 階段 (2短(200ms)/loop, 300mS間隔) * I2C Slaver 階段 (1短(200ms)/loop) * 讀取config 階段 (1長(1000ms)) * 睡眠 階段 (關閉) 2. 開機後先進入Master階段讀取config及INA219 3. 開啟MCU電源後,立刻進入slaver階段等待MCU下指令 4. MCU開機進行Setup 5. MCU再Loop結束前須決定是否要轉移給PMU控制電源/PMU控制+休眠/MCU持續運作 6. PMU收到關閉指令後,立即把I2C切換成Master 7. PMU睡醒後須先讀取INA219,按照設定決定要不要啟動MCU ![目前想法](https://i.imgur.com/nybAIxm.png) ### 控制迴路 1.持續供電: Arduino Pro Mini 2.控制迴路A:INA219 3.控制迴路B:LinkIt7697 4.控制迴路C:SIMCOM700E / --- ## Arduino Mini Pro 省電模式測試 * [參考來源](http://www.home-automation-community.com/arduino-low-power-how-to-run-atmega328p-for-a-year-on-coin-cell-battery/) * [使用library:RoketScream](https://github.com/rocketscream/Low-Power) * BOD的說明(TODO:待測試) * [參考來源:BOD](http://ww1.microchip.com/downloads/en/devicedoc/doc7903.pdf) * 目前測試下免兩個差異不大 > *(Timer 2 還不知道怎麼用 orz)* > * powerDown(period_t period, adc_t adc, bod_t bod) > * powerSave(period_t period, adc_t adc, bod_t bod, timer2_t timer2) ### 使用Raw腳供電(4-12V輸入) * [Sparkfun 教學](https://learn.sparkfun.com/tutorials/using-the-arduino-pro-mini-33v) ![Pinout](https://i.imgur.com/R8vaMXY.png) ### 睡眠測試:1.359mA, 未拆LED及線性穩壓器(LDO) ```cpp=1 // **** INCLUDES ***** #include "LowPower.h" #define LED 13 uint16_t c = 0; // 控制LED閃爍的funciton void LEDFlash(uint8_t _ts) { for (uint8_t _i = 0; _i < _ts; _i++) { digitalWrite(LED, HIGH); delay(250); digitalWrite(LED, LOW); delay(250); } } void setup() { Serial.begin(115200); pinMode(LED, OUTPUT); LEDFlash(3); } void loop() { Serial.print(c); Serial.print(F("-開始睡眠: ")); switch (c % 3) { case 0: Serial.print(F("Power Down Mode")); delay(500); // 預留一些時間讓uart 能把資料吐完 LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); // 進入睡眠模式 break; case 1: Serial.print(F("Power Save Mode")); delay(500); LowPower.powerSave(SLEEP_4S, ADC_OFF, BOD_OFF, TIMER2_OFF); break; default: Serial.print(F("active Mode")); delay(500); delay(4000); } Serial.println(F("\t-起床")); LEDFlash(3); c++; } ``` ## 測試:Arduino Mini Pro ### Upload: * 編譯的時候先按下RESET鈕,看到Uploading時再放開就可以上傳 ### SoftReset: ```cpp=1 // 重新啟動 // Restarts program from beginning but does not reset the peripherals and registers void vSoftwareReset(void) { asm __volatile__(" jmp 0"); } ``` ### SRAM size * [參考來源](https://playground.arduino.cc/Code/AvailableMemory/?fbclid=IwAR0qzHze5c3ZWY6_otxIAVZlpPmcJ-2MNviBiAMuyr91_M39ZtlslZf-_LI) ```cpp=1 // 剩餘的SRAM // Arduino Mini Pro 共有2048bytes空間(2K) int iGetFreeRam(void) { extern int _heap_start, * __brkval; int v; return (int)&v - (__brkval == 0 ? (int)&__malloc_heap_start : (int)__brkval); } ``` ### I2C communication * [參考來源](https://www.arduino.cc/en/reference/wire) * ## 測試:PMU端 ### PMU端 WaterBox_PMU.h 檔 ```cpp=1 #include <Arduino.h> #ifndef _WATERBOX_PMU_ #define _WATERBOX_PMU_ #define _I2C_BUFFER_SIZE 30 #define COMMUNICATIONMODULE enum POWER { OFF, ON }; enum STATE { MASTER, SLEEP, SLAVER, }; enum UART { NONE, EOL, H_PMU, H_I2C, H_CMD }; enum IC2Request { Req_NONE, // 無Request Req_ERROR, // 錯誤指令 Req_TIME, // 設定鬧鐘(秒), 回傳OK -> timer ? sec Req_SLEEP, // 進入睡眠, 不回傳 Req_LOWPOWER, // 省電模式, 回傳OK->LowPower ON/OFF Req_BAT_VOLATE, // 電池電壓, 回傳OK->volate Req_BAT_CURRENT, // 電池電壓, 回傳OK->current Req_AT // AT Cmd( 給外面的NBIOT用) }; class WaterBox_PMU { public: WaterBox_PMU(); // 建構函式 WaterBox_PMU(uint8_t _addr); // 建構函式(指定 Slaver時的I2C Address) ~WaterBox_PMU(); // 解構函式 void init(uint16_t _pin); void setINA219(uint8_t _addr); static void setDebuger(Stream& refSer); // 設定debug用的輸出 static void setWakeUpVolate(float _v); // 設定喚醒電壓 static void setSleepSec(uint32_t _sec); static uint8_t Sleep(); // 開始睡眠:切換到Master,關閉供電後開始進入睡眠循環,循環結束時更新電池狀態,低於喚醒電源後再開始供電返回1 (可以用while(Sleep())一值睡 static void PowerSaveMode(POWER _state); static void ControlPower(POWER _state); static void getBetteryState(); // 取得電池狀態:切換到Master,呼叫INA219拿資料後更新變數 static void LED(uint16_t _times, uint16_t _interval); static float Volate; // 電池上次的電壓 static float Current; // 電池上次的電流量 static enum STATE stete; #ifdef COMMUNICATIONMODULE static String ATCMD; // 給NBIOT的Command static void ATClear(); #endif // COMMUNICATIONMODULE private: static uint8_t _Debug; static uint16_t _ControlPin; static Stream& refSerial; static uint8_t _Addr; uint8_t _INA219Addr = 0x40; //uint8_t _SleepMode; // 未使用 static uint8_t _PowerSave; // 定義是不是要進入省電模式 static uint16_t _SleepSec; // 睡眠秒數 static uint16_t _i_for; static float _WakeUpVoltage; static void _SwitchToSlaver(uint8_t _addr); static void _receiveEvent(int howMany); static void _requestEvent(); static void _cmd(String _str); static String _ComStr; static String _recBuffer; static IC2Request _REQUEST; static void _Deguber(String _msg, UART _header, UART _uart = NONE); }; #endif ``` ### PMU端 WaterBox_PMU.cpp 檔 ```cpp=1 #include "WaterBox_PMU.h" #include <Wire.h> #include <LowPower.h> #include <Adafruit_INA219.h> #define SLEEPTIME SLEEP_1S uint8_t WaterBox_PMU::_Debug; Stream& WaterBox_PMU::refSerial = Serial; uint16_t WaterBox_PMU::_i_for; uint8_t WaterBox_PMU::_PowerSave = false; uint16_t WaterBox_PMU::_SleepSec; IC2Request WaterBox_PMU::_REQUEST; String WaterBox_PMU::_ComStr; String WaterBox_PMU::_recBuffer; float WaterBox_PMU::_WakeUpVoltage = 3.6; float WaterBox_PMU::Volate; float WaterBox_PMU::Current; enum STATE WaterBox_PMU::stete = MASTER; uint16_t WaterBox_PMU::_ControlPin; uint8_t WaterBox_PMU::_Addr = 0x70; #ifdef COMMUNICATIONMODULE String WaterBox_PMU::ATCMD; #endif // COMMUNICATIONMODULE WaterBox_PMU::WaterBox_PMU() { } WaterBox_PMU::WaterBox_PMU(uint8_t _addr) { _Addr = _addr; } WaterBox_PMU::~WaterBox_PMU() { } void WaterBox_PMU::init(uint16_t _pin) { _ControlPin = _pin; pinMode(_ControlPin, OUTPUT); } void WaterBox_PMU::setINA219(uint8_t _addr) { _INA219Addr = _addr; _Deguber(F("Setting INA219 I2C address: 0x"), H_PMU); _Deguber(String(_INA219Addr, HEX), EOL); } void WaterBox_PMU::setDebuger(Stream& refSer) { _Debug = true; refSerial = refSer; } void WaterBox_PMU::setWakeUpVolate(float _v) { _WakeUpVoltage = _v; _Deguber(F("Setting WAKE UP Volate: "), H_PMU); _Deguber(String(_WakeUpVoltage), NONE); _Deguber(F(" V."), NONE, EOL); } void WaterBox_PMU::setSleepSec(uint32_t _sec) { _SleepSec = _sec; _Deguber(F("Setting Sleep Time: "), H_PMU); _Deguber(String(_SleepSec), NONE); _Deguber(F(" sec."), NONE, EOL); } // 開始睡眠:切換到Master,關閉供電後開始進入睡眠循環,循環結束時更新電池狀態,低於喚醒電源後再開始供電返回1 (可以用while(Sleep())一值睡 uint8_t WaterBox_PMU::Sleep() { LED(1,700); _Deguber(F("Prepare SLEEP Mode"), H_PMU, EOL); _Deguber(F("Off the LED & Control POWER"), H_PMU, EOL); digitalWrite(LED_BUILTIN, LOW); ControlPower(OFF); _Deguber(F("Enter SLEEP Mode"), H_PMU, EOL); delay(100); for (_i_for = 0; _i_for < _SleepSec; _i_for++) { if (_PowerSave) LowPower.powerDown(SLEEPTIME, ADC_OFF, BOD_OFF); else delay(1000); } stete = MASTER; _Deguber(F("Waker up, init I2C with Master and get bettery state..."), H_PMU, EOL); ControlPower(ON); Wire.begin(); getBetteryState(); ControlPower(OFF); if (Volate < _WakeUpVoltage) { _Deguber(F("ERROR: Volate < Wake up voltage"), H_PMU); _Deguber(String(_WakeUpVoltage), NONE, EOL); return 1; } else { ControlPower(ON); _Deguber(F(" I2C --> Slaver"), H_PMU, EOL); _SwitchToSlaver(_Addr); stete = SLAVER; return 0; } } void WaterBox_PMU::PowerSaveMode(POWER _state) { if (_state == ON) _Deguber(F("Power Save Mode: ON"), H_PMU, EOL); else if (_state == OFF) _Deguber(F("Power Save Mode: OFF"), H_PMU, EOL); _PowerSave = _state; } void WaterBox_PMU::ControlPower(POWER _state) { if (_state == ON) { digitalWrite(_ControlPin, HIGH); _Deguber(F("Control: ON"), H_PMU, EOL); } else if (_state == OFF) { digitalWrite(_ControlPin, LOW); _Deguber(F("Control: OFF"), H_PMU, EOL); } } void WaterBox_PMU::getBetteryState() { Adafruit_INA219 bettery(INA219_ADDRESS); bettery.begin(); // To use a slightly lower 32V, 1A range (higher precision on amps): //ina219.setCalibration_32V_1A(); // Or to use a lower 16V, 400mA range (higher precision on volts and amps): bettery.setCalibration_16V_400mA(); Volate = bettery.getBusVoltage_V(); Current = bettery.getCurrent_mA(); _Deguber(F("Bettery Volate: "), H_PMU); _Deguber(String(Volate), NONE); _Deguber(F(", Current: "), NONE); _Deguber(String(Current), NONE, EOL); } void WaterBox_PMU::LED(uint16_t _times, uint16_t _ratio) { pinMode(LED_BUILTIN, OUTPUT); for (_i_for = 0; _i_for < _times; _i_for++) { digitalWrite(LED_BUILTIN, HIGH); delay(_ratio); digitalWrite(LED_BUILTIN, LOW); delay(300); } } void WaterBox_PMU::ATClear() { ATCMD = ""; } void WaterBox_PMU::_Deguber(String _msg, UART _header, UART _uart = NONE) { if (_Debug) { switch (_header) { case H_PMU: refSerial.print(F("[PMU]\t")); break; case H_I2C: refSerial.print(F("[I2C]\t")); break; case H_CMD: refSerial.print(F("[CMD]\t")); break; default: break; } switch (_uart) { case NONE: refSerial.print(_msg); break; case EOL: refSerial.println(_msg); break; default: break; } } } void WaterBox_PMU::_requestEvent() { switch (_REQUEST) { case Req_NONE: _recBuffer = F("No String"); break; case Req_TIME: _recBuffer = F("OK,timer -> "); _recBuffer += String(_SleepSec); _recBuffer += F(" sec"); break; case Req_SLEEP: _recBuffer = F("Sleep"); break; case Req_LOWPOWER: _recBuffer = F("OK, LowPower -> "); _recBuffer += String(_PowerSave); break; case Req_BAT_VOLATE: _recBuffer = F("OK,"); _recBuffer += String(Volate); break; case Req_BAT_CURRENT: _recBuffer = F("OK,"); _recBuffer += String(Current); break; case Req_AT: _recBuffer = F("OK"); break; default: _recBuffer = F("Command ERROR"); break; } uint16_t _BufferSize = _recBuffer.length(); for (_i_for = 0; _i_for + _BufferSize < _I2C_BUFFER_SIZE; _i_for++) { _recBuffer += F(" "); } _Deguber(_recBuffer, H_I2C, EOL); _Deguber("", NONE, EOL); Wire.write(_recBuffer.c_str()); } void WaterBox_PMU::_receiveEvent(int howMany) { _ComStr = ""; while (Wire.available()) { char _c_ = Wire.read(); _ComStr += String(_c_); } LED(1,300); _cmd(_ComStr); } void WaterBox_PMU::_cmd(String _str) { /* TIME,sec // 設定鬧鐘(秒) SLEEP // 進入睡眠 LOWPOWER,1 // 省電模式 VOLATE // 回傳 volate CURRENT // 回傳 current ATCMD,***** // 輸入AT Commend 資料 */ _str.toUpperCase(); _ComStr = _str.substring(_str.indexOf(F(",")) + 1); // 重新利用_ComStr if (_str.length() > 0) _REQUEST = Req_ERROR; else _REQUEST = Req_NONE; if (_str.indexOf(F("TIME")) > -1) { _Deguber(F("TIME -> "), H_CMD); _Deguber(_ComStr, NONE, EOL); _SleepSec= _ComStr.toInt(); setSleepSec(_SleepSec); _REQUEST = Req_TIME; } if (_str.indexOf(F("SLEEP")) > -1) { _Deguber(F("Enter SLEEP"), H_CMD,EOL); Sleep(); _REQUEST = Req_SLEEP; } if (_str.indexOf(F("LOWPOWER")) > -1) { _Deguber(F("LOWPOWER -> "), H_CMD); _Deguber(_ComStr, NONE, EOL); _PowerSave = _ComStr.toInt(); PowerSaveMode(POWER(_PowerSave)); _REQUEST = Req_LOWPOWER; } if (_str.indexOf(F("VOLATE")) > -1) { _Deguber(F("GET BATTERY VOLATE"), H_CMD, EOL); _REQUEST = Req_BAT_VOLATE; } if (_str.indexOf(F("CURRENT")) > -1) { _Deguber(F("GET BATTERY CURRENT"), H_CMD, EOL); _REQUEST = Req_BAT_CURRENT; } if (_str.indexOf(F("ATCMD")) > -1) { ATClear(); _Deguber(F("ATCMD >> "), H_CMD); _Deguber(_ComStr, NONE, EOL); ATCMD = _ComStr; _REQUEST = Req_AT; } } void WaterBox_PMU::_SwitchToSlaver(uint8_t _addr) { Wire.begin(_addr); Wire.onRequest(&WaterBox_PMU::_requestEvent); // I2C Master的指令:回傳 Wire.onReceive(&WaterBox_PMU::_receiveEvent); // I2C Master的指令:不回傳 } ``` ### PMU端 *.ino 檔 ```cpp=1 /* Name: PowerManagUnit.ino Created: 2020/2/18 下午 07:37:23 Author: Liu */ #include "WaterBox_PMU.h" #define CONTROL_PIN 10 #include <SoftwareSerial.h> #define UART_TX 8 #define UART_RX 9 WaterBox_PMU PMU; static int _c = 0; void showState() { Serial.print(F("PMU STATE >> ")); switch (PMU.stete) { case MASTER: Serial.println(F("MASTER")); break; case SLEEP: Serial.println(F("SLEEP")); break; case SLAVER: Serial.println(F("SLAVER")); break; default: break; } } void setup() { Serial.begin(115200); PMU.init(CONTROL_PIN); PMU.setDebuger(Serial); PMU.setSleepSec(5); PMU.setWakeUpVolate(3.5); PMU.PowerSaveMode(ON); Serial.println(F("Setup Done")); showState(); PMU.Sleep(); showState(); } void loop() { //Serial.print(F("Loop ")); //Serial.println(_c); if (PMU.ATCMD.length() > 0) { Serial.println(F("[LOOP]\t")); Serial.print(F("[AT] \t")); Serial.println(PMU.ATCMD); PMU.ATClear(); PMU.LED(3,200); } _c++; //if(_c%50==0) PMU.Sleep(); //else delay(1000); } ``` ## 測試:7697端(受控制端) ### 受控制端 WaterBox_PowerSaving.h ```cpp=1 #include <Arduino.h> #ifndef _WATERBOX_POWERSAVING_ #define _WATERBOX_POWERSAVING_ #define RequestBufferSize (uint8_t)30 class WaterBox_PowerSaving { public: WaterBox_PowerSaving(uint8_t _addr); ~WaterBox_PowerSaving(); enum POWER { NORMAL, // 對照OFF LOWPOWER // 對照ON }; void init(); void setDebuger(Stream& refSer); // 設定Deguber void setSleepSec(uint32_t _sec); // 設定睡眠時間(秒) void setSleepMode(POWER _state); // 設定睡眠模式 void sendData(String _data); void getState(); void Sleep(); // 進入睡眠狀態 static void _Receive(uint8_t _addr, String _cmd); // I2C Master的指令:回傳 static void _Reques(uint8_t _addr); // I2C Master的指令:不回傳 static String ReqString; // I2C 回傳字串 static float Volate; // 系統電壓 static float Current; // 系統電池 private: enum UART { NONE, EOL, H_PMU, H_I2C, H_CMD }; struct COMMAND { String TIME = F("TIME,"); String AT = F("ATCMD,"); String SLEEP = F("SLEEP"); String VOLATE = F("VOLATE"); String CURRENT = F("CURRENT"); String LOWPOWER = F("LOWPOWER,"); }; static uint8_t _Debug; static Stream& refSerial; static uint8_t _Addr; static String _CMDBuffer; static void _sendCMD(String _cmd, uint8_t _req = false); static void _Deguber(String _msg, UART _header, UART _uart = NONE); COMMAND _cmd; }; #endif ``` ### 受控制端 WaterBox_PowerSaving.cpp ```cpp=1 #include "WaterBox_PowerSaving.h" #include <Wire.h> #include <Adafruit_INA219.h> uint8_t WaterBox_PowerSaving::_Debug = false; Stream& WaterBox_PowerSaving::refSerial = Serial; uint8_t WaterBox_PowerSaving::_Addr = 0x70; String WaterBox_PowerSaving::_CMDBuffer = ""; String WaterBox_PowerSaving::ReqString = ""; WaterBox_PowerSaving::WaterBox_PowerSaving(uint8_t _addr) { _Addr = _addr; } WaterBox_PowerSaving::~WaterBox_PowerSaving() { } void WaterBox_PowerSaving::init() { Wire.begin(); } void WaterBox_PowerSaving::setDebuger(Stream& refSer) { _Debug = true; refSerial = refSer; } void WaterBox_PowerSaving::setSleepSec(uint32_t _sec) { _CMDBuffer = _cmd.TIME + String(_sec); _sendCMD(_CMDBuffer, true); } void WaterBox_PowerSaving::setSleepMode(POWER _state) { _CMDBuffer = _cmd.LOWPOWER + String(_state); _sendCMD(_CMDBuffer, true); } void WaterBox_PowerSaving::sendData(String _data) { _CMDBuffer = _cmd.AT + _data; _sendCMD(_CMDBuffer, true); } void WaterBox_PowerSaving::getState() { _sendCMD(_cmd.VOLATE, true); _sendCMD(_cmd.CURRENT, true); } void WaterBox_PowerSaving::Sleep() { _sendCMD(_cmd.SLEEP, false); } void WaterBox_PowerSaving::_Receive(uint8_t _addr, String _cmd) { Wire.beginTransmission(_addr); Wire.write(_cmd.c_str()); Wire.endTransmission(); } void WaterBox_PowerSaving::_Reques(uint8_t _addr) { Wire.requestFrom(_addr, RequestBufferSize); ReqString = ""; while (Wire.available()) { char c = Wire.read(); ReqString += String(c); } _Deguber(ReqString, H_I2C, EOL); } void WaterBox_PowerSaving::_sendCMD(String _cmd, uint8_t _req) { _Deguber(_cmd, H_CMD, EOL); _Receive(_Addr, _cmd); delay(10); // 必須留時間做為緩衝 if (_req) _Reques(_Addr); } void WaterBox_PowerSaving::_Deguber(String _msg, UART _header, UART _uart) { if (_Debug) { switch (_header) { case H_PMU: refSerial.print(F("[PMU]\t")); break; case H_I2C: refSerial.print(F("[I2C]\t")); break; case H_CMD: refSerial.print(F("[CMD]\t")); break; default: break; } switch (_uart) { case NONE: refSerial.print(_msg); break; case EOL: refSerial.println(_msg); break; default: break; } } } ``` ### 受控制端 *.ino ```cpp=1 /* Name: PowerControled.ino Created: 2020/3/2 上午 11:49:52 Author: Liu */ #include "WaterBox_PowerSaving.h" WaterBox_PowerSaving PSM(0x70); void setup() { Serial.begin(9600); PSM.init(); PSM.setDebuger(Serial); } uint8_t _c = 0; void loop() { switch (_c % 6) { case 0: Serial.println("設定睡眠模式"); PSM.setSleepMode(PSM.NORMAL); break; case 1: Serial.println("設定睡眠秒數:增加"); PSM.setSleepSec(30 + _c); break; case 2: Serial.println("讀取狀態"); PSM.getState(); break; case 3: Serial.println("設定睡眠模式:低功耗"); PSM.setSleepMode(PSM.LOWPOWER); break; case 4: Serial.println("AT 指令"); PSM.sendData("AT=123456\n\r"); break; case 5: Serial.println("開始睡眠"); PSM.Sleep(); delay(50000); break; } _c++; if (_c > 20) _c = 0; delay(5000); } ```

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully