Skip to Content

Controlar o LED Flash do ESP32-CAM

Controlar o LED Flash do ESP32-CAM

Este pequeno tutorial mostra como ligar ou desligar o LED Flash do ESP32-CAM, com e sem deep-sleep. Também aprenderás a controlar o brilho do LED e o que ter em atenção ao usar o LED e a interface do cartão SD em conjunto.

Peças Necessárias

Vais precisar de um ESP32-CAM para experimentar os exemplos de código. Podes obter um ESP32-CAM com um USB-TTL Shield para programação ou um Adaptador FTDI USB-TTL. Recomendo o Adaptador FTDI USB-TTL, pois é mais prático para programar, mas listei ambas as opções abaixo.

Se quiseres usar o leitor de cartão SD, precisarás de um cartão SD que não seja maior que 16 GB. No entanto, não é necessário para este tutorial.

ESP32-CAM com USB-TTL Shield

Adaptador FTDI USB-TTL

Cartão MicroSD 16GB

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Piscar o LED Flash

Se não usares o cartão SD ou o modo deep-sleep do ESP32-CAM, controlar o LED flash é simples. O LED flash está ligado ao GPIO 4 e o código habitual Blink funciona perfeitamente.

void setup() {
  pinMode(GPIO_NUM_4, OUTPUT);
}

void loop() {
  digitalWrite(GPIO_NUM_4, HIGH);
  delay(1000);
  digitalWrite(GPIO_NUM_4, LOW);
  delay(1000);
}

Se selecionares a placa AI Thinker ESP32-CAM, a constante GPIO_NUM_4 para o GPIO 4 é definida.

Select AI Thinker ESP32-CAM  as board
Seleciona AI Thinker ESP32-CAM como placa

Na função setup podemos então usar GPIO_NUM_4 para definir o GPIO 4 como saída. Na função loop temos o código habitual Blink que liga o LED durante um segundo e desliga durante outro segundo.

Se não sabes como carregar código no ESP32-CAM, dá uma vista de olhos ao tutorial Programming the ESP32-CAM.

Controlar o brilho do LED Flash

O GPIO 4 também suporta PWM (Pulse Width Modulation), o que significa que podes controlar o brilho do LED flash. O exemplo seguinte aumenta o brilho b de 0 (desligado) até ao máximo (255) num ciclo:

void setup() {
  pinMode(GPIO_NUM_4, OUTPUT);
}

void loop() {
  for (int b = 0; b < 256; b++) {
    analogWrite(GPIO_NUM_4, b);
    delay(10);
  }
}

Piscar o LED Flash com deep-sleep

As coisas complicam-se quando queres piscar o LED em combinação com deep-sleep. Por exemplo, queres colocar o ESP32-CAM a dormir, acordá-lo quando um objeto passar, ligar o LED flash, tirar uma foto, desligar o LED e voltar a dormir.

O problema é que o estado de saída dos pinos GPIO normalmente se perde quando o ESP32 entra em deep-sleep. Os pinos ficam flutuantes, sem um valor definido. Podes evitar isto chamando a função rtc_gpio_hold_en(pin) para um pino específico ou a função rtc_gpio_force_hold_en_all() para congelar todos os pinos no seu estado atual.

No entanto, quando o ESP32 acorda do deep-sleep, precisas de desativar esta retenção dos pinos, caso contrário não consegues alterar o estado dos pinos. Para desativar a retenção podes chamar as funções rtc_gpio_hold_dis(pin) ou rtc_gpio_force_hold_dis_all().

O exemplo de código seguinte mostra como usar estas funções para desligar o LED durante um segundo, enquanto o ESP32 está acordado, e depois ligar o LED enquanto o ESP32 dorme por um segundo:

#include "driver/rtc_io.h"

void setup() {
  rtc_gpio_hold_dis(GPIO_NUM_4);
  pinMode(GPIO_NUM_4, OUTPUT);

  digitalWrite(GPIO_NUM_4, LOW);
  delay(1000);
  digitalWrite(GPIO_NUM_4, HIGH);

  rtc_gpio_hold_en(GPIO_NUM_4);
  esp_sleep_enable_timer_wakeup(1 * 1000 * 1000);
  esp_deep_sleep_start();
}

