arduino
시간 관리
수색…
통사론
부호없는 long millis ()
부호없는 긴 마이크로 ()
void 지연 (부호없는 긴 밀리 초)
void delayMicroseconds (부호 없음 long 마이크로 초)
해당 클래스의 생성자와 연산자에 대해서는 elapsedMillis 헤더 를 참조하십시오. 간단히 말해서 :
- elapsedMillis elapsedMillisObject; 생성 된 이후 또는 다른 명시 적으로 설정된 특정 시점 이후의 시간을 추적하는 객체를 생성합니다.
- elapsedMillisObject = 0; 객체에 의해 추적 된 시간을 "지금부터"로 재설정합니다.
- 부호없는 long deltaT = elapsedMillisObject; 추적 시간을 살펴 봅니다.
- elapsedMillisObject + = 및 - = 예상대로 작동합니다.
비고
차단 대 비 차단 코드
매우 간단한 스케치의 경우 delay()
및 delayMicroseconds()
사용하여 차단 코드를 작성하는 것이 적절할 수 있습니다. 상황이 더욱 복잡 해지면 이러한 함수를 사용하면 몇 가지 단점이 생길 수 있습니다. 이들 중 일부는 다음과 같습니다.
- CPU 시간 낭비 : 더 복잡한 스케치는 LED 깜박임 기간이 끝나기를 기다리는 동안 다른 것을 위해 CPU가 필요할 수 있습니다.
- 예상치 못한 지연 :
delay()
가 명시 적으로 호출되지 않은 서브 루틴, 예를 들어 포함 된 라이브러리에서 호출 될 때. - 지연 중에 발생하는 누락 된 이벤트 및 인터럽트 처리기에서 처리하지 않는 이벤트 (예 : 폴링 된 단추 누름) : 100ms 동안 단추가 눌러 지지만
delay(500)
으로delay(500)
섀도 잉 될 수 있습니다.
구현 세부 사항
millis()
일반적으로 1 kHz보다 훨씬 빠른 속도로 실행되는 하드웨어 타이머를 사용합니다. millis()
가 호출되면, 구현은 어떤 값을 리턴하지만 실제로 얼마나 오래되었는지 알지 못합니다. "현재"밀리 초가 방금 시작되었거나 해당 함수 호출 직후에 종료 될 수 있습니다. 즉, millis()
두 결과 간의 차이를 계산할 때 거의 0에서 거의 1 밀리 초 사이의 값을 가질 수 있습니다. 더 높은 정밀도가 필요한 경우 micros()
사용하십시오.
elapsedMillis
의 소스 코드를 살펴보면 내부적으로 millis()
를 사용하여 두 지점을 비교하는 것으로 나타 elapsedMillis
효과도 있습니다. 다시 말하지만, 동일한 라이브러리에서 더 높은 정밀도를위한 대체 elapsedMicros
가 있습니다.
지연 (blinky with delay) 차단
LED를 깜박이는 가장 직접적인 방법 중 하나는 켜기, 조금 기다린 후 끄고 다시 기다리고 끝없이 반복하는 것입니다.
// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500
void setup()
{
pinMode(OUTPIN, OUTPUT); // sets the digital pin as output
}
void loop()
{
digitalWrite(OUTPIN, HIGH); // sets the pin on
delayMicroseconds(PERIOD); // pauses for 500 miliseconds
digitalWrite(OUTPIN, LOW); // sets the pin off
delayMicroseconds(PERIOD); // pauses for 500 milliseconds
// doing other time-consuming stuff here will skew the blinking
}
그러나 위의 예 에서처럼 대기하면 CPU주기가 낭비됩니다. 특정 시점을 기다리는 루프에 그냥 있기 때문입니다. 이것이 millis()
또는 elapsedMillis
사용하는 비 차단 방식이 하드웨어의 많은 기능을 소모하지 않는다는 점에서 더 좋습니다.
elapsedMillis 라이브러리 (및 클래스)로 블로킹 (blinky)
elapsedMillis 라이브러리 는 클래스가 만들어 지거나 경과 된 시간을 추적하는 동일한 이름을 클래스에 제공합니다.
#include <elapsedMillis.h>
#define OUTPIN LED_BUILTIN
#define PERIOD 500
elapsedMillis ledTime;
bool ledState = false;
void setup()
{
// initialize the digital pin as an output.
pinMode(OUTPIN, OUTPUT);
}
void loop()
{
if (ledTime >= PERIOD)
{
ledState = !ledState;
digitalWrite(OUTPIN, ledState);
ledTime = 0;
}
// do other stuff here
}
이 예제에서 LED 핀이 토글되었을 때 ledTime
객체가 0으로 지정되었음을 알 수 있습니다. 얼핏보기에는 놀랄만 한 일은 아니지만 더 많은 시간이 걸리면 효과가 있습니다.
ledTime
과 PERIOD
를 750 밀리 초 후에 비교하는 경우를 생각해보십시오. 그런 다음 ledTime
을 0으로 설정하면 다음의 모든 토글 조작이 250ms "늦게"수행됩니다. 대조적으로, PERIOD
를 ledTime
에서 ledTime
, LED는 짧은 기간을 보게되고 아무 일도없는 것처럼 계속 깜박입니다.
millis ()로 blinky 비 블로킹
arduino 문서의 예제와 매우 비슷합니다.
// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500 // this is in milliseconds
int ledState = LOW;
// millis() returns an unsigned long so we'll use that to keep track of time
unsigned long lastTime = 0;
void setup() {
// set the digital pin as output:
pinMode(OUTPIN, OUTPUT);
}
void loop() {
unsigned long now = millis();
if (now - lastTime >= PERIOD) // this will be true every PERIOD milliseconds
{
lastTime = now;
if (ledState == LOW)
{
ledState = HIGH;
}
else
{
ledState = LOW;
}
digitalWrite(OUTPIN, ledState);
}
// now there's lots of time to do other stuff here
}
이런 방식으로 millis()
를 사용하여 - 비 - 블로킹 방식으로 작업 시간을 elapsedMillis
일은 - 자주 필요로하는 일이기 때문에이를 위해 elapsedMillis
라이브러리 사용을 고려하십시오.
elapsedMillis 및 elapsedMicros를 사용하여 일정 기간 측정
#include <elapsedMillis.h>
void setup() {
Serial.begin(115200);
elapsedMillis msTimer;
elapsedMicros usTimer;
long int dt = 500;
delay(dt);
long int us = usTimer;
long int ms = msTimer;
Serial.print("delay(");Serial.print(dt);Serial.println(") took");
Serial.print(us);Serial.println(" us, or");
Serial.print(ms);Serial.println(" ms");
}
void loop() {
}
이 예제에서 elapsedMillis
객체와 elapsedMicros
객체는 무언가가 걸린 시간을 측정하는 데 사용됩니다. 시간을 계산하려는 표현식이 실행되기 직전에 객체를 생성하고 나중에 값을 가져 오는 방식으로 사용합니다. 약간 다른 결과가 표시되지만 밀리 초 결과는 1 밀리 초 이상 벗어나지 않습니다.
지연없이 1 개 이상의 작업 ()
서로 다른 간격으로 반복적으로 실행하는 태스크가 두 개 이상인 경우이 예제를 시작점으로 사용하십시오.
unsigned long intervals[] = {250,2000}; //this defines the interval for each task in milliseconds
unsigned long last[] = {0,0}; //this records the last executed time for each task
void setup() {
pinMode(LED_BUILTIN, OUTPUT); //set the built-it led pin as output
Serial.begin(115200); //initialize serial
}
void loop() {
unsigned long now = millis();
if(now-last[0]>=intervals[0]){ last[0]=now; firstTask(); }
if(now-last[1]>=intervals[1]){ last[1]=now; secondTask(); }
//do other things here
}
void firstTask(){
//let's toggle the built-in led
digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN)?0:1);
}
void secondTask(){
//say hello
Serial.println("hello from secondTask()");
}
다른 작업을 추가하여 매 15 초마다 실행하려면 변수 intervals
연장하고 last
:
unsigned long intervals[] = {250,2000,15000};
unsigned long last[] = {0,0,0};
그런 다음 if
문을 추가하여 새 작업을 실행합니다. 이 예제에서는 이름을 thirdTask
지정했습니다.
if(now-last[2]>=intervals[2]){ last[2]=now; thirdTask(); }
마지막으로 함수를 선언하십시오.
void thirdTask(){
//your code here
}