O manuseio de vários padrões ao mesmo tempo é certamente possível com uma plataforma como o Arduino, e há várias maneiras de você fazer isso.
Um método que eu consideraria é escrever funções que efetivamente representam cada padrão matematicamente. Você passaria o tempo total decorrido no seu programa até agora e executará a ação apropriada para esse momento específico. Ele retornará imediatamente depois (sem atrasos ou qualquer coisa).
Para fazer isso, primeiro você precisa saber quanto tempo dura um único ciclo do padrão. Você pode usar o operador módulo para descobrir até que ponto você está no ciclo atual. A partir daí, tudo o que você precisa fazer é ter algumas if
condições para determinar o que fazer a qualquer momento.
Veja como pode ser o seu padrão "5 segundos ligado e 5 segundos desligado":
function pattern5on5off(unsigned long totalTime)
{
// Calculate how far through the current cycle we are
const unsigned long cycleTime = totalTime % 10000;
// If we're in the first 5 seconds of the cycle then turn the light on.
// Otherwise, turn it off.
if (cycleTime < 5000)
digitalWrite(3, HIGH);
else
digitalWrite(3, LOW);
}
É verdade que telefonar constantemente digitalWrite()
quando você não precisa tecnicamente não é muito eficiente. Porém, não deve causar nenhum dano e é bastante fácil de otimizar, se necessário.
Para usar o exemplo acima em um esboço, você só precisa chamá-lo loop()
e passar o número do qual obtém millis()
; por exemplo:
void loop()
{
const unsigned long totalTime = millis();
pattern5on5off(totalTime);
// call other patterns here...
}
Outros padrões serão mais complexos, mas seguem o mesmo princípio. Você apenas usaria if
declarações apropriadas para expressar sua lógica.
O essencial é lembrar que a função representa um momento específico no tempo. Ele nunca deve pausar ou atrasar o programa, caso contrário, impedirá a execução de outros padrões.
Edit: Tempo no primeiro ciclo
Como jfpoilpret observou nos comentários, o primeiro ciclo começará em um ponto aleatório. Isso ocorre porque a primeira vez que você chamar millis()
em loop()
, ele não vai começar em 0 (o dispositivo já terá sido executado por um curto período de tempo antes loop()
é chamado). É fácil resolver, se necessário.
Você faria isso deslocando o totalTime
valor pelo valor que você obteve na primeira vez loop()
. Por exemplo:
unsigned long g_startTime = 0;
void loop()
{
unsigned long totalTime = 0;
if (g_startTime == 0) {
// This is the first cycle.
// Store the start time so we can compensate later.
g_startTime = millis();
} else {
// This is not the first cycle.
// Compensate for the start time.
totalTime = millis() - g_startTime;
}
pattern5on5off(totalTime);
// etc..
}