You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

二、库安装与代码集成步骤

  1. 在Arduino IDE的库管理器中搜索并安装DS1302库(推荐Makuna/DS1302,兼容性强)
  2. 对原有代码做如下修改:
    • 引入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:35:06