那曲檬骨新材料有限公司

電子發燒友App

硬聲App

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示
電子發燒友網>電子資料下載>電子資料>使用Arduino創建智能灌溉控制器

使用Arduino創建智能灌溉控制器

2022-11-03 | zip | 0.77 MB | 次下載 | 免費

資料介紹

描述

使用 Arduino 創建智能灌溉控制器

通過動態水循環智能灌溉您的院子。如果下雨或自上次澆水后一直下雨,請停止給院子澆水。使用光傳感器檢測日出時間并相應地自動調整水開始時間。如果太冷,請停止給院子澆水。

功能列表

  • 室外溫度傳感器
  • 室外雨量傳感器
  • 外光傳感器
  • 電池支持的實時時鐘,用于每周調度
  • 非易失性存儲 - 永遠不會因斷電而失去澆水
  • 日出檢測
  • 智能澆水節省您的水費
  • 日出前澆水以留出適當的浸泡時間
  • 外面太冷時停止澆水
  • 減少真菌生長
  • 輕松的日程控制
?
poYBAGNh7LCAXBooAAVR6dCdxQY024.jpg
所需零件
?

構建智能灌溉控制器所需的部件

接線圖

?
poYBAGNh7L6AS7siAAVhvK9Zzdw565.jpg
接線圖
?

OLED顯示器

?
pYYBAGNh7MSATQ91AADIw5wEBcg684.jpg
OLED顯示器
?

按下菜單按鈕顯示菜單并繼續按下按鈕循環瀏覽所有菜單選項。不活動 30 秒后菜單將自動刪除。按選擇按鈕執行所需的菜單功能。

那么為什么要使用 IO 擴展器呢?

  • 設計更簡單
  • 現成的零件
  • 無需編寫 1-Wire 驅動程序
  • 無需編寫 DS3231 RTC 驅動程序
  • 無需寫入 EEPROM 驅動程序
  • 無需編寫 OLED 顯示驅動程序
  • 沒有顯示字體占用 Arduino 代碼空間
  • 無需編寫溫度傳感器驅動程序
  • 無需寫入光學雨量傳感器驅動器
  • 節省 Arduino 上的代碼空間;僅 12710 字節 (39%)
  • 寫代碼只用了三天
  • 使用標準 RJ11 電話線輕松接線
  • 沒有傳感器電纜長度問題
  • 比類似的商業系統更便宜
  • 易于更改以適應個性化需求
  • 單電源

構建系統

將 Arduino Nano 連接到IO 擴展器并使用以下代碼對其進行編程6 針接頭是軟件串行調試端口,最終安裝時不需要。

?
pYYBAGNh7NeAQMlbAAMZZ3scr_c724.jpg
Arduino編程
?

確保更改 ONEWIRE_TO_I2C_ROM1 和 ONEWIRE-TO_I2C_ROM2 定義的地址以匹配您的1-Wire 到 I2C地址。

/* IO Expander sketch optimized
*
* Irrigation System v1.1
*
*/

#include 
#include <time.h> // File located \Program Files (x86)\Arduino\hardware\tools\avr\avr\include\time.h
#include 
#include 
#include 
#include "IOExpander.h"

#define FAHRENHEIT
#define INIT_BOARD              "g5w1;g11w1;g11d0,75;g12w1;g12d0,75;rsf"
#define ONEWIRE_TO_I2C_ROM1     "i4scc"
#define ONEWIRE_TO_I2C_ROM2     "i6s8f"
#define ONEWIRE_TEMPERATURE     "t6s0300"
#define RTC_SENSOR              "s4te"
#define I2C_EEPROM              "s4tf"
#define I2C_OLED                "s4t10"
#define I2C_LIGHT               "s3t9;sc0"
#define OPTICAL_SENSOR          "g5a"
#define BUTTON1                 "g11d"
#define BUTTON2                 "g12d"

#define WATER_TIME_BEFORE_SUNRISE 60
#define SUNRISE_LUX             100
#define RAIN_DETECT_LEVEL       4.0
#define DO_NOT_WATER_TEMP       4.4444 // 40F

