Código para execução única no Arduino

12

Pergunta: Onde coloco o código se quero que ele seja executado apenas uma vez por inicialização do Arduino?

Antecedentes: costumo usar meu Arduino para executar tarefas que devem ser executadas uma vez por ciclo de energia. (Por exemplo, meu robô só deve avançar uma vez toda vez que o ligar - mais do que isso, e pode cair da mesa.)

O "modelo" padrão do Arduino IDE consiste em loop()uma setup()função. O setupcódigo é executado uma vez por ciclo de energia e loopé reiniciado toda vez que termina.

Vejo duas abordagens para codificar "tarefas únicas:"

Método 1: "Loop uma vez"

void setup() {
  //do setup stuff
}

void loop() {
  //do task

  while(1) ; //Repeat forever, preventing function from re-starting
}

Método 2: "Somente instalação"

void setup() {
  //do setup stuff

  //do task
}

void loop() {
  //do nothing
}

Forma mais detalhada de pergunta: Um desses métodos é "melhor" no sentido de hardware / software? (por exemplo, existe algo "especial" sobre a setupfunção, que só pode ser executada por tanto tempo?)
E, se forem iguais da perspectiva do hardware / software, existe uma "melhor prática" ou uma maneira padrão de escrever código para essas situações na comunidade Arduino?

apnorton
fonte
Algum uso do exitcomando é discutido em arduino.stackexchange.com/questions/188/…
TheDoctor

Respostas:

13

Estou meio confuso com sua pergunta. Você pergunta onde deseja colocar as funções de configuração uma vez por inicialização e discute a função de configuração. É para isso que serve a função de configuração.

Como tal, a funcionalidade de configuração única entra na função de configuração.

FWIW, se você procurar no arquivo que chama as funções setupe loop:

#include <Arduino.h>

int main(void)
{
    init();

#if defined(USBCON)
    USBDevice.attach();
#endif

    setup();
    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }
    return 0;
}

Para todos os efeitos, as duas opções são completamente idênticas. De qualquer forma, você obtém um loop de espera por ocupado vazio. Francamente, eu esperaria que as duas opções diferentes provavelmente emitissem o mesmo código de máquina, então a coisa toda é um problema.

Nota:
if (serialEventRun) serialEventRun();parece ser um recurso para permitir que você anexe uma função chamada após a recepção de dados seriais, mas se você não definir uma função void serialEvent(){}no seu código, ela será compilada completamente e não estará presente no código de máquina produzido.

Connor Wolf
fonte
É estranho aceitar uma resposta que ainda não é a mais votada. Mas, ver a main()definição da função foi realmente útil para minha pergunta. (E você indica um consenso com o grupo usando em setupvez de loop). Obrigado pela ajuda.
apnorton
1
@ anorton - Em caso de dúvida, olhe embaixo das cobertas. Acho a plataforma do arduino conveniente para a criação de protótipos, mas em grande parte é apenas um código padrão. Compreender o que está fazendo pode ser extremamente útil para decidir como arquitetar algo.
Connor Lobo
6

Eu costumo ir com o método 2, mas acabo fazendo isso:

void setup() {
  //do setup stuff

  //do task
  init(); //Do start-up initialization steps
}

void init() {
  // do tasks on startup
}

void loop() {
  //do looping code
}

Com a configuração acima, permite que meu código seja ainda mais organizado.

Steven10172
fonte
a melhor resposta até agora +1, obrigado cara você me salvou!
Kyle
5

Eu preferiria fortemente o método 2. Se você planeja adicionar código para lidar com entrada, saída, etc., é fácil com o método 2 - basta preencher loop(), mas requer retrabalho / refatoração no método 1.

Matthew G.
fonte
3

Não há limite de tempo na função de configuração. Prefiro o método 2 porque o loop pode ser preenchido com o que você precisar posteriormente.

O médico
fonte
1

Definitivamente, vá com o método dois. É para isso que serve a função de configuração. É muito mais fácil ler também. Qualquer coisa no loop()implícito será executado em um loop.

sachleen
fonte
0

Como muitas outras respostas, eu usaria o método 2.

Mas eu tentava evitar a chamada, pela biblioteca do Arduino, para um loop() que faça o Atmel consumir "muita" corrente por nada.

Editar:

Como alguns comentários apontaram, o uso de delay()in loop()vai mudar o consumo de energia.

Portanto, se você quiser reduzir o consumo de energia após a setup()execução, precisará jogar com os modos de suspensão do Atmel. Você pode dar uma olhada neste artigo que mostra como lidar com os modos de suspensão de seus esboços do Arduino; ele faz mais do que apenas colocar o Atmel para dormir, mas é uma leitura boa (e simples) se você quiser brincar com os modos de suspensão.

jfpoilpret
fonte