Estou usando um Arduino Uno para enviar informações de tempo e tensão pela porta serial para o Python para plotar. No entanto, os intervalos de tempo entre carimbos de hora sucessivos parecem estar aumentando ao longo do tempo, afetando minha plotagem. Isso é especialmente verdade quando a taxa de transmissão é definida como 9600, onde minhas diferenças de tempo iniciais podem ser de 1320 e aumentam para 16400 após um período de tempo relativamente curto. Quando essa taxa é colocada no máximo em 115200 bps, a alteração é mais lenta e menos perceptível, de cerca de 1340 a 1500, mesmo após um período relativamente longo de envio. Todos os horários são dados em microssegundos.
Gostaria de saber se posso reduzir ou eliminar esse efeito e, se não entender, por que ele existe. Eu li coisas sobre interrupções e atrasos que causam isso, mas não aprecio completamente a complexidade dos eletrônicos disponíveis e gostaria de saber:
- Posso obter maior precisão no tempo?
- O que causa essa mudança no tempo?
Aqui está o que eu tenho atualmente:
#include <eHealth.h>
extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;
byte serialByte;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='S'){
while(1){
fanalog0=eHealth.getECG();
// Use the timer0 => 1 tick every 4 us
time=(timer0_overflow_count << 8) + TCNT0;
// Microseconds conversion.
time=(time*4);
//Print in a file for simulation
//Serial.print(time);
//Serial.print(" ");
Serial.print(fanalog0,5);
Serial.print("\n");
if (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='F') break;
}
}
}
}
}
fonte
eHealth.getECG()
faz? Essa chamada sempre dura a mesma quantidade de tempo?Respostas:
Use um timer e ISR (rotina de serviço de interrupção) para tornar o tempo mais preciso.
Veja minha Prova de conceito de interrupção cronometrada de 1 ms . A idéia é ter um batimento cardíaco razoavelmente preciso de 1ms no sistema que pode ser usado para acionar outros eventos. No PoC, é usado para piscar um LED a ½Hz, mas ter acesso às novas variáveis
millisecondCounter
esecondCounter
permite disparar eventos no loop principal em momentos arbitrários (mas com tempo preciso).fonte
loop()
), esse valor sendo modificado por um ISR. Pode acontecer queloop()
leia um valor ruim (no meio de uma modificação pelo ISR). Eu publiquei um comentário no seu blog sobre isso.loop()
: minha amostra acabou de obter o valor de milissegundos, omite-o para o valor de leitura anterior e, se a diferença> 0 (diferente de redefinir o contador para 0), exibir uma mensagem.Posso pensar em algumas coisas que podem afetar a "consistência" dos tempos de gravação em série:
isso pode ser a coisa mais óbvia em que pensar, mas, na verdade, quanto mais você imprimir, mais será necessário para lidar com isso.
Solução: imprima o formato da sequência em uma sequência de comprimento conhecido.
no unix, você pode acessar a porta serial usando uma maneira em buffer ou sem buffer. Usar o modo de buffer por um longo tempo pode torná-lo um pouco mais lento à medida que o buffer é preenchido, geralmente acontece quando os dados são recebidos mais rapidamente do que você está lendo…
Solução: use a linha serial sem buffer ( por exemplo : no Darwin / OSX, em
/dev/cu.usbmodemXXX
vez de/dev/tty.usbmodemXXX
)parece que você está usando uma interrupção de TC e os AVRs têm prioridades na maneira como as interrupções são tratadas, não sei a ordem de prioridade do Atmega328 e não é um dos recursos mais documentados, por isso não sei quão seguro é o TC0 versus a interrupção UART.
Solução: consulte mais detalhadamente na documentação / folha de dados sobre prioridades de interrupção e altere o cronômetro, se necessário; e / ou faça um teste sem ter o outro timer em execução.
alguns drivers precisam calcular a média ou executar algumas operações em relação aos valores anteriores. Portanto, quanto mais valores você mede, mais longo o buffer e mais demorado para calcular o valor, até atingir o tamanho máximo do buffer.
Solução: observe o código-fonte da biblioteca que você está usando e otimize-o, remova o cálculo se houver um ou leve em consideração esse tempo de processamento crescente.
mas se você realmente deseja otimizar a saída serial do arduino, evite usar a sobrecarga do arduino ... Mas é muito menos elegante e confortável de usar.
Tenho certeza de que há outros pontos que estou perdendo, mas essas são as primeiras coisas que eu verificaria antes de prosseguir.
HTH
fonte
Seu código inclui a duração da saída em medições subsequentes. Assim, dependendo do comprimento da saída, você medirá diferentes tempos. Isso pode ser corrigido através da formatação na saída de comprimento fixo.
A próxima questão é que a ONU tem uma base de tempo muito ruim. Veja aqui uma comparação dos diferentes tipos de Arduino versus a referência de tempo do DCF77.
Conclusão: se você precisar de tempo preciso, adquira um Arduino com cristal ou opte por um RTC. Eu recomendo os RTCs DS3231 / DS3232, pois eles geralmente atingem uma precisão de 2 ppm imediata.
fonte