Cuidado com o Watchdog Timer no Arduino

Mesmo já tendo utilizados outras famílias de microcontroladores nem sempre você acaba lembrando do básico quando utiliza Arduino, e isso pode se um problema.

Para controlar o portão eletrônico e o alarme do condomínio, fiz um sistema utilizando um Arduino Uno, um Shield Ethernet e 2 relés juntamente com um controle que funcionava tanto para o portão quanto para o alarme. O sistema fica ligado ao roteador e funciona mesmo fora da rede local através da web.

Um problema que percebi é que nem sempre o sistema estava ativo e como não sabia ainda qual era realmente o problema resolvi ativar o WDT (Watchdog Timer) do Arduino. Para quem não sabe o WTD é uma parte independente do processamento principal do microcontrolador que, quanto ativo, realiza uma contagem e se chegar ao limite gera uma interrupção reiniciando o sistema para previnir que este fique travado durante muito tempo por algum problema ocorrido. Para que não ocorra sempre você deve resetar o WDT para que ele nunca alcance seu limite e assim seu código possa ser executado normalmente.

Quando ativei o WTD do meu sistema ele não funcionou bem como deveria. O sistema ficou se reiniciando o tempo todo (é o que acho, não cheguei a esta conclusão empiricamente) e dessa forma eu não conseguia realizar um novo upload para o Arduino e achei que equele chip estava perdido, pois sempre ocorria um timeout na gravação e um mensagem “avrdude: stk500_getsync(): not in sync: resp=0x00”, como se minha placa não fosse a correta ou não estivesse funcionando corretamente.

errowtd
Código que causa loop infinito de resets no Arduino.

Após fazer algumas pesquisas sem sucesso na web resolvi fazer uma tentativa fora do comum para gravar o chip. Após a etapa de compilação e um pouco depois do aparecimento da mensagem “Uploading…”, eu fiz um curto rápido, utilizando um fio, entre o GND e o 5V da placa. Após o curto a placa faz um reset diferente do realizando através do botão e o Arduino consegui entrar em modo gravação. Tentei muitas coisas sem sucesso antes dessa sugestão desesperada. Fiz a mesma coisa em um Arduino Nano e também tive sucesso.

Não tenho tanta experiência com Arduino e não sou profissional na área. Se alguém quiser enviar ou, por comentário mesmo, fazer alguma observação ou sugestão fiquem à vontade.

 

