如何在Arduino自动送餐系统代码中集成DS1302实现定时运行
DS1302实时时钟集成到自动送餐系统的实现方案
一、硬件接线说明
DS1302时钟模块需要3个IO引脚与Arduino连接,需避开现有代码已占用的引脚(10、9、8、7、6、5、A0-A5),推荐接线:
- DS1302的RST引脚 → Arduino引脚2
- DS1302的DAT引脚 → Arduino引脚3
- DS1302的CLK引脚 → Arduino引脚4
- DS1302的VCC接5V,GND接Arduino GND
二、库安装与代码集成步骤
- 在Arduino IDE的库管理器中搜索并安装
DS1302库(推荐Makuna/DS1302,兼容性强) - 对原有代码做如下修改:
- 引入DS1302库并定义时钟引脚
- 初始化时钟模块,第一次烧录时设置正确的系统时间
- 将原有送餐逻辑封装为独立函数,通过时钟判断触发时机
- 主循环仅做时钟检测,满足条件才执行送餐任务
三、修改后的完整代码
#include <DS1302.h> // DS1302时钟引脚定义 #define DS1302_RST 2 #define DS1302_DAT 3 #define DS1302_CLK 4 DS1302 rtc(DS1302_RST, DS1302_DAT, DS1302_CLK); // 原有硬件引脚定义 #define enA 10//Enable1 L298 Pin enA #define in1 9 //Motor1 L298 Pin in1 #define in2 8 //Motor1 L298 Pin in2 #define in3 7 //Motor2 L298 Pin in3 #define in4 6 //Motor2 L298 Pin in4 #define enB 5 //Enable2 L298 Pin enB #define L_S A0 //ir sensor Left #define R_S A1 //ir sensor Right #define echo A2 //Echo pin #define trigger A3 //Trigger pin #define servo A5 int Set=15; int distance_L, distance_F, distance_R; bool isTaskRunning = false; // 标记任务是否正在执行 void setup(){ Serial.begin(9600); // 初始化时钟模块 rtc.halt(false); // 启动时钟 rtc.writeProtect(false); // 关闭写保护 // 第一次烧录时设置时间,格式:年,月,日,星期,时,分,秒 // rtc.time(Time(2024, 10, 26, 6, 12, 0, 0)); // 示例:2024年10月26日,周六,12点0分0秒 // 设置完成后注释掉该行,避免每次重启重置时间 // 原有硬件初始化 pinMode(R_S, INPUT); pinMode(L_S, INPUT); pinMode(echo, INPUT ); pinMode(trigger, OUTPUT); pinMode(enA, OUTPUT); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); pinMode(enB, OUTPUT); analogWrite(enA, 200); analogWrite(enB, 200); pinMode(servo, OUTPUT); for (int angle = 70; angle <= 140; angle += 5) { servoPulse(servo, angle); } for (int angle = 140; angle >= 0; angle -= 5) { servoPulse(servo, angle); } for (int angle = 0; angle <= 70; angle += 5) { servoPulse(servo, angle); } distance_F = Ultrasonic_read(); delay(500); } void loop(){ Time t = rtc.time(); // 获取当前时间 // 定时触发条件:12点整,或每15分钟的整分时刻(0、15、30、45分),且任务未在执行 if((t.hour == 12 && t.min == 0 && t.sec == 0) || (t.min %15 ==0 && t.sec ==0)){ if(!isTaskRunning){ isTaskRunning = true; runDelivery(); // 执行送餐任务 isTaskRunning = false; } }else{ Stop(); // 未到时间,电机停止 } delay(1000); // 每秒检测一次时间,避免频繁读取时钟 } // 封装原有送餐逻辑为独立函数 void runDelivery(){ unsigned long startTime = millis(); // 可设置单次任务最长运行时间,比如30分钟:1800000ms while(millis() - startTime < 1800000){ distance_F = Ultrasonic_read(); Serial.print("D F=");Serial.println(distance_F); if((digitalRead(R_S) == 0)&&(digitalRead(L_S) == 0)){ if(distance_F > Set){forword();} else{Check_side();} } else if((digitalRead(R_S) == 1)&&(digitalRead(L_S) == 0)){turnRight();} else if((digitalRead(R_S) == 0)&&(digitalRead(L_S) == 1)){turnLeft();} delay(10); } Stop(); // 任务结束后停止电机 } // 以下为原有函数,保持不变 void servoPulse (int pin, int angle){ int pwm = (angle*11) + 500; digitalWrite(pin, HIGH); delayMicroseconds(pwm); digitalWrite(pin, LOW); delay(50); } long Ultrasonic_read(){ digitalWrite(trigger, LOW); delayMicroseconds(2); digitalWrite(trigger, HIGH); delayMicroseconds(10); long time = pulseIn (echo, HIGH); return time / 29 / 2; } void compareDistance(){ if(distance_L > distance_R){ turnLeft(); delay(500); forword(); delay(600); turnRight(); delay(500); forword(); delay(600); turnRight(); delay(400); } else{ turnRight(); delay(500); forword(); delay(600); turnLeft(); delay(500); forword(); delay(600); turnLeft(); delay(400); } } void Check_side(){ Stop(); delay(100); for (int angle = 70; angle <= 140; angle += 5) { servoPulse(servo, angle); } delay(300); distance_R = Ultrasonic_read(); Serial.print("D R=");Serial.println(distance_R); delay(100); for (int angle = 140; angle >= 0; angle -= 5) { servoPulse(servo, angle); } delay(500); distance_L = Ultrasonic_read(); Serial.print("D L=");Serial.println(distance_L); delay(100); for (int angle = 0; angle <= 70; angle += 5) { servoPulse(servo, angle); } delay(300); compareDistance(); } void forword(){ digitalWrite(in1, LOW); digitalWrite(in2, HIGH); digitalWrite(in3, HIGH); digitalWrite(in4, LOW); } void backword(){ digitalWrite(in1, HIGH); digitalWrite(in2, LOW); digitalWrite(in3, LOW); digitalWrite(in4, HIGH); } void turnRight(){ digitalWrite(in1, LOW); digitalWrite(in2, HIGH); digitalWrite(in3, LOW); digitalWrite(in4, HIGH); } void turnLeft(){ digitalWrite(in1, HIGH); digitalWrite(in2, LOW); digitalWrite(in3, HIGH); digitalWrite(in4, LOW); } void Stop(){ digitalWrite(in1, LOW); digitalWrite(in2, LOW); digitalWrite(in3, LOW); digitalWrite(in4, LOW); }
四、定时逻辑说明
- 首次触发:每日12:00:00,启动送餐任务
- 重复触发:之后每到整15分钟时刻(如12:15:00、12:30:00等),再次启动任务
- 任务保护:通过
isTaskRunning标记避免同一时间重复触发任务,同时设置单次任务最长运行时间防止死循环
五、注意事项与技巧
- 时钟校准:第一次烧录时务必设置准确的当前时间,设置完成后立即注释掉时间设置代码,避免每次重启重置时钟
- 引脚冲突:选择DS1302引脚时,必须避开原有代码中已使用的引脚(包括数字引脚和模拟引脚)
- 电源稳定性:DS1302模块建议外接纽扣电池,避免Arduino断电后时钟丢失时间
- 非阻塞优化:如果原有代码中的
delay导致时间检测不精准,可以将delay替换为millis()实现的非阻塞延时,保证时钟检测的实时性 - 调试建议:烧录前先通过串口打印当前时钟时间,确认时钟工作正常后再接入电机负载
内容的提问来源于stack exchange,提问作者Marwan Sherif
相关产品推荐
相关产品推荐

