【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

这篇具有很好参考价值的文章主要介绍了【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1 简介

Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目,大家可用于 课程设计 或 毕业设计

基于Arduino的智能灌溉系统


单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052文章来源地址https://www.toymoban.com/news/detail-450980.html


【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

1 硬件要求

rduino NANO开发板 1块

IO扩展板 1块

IO扩展模块包 1套

开发工具

2 项目背景

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

智能灌溉您的院子或花园用动态水循环。如果正在下雨,或者自从上次浇水后就已经下雨了,不要再给院子浇水了。使用光传感器检测日出时间,并自动调整水开始时间。如果天气太冷,就停止给院子浇水。

3 实现功能

  • 户外温度传感器
  • 户外下雨传感器
  • 户外光照传感器
  • 有电池的RTC支持按周的灌溉调度
  • 非易失性存储-永远不会因为断电而丢失灌溉设置参数
  • 日出检测
  • 智能的浇水可以节省你的水费
  • 日出前浇水,留出适当的渗透时间
  • 减少真菌生长
  • 简单的调度控制

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

制作智能灌溉控制器所需的零件清单

  • IO扩展板 1块
  • 单总线转I2C 2块
  • 单线连接器 1个
  • 光纤连接器 1个
  • 光分路器 1个
  • Arduino Nano开发板 1块
  • 4路直流5V继电器
  • TSL2561光传感器
  • DS18B20防水温度传感器
  • 光学红外水位传感器
  • DS3231 AT24C32 IIC精密实时时钟
  • I2C SSD1306 OLED 128x64显示屏
  • 透明防水塑料外壳200x120x75mm
  • 透明防水塑料外壳100x68x50mm
  • ip68 pg7防水尼龙电缆盖
  • ip68 pg11防水尼龙电缆盖
  • RJ11 螺钉接线端子
  • 50英尺4C4P RJ11线
  • 6" 4C4P RJ11线
  • 2.54毫米接头线
  • 2引脚SPST瞬时微动按钮开关 2个
  • 12VDC 1A适配器电源

接线图

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

4 OLDE显示屏

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

点击Menu按钮显示菜单,并继续点击此按钮循环完成所有菜单选项。如果30秒没有操作这个菜单将会自动返回。按下选择按钮以执行所需的菜单功能。

5 IO扩展器

使用io扩展器的优点如下

  • 设计更简单
  • 现成的零件
  • 不需要编写单线驱动程序
  • 不需要编写DS3231 RTC驱动程序
  • 不需要编写EEPROM 驱动程序
  • 不需要编写OLED驱动程序
  • 没有显示字体占用Arduino代码空间
  • 不需要编写温度传感器驱动程序
  • 不需要编写光学雨感测器驱动程序
  • 节省Arduino上的代码空间;只有12710字节(39%)
  • 只要三天的时间来写代码
  • 易于电线使用标准的RJ11电话电缆
  • 无传感器电缆长度问题
  • 比类似的商业系统更便宜
  • 易于进行更改以适应个别需求
  • 单电源供电

6 系统构建

将Arduino Nano连接到IO扩展器,并使用以下代码对其进行编程。6 pin头是软件的串行调试端口,在最终的安装中是不需要的。

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

这里要确保更改了ONEWIRE_TO_I2C_ROM1和ONEWIRE-TO_I2C_ROM2定义的地址,使单总线地址与I2C地址相匹配。

注意:如果使用USB端口来给Arduino Nano编程,必须断开它与IO扩展器的连接,因为它也使用相同的单一串行端口,相反,如果想调试使用ICSP端口来编程ATmega328P。要启用软件调试端口,请取消对SERIAL_DEBUG定义的注释。

分配器必须首先配置为将光学红外传感器数据线与单线远程传感器线隔离。在R2处焊接零欧姆0603电阻。

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

将SPST轻触按钮微动开关接上RJ11螺丝端子。使用热收缩管绝缘接触端。

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

连接所有电线和组装/馈送所有部件到大外壳。将所有部件装到大外壳里,并连接所有导线。

用于连接远程传感器的50英尺的RJ11电缆应该刚好穿过PG11防水头,而不用剪断它。

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