#define MAX_ZONES               4

#define HOUR_IN_DAY             24L
#define MIN_IN_HOUR             60L
#define SEC_IN_MIN              60L
#define SEC_IN_HOUR             (MIN_IN_HOUR * SEC_IN_MIN)
#define SEC_IN_DAY              (HOUR_IN_DAY * SEC_IN_HOUR)
#define DAYS_IN_WEEK            7
#define SEC_IN_WEEK             (SEC_IN_DAY * DAYS_IN_WEEK)

#define SUN                     0x01
#define MON                     0x02
#define TUE                     0x04
#define WED                     0x08
#define THR                     0x10
#define FRI                     0x20
#define SAT                     0x40
#define EVERYDAY                (SUN | MON | TUE | WED | THR | FRI | SAT)

#define SUNRISE                 0x80

#define MENU_OPTIONS            9
#define MENU_TIME               30

#define OFF                     0
#define ON                      1

#define STATE_ON_OFF            0x01

//#define SERIAL_DEBUG

#ifdef SERIAL_DEBUG
SoftwareSerial swSerial(8,7);
#endif

char weekday[][4] = {"SUN","MON","TUE","WED","THU","FRI","SAT"};

char menu[][13] = {"Next",
                   "Water",
                   "Reset",
                   "Clock Min +",
                   "Clock Min -",
                   "Clock Hour +",
                   "Clock Hour -",
                   "Sunrise",
                   "ON/OFF"};

enum {
  MENU_NEXT,
  MENU_WATER,
  MENU_RESET,
  MENU_CLOCK_MIN_PLUS,
  MENU_CLOCK_MIN_MINUS,
  MENU_CLOCK_HOUR_PLUS,
  MENU_CLOCK_HOUR_MINUS,
  MENU_SUNRISE,
  MENU_ON_OFF
};

typedef struct {
  char description[16];
  uint8_t relay;
} ZONE;

typedef struct {
  uint8_t zone;
  uint8_t days;
  int8_t hour;
  int8_t min;
  uint8_t duration;
} SCHEDULE;

typedef struct {
  time_t sunrise_time;
  time_t last_water_time;
  uint8_t water_schedule;
  uint8_t water_duration;
  uint8_t rain[MAX_ZONES];
  uint8_t state;
  uint8_t crc;
} NVRAM;

enum {
  ZONE1,
  ZONE2,
  ZONE3,
  ZONE4
};

enum {
  RELAY1 = 1,
  RELAY2,
  RELAY3,
  RELAY4
};

ZONE zone[] = {
  {"Front Right", RELAY1},
  {"Front Left",  RELAY2},
  {"Bushes",      RELAY3},
  {"Left Side",   RELAY4},
};

SCHEDULE schedule[] = {
  {ZONE1, SUNRISE | EVERYDAY, -1, 0,  4},
  {ZONE2, EVERYDAY,            6, 15, 5},
  {ZONE3, EVERYDAY,            6, 0,  10},
  {ZONE4, EVERYDAY,            6, 10, 6},
};

NVRAM nvram;
bool update_nvram = false;

uint8_t crc8(uint8_t* data, uint16_t length)
{
  uint8_t crc = 0;

  while (length--) {
    crc = _crc8_ccitt_update(crc, *data++);
  }
  return crc;
}

int led = 13;
bool init_oled = true;
bool update_oled = true;
bool init_board = true;

#ifdef FAHRENHEIT
#define C2F(temp)   CelsiusToFahrenheit(temp)
float CelsiusToFahrenheit(float celsius)
{
  return ((celsius * 9) / 5) + 32;
}
#else
#define C2F(temp)   (temp)
#endif

void SerialPrint(const char* str, float decimal, char error)
{
  Serial.print(str);
  if (error) Serial.print(F("NA"));
  else Serial.print(decimal, 1);
}

