Eis mais uma novidade trazida pelo nosso parceiro Saravati. A TTGO T-Camera, que possui display OLED, botão de uso geral, botão de reset, sensor PIR e, claro, a câmera. Além desses recursos, ela tem um pad para adicionar o sensor BME280, que não vem por padrão, mas uma das razões é que a temperatura da placa influencia no sensor de temperatura, por ser muito sensível.
Table of Contents
Características
Essa placa é incrível. Já escrevi alguns artigos sobre o ESP32-CAM, mas são placas bastante distintas.
Os botões quadrados da TTGO T-Camera são emborrachados, bastante agradáveis. Na borda inferior possui uma porta micro-USB, logo acima está o sensor PIR.
A câmera é uma OV2640, podendo ser a tradicional ou a fish-eye. A minha é a fish-eye, com uma imagem boa o suficiente em modo SVGA.
Ela possui outros formatos, inclusive grayscale para quem quiser imagens em formatos maiores sem perder fps – o que digo assim de passagem, pode ser o ideal para utilizar com visão computacional e inteligência artificial, pois é comum utilizar grayscale.
Na parte de trás da placa estão dispostos pinos de 5V, 3V3, GND e os pinos 21 e 22 para acesso ao barramento I2C, permitindo adicionar outros dispositivos, como por exemplo, um expansor de IO. Por essa razão, a ausência de outros pinos de IO não é um problema.
Na lateral, próximo à câmera, ela possui um conector para 5V onde podemos colocar uma bateria li-ion para alimentar o ESP32. O conector acompanha a placa.
Inicialização
Por padrão, essa placa vem configurada como AP, utilizando (infelizmente) o IP 192.168.1.1, que é comum ser o gateway de muitas redes domésticas. A rede deve aparecer como TTGO-CAMERA-xx:yy, sendo dois octetos referentes a uma parte do MAC address. A senha padrão é 12345678.
Ao acessar diretamente o IP no browser, deve iniciar uma streaming. Usando /jpg ao final do endereço, apenas um frame é capturado. Só que um dos meus roteadores WiFi utiliza justamente esse endereço IP, daí quis de imediato subir outro sketch. Pense em um sofrimento.
Subir novo sketch na TTGO T-Camera
O código que disponibilizo aqui foi um trabalho de mais de 12 horas de testes, quase desisti de fazer isso agora pela falta de informação e dificuldade de debug. Vamos começar a falar dos detalhes, depois assista ao vídeo também em nosso canal DobitAoByteBrasil no Youtube para ficar mais claro ainda.
Não use a biblioteca OV2640 – use a esp_camera
Para instanciar a câmera, é necessário alimentar uma struct contida na biblioteca que gerenciará a câmera. Acontece que a OV2640 não tem a configuração para o pino PWDN, que no caso dessa câmera, não pode ser nulo. Esse pino (PWDN) deve ser colocado em OUTPUT e HIGH. Não foi necessário fazê-lo, mas li algumas documentações que diziam ser necessário colocar IOD e IOS em PULLUP, então deixei comentado no código para um teste posterior, caso necessário fosse.
Outra coisa importante é que essa placa tem algumas variações de modelo e para cada modelo tem uma pinagem diferente da câmera. A melhor referência é a desse repositório, do qual será necessário cloná-lo para dentro de seu diretório de bibliotecas do Arduino.
Mais bibliotecas
Nesse primeiro sketch que disponibilizo nesse artigo não adicionei os demais recursos, como PIR e botão. Farei isso em outro artigo, não tem complicação nessa parte.
Instale a biblioteca ESP8266-OLED-SSD1306. NO repositório oficial do Arduino está nomeado como ESP8266-OLED, mas você pode pegá-la também clonando esse repositório.
Para o botão, uma das opções é utilizar a biblioteca OneButton, conforme será mostrado em outro artigo. Também está disponível no repositório oficial do Arduino.
Essa tabela contém o pinout de todos os modelos da TTGO-Camera, incluindo a TTGO T-Camera, que é essa sem microfone.
Name | BME280/NoBME280-Version | Microphone-Version | T-Jornal | T-Camera Plus |
---|---|---|---|---|
Y9 | 39 | 36 | 19 | 36 |
Y8 | 36 | 15 | 36 | 37 |
Y7 | 23 | 12 | 18 | 38 |
Y6 | 18 | 39 | 39 | 39 |
Y5 | 15 | 35 | 5 | 35 |
Y4 | 4 | 14 | 34 | 26 |
Y3 | 14 | 13 | 35 | 13 |
Y2 | 5 | 34 | 17 | 34 |
VSNC | 27 | 5 | 22 | 5 |
HREF | 25 | 27 | 26 | 27 |
PCLK | 19 | 25 | 21 | 25 |
PWD | 26 | N/A | N/A | N/A |
XCLK | 32 | 4 | 27 | 4 |
SIOD | 13 | 18 | 25 | 18 |
SIOC | 12 | 23 | 23 | 23 |
RESET | N/A | N/A | N/A | N/A |
SDA | 21 | 21 | 14 | ! |
SCL | 22 | 22 | 13 | ! |
Button | 34 | 0 | 32 | N/A |
PIR | 33 | 19 | N/A | N/A |
Na caixa da placa vem anotado o pinout, mas não é muito intuitivo, porque tanto na struct quanto na declaração de exemplo de qualquer sketch, os nomes e números são completamente diferentes.
Outra coisa interessante é que nos códigos de exemplo o display OLED é configurado com a resolução de 128×32, sendo que ele é um display de 128×64. Enfim, sequer chegou a ser um problema. Pra por a câmera pra funcionar sem usar o sketch padrão, aí sim foi um problemão, mas pelo qual você não precisará passar, bastando seguir esse artigo.
Código para TTGO T-Camera
Esse código está funcional para streaming e captura de uma amostra. Para streaming, use:
http://<IP que aparecer no display>
E para pegar uma amostra JPG, use:
http://<IP que aparece no display>/jpg
Uma outra forma de suprir as dependências é colocar esse código para compilar e ler as mensagens de erro retornadas pelo compilador. Mas se leu o artigo até aqui, não terá problema para fazer a placa funcionar. Lembre-se apenas de escolher o modelo WROVER na IDE do Arduino quando criar seu projeto.
#include <Arduino.h> #include "esp_camera.h" #include "SSD1306.h" #include "OLEDDisplayUi.h" #include <WiFi.h> #include <WebServer.h> #include <WiFiClient.h> /* define dos pinos do display*/ #define PWDN_GPIO_NUM 26 #define ENABLE_OLED #ifdef ENABLE_OLED #include "SSD1306.h" #define OLED_ADDRESS 0x3c #define I2C_SDA 21 #define I2C_SCL 22 SSD1306Wire display(OLED_ADDRESS, I2C_SDA, I2C_SCL, GEOMETRY_128_64); #endif //OV2640 cam; WebServer server(80); const char *ssid = "seuSSID"; const char *password = "suaSENHA"; void info(char *msg); void info(char *msg) { display.clear(); display.drawString(128 / 2, 32 / 2, msg); display.display(); } void handle_jpg_stream(void) { WiFiClient client = server.client(); String response = "HTTP/1.1 200 OK\r\n"; response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n"; server.sendContent(response); camera_fb_t *fb = NULL; size_t fb_len = 0; while (1) { //cam.run(); if (!client.connected()) break; response = "--frame\r\n"; response += "Content-Type: image/jpeg\r\n\r\n"; server.sendContent(response); fb = esp_camera_fb_get(); if (!fb) { Serial.printf("Camera capture failed"); info("Camera failed :("); return; } fb_len = fb->len; client.write((const char *)fb->buf, fb->len); //client.write((char *)cam.getfb(), cam.getSize()); server.sendContent("\r\n"); if (!client.connected()) break; } } void handle_jpg(void) { info("JPG requested."); Serial.println("JPG requested."); WiFiClient client = server.client(); info("Taking a shot..."); Serial.println("Taking a shot..."); camera_fb_t *fb = NULL; fb = esp_camera_fb_get(); if (!fb) { Serial.printf("Camera capture failed"); info("Camera failed :("); return; } size_t fb_len = 0; fb_len = fb->len; //cam.run(); if (!client.connected()) { Serial.println("fail ... \n"); return; } String response = "HTTP/1.1 200 OK\r\n"; response += "Content-disposition: inline; filename=capture.jpg\r\n"; response += "Content-type: image/jpeg\r\n\r\n"; server.sendContent(response); info("Sending sample..."); Serial.println("Sending sample..."); //client.write((char *)cam.getfb(), cam.getSize()); client.write((const char *)fb->buf, fb->len); Serial.println("Done."); info("Done."); } void handleNotFound() { String message = "Server is running!\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; server.send(200, "text/plain", message); } void setup() { pinMode(PWDN_GPIO_NUM, PULLUP); digitalWrite(PWDN_GPIO_NUM, HIGH); //pinMode(13, INPUT_PULLUP); //pinMode(14, INPUT_PULLUP); display.init(); //display.flipScreenVertically(); display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_CENTER); display.clear(); display.display(); info("Starting serial..."); Serial.begin(9600); while (!Serial); camera_config_t camera_config; camera_config.ledc_channel = LEDC_CHANNEL_0; camera_config.ledc_timer = LEDC_TIMER_0; camera_config.pin_pwdn = 26; camera_config.pin_d0 = 5; camera_config.pin_d1 = 14; //input_pullup ? camera_config.pin_d2 = 4; camera_config.pin_d3 = 15; camera_config.pin_d4 = 18; camera_config.pin_d5 = 23; camera_config.pin_d6 = 36; camera_config.pin_d7 = 39; camera_config.pin_xclk = 32; camera_config.pin_pclk = 19; camera_config.pin_vsync = 27; camera_config.pin_href = 25; camera_config.pin_sscb_sda = 13; //input_pullup ? camera_config.pin_sscb_scl = 12; //12 camera_config.pin_reset = 255; camera_config.xclk_freq_hz = 20000000; camera_config.pixel_format = PIXFORMAT_JPEG; camera_config.frame_size = FRAMESIZE_SVGA; camera_config.jpeg_quality = 12; camera_config.fb_count = 1; //sensor_t *s = esp_camera_sensor_get(); //s->set_framesize(s, FRAMESIZE_QVGA); info("Starting camera..."); esp_err_t err = esp_camera_init(&camera_config); if (err != ESP_OK) { Serial.printf("Camera init Fail"); info("Camera failed :("); } info("Connecting..."); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(F(".")); } Serial.println(F("WiFi connected")); Serial.println(""); Serial.println(WiFi.localIP()); display.clear(); display.drawString(128 / 2, 32 / 2, WiFi.localIP().toString()); display.display(); server.on("/", HTTP_GET, handle_jpg_stream); server.on("/jpg", HTTP_GET, handle_jpg); server.onNotFound(handleNotFound); server.begin(); } void loop() { server.handleClient(); }
Essas 200 linhas são o resultado após ter escrito umas 2k linhas de testes, sem exagero.
Onde comprar a TTGO T-Camera?
A TTGO T-Camera está disponível no nosso parceiro Saravati, que possui loja física na Santa Efigênia e para quem é da capital de São Paulo, deve valer o passeio. De outro modo, a compra pode ser feita diretamente pelo site, através desse link.
Vídeo
O vídeo, como supracitado, pode ser visto em nosso canal Dobitaobytebrasil no Youtube. Se não é inscrito, inscreva-se, clique no sininho para receber notificações assim que o vídeo estiver online e deixe seu like, que é muito importante para o canal!
Curso “Raspberry para hobistas e profissionais”
E continuando a divulgação do meu curso na Udemy, por R$21,00 usando o cupom de desconto DOBITAOBYTE você pode adquirir algum conhecimento diferenciado do que se vê por padrão em artigos e cursos online, além de contribuir com o blog. Aproveite, são 3 horas de vídeo aulas, mas que lhe prenderão por um bom tempo.
2 thoughts on “TTGO T-Camera com ESP32 WROVER”
Comments are closed.