如何使millis()在arduino中精确计数1秒?

时间:2019-02-20 01:31:17

标签: arduino

当前,我正在Arduino上进行一个项目,其中Arduino必须计算1秒,而Arduino必须运行一定的功能(每秒钟我要说的是完整的秒而不是一个秒的实例)。

  

如果((((millis())%1000)== 0)         {           tym_countdown();           Serial.println(“ Refresh”);

正在发生的事情如您在下面看到的那样,我的Arduino在计数实例而不是完整秒。

  

20:54:04.145->刷新       20:54:04.145->刷新       20:54:05.119->刷新       20:54:05.119->刷新       20:54:05.119->刷新       20:54:05.119->刷新       20:54:05.119->刷新       20:54:05.165->刷新       20:54:05.165->刷新       20:54:05.165->刷新       20:54:06.103->刷新       20:54:06.103->刷新       20:54:06.103->刷新       20:54:06.150->刷新


#define X 13
#define Y 12
#define Z 11

char txt[15];
char tym[6];
int index,tym_index;
int pin_status_array[2][3]={0,0,0,0,0,0};

void setup() {
  // put your setup code here, to run once:
  pinMode(X,OUTPUT);// setting the pin flow of control as output
  pinMode(Y,OUTPUT);
  pinMode(Z,OUTPUT);

  Serial.begin(9600);
  while(!Serial)
  {
    ;  //to wait for pc to connect
  }
  Serial.println("\nHome Automation");
  initial_dash_print();  


}

void loop() {
  // put your main code here, to run repeatedly:
  read_incomming_serial_data();
  if(((millis())%1000)==0)
  {
    tym_countdown();
    Serial.println("Refresh");
  }
  turn_on_n_off();

}


void initial_dash_print() //to print dashes
{ Serial.println("-----------------------------------------------");
  Serial.println("give me some command"); //ask for command
   }

void read_incomming_serial_data()// read incoming data from serial
{
 if(Serial.available()>0) 
  { delay(17); // delay for arduino to wait and read commands,1ms per char.
    index=0;
    tym_index=0;
    while(Serial.available()>0)   //if serial available
    { char inchar=Serial.read();
      txt[index]=inchar; // add char to txt string
      index++;// increment to where to write next

      if(index>4)
      { tym[tym_index]=inchar;
        tym_index++; 
      }
     }
   Serial.print(txt);

   check_data_from_serial();

   }
  }

void check_data_from_serial() // to check data from serial
{ 
  if(strncmp(txt,"ON X",4)==0)
  { 
    pin_status_array[0][0]=1;
    if(tym_index!=0)
    {     
     tym_update(X);
      }
    }
  else if(strncmp(txt,"OFF X",5)==0)
  { 
    pin_status_array[0][0]=0;
    }
    if(strncmp(txt,"ON Y",4)==0)
  { 
    pin_status_array[0][1]=1;
    if(tym_index!=0)
    {     
     tym_update(Y);
      }
    }
  else if(strncmp(txt,"OFF Y",5)==0)
  { 
    pin_status_array[0][1]=0;
    }
    if(strncmp(txt,"ON Z",4)==0)
  { 
    pin_status_array[0][2]=1;
    if(tym_index!=0)
    {     
     tym_update(Z);
      }
    }
  else if(strncmp(txt,"OFF Z",5)==0)
  { 
    pin_status_array[0][2]=0;
    }
  else if(txt=="STATUS")
  { 
      }


}

void tym_update(int pin) // update time row
{ 
  int temp=pin-13; // pin to array coloumn equivalent
  pin_status_array[1][temp]=atoi(tym);
}

void tym_countdown() //to perform time countdown
{ for(int temp_index=0; temp_index<4; temp_index++)
  {
   if(pin_status_array[0][temp_index]==1 && pin_status_array[1][temp_index]>0) // '0' => txt '1' => tym
   {
     int temp=pin_status_array[1][temp_index];
     temp--;
     pin_status_array[1][temp_index]=temp;
     if(temp==0)
     {
       pin_status_array[0][temp_index]=0; //turn off
     }
   }
  }
}

void turn_on_n_off()
{
  if(pin_status_array[0][0]==1)
  {
    digitalWrite(X,HIGH);
  }
  if(pin_status_array[0][0]==0)
  {
    digitalWrite(X,LOW);
  }
  if(pin_status_array[0][1]==1)
  {
    digitalWrite(Y,HIGH);
  }
  if(pin_status_array[0][1]==0)
  {
    digitalWrite(Y,LOW);
  }
  if(pin_status_array[0][2]==1)
  {
    digitalWrite(Z,HIGH);
  }
  if(pin_status_array[0][2]==0)
  {
    digitalWrite(Z,LOW);
  }

}

2 个答案:

答案 0 :(得分:0)

如果您需要精确地每1秒触发一次操作,则应尝试使用中断服务程序(ISR)。根据您使用的板,可以使用Timer library完成此操作。您需要使ISR保持简短,否则可以将处理推迟到loop()函数中。

如果您没有如此严格的实时要求,而仅需要每秒执行一次操作,则可以在loop()中记录操作最后一次运行的时间。然后检查自loop()的上一次迭代以来至少经过1000毫秒。

例如

unsigned long lastTriggerTime = 0;

void loop() {
  read_incomming_serial_data();
  auto currentLoopTime = millis();
  if(currentLoopTime - lastTriggerTime >= 1000)
  {
    lastTriggerTime = currentLoopTime;
    tym_countdown();

答案 1 :(得分:0)

您可以轻松地将blt的建议“同步”到精确的1000毫秒间隔:

unsigned long lastTriggerTime = 0;

void loop() {
  read_incomming_serial_data();
  unsigned long currentLoopTime = millis();
  if(currentLoopTime - lastTriggerTime >= 1000)
  {
     lastTriggerTime += 1000;  // will increment in 1000's steps
     tym_countdown();
...

当然,这与现实世界的秒数无关,并且精度约为0.1%