前几天买了一个自动浇水diy版,就是这样用土壤湿度传感器来控制电机浇水。算是我的diy入门之路了。这几天把它按自己想法改装了一下。
改装后不在使用湿度传感器,而是使用倒计时间隔浇水,比如每24小时浇水15秒这样。
于是又买了一个抽水的,把它开关按键拆了接在了旧的系统继电器上,买了一个Arduino mini板。来控制。
折腾了一下,散装系统已经上线运行了。
代码都是拿chat gpt中文镜像版写的现在跑起来没问题:
#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;
}
}
chatgpt 直接生成的代码?然后改了改?