void loop() {}

Vamos analisar isto com mais detalhe.

Primeiro, importamos o ficheiro driver/rtc_io.h, que é necessário para as funções rtc_gpio_hold_xxx.

Na função setup, começamos por chamar rtc_gpio_hold_dis(GPIO_NUM_4). Isto desativa qualquer retenção que tenhamos no pino GPIO 4. Sem isto, não conseguiríamos alterar o estado do pino 4 mais tarde.

Na linha seguinte chamamos pinMode(GPIO_NUM_4, OUTPUT) para definir o pino GPIO 4 como saída. Depois podemos definir o pino 4 para LOW (desligar o LED) chamando digitalWrite(GPIO_NUM_4, LOW).

Após um atraso de um segundo, definimos o pino 4 para HIGH e aí fica interessante. Queremos entrar em deep-sleep mas perderíamos o estado do pino 4. Por isso, precisamos de chamar rtc_gpio_hold_en(GPIO_NUM_4) para manter o estado atual HIGH do pino 4.

Finalmente, definimos o temporizador de deep-sleep para um segundo (esp_sleep_enable_timer_wakeup) e entramos em deep-sleep via esp_deep_sleep_start().

Quando o ESP32 acorda após um segundo, começa novamente no início da função setup. A função loop nunca é chamada.

LED Flash e Interface do Cartão SD

Controlar o LED flash é especialmente complicado quando queres usar o cartão SD também. Isto acontece porque a linha de dados HS2_DATA1 da interface do cartão SD é partilhada pelo LED flash. O diagrama seguinte mostra o circuito de controlo do LED flash.

ESP32-CAM LED Flash wired to HS2_DATA1
LED Flash do ESP32-CAM ligado ao HS2_DATA1 (source)

Podes ver que a alimentação do LED_FLASH é comutada através do transistor Q1, que é controlado por uma linha de sinal rotulada HS2_DATA1. Se agora olhares para o diagrama de ligação do soquete do cartão SD, também verás a linha HS2_DATA1 (último fio), que é usada para transferir dados para o cartão SD:

ESP32-CAM wiring of SD Card Socket
Ligação do soquete do cartão SD no ESP32-CAM (source)

Esta é a razão pela qual o LED do ESP32-CAM normalmente pisca brevemente quando escreves no cartão SD.

Como o LED e o cartão SD usam ambos HS2_DATA1, tens de garantir que não manténs o GPIO 4 ou fazes algo com o LED/GPIO 4 enquanto escreves ou lês do cartão SD.

O exemplo de código seguinte demonstra como ligar o LED, tirar uma foto, guardar no cartão SD, desligar o LED e depois dormir por 5 segundos até à próxima iteração.

#include "FS.h"
#include "SD_MMC.h"
#include "driver/rtc_io.h"
#include "esp32cam.h"

const auto RES = esp32cam::Resolution::find(800, 600);
RTC_DATA_ATTR uint16_t counter = 0;

void takeAndSavePic() {
  static char path[64];
  auto frame = esp32cam::capture();
  if (frame) {
    sprintf(path, "/img%d.jpg", counter++);
    File file = SD_MMC.open(path, FILE_WRITE);
    frame->writeTo(file);
    file.close();
    Serial.printf("Wrote: %s\n", path);
    delay(10);
  }
}

void initCamera() {
  using namespace esp32cam;
  Config cfg;
  cfg.setPins(pins::AiThinker);
  cfg.setResolution(RES);
  cfg.setJpeg(80);
  Camera.begin(cfg);
}

void setup() {
  Serial.begin(115200);
  rtc_gpio_hold_dis(GPIO_NUM_4);
  
  SD_MMC.begin();
  initCamera();

  pinMode(GPIO_NUM_4, OUTPUT);
  digitalWrite(GPIO_NUM_4, HIGH);
  takeAndSavePic();
  digitalWrite(GPIO_NUM_4, LOW);

  rtc_gpio_hold_en(GPIO_NUM_4);
  esp_sleep_enable_timer_wakeup(5 * 1000 * 1000);
  esp_deep_sleep_start();
}

