Medindo Níveis de CO₂: Descobrindo o Multiplicador de Sonolência
Componentes e Materiais
| Andium Anduino WiFi | 1 | |
| Arduino Due | 1 | |
| Sensor de CO₂ (NDIR, ex: Cozir) | 1 |
Aplicativos e Serviços Online
| Arduino IDE |
| Adafruit IO |
Sobre este Projeto
Motivação
Já teve dificuldade para aguentar uma reunião à tarde? Não para de bocejar? Dorme durante aulas de 3 horas? Não, não estou vendendo suplemento energético. Você provavelmente não dormiu o suficiente ontem, como a maioria de nós. Mas sua sonolência pode não ser totalmente sua culpa! Ventilação ruim e altos níveis de dióxido de carbono podem estar causando esse cansaço!
Usando este sensor NDIR de CO₂, você mede os níveis com precisão e lê os valores via interface serial UART simples. Sensores convencionais consumiam muita energia e levavam tempo para aquecer a lâmpada antes de estarem prontos. Agora, com um LED e detector infravermelho, você mede gases com precisão usando este sensor de 3.3V que consome menos de 1.5mA em média. Ele usa dispersão óptica e "outras bruxarias" — confira o datasheet da Cozir para detalhes, é impressionante.

Primeiros Passos
O que preciso para começar a medir o "fator sonolência" do meu cubículo?
- Arduino Due ou Zero
- Shield AnduinoWiFi
- Sensor CO₂ Cozir
- Alguns jumpers para conectar e alimentar o sensor.
Conexões são simples: o sensor tem 10 pinos, mas você só precisa ligar 4.

No Due: 3.3V → 3V3, GND → GND, Rx (DIO19) → Tx do sensor, Tx (DIO18) → Rx do sensor. Cruze os fios UART e lembre-se: não use Tx (DIO1) e Rx (DIO0) se quiser manter o monitor serial para acompanhar leituras. Usei Serial1 para o sensor, mas poderia usar qualquer das outras 3 UARTs.
** Para testar comandos diretos ao sensor sem Arduino, abra PuTTY ou seu terminal serial favorito e conecte a 9600 baud, 8 bits, sem paridade, 1 stop bit. Pode precisar habilitar envio de '\r\n' a cada envio ASCII.
*** Este sensor é 3.3V TTL — use level shifter se a comunicação vier de fonte 5V.
Calibrando o Sensor
Existem algumas formas de calibrar. Uma das melhores é saturar o sensor com gás conhecido (Nitrogênio), que não contém CO₂, gerando leitura zero conhecida. Se não tem nitrogênio, pode calibrar razoavelmente bem com ar fresco. Pegue seus óculos, vamos a campo!



Ao ar livre, rode o sketch de exemplo abaixo e descomente calibrateFreshAir(); no setup(). Isso envia o comando 'G' via serial ao sensor solicitando calibração!