在小外壳的顶部钻一个9/16英寸的孔,用于安装光学红外水传感器。使用达美电磨工具稍微把孔扩大一点,直到传感器安装到位。小型远程传感器与外壳紧密贴合,但是如果传感器是按照推荐的方向放置的,那么它应该刚好合适。使RJ11电缆尽可能短将有助于把它塞进更小的外壳。组装完成后,建议在拧上螺母之前在压盖螺母垫圈中添加一些防水胶,将会有更好的密封效果。

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网

测试系统,确保一切正常。要测试继电器和传感器,请断开Arduino与IO扩展器的连接,并将其直接连接到您的计算机以手动控制它。一旦您确认一切正常,使用双面胶带和包装泡沫将所有部件组装到外壳中,以保护您的电路板,并享受智能灌溉控制器带来的好处和节约用水。

7 完整代码

使用你的Arduino智能浇灌你的院子或花园。

#include <math.h>
#include <time.h> // File located \Program Files (x86)\Arduino\hardware\tools\avr\avr\include\time.h
#include <util/crc16.h>
#include <avr/wdt.h>
#include <SoftwareSerial.h>
#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();
}

单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052


8 最后

到了这里,关于【毕业设计】基于Arduino的智能灌溉系统 - 嵌入式 单片机 物联网的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于人工智能的智能教育系统设计与实现 毕业设计开题报告

     博主介绍 :《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月05日
    浏览(44)
  • 毕业设计-基于深度学习的智能车牌识别系统

    目录 前言 课题背景和意义 实现技术思路 一、车牌识别的一般流程 二、智能车牌识别系统的设计思路 三、基于深度学习的智能车牌识别系统的实现 四、智能车牌识别系统的训练与测试 五、总结 实现效果图样例 最后     📅大四是整个大学期间最忙碌的时光,一边要忙着备考

    2024年02月06日
    浏览(53)
  • 人工智能课程设计毕业设计——基于机器学习的手写汉字识别系统

    《机器学习》课程设计实验 报告 题目:基于深度学习的手写汉字识别系统 目录 基于深度学习的手写汉字识别系统实验报告 1. 绪论 ............................................................................................................................................................ 1 1.1 研究背景及意义..

    2024年02月20日
    浏览(53)
  • 毕业设计 基于Arduino的计算器

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月11日
    浏览(35)
  • 毕业设计 基于51单片机智能停车场管理车位引导系统设计

    选题之前,同学们要弄明白一件事情,做毕业设计是干什么用的! 这里我告诉大家,毕业设计对于你来说,不是让你去搞研究,掌握运用所学知识的,也不是让你去比谁做的毕业设计多么牛逼,多么厉害。 说白点,它的作用就是一个,让你顺利毕业,能够拿到学位证,毕业

    2023年04月15日
    浏览(65)
  • STM32毕业设计——基于STM32+MQTT+WiFi技术的智能家居系统设计与实现(毕业论文+程序源码)——智能家居系统

    大家好,今天给大家介绍基于STM32+MQTT+WiFi技术的智能家居系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报告PPT模板及论文答辩PPT模板等的小伙伴,可以进入我的博客主页查看左侧最下面栏目中的自助下载方法哦 文章目录: 智能家居技术

    2024年02月10日
    浏览(56)
  • 毕业设计-基于计算机图像识别的垃圾智能分类系统

    目录 前言 课题背景和意义 实现技术思路 一、YOLOv3 算法 二、基于 Tensorflow2 的 YOLOv3 算法垃圾识别 三、总结 实现效果图样例 最后     📅大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学

    2024年02月08日
    浏览(65)
  • 毕业设计:基于深度学习的图像分类识别系统 人工智能

    目录 前言 项目背景 数据集 设计思路 自注意力 网络模型 实验环境 实验结果分析 更多帮助     📅大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课

    2024年04月16日
    浏览(61)
  • 基于Java(SpringBoot框架)毕业设计作品成品(30)AI毕业设计AI智能动物大全识别系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月08日
    浏览(44)
  • 基于Java(SpringBoot框架)毕业设计作品成品(29)AI毕业设计AI智能植物大全识别系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月08日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包