time_t NextScheduleTime(time_t last_time, uint8_t* next_schedule)
{
  time_t next_time = -1;
  time_t clk_time;
  uint8_t i;
  tm clk;
  uint8_t wday;

  for (i = 0; i < sizeof(schedule) / sizeof(SCHEDULE); i++) {
    if (schedule[i].days & SUNRISE) {
      clk_time = nvram.sunrise_time;
      clk_time += schedule[i].hour * SEC_IN_HOUR;
      clk_time += schedule[i].min * SEC_IN_MIN;
      localtime_r(&clk_time, &clk);
    }
    else {
      localtime_r(&last_time, &clk);
      clk.tm_hour = schedule[i].hour;
      clk.tm_min = schedule[i].min;
      clk.tm_sec = 0;
      clk_time = mktime(&clk);
    }
    wday = clk.tm_wday;
    while (clk_time <= last_time || !(schedule[i].days & (1 << wday)))
    {
      clk_time += SEC_IN_DAY;
      if (++wday > SATURDAY) wday = SUNDAY;
      if (wday == clk.tm_wday) break; // Only check one week
    }
    if (clk_time < next_time) {
      next_time = clk_time;
      *next_schedule = i;
    }
  }
  return next_time;
}

void StartScheduleTime(time_t start_time, uint8_t start_schedule)
{
  uint8_t i;

  nvram.last_water_time = start_time;
  nvram.water_schedule = start_schedule;
  nvram.water_duration = schedule[start_schedule].duration+1;
  update_nvram = true;
  // Check if it rained
  i = schedule[start_schedule].zone;
  if (i < MAX_ZONES && nvram.rain[i] > 0) {
    if (nvram.rain[i] > nvram.water_duration) nvram.water_duration = 0;
    else nvram.water_duration -= nvram.rain[i];
    nvram.rain[i] = 0;
  }
}

void WaterScheduleTime(void)
{
  uint8_t i;

  nvram.water_duration--;
  update_nvram = true;
  i = schedule[nvram.water_schedule].zone;
  if (i < MAX_ZONES) {
    Serial.print("r");
    Serial.print(zone[i].relay);
    if (nvram.water_duration > 0) Serial.println("o");
    else Serial.println("f");
    SerialReadUntilDone();
   }
}

void setup() {
  Serial.begin(115200);
#ifdef SERIAL_DEBUG
  swSerial.begin(115200);
#endif
  pinMode(led, OUTPUT);
  //delay(1000);
  wdt_enable(WDTO_8S);
}