Não é perfeito, pois não sei a concentração exata de CO₂ no 14º andar em NYC (possivelmente mais alta que a média "da Terra" no Havaí). Mas como nossos limiares para perceber diferenças físicas no ambiente estão na casa dos milhares de ppm, acho seguro usar esta leitura de 450 ppm de ar fresco como ponto de calibração para medir salas de reunião e salas de aula.
Sketch de Exemplo (Calibração e Leitura)
char buffer[20] = {0}; int c = 0;
void setup() {
Serial.begin(9600); while(!Serial){};
Serial1.begin(9600); while(!Serial){};
Serial.println("Iniciando leitura de niveis de CO2");
// setOperatingMode(CZR_STREAMING);
// setOperatingMode(CZR_POLLING);
// calibrateFreshAir();
}
void loop() {
delay(10000);
c = Request("Z");
Serial.print("CO2 : "); Serial.println(c); Serial.println("");
}
int Request(char* s) {
buffer[0] = '\0'; int idx = 0;
Command(s); delay(250);
while(Serial1.available()) { buffer[idx++] = Serial1.read(); }
buffer[idx] = '\0'; uint16_t rv = 0;
switch(buffer[1]) {
case 'T': rv = atoi(&buffer[5]); if (buffer[4] == 1) rv += 1000; break;
default: rv = atoi(&buffer[2]); break;
} return rv;
}
void Command(char* s) { Serial1.print(s); Serial1.print("\r\n"); }
uint16_t calibrateFreshAir() { return Request("G"); }
void setOperatingMode(uint8_t mode) { sprintf(buffer, "K %u", mode); Command(buffer); }
Note os dois #define no topo. Ao tirar o sensor da caixa, pode precisar configurá-lo com setOperatingMode(). Este sketch funciona em polling mode. Se calibrou com sucesso e lê níveis de CO₂ no terminal, pronto para publicar na nuvem. Vamos conectar ao Adafruit IO e visualizar os dados.
Publicando Métricas de CO₂ na Nuvem
Se ainda não conectou ao Adafruit IO com AnduinoWiFi, veja este writeup do projeto que cobre os detalhes. Aqui está o sketch para publicar seus níveis de CO₂ a cada minuto:
#include <WiFi101.h> #include "Adafruit_MQTT.h" #include "Adafruit_MQTT_Client.h" #include "AnduinoLCD.h"
// WiFi
#define WLAN_SSID "SEU_SSID"
#define WLAN_PASS "SUA_SENHA"
// Adafruit IO
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "SEU_USUARIO_AIO"
#define AIO_KEY "SUA_CHAVE_AIO"
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// Feed para CO2
Adafruit_MQTT_Publish carbonDioxide = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/co2");
AnduinoLCD LCD = AnduinoLCD(ST7735_CS_PIN, ST7735_DC_PIN, 13);
static int co2 = 0, co2Prev = 0;
#define CZR_STREAMING 0x01
#define CZR_POLLING 0x02
char buffer[20] = {0};
void setup() {
Serial.begin(115200); delay(3000);
Serial1.begin(9600);
connectToWiFi(); connectToAdafruit();
LCD.begin(); LCDinit();
// setOperatingMode(CZR_STREAMING);
// setOperatingMode(CZR_POLLING);
// calibrateFreshAir();
}
void loop() {
if(! mqtt.ping(3)) { if(! mqtt.connected()) connect(); }
co2 = Request("Z");
char b[20]; String str = String(co2);
for(int i=0; i<str.length(); i++) b[i]=str.charAt(i);
b[str.length()+1]=0;
if (!carbonDioxide.publish((char*)b)) { Serial.println(F("Falha ao publicar co2")); }
else { Serial.print(F("co2 publicado: ")); Serial.println(co2); displayCo2(co2, co2Prev); }
Serial.print("CO2 : "); Serial.println(co2); Serial.println("");
co2Prev = co2; delay(60000);
}
void connect() {
Serial.print(F("Conectando ao Adafruit IO... "));
int8_t ret;
while ((ret = mqtt.connect()) != 0) {
switch (ret) {
case 1: Serial.println(F("Protocolo errado")); break;
case 2: Serial.println(F("ID rejeitado")); break;
case 3: Serial.println(F("Servidor indisponivel")); break;
case 4: Serial.println(F("Usuario/senha invalidos")); break;
case 5: Serial.println(F("Nao autenticado")); break;
case 6: Serial.println(F("Falha ao assinar")); break;
default: Serial.println(F("Falha na conexao")); break;
}
if(ret >= 0) mqtt.disconnect();
Serial.println(F("Tentando novamente...")); delay(5000);
}
Serial.println(F("Adafruit IO Conectado!"));
}
void displayCo2(int co2, int co2Prev) {
LCD.setTextColor(ST7735_BLACK); LCD.setTextSize(2); LCD.setTextWrap(true);
LCD.setCursor(40,60); LCD.setTextSize(3); LCD.print(co2Prev); LCD.setTextSize(1); LCD.print("ppm");
LCD.setTextColor(ST7735_WHITE); LCD.setTextSize(2); LCD.setTextWrap(true);
LCD.setCursor(40,60); LCD.setTextSize(3); LCD.print(co2); LCD.setTextSize(1); LCD.print("ppm");
}
void connectToWiFi() {
delay(10); Serial.print(F("Conectando a ")); Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(F(".")); }
Serial.println(F("WiFi conectado!"));
}
void connectToAdafruit() { connect(); }
void LCDinit() {
LCD.setBacklight(ON); LCD.fillScreen(ST7735_BLACK);
LCD.showBanner(); LCD.setTextColor(ST7735_WHITE); LCD.setTextSize(2);
LCD.setTextWrap(true); LCD.setCursor(0,40); LCD.print("CO2: ");
}
uint16_t Request(char* s) {
buffer[0] = '\0'; int idx = 0;
Command(s); delay(250);
while(Serial1.available()) { buffer[idx++] = Serial1.read(); }
buffer[idx] = '\0'; uint16_t rv = 0; rv = atoi(&buffer[2]); return rv;
}
void Command(char* s) { Serial1.print(s); Serial1.print("\r\n"); }
uint16_t calibrateFreshAir() { return Request("G"); }
void setOperatingMode(uint8_t mode) { sprintf(buffer, "K %u", mode); Command(buffer); }
É Isso!
Este sensor é super sensível — dá para quase rastrear níveis de ocupação da sala pela concentração de CO₂ mesmo em ambientes bem ventilados. Hora de provar ao seu professor que não é a "equação diferencial" que está te derrubando, é a ventilação ruim! Hora de mover a aula para a praia!

Código
Anduino
Biblioteca Arduino para shield Andium(Anduino). Transforme seu Arduino em um AndiumNode. https://github.com/andium/Anduino
Processo de manufatura
- Sensirion Lança SCD40: Sensor CO₂ e RH/T Ultra-Miniaturizado
- Integração de Dados de Sensores no Raspberry Pi: Guia Prático
- Construa Sensores de Objeto Personalizados para LEGO Mindstorms EV3: "Olhos" DIY Baseados em Luz
- Conectar Diretamente Sensor Ultrassônico NXT do Lego Mindstorms ao Raspberry Pi
- Conectando Sensor Ultrassônico HC-SR04 ao Raspberry Pi – Guia Prático
- Integrando Radar Pulsado Acconeer A111 com Raspberry Pi: Guia Prático
- Eleve o Atendimento ao Cliente na Prateleira: Estratégias Avançadas para Visibilidade e Eficiência
- Energia Sem Fio RF Impulsiona Adoção Universal de Redes de Sensores
- Sensor RapidPlex: 5 Perguntas Essenciais Sobre Teste Caseiro de SARS-CoV-2
- Manutenção Industrial: 5 Níveis Essenciais Explicados