[分享] 自动浇水系统定时版-附chat gpt镜像版写的Arduino运行代码分享

Ai写代码   2024-10-9 17:14 楼主

前几天买了一个自动浇水diy版,就是这样用土壤湿度传感器来控制电机浇水。算是我的diy入门之路了。这几天把它按自己想法改装了一下。

feee6dfd97c249508c03e960fd8ef783.png

 

改装后不在使用湿度传感器,而是使用倒计时间隔浇水,比如每24小时浇水15秒这样。 

 

3f7be478f4d847ce95447ec47d00602a.jpg

 

于是又买了一个抽水的,把它开关按键拆了接在了旧的系统继电器上,买了一个Arduino mini板。来控制。

 

90b795eeef7b4de289b5fc0f4dd6a825.jpg

 

折腾了一下,散装系统已经上线运行了。

 

d5bb8225cd30496382a4871de95b5cfc.jpg

 

代码都是拿chat gpt中文镜像版写的现在跑起来没问题:

 

9b402d23ddb24ebca184451086824274.png
#include <U8g2lib.h>
#include <Wire.h>

// --------------------- 硬件配置 ---------------------
// 继电器模块连接到 Arduino 数字引脚 D3
const int relayPin = 4;

// OLED 显示屏配置
// 注意:根据具体的 128x64 OLED 屏幕,原点在 (30, 14)
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(
  U8G2_R0,        // 旋转角度
  A5,             // SCL 引脚
  A4,             // SDA 引脚
  U8X8_PIN_NONE   // 无重置引脚
);

// --------------------- 变量定义 ---------------------
// 定时变量
unsigned long countdownStartTime = millis();            // 倒计时的起始时间
const unsigned long initialCountdownDuration = 16000; // 初始倒计时时间(16秒,单位为毫秒)
const unsigned long mainCountdownDuration = 96400000;  // 主倒计时时间(24小时,单位为毫秒)

unsigned long relayStartTime = millis();                 // 继电器运行的起始时间
const unsigned long relayDuration = 15000;         // 继电器运行持续时间(15秒,单位为毫秒)
unsigned long runCount = 0;                        // 继电器运行次数计数

unsigned long lastDisplayUpdate = millis();
const unsigned long displayInterval = 500;        // 屏幕刷新间隔(500毫秒)

// 显示更新变量
char lastCountdownStr[16] = "";
char lastStatusAndCount[24] = "";

// 状态枚举
enum State {
  INITIAL_COUNTDOWN,
  MAIN_COUNTDOWN,
  RELAY_RUNNING
};

State currentState = INITIAL_COUNTDOWN;

// --------------------- 函数定义 ---------------------
unsigned long calculateRemainingTime(unsigned long startTime, unsigned long duration) {
  unsigned long currentMillis = millis();
  unsigned long elapsed;
  if (currentMillis >= startTime) {
    elapsed = currentMillis - startTime;
  } else {
    // Handle millis() overflow
    elapsed = (ULONG_MAX - startTime + 1) + currentMillis;
  }
  return (elapsed >= duration) ? 0 : (duration - elapsed);
}

void controlRelay(unsigned long currentMillis) {
  if (currentState == RELAY_RUNNING && (currentMillis - relayStartTime >= relayDuration)) {
    digitalWrite(relayPin, LOW); // 关闭继电器
    currentState = MAIN_COUNTDOWN;
    countdownStartTime = currentMillis; // 重置主倒计时起始时间
  }
}