10 thoughts on “Cuidado com o Watchdog Timer no Arduino

  1. Cara, estive fazendo uns testes com WDT também e estou com um chip 328 travado igual ao seu.
    Vou fazer um curto desses para testar…afinal, já tá perdido mesmo…rs

    Abraços.

  2. Meu amigo, você me salvou! Na realidade o que você fez foi desligar o Arduino ao fechar o curto na alimentação. Eu não corri esse risco, simplesmente desliguei a alimentação e só religuei no momento que a IDE informou que estava carregando e finalmente deu certo! Ao desligar a alimentação, o Arduino demora para reiniciar e da tempo de carregar o novo programa antes do Watchdog começar a atuar.

  3. Acredito que definir um timer de watchdog maior, tipo uns 8 segundos pode evitar problemas desse tipo, ou até mesmo quando aparecer uploading na ide, apertar o botão de reset do arduíno (não é pra apertar o reset enquanto está compilando, apenas quando aparecer que está enviando, mas tem que ser rápido). Fechar curto nos 5v em alguns computadores pode danificar a placa, queimando componentes da placa principalmente de notebooks. Até porque o arduino está ligado ao seu computador.

    1. É ótima sua observação Isael, a minha abordagem realmente foi um ato de desespero! Como mencionei, eu testei tudo que podia inclusive o botão de reset em diferentes momentos. Realmente corri o risco de danificar minha USB. Se fosse para testar algo do tipo novamente (espero que nunca!) o faria em um HUB USB, que tem um circuito a parte, não diretamente na porta no notebook.

  4. Amigo, tive o mesmo problema! O que aconteceu foi que defini um tempo muito pequeno para o WDT e por isso ele sempre ficava reiniciando, dessa forma não tinha tempo suficiente para fazer o upload do novo código. Resolvi esse problema regravando o bootload do arduino usando um outro arduino.

  5. Boa noite,

    Alguem sabe me dizer como coloco um watchdog neste codigo?

    //RFID – Controle de Acesso com leitor RFID 13.56

    //Biblioteca do protocolo SPI
    #include
    //Biblioteca do RFID
    #include

    /*-importacao Necessaria para LCD + I2C*/
    #include
    #include

    //Pinos de definição
    #define SS_PIN 10
    #define RST_PIN 9
    //Cria a instacia do RFID (mfrc522)
    MFRC522 mfrc522(SS_PIN, RST_PIN);

    //Aqui colocamos as Tags que desejamos autorizar
    String tagsCadastrada[3] ={“F5 EA 0F AB”,”C0 32 B8 4F”,”71 91 6A C5″};

    //————Objeto do LCD + I2C
    LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    //Pinos do LED RGB
    int ledVermelho =2;
    int ledVerde =3;
    int ledAzul =4;

    //Esta parte do Rele é apenas 1 exemplo de utilidade———
    //neste caso precisaremos de fonte externa para o acionamento——–
    //decidi não colocar para não complicar muito o exemplo—————
    //basta tirar o comentario para usar——————
    //int relay =7;

    void setup()
    {
    // Inicia a serial
    Serial.begin(9600);
    //Inicia o LCD como 16 linhas e 2 colunas
    lcd.begin(16,2);
    //inicia a conexão SPI
    SPI.begin();
    // Inicia MFRC522
    mfrc522.PCD_Init();
    Serial.println();

    //Inicia os pinos do LED RGB como saida
    pinMode(ledVermelho, OUTPUT);
    pinMode(ledVerde, OUTPUT);
    pinMode(ledAzul, OUTPUT);

    //Metodo inicial (Menu)
    mensageminicial();

    //Esta parte do Rele é apenas 1 exemplo de utilidade———
    //neste caso precisaremos de fonte externa para o acionamento——–
    //decidi não colocar para não complicar muito o exemplo—————
    //basta tirar o comentario para usar——————
    //pinMode(relay, OUTPUT);
    }

    void loop()
    {

    //Aguarda proximidade do cartão / tag
    if ( ! mfrc522.PICC_IsNewCardPresent())
    {
    return;
    }
    //Seleciona o cartão / tag
    if ( ! mfrc522.PICC_ReadCardSerial())
    {
    return;
    }
    //Mostra UID na serial
    Serial.print(“UID da tag :”);
    //String que armazenará o UID do cartão
    String conteudo= “”;
    //variavel que coletará os bytes lidos
    byte letra;

    //dentro deste FOR, armazena byte a byte e
    //concatena na variavel conteudo
    for (byte i = 0; i < mfrc522.uid.size; i++)
    {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
    }

    Serial.println();
    //booleana que valida a tag lida
    //como autorizada ou não
    boolean tagVerificada = false;

    //Limpa o LCD
    lcd.clear();
    //Seta o cursor para linha e coluna 0
    lcd.setCursor(0,0);

    Serial.print("Leitura : ");

    //coloca o valor da variavel conteudo toda em Maisculo
    conteudo.toUpperCase();

    //verifica se a tag lida coincide com uma das tags
    //cadastada no array
    for(int indice =0; indice < sizeof(tagsCadastrada); indice++){
    //if (conteudo.substring(1) == "F5 EA 0F AB") //UID 1
    if (conteudo.substring(1) == tagsCadastrada[0]) //UID 1
    {
    //Se sim imprime no LCD e na Serial
    Serial.println("Ola Eva!");
    Serial.println("Acesso Liberado!");

    lcd.print("Ola Eva!");
    lcd.setCursor(0,1);
    lcd.println("Acesso Liberado!");

    //tag encontrada
    tagVerificada = true;
    //este metodo acende o led verde (autorizado)
    //e liga o rele
    tagValida();
    delay(3000);
    //Incia o processo novamente
    mensageminicial();
    //limpa a String conteudo para fazer nova leitura
    conteudo= "";

    }

    //if (conteudo.substring(1) == "C0 32 B8 4F") //UID 1

    //verifica se a tag lida coincide com uma das tags
    //cadastada no array
    if (conteudo.substring(1) == tagsCadastrada[1]) //UID 1
    {

    //Se sim imprime no LCD e na Serial
    Serial.println("Ola Marcos! ");
    Serial.println("Acesso Liberado!");

    lcd.print("Ola Marcos!");
    lcd.setCursor(0,1);
    lcd.println("Acesso Liberado!");

    //tag encontrada
    tagVerificada = true;
    //este metodo acende o led verde (autorizado)
    //e liga o rele
    tagValida();
    delay(3000);
    //Incia o processo novamente
    mensageminicial();
    //limpa a String conteudo para fazer nova leitura
    conteudo= "";
    }

    //if (conteudo.substring(1) == "71 91 6A C5") //UID 1

    //verifica se a tag lida coincide com uma das tags
    //cadastada no array
    if (conteudo.substring(1) == tagsCadastrada[2]) //UID 1
    {

    //Se sim imprime no LCD e na Serial
    Serial.println("Ola Visitante! ");
    Serial.println("Acesso Liberado!");

    lcd.print("Ola Visitante!");
    lcd.setCursor(0,1);
    lcd.println("Acesso Liberado!");

    //tag encontrada
    tagVerificada = true;
    //este metodo acende o led verde (autorizado)
    //e liga o rele
    tagValida();
    delay(3000);
    //Incia o processo novamente
    mensageminicial();
    //limpa a String conteudo para fazer nova leitura
    conteudo= "";
    }

    //caso o conteudo não seja "" e a tag Verficada
    //esteja falsa.
    //Informa o usuario que não tem acesso
    if((tagVerificada == false)&&(conteudo != "")){

    //Se ambas condições forem verdadeira
    //imprime no LCD e na Serial uma mensagem de negação ao usuario
    Serial.println("Usuario Desconhecido! ");
    Serial.println("Acesso Negado!!");

    lcd.print("Usuario Negado!");
    lcd.setCursor(0,1);
    lcd.println("Acesso Negado! ");

    //este metodo acende o led vermelho (nãp autorizado)
    //e matem o rele desligado
    tagInvalida();
    delay(3000);
    //Incia o processo novamente
    mensageminicial();
    //limpa a String conteudo para fazer nova leitura
    conteudo= "";
    }
    }

    }

    //Metodo Inicial que informa ao usuario o que deve ser feito
    void mensageminicial()
    {
    Serial.println();
    Serial.println("Aproxime o seu cartao de leitor");

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Aproxime a sua");
    lcd.setCursor(0,1);
    lcd.print("tag p/ Leitura!");

    digitalWrite(ledAzul,LOW);
    digitalWrite(ledVermelho, HIGH);
    digitalWrite(ledVerde, HIGH);

    //Esta parte do Rele é apenas 1 exemplo de utilidade———
    //neste caso precisaremos de fonte externa para o acionamento——–
    //decidi não colocar para não complicar muito o exemplo—————
    //basta tirar o comentario para usar——————
    //digitalWrite(relay, HIGH);
    Serial.println();

    }

    //Metodo chamado quando a tag é valida e cadastrada
    void tagValida()
    {
    digitalWrite(ledAzul,HIGH);
    digitalWrite(ledVermelho, HIGH);
    digitalWrite(ledVerde, LOW);

    //Esta parte do Rele é apenas 1 exemplo de utilidade———
    //neste caso precisaremos de fonte externa para o acionamento——–
    //decidi não colocar para não complicar muito o exemplo—————
    //basta tirar o comentario para usar——————
    //digitalWrite(relay, LOW);

    }

    //Metodo chamado quando a tag invalida / desconhecida
    void tagInvalida()
    {
    digitalWrite(ledAzul,HIGH);
    digitalWrite(ledVermelho, LOW);
    digitalWrite(ledVerde, HIGH);

    //Esta parte do Rele é apenas 1 exemplo de utilidade———
    //neste caso precisaremos de fonte externa para o acionamento——–
    //decidi não colocar para não complicar muito o exemplo—————
    //basta tirar o comentario para usar——————
    //digitalWrite(relay, HIGH);
    }

    1. Oi Marcos.

      A imagem do post é uma for de usar o WDT no Arduino mas é algo que pode trazer uma grande dor de cabeça porque o tempo máximo é 8s, o que não é suficiente para regravar o sketch se estiver em um loops de resets, como é o caso do código apresentado.

      Você pode usar o código da imagem como referência, mas tenha em mente que se deixar o WDT resetando o Arduino ao carregar talvez você entre em um softbrick e só consiga resolver regravando o bootloader ou o sketch seguindo as sugestões dos comentários deste post.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.