Ai写代码 发表于 2024-10-9 17:14

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

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

<div style="text-align: center;"></div>

<p>&nbsp;</p>

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

<p>&nbsp;</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

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

<p>&nbsp;</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

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

<p>&nbsp;</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

<p>代码都是拿<a href="https://tz.zhufushipinzhizuo.com/17.html" rel="noopener" target="_blank">chat gpt中文镜像版</a>写的现在跑起来没问题:</p>

<p>&nbsp;</p>

<div style="text-align: center;"></div>

<pre>
<code class="language-cs">#include &lt;U8g2lib.h&gt;
#include &lt;Wire.h&gt;

// --------------------- 硬件配置 ---------------------
// 继电器模块连接到 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 = "";
char lastStatusAndCount = "";

// 状态枚举
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 &gt;= startTime) {
    elapsed = currentMillis - startTime;
} else {
    // Handle millis() overflow
    elapsed = (ULONG_MAX - startTime + 1) + currentMillis;
}
return (elapsed &gt;= duration) ? 0 : (duration - elapsed);
}

void controlRelay(unsigned long currentMillis) {
if (currentState == RELAY_RUNNING &amp;&amp; (currentMillis - relayStartTime &gt;= 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; // "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;
snprintf(runCountStr, sizeof(runCountStr), "C:%lu", runCount);

// 将状态和运行次数合并到一个字符串中
char statusAndCount;
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 &gt;= displayInterval) {
    unsigned long remainingTime = (currentState == INITIAL_COUNTDOWN)
                                    ? calculateRemainingTime(countdownStartTime, initialCountdownDuration)
                                    : calculateRemainingTime(countdownStartTime, mainCountdownDuration);
    updateDisplay(remainingTime, (currentState == RELAY_RUNNING));
    lastDisplayUpdate = currentMillis;
}
}</code></pre>

<p>&nbsp;</p>

Jacktang 发表于 2024-10-10 07:28

<p>Arduino mini板控制这个系统应该么有问题</p>

wangerxian 发表于 2024-10-10 17:43

<p>chatgpt 直接生成的代码?然后改了改?</p>
页: [1]
查看完整版本: 自动浇水系统定时版-附chat gpt镜像版写的Arduino运行代码分享