Eu tenho usado o Arduino para gravar alguns dados. No meu esboço do Arduino, também usei a millis()
função para acompanhar o tempo em que cada valor que estou medindo é obtido. No entanto, notei que o momento não está correto. Por exemplo, 30 segundos na vida real sai apenas em 10 segundos (exemplo inventado).
Estou correto ao dizer que a função de atraso do Arduino afeta o tempo de uso millis()
? Em outras palavras, suponha que eu tenha um atraso de 50ms, isso significa que a millis()
função também será interrompida por essa duração e continuará durante a conexão? Percebi isso quando tentei traçar alguns dados e descobri que a frequência dos picos nos meus dados era muito frequente, dado o tempo que passava. Então, eu quero saber se esse é o motivo dessa incompatibilidade de tempo e, em caso afirmativo, como faço para corrigir isso para manter o tempo em que cada amostra ocorre?
Para dar algum contexto aqui é o meu esboço:
#include <eHealth.h>
unsigned long time;
// The setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
}
// The loop routine runs over and over again forever:
void loop() {
float ECG = eHealth.getECG();
time = millis();
Serial.print(time);
Serial.print(" ");
Serial.print(ECG, 5);
Serial.println("");
delay(50);
}
fonte
millis()
é acionado por interrupção, portantodelay()
não deve afetá-lo.Respostas:
millis()
é acionado por interrupção, portantodelay()
não o afetará, pelo menos não em uma placa baseada no ATmega.Isso não quer dizer que
millis()
seja totalmente preciso também. Cada marca do cronômetro não é exatamente 1ms, mas é 1.024ms. Este erro se acumula gradualmente até que uma correção seja feita. Isso pode ser visto na implementação do manipulador de interrupção TIMER0_OVF (timer 0 overflow).Outra fonte de imprecisão é o próprio oscilador / cristal, que não é exatamente 16MHz. É bem perto, porém, e desde que a temperatura não mude muito, é relativamente estável.
O exposto acima significa que você pode demorar cerca de 1 ms ao usar
millis()
. Isso não soa como seu problema.Outra questão em potencial seria o que
getECG()
está fazendo - pode ser muito lento.analogRead()
é lento, mas não tão lento a ponto de impactar um loop como este.Outro problema que tenho visto é que as pessoas alteram a velocidade do relógio, mas não alteram corretamente o boards.txt. Isso significa que as constantes usadas na
millis()
implementação estão erradas e os horários estão errados.Se você realmente deseja ler valores a cada 50ms, uma maneira muito melhor de implementar isso é fazer o seguinte
Nós realmente precisamos ver os registros de data e hora que você está recebendo. Se você realmente vê 30s aparecendo como 10s, então há outra coisa em ação.
fonte
Se as interrupções forem desativadas por qualquer
eHealth.getECG()
duração significativa da chamada de fração ,millis()
a contagem poderá ficar para trás. Caso contrário, vocêmillis()
deve retornar um tempo muito mais preciso do que os erros de 3x que você descreveu.Você disse que o sinal amostrado parece ter uma frequência mais alta do que o esperado, o que pode acontecer se a taxa de amostragem for menor do que o pretendido. Você está assumindo uma taxa de amostragem de 20Hz? Seu loop pode demorar um pouco mais de 50 ms, o que você veria nos tempos impressos, mas eles ainda devem acompanhar o tempo do relógio. Se você não considerou isso, mas assumiu 50ms / amostra, verá uma aceleração aparente dos dados.
Se esse não for o problema, o próximo passo seria alternar uma saída enquanto você estiver dentro
loop()
e medir a frequência da onda quadrada resultante com um medidor de frequência (alguns DVMs baratos podem fazer isso) ou um escopo. Faça a mesma coisa com um vazioloop()
. O primeiro experimento será sua taxa ou intervalo de amostragem real; o segundo dirá semillis()
(ou seja, a frequência do timer0) é o que você esperava.fonte
O mesmo aqui. Posso acrescentar que, se as interrupções forem desativadas, o tempo medido será "tempo real". Enfim, eu não entendo por que esse atraso, porque se o loop demorar muito, de qualquer maneira o millis () deve retornar valores em tempo real (apenas com mais distância entre cada valor)
fonte