void loop() {
  static tm rtc;
  tm clk, sunrise_clk;
  time_t rtc_time;
  time_t clk_time;
  static time_t next_time;
  static uint8_t last_sec;
  static uint8_t last_min;
  bool error_rtc;
  bool error_light;
  bool error_temp;
  static long lux = 0;
  static float temp, rain;
  static uint8_t sunrise_counter = MIN_IN_HOUR;
  static bool check_sunrise = false;
  uint8_t i;
  static bool read_nvram = true;
  static time_t water_time;
  static uint8_t water_schedule;
  uint8_t sz;
  uint8_t wday;
  long n;
  bool button1, button2;
  static int8_t menu_select = -1;
  static time_t menu_time = 0;

  Serial.println();
  if (SerialReadUntilDone()) {
    if (init_board) {
      SerialCmdDone(INIT_BOARD);
      init_board = false;
    }

    if (init_oled) {
      if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)) {
        SerialCmdDone(I2C_OLED ";si;sc;sd");
        init_oled = false;
      }
    }

    if (SerialCmdDone(RTC_SENSOR)) {
      error_rtc = !SerialReadTime(&rtc);
      if (!error_rtc) {
        clk = rtc; // mktime() can change struct tm
        rtc_time = mktime(&clk);
        localtime_r(&rtc_time, &rtc);  // Get wday.
      }

      if (read_nvram) {
        if (SerialCmdNoError(I2C_EEPROM)) {
          SerialReadEEPROM((uint8_t*)&nvram, 0, sizeof(nvram));
          if (nvram.crc != crc8((uint8_t*)&nvram, sizeof(nvram)-sizeof(uint8_t))) {
            //swSerial.println("CRC8 Failure!");
            // Initialize nvram
            memset(&nvram, 0, sizeof(nvram));
            clk = rtc;
            clk.tm_hour = 6;
            clk.tm_min = 0;
            clk.tm_sec = 0;
            nvram.sunrise_time = mktime(&clk);
            if (nvram.sunrise_time < rtc_time) nvram.sunrise_time + SEC_IN_DAY;
            update_nvram = true;
          }
          // Check last water time no less than one week
          if (rtc_time - nvram.last_water_time > SEC_IN_WEEK) nvram.last_water_time = rtc_time - SEC_IN_WEEK;
          // Check sunrise time
          if (rtc_time > nvram.sunrise_time) {
            localtime_r(&nvram.sunrise_time, &sunrise_clk);
            clk = rtc;
            clk.tm_hour = sunrise_clk.tm_hour;
            clk.tm_min = sunrise_clk.tm_min;
            clk.tm_sec = sunrise_clk.tm_sec;
            nvram.sunrise_time = mktime(&clk);
            if (nvram.sunrise_time < rtc_time) nvram.sunrise_time + SEC_IN_DAY;
          }
          if (nvram.water_duration) {
            nvram.water_duration++;
            water_time = nvram.last_water_time;
          }
          else {
            clk_time = (nvram.last_water_time) ? nvram.last_water_time : rtc_time;
            water_time = NextScheduleTime(clk_time, &water_schedule);
          }
          read_nvram = false;
        }
      }
    }

    // Process only once every minute
    if (rtc.tm_min != last_min)
    {
      // Request a 1-Wire temperature measurement.  Read it later.
      error_temp = !SerialCmdNoError(ONEWIRE_TEMPERATURE);
      if (!error_temp) SerialCmdDone("tt");

      error_light = !SerialCmdNoError(ONEWIRE_TO_I2C_ROM2 ";oo0");
      if (!error_light) {
        SerialCmdDone(I2C_LIGHT); // Do not use overdrive
        SerialCmd("sr");
        SerialReadInt(&lux);
        SerialReadUntilDone();
      }

      if (SerialCmd(OPTICAL_SENSOR)) {
        SerialReadFloat(&rain);
        SerialReadUntilDone();
      }

      error_temp = !SerialCmdNoError(ONEWIRE_TEMPERATURE);
      if (!error_temp) {
        SerialCmd("tr");
        SerialReadFloat(&temp);
        SerialReadUntilDone();
      }

      // Is it sunrise?
      if (lux < SUNRISE_LUX) {
        if (sunrise_counter > 0) sunrise_counter--;
        else check_sunrise = true;
      }
      else {
        if (sunrise_counter < MIN_IN_HOUR) {
          sunrise_counter++;
          if (check_sunrise && sunrise_counter == MIN_IN_HOUR) {
            nvram.sunrise_time = rtc_time + (SEC_IN_DAY - SEC_IN_HOUR);
            check_sunrise = false;
            update_nvram = true;
          }
        }
      }

      // Is it raining?
      if (rain <= RAIN_DETECT_LEVEL) {
        for (i = 0; i < MAX_ZONES; i++) {
          if (nvram.rain[i] < -1) nvram.rain[i]++;
        }
        update_nvram = true;
      }

      // Check schedule
      if (menu_select == -1 && !nvram.water_duration) {
        while (water_time + (schedule[water_schedule].duration * SEC_IN_MIN) < rtc_time) {
          water_time = NextScheduleTime(water_time, &water_schedule);
        }
        if (water_time <= rtc_time) {
          StartScheduleTime(water_time, water_schedule);
          if (temp <= DO_NOT_WATER_TEMP || nvram.state & STATE_ON_OFF == OFF)
            nvram.water_duration = 0;
        }
      }

      // Do we need to water?
      if (nvram.water_duration) {
        WaterScheduleTime();
        if (!nvram.water_duration)
          water_time = NextScheduleTime(water_time, &water_schedule);
      }

      last_min = rtc.tm_min;
      update_oled = true;
    }

    // Check buttons
    button1 = SerialReadButton(BUTTON1);
    if (button1) {
      if (menu_select == -1) menu_select = 0;
      else {
        if (++menu_select >= MENU_OPTIONS)
          menu_select = 0;
      }
      menu_time = rtc_time;
      update_oled = true;
    }
    if (menu_select >= 0) {
      button2 = SerialReadButton(BUTTON2);
      if (button2) {
        clk_time = rtc_time;
        switch(menu_select) {
          case MENU_NEXT:
          case MENU_RESET:
            if (nvram.water_duration) {
              nvram.water_duration = 1;
              WaterScheduleTime();
            }
            water_time = NextScheduleTime((menu_select == MENU_NEXT) ? water_time : rtc_time, &water_schedule);
            break;
          case MENU_WATER:
            StartScheduleTime(water_time, water_schedule);
            WaterScheduleTime();
            break;
          case MENU_CLOCK_MIN_PLUS:
            clk_time += SEC_IN_MIN;
            break;
          case MENU_CLOCK_MIN_MINUS:
            clk_time -= SEC_IN_MIN;
            break;
          case MENU_CLOCK_HOUR_PLUS:
            clk_time += SEC_IN_HOUR;
            break;
          case MENU_CLOCK_HOUR_MINUS:
            clk_time -= SEC_IN_HOUR;
            break;
          case MENU_ON_OFF:
            nvram.state ^= STATE_ON_OFF;
            update_nvram = true;
            break;
        }
        if (clk_time != rtc_time) {
          if (SerialCmdDone(RTC_SENSOR)) {
            localtime_r(&clk_time, &clk);
            SerialWriteTime(&clk);
            rtc_time = clk_time;
          }
        }
        menu_time = rtc_time;
        update_oled = true;
      }
    }
    if (menu_select >= 0 && rtc_time - menu_time > MENU_TIME) {
      menu_select = -1;
      update_oled = true;
    }

    if (update_oled) {
      if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)) {
        Serial.print("st10;so1;sc;sf0;sa0;sd0,0,"");
        if (nvram.water_duration) Serial.print(nvram.water_duration);
        else {
          if ((nvram.state & STATE_ON_OFF) == OFF) Serial.print("OFF");
          else if (rain <= RAIN_DETECT_LEVEL) Serial.print("Rain");
          else if (temp <= DO_NOT_WATER_TEMP) Serial.print("Cold");
          else Serial.print("v1.1");
        }
        Serial.print("";sf2;sa1;sd75,0,"");
        if (menu_select == 7) { // Sunrise
          clk_time = nvram.sunrise_time;
          localtime_r(&clk_time, &clk);
        }
        else clk = rtc;
        Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0));
        Serial.print(":");
        if (clk.tm_min < 10) Serial.print("0");
        Serial.print(clk.tm_min);
        Serial.println(""");
        SerialReadUntilDone();

        Serial.print("sf1;sa0;sd79,8,"");
        Serial.print((clk.tm_hour>12)?"PM":"AM");
        Serial.print("";sf0;sa1;sd127,1,"");
        Serial.print(weekday[clk.tm_wday]);
        Serial.print("";sd127,13,"");
        Serial.print(clk.tm_mon+1);
        Serial.print("/");
        Serial.print(clk.tm_mday);
        Serial.println(""");
        SerialReadUntilDone();

        Serial.print("sf0;sa0;sd1,36,"");
        i = schedule[water_schedule].zone;
        if (i < MAX_ZONES) Serial.print(zone[i].description);
        localtime_r(&water_time, &clk);
        if (water_time - rtc_time > SEC_IN_DAY) {
          Serial.print("";sa1;sd126,36,"");
          Serial.print(clk.tm_mon+1);
          Serial.print("/");
          Serial.print(clk.tm_mday);
          Serial.print(" ");
          Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0));
          Serial.print(":");
          if (clk.tm_min < 10) Serial.print("0");
          Serial.print(clk.tm_min);
          Serial.print(" ");
        }
        else {
          Serial.print("";sf1;sa1;sd111,30,"");
          Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0));
          Serial.print(":");
          if (clk.tm_min < 10) Serial.print("0");
          Serial.print(clk.tm_min);
          Serial.print("";sf0;sd126,36,"");
        }
        Serial.print((clk.tm_hour>12)?"PM":"AM");
        if (nvram.water_duration) Serial.print("";so2;sc0,29,128,19");
        Serial.println();
        SerialReadUntilDone();

        if (menu_select == -1) {
          //Serial.print("";sa0;sd0,52,"");
          //Serial.print(rain);
          SerialPrint("";so1;sa2;sd63,52,"", C2F(temp), error_temp);
          if (!error_temp) Serial.print("",248,""
#ifdef FAHRENHEIT
            "F"
#else
            "C"
#endif
            );
          Serial.print(" / ");
          Serial.print(lux);
        }
        else {
          Serial.print("";so0;sc0,51,128,14;sf0;sa2;sd63,52,"");
          if (menu_select == MENU_ON_OFF) {
            Serial.print((nvram.state & STATE_ON_OFF) ? "OFF" : "ON");
          }
          else Serial.print(menu[menu_select]);
        }
        Serial.println("";sd");
        SerialReadUntilDone();
        update_oled = false;
      }
      else init_oled = true;
    }

    if (update_nvram) {
      if (SerialCmdNoError(I2C_EEPROM)) {
        nvram.crc = crc8((uint8_t*)&nvram, sizeof(nvram)-sizeof(uint8_t));
        //swSerial.println(nvram.crc, HEX);
        SerialWriteEEPROM((uint8_t*)&nvram, 0, sizeof(nvram));
        update_nvram = false;
      }
    }

    delay(50);
  }
  else {
    digitalWrite(led, HIGH);
    delay(500);
    digitalWrite(led, LOW);
    delay(500);
    init_board = true;
    init_oled = true;
  }
  wdt_reset();
}