void loop() { }

Para este código vais precisar da biblioteca esp32cam, que facilita o manuseamento da câmara. Podes instalá-la via o Library Manager no Arduino IDE. Basta procurar por “esp32cam”:

esp32cam library installed via Library Manager
Biblioteca esp32cam instalada via Library Manager

Não vou entrar em detalhes sobre como o código da câmara funciona, mas vou focar na interação entre tirar uma foto, guardar no cartão SD, controlar o LED flash e usar deep-sleep. Tudo isto acontece na função setup.

Como podes ver, a primeira coisa é chamar rtc_gpio_hold_dis(GPIO_NUM_4) para desativar qualquer retenção no GPIO 4. Caso contrário, não conseguimos controlar o flash nem usar o cartão SD.

De seguida, inicializamos a interface do cartão SD via SD_MMC.begin() e também inicializamos a câmara via initCamera().

Depois ligamos o LED flash chamando digitalWrite(GPIO_NUM_4, HIGH), tiramos uma foto, guardamos no cartão SD e depois desligamos o LED novamente.

Antes de entrar em deep-sleep, tens de chamar rtc_gpio_hold_en(GPIO_NUM_4) para garantir que o GPIO 4 mantém o seu estado (LOW) durante o deep-sleep e o LED flash permanece desligado.

Depois disso, definimos o temporizador para deep-sleep para 5 segundos e iniciamos o modo deep-sleep. O ESP32 acordará automaticamente após 5 segundos e o ciclo repete-se.

Desligar o Flash ao escrever no cartão SD

Como mencionado antes, o LED flash e o cartão SD partilham a mesma linha de sinal rotulada HS2_DATA1, e por isso o LED pisca brevemente quando escreves no cartão SD. Podes evitar isto ativando o modo 1-bit para o SD Card interface:

 SD_MMC.begin("/sdcard", true);

O segundo argumento mode1bit==true ativa o modo 1-bit. Neste modo, a linha HS2_DATA1 (GPIO 4) não é usada e o LED não piscará ao escrever no cartão SD. Embora a velocidade de escrita seja mais lenta, agora podes controlar livremente o GPIO 4, pois ele será usado apenas pelo LED.

Podes experimentar isto com o seguinte código de teste. Ele desliga o LED e escreve um ficheiro 10 vezes:

#include "FS.h"
#include "SD_MMC.h"

void setup() {
  Serial.begin(115200);

  pinMode(GPIO_NUM_4, OUTPUT);
  digitalWrite(GPIO_NUM_4, LOW);  

  //SD_MMC.begin();  // LED will switch on
  SD_MMC.begin("/sdcard", true);  // LED remains off

  for (int i = 0; i < 10; i++) {
    delay(1000);
    File file = SD_MMC.open("/test.txt", FILE_WRITE);
    file.println("TEST");
    file.close();
    Serial.println("File written");
  }
}

void loop() { }

Com SD_MMC.begin(), o LED liga-se (apesar de estar configurado para desligado) assim que o código começa a escrever os ficheiros. Com SD_MMC.begin("/sdcard", true), por outro lado, o LED fica desligado e permanece desligado.

Conclusões

Neste tutorial aprendeste a controlar o LED flash do ESP32-CAM em vários cenários, especialmente em combinação com deep-sleep e suporte a cartão SD.

Vale a pena mencionar que deves evitar ligar o LED flash por períodos prolongados. O diagrama do circuito revela que não há resistor limitador de corrente para o LED, o que significa que pode facilmente sobreaquecer e queimar.

Se precisares de informações mais básicas sobre o ESP32-CAM, dá uma vista de olhos ao tutorial Programming the ESP32-CAM. Se quiseres aplicar o que aprendeste aqui para construir uma câmara ativada por movimento, vê o tutorial Motion Activated ESP32-CAM. E finalmente, se quiseres usar o ESP32-CAM para deteção de objetos, o Object Detection with ESP32-CAM and YOLO será útil.

Se tiveres alguma dúvida, não hesites em deixar nos comentários.

Boas experiências ; )