Arduino中的AlarmRepeat函数

Posted

技术标签:

【中文标题】Arduino中的AlarmRepeat函数【英文标题】:AlarmRepeat function in Arduino 【发布时间】:2015-04-11 02:30:05 【问题描述】:

我在 Arduino 中使用 Time.h 和 TimeAlarms.h 库。我尝试在一天中的特定时间(每天)调用一个函数。该功能在第一天被调用,但在第二天似乎警报停止工作,尽管它应该每天重复。任何想法我的草图有什么问题?

#include <Time.h>
#include <TimeAlarms.h>

#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by Unix time_t as ten ASCII digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message
#define TIME_REQUEST  7    // ASCII bell character requests a time sync message 

// The constant variables used in the code:
const unsigned long shock_delay = 10;       // shock stimulus duration (s)

// Edit below only if you make changes to the hardware configuration:
const int tonePin =  13;      // the number of the LED pin
const int shockPin = 12;      // the number of the shocker pin
const int buzzerOut = 8;      // the number of the tone producer
const int trialButton=2;      // the number of the trial button
const int controlButton=3;    // the number of the control button

// Define the variables that will change in the code
unsigned int Interval1;                // the interval between the beginning of the hour and the first footshock
unsigned int Interval2;                // the interval between the first and the second footshock 

void setup()

  Serial.begin(9600);               // opens serial port, sets data rate to 9600 bps  
  setTime(23,59,50,10,4,15);          // The current time (HH,MM,SS,DD,MM,YY)

  // Define the position of the different digital pins
  pinMode(tonePin, OUTPUT);         // The tone LED (red)
  pinMode(shockPin, OUTPUT);        // The shock output, which will coincide with green LED
  pinMode(trialButton, INPUT);      // The trial input button
  pinMode(controlButton, INPUT);    // The control input button

   Alarm.alarmRepeat(20,00,0,RandomShock);        // Initiate the user defined RandomShock function          
   Alarm.alarmRepeat(21,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(22,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(23,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(0,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(1,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(2,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(3,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(4,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(5,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(6,00,0,RandomShock);        // Initiate the user defined RandomShock function
   Alarm.alarmRepeat(7,00,0,RandomShock);        // Initiate the user defined RandomShock function
  

void  loop()  
    // Create a message that gives the current time and date on the monitor     
    if(Serial.available() ) 
      
        processSyncMessage();
      
      if(timeStatus() == timeNotSet) 
        Serial.println("waiting for sync message");
      else     
          digitalClockDisplay();                                       // The function that calls on the time display
          Alarm.delay(1000);                                           // Delay of 1 minute between time display
           

     void digitalClockDisplay()
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 


void printDigits(int digits)
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);


void processSyncMessage() 
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN )  // time message consists of header & 10 ASCII digits
    char c = Serial.read() ; 
    Serial.print(c);  
    if( c == TIME_HEADER )        
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++)   
        c = Serial.read();          
        if( c >= '0' && c <= '9')   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        
         
      setTime(pctime);   // Sync Arduino clock to the time received on the serial port
      
  


void RandomShock () 
       Interval1 = random(0,60);                               // Random value between 0 and 59 [min]
       digitalWrite(tonePin,HIGH);                             // Indicate the shock program is ON by the red LED
       Alarm.delay(Interval1*60000);                           // Wait for the duration of the first interval
       digitalWrite(tonePin,LOW);                              // Turn the red LED OFF
       digitalWrite(shockPin, HIGH);                           // Apply the first shock (green LED will turn ON)
       Serial.println("Applying an electeric shock at:");      // Write a message indicating a shock is applied
       digitalClockDisplay();                                  // Display the time during which the shock was applied
       Alarm.delay(shock_delay*1000);                          // The duration of the shock [10 seconds]
       digitalWrite(shockPin, LOW);                            // Terminate the first shock (green LED will turn OFF)
       Interval2 = random(0,(61-Interval1));                   // Randomly asign a value to the second interval [min]
       digitalWrite(tonePin,HIGH);                             // Indicate the shock program is ON by the red LED
       Alarm.delay(Interval2*60000-20000);                     // Wait for the duration of the second interval
       digitalWrite(tonePin,LOW);                              // Turn the red LED OFF
       digitalWrite(shockPin,HIGH);                            // Apply the second shock (green LED will turn ON)
       Serial.println("Applying an electeric shock at:");      // Write a message indicating a shock is applied
       digitalClockDisplay();                                  // Display the time during which the shock was applied
       Alarm.delay(shock_delay*1000);                          // The duration of the shock [10 seconds]
       digitalWrite(shockPin,LOW);                             // Terminate the second shock
       digitalWrite(tonePin,HIGH);                             // Indicate the shock program is ON by the red LED
       Alarm.delay((60-Interval1-Interval2)*60000);            // Wait until the hour is completed
       digitalWrite(tonePin,LOW);                              // Turn the red LED OFF

【问题讨论】:

你能分享你遇到的错误吗? 感谢您的回复。没有错误消息。草图运行顺利。我进行了一次测试,发现它在第一天运行良好,但是一旦日期在午夜打开,alarmRepeat 函数就停止调用我的函数 (RandomShock)。据我了解,不应该是这样的。 AlarmRepeat 应该每天在同一时间调用我的函数。 已解决:我写的草图有两个问题:1)Alarm.alarmRepeat 函数似乎无法在午夜(00:00:00)准确地调用我的函数,但是,如果我将它安排到任何其他时间(例如,00:00:01),它就可以正常工作。 2)您可以调度的警报数量有限制:最大警报数量为6。解决方案是更改此阈值,或减少警报数量。修正这两个问题后,草图工作顺利。 @cassiopeiam 请将您的解决方案发布为答案并将其标记为已接受(您不会因此获得任何代表,但我会支持它)。 【参考方案1】:

我写的草图有两个问题:

    Alarm.alarmRepeat 函数似乎无法调用我的 正好在午夜 (00:00:00) 运行,但是,如果我安排它 到任何其他时间(例如,00:00:01)它工作得很好。

    您可以安排的警报数量有限制: 最大警报数量为 6。解决方法是更改​​此阈值,或减少警报数量。

在纠正这两个问题后,草图工作顺利。

【讨论】:

【参考方案2】:

似乎 TimeAlarm 库无法将闹钟设置为午夜 https://github.com/PaulStoffregen/TimeAlarms/issues/3

试试这个拉取请求https://github.com/PaulStoffregen/TimeAlarms/pull/4

【讨论】:

【参考方案3】:

如果您需要超过 6 个警报,只需在库中的 TimeAlarms.h 中查找:

#if defined(__AVR__)
#define dtNBR_ALARMS 6 // max is 255
#else
#define dtNBR_ALARMS 12  // assume non-AVR has more memory
#endif

并根据您的需要更改(例如:24)

#if defined(__AVR__)
#define dtNBR_ALARMS 24 // max is 255
#else
#define dtNBR_ALARMS 12  // assume non-AVR has more memory
#endif

【讨论】:

以上是关于Arduino中的AlarmRepeat函数的主要内容,如果未能解决你的问题,请参考以下文章

Arduino编译bootloader

使用串行通信在 python 和 arduino 之间进行同步

Arduino中的setup()和loop()函数

关于通过 USART 上的 MDB 协议与自动售货机通信时 Arduino 的 TX 线的问题

为堆中的对象保留内存而不在 Arduino 上调用其构造函数

arduinodelay函数卡死