注意:如果您使用 USB 端口對 Arduino Nano 進行編程,則必須將其與IO 擴展器斷開,因為它也使用相同的單個串行端口,而不是如果您想調試使用 ICSP 端口對 ATmega328P 進行編程。要啟用軟件調試端口,請取消注釋 SERIAL_DEBUG 定義。

必須首先配置分路器以將光學紅外傳感器數據線與 1-Wire 遠程傳感器線隔離。在 R2 處焊接一個零歐姆 0603 電阻

?
pYYBAGNh7NqAXMosAABRe3TW_TY491.jpg
分路器配置
?

在 PG7 和 PG11 右側的小外殼上鉆一個 7/16" 的孔,在較大的外殼上鉆一個 11/16" 的孔。使用 dremel 工具稍微擴大孔,直到壓蓋貼合。PG7 將為遠程傳感器和 PG11 供電,用于 12VDC、24VAC、歧管線和 RJ11 遠程傳感器線。

?
poYBAGNh7OaAfp_HAABEfP_oOao012.jpg
外殼鉆孔
?

連接 SPST 瞬時按鈕微動開關并將其連接到 RJ11 螺釘端子。使用熱縮管對觸點進行絕緣。

?
pYYBAGNh7OeAKct4AAAde1fe9eo077.jpg
按鈕接線
?

