Как заставить миллисис () считать 1 сек точно в ардуино? - PullRequest
0 голосов
/ 20 февраля 2019

Я работаю над проектом на Arduino, в котором Arduino должен считать 1 секунду, и каждую секунду Arduino должен запускать определенную функцию (каждую секунду я имею в виду целую секунду, а не секунду).

if (((millis()) % 1000) == 0)
{
    tym_countdown();
    Serial.println("Refresh");

То, что происходит, как вы можете видеть ниже, в моем Arduino - это подсчет экземпляров, а не полных секунд.

 20:54:04.145 -> Refresh
 20:54:04.145 -> Refresh
 20:54:05.119 -> Refresh
 20:54:05.119 -> Refresh
 20:54:05.119 -> Refresh
 20:54:05.119 -> Refresh
 20:54:05.119 -> Refresh
 20:54:05.165 -> Refresh
 20:54:05.165 -> Refresh
 20:54:05.165 -> Refresh
 20:54:06.103 -> Refresh
 20:54:06.103 -> Refresh
 20:54:06.103 -> Refresh
 20:54:06.150 -> Refresh

Код:

#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 column 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 голосов
/ 21 февраля 2019

Вы можете легко «синхронизировать» предложение 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%

0 голосов
/ 20 февраля 2019

Если вам нужно запускать действие ровно каждую 1 секунду, вам следует попробовать использовать программу обработки прерываний (ISR).В зависимости от того, какую плату вы используете, это можно сделать с помощью библиотеки Timer .Вам нужно будет оставить ISR коротким, или вы можете отложить обработку до функции loop().

Если у вас нет таких жестких требований в реальном времени и вам нужно выполнять действие только один раз в секунду, тогда выможет записывать последний раз, когда действие выполнялось в loop().Затем проверьте, прошло ли по крайней мере 1000 мс с момента последней итерации loop().

например

unsigned long lastTriggerTime = 0;

void loop() {
  read_incomming_serial_data();
  auto currentLoopTime = millis();
  if(currentLoopTime - lastTriggerTime >= 1000)
  {
    lastTriggerTime = currentLoopTime;
    tym_countdown();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...