void updateDisplay(unsigned long remainingTime, bool relayRunning) {
  // 将剩余时间转换为小时、分钟和秒
  unsigned long totalSeconds = remainingTime / 1000;
  unsigned int hours = totalSeconds / 3600;
  unsigned int minutes = (totalSeconds % 3600) / 60;
  unsigned int seconds = totalSeconds % 60;

  // 准备显示字符串
  char countdownStr[16]; // "T:HH:MM:SS" 或 "T:MM:SS"
  if (currentState == INITIAL_COUNTDOWN) {
    // 初始倒计时显示为 "T:MM:SS"
    snprintf(countdownStr, sizeof(countdownStr), "T:%02u:%02u", minutes, seconds);
  } else {
    // 主倒计时显示为 "T:HH:MM:SS"
    snprintf(countdownStr, sizeof(countdownStr), "T:%02u:%02u:%02u", hours, minutes, seconds);
  }

  // 继电器状态字符串
  const char* statusStr = relayRunning ? "S:ON" : "S:OFF";

  // 继电器运行次数字符串
  char runCountStr[12];
  snprintf(runCountStr, sizeof(runCountStr), "C:%lu", runCount);

  // 将状态和运行次数合并到一个字符串中
  char statusAndCount[24];
  snprintf(statusAndCount, sizeof(statusAndCount), "%s  %s", statusStr, runCountStr);

  // 仅在显示内容发生变化时更新 OLED 显示屏
  if (strcmp(countdownStr, lastCountdownStr) != 0 || strcmp(statusAndCount, lastStatusAndCount) != 0) {
    u8g2.firstPage();
    do {
      // 设置统一的小字体
      u8g2.setFont(u8g2_font_ncenB08_tr);

      // 显示时间
      int16_t time_x = 30; // 基于原点的起始 x 位置
      int16_t time_y = 30; // 调整 y 位置以减少顶部空白
      u8g2.drawStr(time_x, time_y, countdownStr);

      // 显示状态和计数在同一行
      int16_t sc_x = 30; // 基于原点的起始 x 位置
      int16_t sc_y = 50; // 时间下面的 y 位置
      u8g2.drawStr(sc_x, sc_y, statusAndCount);
    } while (u8g2.nextPage());

    // 更新最后显示的字符串
    strncpy(lastCountdownStr, countdownStr, sizeof(lastCountdownStr));
    strncpy(lastStatusAndCount, statusAndCount, sizeof(lastStatusAndCount));
  }
}

// --------------------- Setup 初始化函数 ---------------------
void setup(void) {
  // 初始化继电器引脚
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW); // 默认将继电器关闭(低电平表示继电器关闭)

  // 初始化 OLED 显示屏
  u8g2.setContrast(250); // 设置对比度
  u8g2.begin();           // 初始化显示屏
  u8g2.setContrast(255); // 最大对比度
}

// --------------------- 主循环函数 ---------------------
void loop(void) {
  unsigned long currentMillis = millis(); // 获取当前时间

  // 处理继电器的操作逻辑
  switch (currentState) {
    case INITIAL_COUNTDOWN:
      if (calculateRemainingTime(countdownStartTime, initialCountdownDuration) == 0) {
        currentState = RELAY_RUNNING;
        relayStartTime = currentMillis;
        digitalWrite(relayPin, HIGH); // 激活继电器
        runCount++;
      }
      break;

    case MAIN_COUNTDOWN:
      if (calculateRemainingTime(countdownStartTime, mainCountdownDuration) == 0) {
        currentState = RELAY_RUNNING;
        relayStartTime = currentMillis;
        digitalWrite(relayPin, HIGH); // 激活继电器
        runCount++;
      }
      break;

    case RELAY_RUNNING:
      controlRelay(currentMillis);
      break;
  }

  // 更新显示屏幕
  if (currentMillis - lastDisplayUpdate >= displayInterval) {
    unsigned long remainingTime = (currentState == INITIAL_COUNTDOWN)
                                    ? calculateRemainingTime(countdownStartTime, initialCountdownDuration)
                                    : calculateRemainingTime(countdownStartTime, mainCountdownDuration);
    updateDisplay(remainingTime, (currentState == RELAY_RUNNING));
    lastDisplayUpdate = currentMillis;
  }
}

 

回复评论 (2)

Arduino mini板控制这个系统应该么有问题

点赞  2024-10-10 07:28

chatgpt 直接生成的代码?然后改了改?

点赞  2024-10-10 17:43
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复