連接所有電線并將所有零件組裝/送入大型外殼。用于遠程傳感器的 50 英尺 RJ11 線應剛好穿過 PG11 密封套,而無需切斷它。

?
pYYBAGNh7QGAEkGnAAal_pSNuuc879.jpg
連接項目
?

在光學紅外水傳感器的小外殼頂部鉆一個 9/16" 孔。使用 dremel 工具稍微擴大孔直到傳感器適合。小型遠程傳感器外殼是緊密配合的,但如果內容以建議的方向鋪設,它應該正好適合。使 RJ11 線盡可能短將有助于將其全部塞入較小的外殼中。組裝后,建議在擰緊螺母之前在壓蓋螺母墊圈中添加一些船用膠水,創造更好的印章。

?
pYYBAGNh7QWAOYGDAAHLrVmgC40074.jpg
小型外殼組件
?

將遠程傳感器外殼安裝在室外,并將其安裝在房屋的東側,使光學紅外水傳感器和光傳感器指向天空,無障礙物。

?
poYBAGNh7QiAD9F_AABQ3BMtyV4536.jpg
安裝在外面的小外殼
?

在大外殼的頂部中間底部鉆 1/4" 孔并安裝按鈕。使用 dremel 工具稍微擴大孔,直到按鈕適合。

?
poYBAGNh7ROAQa_gAAW_785hMzk545.jpg
室內外殼的最終組裝。
?

測試系統并確保一切正常。要測試繼電器和傳感器,請斷開 Arduino 與IO 擴展器的連接,并將其直接連接到您的計算機以手動控制它。確認一切正常后,使用雙面膠帶和包裝泡沫將所有部件組裝到外殼中以固定您的電路板,并享受智能灌溉控制器的好處和節省。

2019 年 9 月 12 日更新

發布的 v1.1 修復了系統斷電數天時出現的啟動問題。

2019 年 10 月 2 日更新

將 1-Wire 連接到 I2C 到 DS3231,然后連接到 SSD1306 OLED 屏幕時,您將在 SDA 和 SCL 線上總共有三個不同的上拉電阻,如下圖圓圈所示。這將有效地導致 4.7k / 3 = 1.56k 的上拉,可能太強并導致隨機屏幕損壞。

pYYBAGNh7RWAHDV3AADGgA3SVRo322.jpg
4.7k 引體向上
?

由于 DS3231 使用其他線路使用的電阻器組,請移除其他上拉電阻器:

  • 1-Wire 到 I2C R3 和 R4。
  • SSD1306 OLED R6 和 R7。

下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數據手冊
  2. 1.06 MB  |  532次下載  |  免費
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費
  5. 3TC358743XBG評估板參考手冊
  6. 1.36 MB  |  330次下載  |  免費
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費
  9. 5元宇宙深度解析—未來的未來-風口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費
  11. 6迪文DGUS開發指南
  12. 31.67 MB  |  194次下載  |  免費
  13. 7元宇宙底層硬件系列報告
  14. 13.42 MB  |  182次下載  |  免費
  15. 8FP5207XR-G1中文應用手冊
  16. 1.09 MB  |  178次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費
  3. 2555集成電路應用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費
  7. 4開關電源設計實例指南
  8. 未知  |  21549次下載  |  免費
  9. 5電氣工程師手冊免費下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費
  11. 6數字電路基礎pdf(下載)
  12. 未知  |  13750次下載  |  免費
  13. 7電子制作實例集錦 下載
  14. 未知  |  8113次下載  |  免費
  15. 8《LED驅動電路設計》 溫德爾著
  16. 0.00 MB  |  6656次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉中文版)
  4. 78.1 MB  |  537798次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191187次下載  |  免費
  13. 7十天學會AVR單片機與C語言視頻教程 下載
  14. 158M  |  183279次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138040次下載  |  免費
百家乐系统足球博彩通| 网上百家乐官网公司| 百家乐官网微笑不倒| 太阳百家乐官网游戏| 百家乐开户优惠多的平台是哪家 | 百家乐游戏| 百家乐官网赌缆十三式| 百家乐官网高科技出千工具| 百樂坊百家乐官网的玩法技巧和规则| 真人百家乐官网赌城| 百家乐合理的投注法| 金都百家乐的玩法技巧和规则| 大发888官方爱好| 大发888在线娱乐城合营商| 永州市| 百家乐官网任你博赌场娱乐网规则| 百家乐官网群shozo| 百家乐游戏厅| bet365滚球| 百家乐官网的玩法视频| 跨国际百家乐官网的玩法技巧和规则| 澳门百家乐群策略| 大发888大发888m摩卡游戏博彩官方下载| 浏阳市| 24山向方位度数| 足球百家乐投注网出租| 安图县| 百家乐官网真人视频出售| 威尼斯人娱乐场28gxpjwnsr| 连州市| 网络百家乐最安全| 大发888官网www.dafa888.com| 百家乐官网中B是什么| 百家乐规则博彩正网| 鼎尚百家乐的玩法技巧和规则 | 真人百家乐开户优惠| 12bet备用| AG百家乐官网大转轮| 澳门百家乐怎么| 现金梭哈| 24山吉凶|