Como fazer um Bafômetro com Arduino 67

Neste post vamos ver como montar um Bafômetro com Arduino e um sensor de gás MQ-3 álcool, um dispositivo de fácil conexão e capaz de detectar entre 10 e 10.000 ppm (partes por milhão) de álcool.

Esse sensor funciona por meio de uma reação química, necessitando de um tempo de aquecimento (5 minutos) para entrar em operação e começar a detectar o vapor de álcool. Quando a concentração de álcool fica acima do nível ajustado pelo potenciômetro, a saída digital DOUT fica em estado alto, acionando também o led do módulo.

Módulo MQ-3 - Detalhes pinos

Para acompanhar com um pouco mais de precisão os dados do sensor, pode ser utilizada a saída AOUT, ligada em uma entrada analógica do microcontrolador. No nosso projeto de bafômetro, vamos utilizar o pino AOUT para mostrar os diferentes níveis de álcool detectados pelo sensor MQ-3.

Observe que este é um projeto que deve ser utilizado somente para fins experimentais e educacionais.

Ligação do módulo MQ-3 ao Arduino

Os dados do nosso bafômetro serão mostrados em um display gráfico OLED 128×64, utilizando a mesma ligação via interface I2C e biblioteca que usamos no post Como conectar o display OLED ao Arduino. Já o pino AOUT do sensor MQ-3 será ligado à porta analógica A1 do Arduino.

Circuito Arduino Oled e MQ3

Programa e biblioteca u8glib

No display será mostrado o valor lido da porta analógica A1, e no rodapé da tela uma mensagem correspondente ao nível de álcool detectado pelo sensor. A biblioteca gráfica do display é a u8glib, disponível neste link. É com essa biblioteca que alteramos o tamanho e tipo da fonte, desenhamos linhas, retângulos, curvas, etc.

Como mencionamos anteriormente, esse sensor precisa de um tempo para aquecimento, por volta de 5 minutos, e definimos esse valor na linha 9 do programa utilizando a variável tempo_aquecimento, com o valor em segundos (300 segundos = 5 minutos).

Entre as linhas 108 e 128 você pode alterar os valores de teste da variável valor_sensor, que é utilizado para mostrar as mensagens no display.

// Programa: Bafometro com Arduino
// Autor: FILIPEFLOP

#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);

// Tempo de aquecimento
int tempo_aquecimento = 300;
int valor_sensor = 0;
unsigned long time;
int status = 1;
String estado;
int posicao1;

void draw()
{
  // Comandos graficos para o display devem ser colocados aqui
  // Seleciona a fonte de texto
  u8g.setFont(u8g_font_8x13B);
  // Mensagens iniciais
  u8g.drawRFrame(0, 18, 128, 46, 4);
  u8g.drawStr( 30, 15, "BAFOMETRO");
  u8g.drawStr( 10, 37, "Aguarde");

  // Animacao caneca
  if (status == 1)
  {
    u8g.drawBox(80, 25, 20, 30);
    u8g.drawHLine(77, 24, 26);
    u8g.drawRFrame(78, 25 , 24, 32, 0);
    u8g.drawRFrame(77, 25 , 26, 32, 0);
    u8g.drawHLine(76, 57, 28);
    u8g.drawHLine(76, 58, 28);
    u8g.drawRFrame(102, 30 , 7, 20, 2);
    u8g.drawRFrame(102, 28 , 9, 24, 2);
    u8g.setColorIndex(0);
    if (time == 0)
    {
      time = 1;
    }
    u8g.drawBox(79, 25, 22, time);
    u8g.setColorIndex(1);
  }

  // Apos o aquecimento, exibe dados do sensor
  if (status == 0)
  {
    u8g.setFont(u8g_font_fub20);
    u8g.setColorIndex(0);
    u8g.drawBox(10, 25, 110, 33);
    u8g.setColorIndex(1);
    // Centraliza o valor na tela
    if (valor_sensor <= 99)
    {
      posicao1 = 50;
    }
    else
    {
      posicao1 = 43;
    }
    // Mostra valor do sensor
    u8g.setPrintPos(posicao1, 45);
    u8g.print(valor_sensor);
    u8g.setFont(u8g_font_ncenB08);
    // Imprime mensagem no rodape
    int tamanho = estado.length();
    int posicao = (128 / 2 - 3) - ((tamanho * 5) / 2);
    u8g.setPrintPos(posicao, 60);
    u8g.print(estado);
  }
}

void setup(void)
{
  Serial.begin(9600);
  pinMode(A1, INPUT);
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255, 255, 255);
  }
}

void loop(void)
{
  // Leitura do valor do sensor
  valor_sensor = analogRead(A1);
  time = millis() / 1000;
  u8g.firstPage();
  // Tempo de aquecimento
  if (time <= tempo_aquecimento)
  {
    time = map(time, 0, tempo_aquecimento, 0, 30);
    status = 1;
  }
  else
  {
    status = 0;
  }
  // Mensagem rodape
  if (valor_sensor >= 0 and valor_sensor <= 50)
  {
    estado = "Voce nao bebeu...";
  }
  else if (valor_sensor >= 51 and valor_sensor <= 200)
  {
    estado = "Bebeu 1 cerveja ?";
  }
  else if (valor_sensor >= 201 and valor_sensor <= 400)
  {
    estado = "Bebeu 2 cervejas ?";
  }
  else if (valor_sensor >= 401 and valor_sensor <= 600)
  {
    estado = "Voce cheira a 51 !";
  }
  else if (valor_sensor >= 601)
  {
    estado = "Voce esta bebado !!";
  }

  // Chama a rotina de desenho na tela
  do
  {
    draw();
  }
  while ( u8g.nextPage() );

  delay(50);
}

O programa inicialmente mostra uma pequena animação enquanto aguarda o tempo de aquecimento. Depois disso, passa a mostrar os valores lidos da porta analógica. A leitura do nível de álcool é geralmente feita de forma rápida, mas é normal que o sensor demore um tempo para voltar aos valores iniciais.

 Gostou? Deixe seu comentário logo abaixo.

Deixe uma resposta

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

67 Comentários

  1. Legal, ele detecta outros gases?

    1. Bom dia Eduardo,

      Segundo o datasheet, somente álcool: https://www.pololu.com/file/0J310/MQ3.pdf

      Abraço

      Adilson- Equipe FILIPEFLOP

  2. felipe muito bom seu projeto, mas estou com duvida no codigo fonte, pois não conseguir copilar no programa.

    obs: erro U8GLIB

    1. Olar , gostei bastante deste projeto , mais no momento de copilar ele da um erro na biblioteca ( #include “U8glib.h”) , o que poderia ser este problema , mesma pergunta de nosso amigo salomão zulaia , mostre-nos a solução por favor !!

      1. Boa tarde Arilson,

        Você instalou a biblioteca corretamente ?

        Abraço!

        Adilson – Equipe FILIPEFLOP

  3. Muito legal! Gostaria de saber se vocês conhecem algum simulador que possua essa OLED 128X64, valeu!

  4. Olá.

    Antes de mais nada, parabéns pelo blog.

    Uma dúvida: esse e outros sensores “MQ”, segundo o datasheet, tem 2 características que fazem com que usá-los não seja tão “plug and play”:

    1. eles precisam de um pré-aquecimento demorado antes de serem usados (no datasheet aparece como “Preheat time: over 48 hours”);

    2. em quase todos eles existe uma tensão para mantê-los aquecido e uma tensão para fazer a leitura (vide o MQ-7, que é o que estou trabalhando no momento, e que pede 5V para aquecimento e 1,4V para leitura).

    Minha questão é sobre esses módulos onde os sensores MQ já vem grudados em uma plaquinha com 4 pinos:

    1. eles precisam desse “preheat time” antes de serem usados?

    2. parece que, devido ao número de pinos, não é possível fazer com que trabalhem com essas 2 tensões indicadas no datasheet. Será que isso pode trazer algum problema com relação a precisão na leitura?

    Abraços,
    Mauricio de O. Pena

    1. Boa tarde Maurício,

      Sim, eles precisam desse tempo de aquecimento. No caso do bafômetro, o programa aguarda alguns minutos antes de realizar a leitura justamente por causa disso.

      Quanto à precisão na leitura, não temos informações sobre isso, já que o fabricante não fornece nenhuma indicação de que o moódulo aumenta ou diminui a tensão automaticamente depois de um certo tempo (de aquecimento).

      Abraço e obrigado!

      Adilson – Equipe FILIPEFLOP

  5. Olá,

    Parabéns pelo blog.

    Como consigo o componente MQ-3 para usar no Fritzing? Não encontrei-o na paleta de componentes.
    Valeu!

  6. muito legal, mas e o display oled? nao achei vendendo.

    1. Boa tarde Vinicius,

      Estamos aguardando a chegada do display.

      Abraço.

      Adilson – Equipe FILIPEFLOP

  7. Comprei o display com voces , porem os pinos vcc e gnd estão invertidos, com relaçao ao do exemplo no video, e está ocorrendo de nao aparecer nada no display, estou usando o arduino mega . Ajudas urgente por favor.

  8. Olá, obrigado pelo tutorial,
    como modifico o código pra fazer funcionar com um display OLED 1,3″?
    Obrigado

  9. Bacana, voce saberia como fazer pra mostrar fazer isso com o display 16×2

  10. Poderia explicar o que cada uma dessas linhas estão fazendo, não está muito claro. Grato
    void setup(void)
    {
    Serial.begin(9600);
    pinMode(A1, INPUT);
    if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255); // white
    }
    else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3); // max intensity
    }
    else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1); // pixel on
    }
    else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255, 255, 255);
    }
    }

    Luis Paulo Gomes da Cunha
  11. Estou iniciando no arduino, e apenas copiei e colei o programa, e esta aparecendo que a linha que determina o tipo de display ( adquirido com voces) U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);does not match.
    Poderia me ajudar?

    1. Pode deixar amigo, ja achei um erro que cometi com a biblioteca. Valeu.

      1. qual erro o meu ta aparecendo isso:

        C:UsersDocumentsArduinolibrariesU8glibutilityu8g_rot.c:48:1: warning: initialization from incompatible pointer type [enabled by default]

        u8g_dev_t u8g_dev_rot = { u8g_dev_rot_dummy_fn, NULL, NULL };

        ^

        C:UsersDocumentsArduinolibrariesU8glibutilityu8g_rot.c:48:1: warning: (near initialization for ‘u8g_dev_rot.dev_fn’) [enabled by default]

        O sketch usa 24.090 bytes (9%) de espaço de armazenamento para programas. O máximo são 253.952 bytes.
        Variáveis globais usam 551 bytes (6%) de memória dinâmica, deixando 7.641 bytes para variáveis locais. O máximo são 8.192 bytes.

      2. Caro amigo parabéns pelo blog preciso de uma ajuda tenho que fazer um projeto identico a este, mas não estou conseguindo falta alguma coisa pode me ajudar?
        estou com arduino mega 2560
        display OLED 0.96″12C Azul Amarelo
        sensor MQ-3 alcool

        me ajude!!!

        copiei e colei sua programação e quando faço upload aparece a seguinte mensagem:

        C:UsersDocumentsArduinolibrariesU8glibutilityu8g_rot.c:48:1: warning: initialization from incompatible pointer type [enabled by default]

        u8g_dev_t u8g_dev_rot = { u8g_dev_rot_dummy_fn, NULL, NULL };

        ^

        C:UsersDocumentsArduinolibrariesU8glibutilityu8g_rot.c:48:1: warning: (near initialization for ‘u8g_dev_rot.dev_fn’) [enabled by default]

        O sketch usa 24.090 bytes (9%) de espaço de armazenamento para programas. O máximo são 253.952 bytes.
        Variáveis globais usam 551 bytes (6%) de memória dinâmica, deixando 7.641 bytes para variáveis locais. O máximo são 8.192 bytes.

        daí não roda nada, o arduino acende os leds de alimentação e mais nada

    2. Qual era o erro amigo? estou com o mesmo problema..

      1. Ja resolvi alterando a inicializacao do display. para U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);

        1. Fiz a alteração (U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
          e continua com erro, poderia me ajudar?
          Se possível enviar e-mail para giovani-meirelles@hotmail.com

    3. O meu tbm esta dando esse erro. Vc pode me ajudar?

      1. Está faltando importar a biblioteca da maneira correta.

  12. Como deixar o medidor já marcando zero, e fixar o número mais alto depois de assoprar?

    1. Boa tarde Neudivan,

      O sensor de álcool precisa de pelo menos 15 minutos de “aquecimento”, e o número que ele mostra depois desse tempo costuma variar um pouco, mas nada impede que você espere esses 15 minutos e depois zere a variável para ficar do jeito que você precisa.

      Abraço!

      Adilson – Equipe FILIPEFLOP

      1. Boa tarde,

        Não consegui reproduzir o erro aqui. Usei um Arduino Mega + Oled + IDE versão 1.6.8, rodando o exemplo do post. Funcionou normalmente.

        Sua biblioteca está completa ?

        Abraço!

        Adilson – Equipe FILIPEFLOP

      2. conseguiu zerar ele

    2. Você pode procurar por eeprom eh uma memoria do arduino. Assim o valor fica na eeprom e não eh removido ate que a eeprom seja limpa (isso so eh possível por código)

  13. Poderiam me informar qual a relação de Volts para mg/L desse sensor?

    1. Também quero saber a relação mG/l versus mV.

    2. Boa, também tenho esta dúvida, se puder ajudar.
      Gostaria desta informação para verificar a calibração do mesmo.

  14. Bom Dia,
    Gostaria de que me enviasse um orçamento total do projeto de Bafômetro com Arduíno, incluindo o nome dos materiais necessários.
    ATT
    Giovanna

    GIOVANNA DE ALMEIDA SOUSA
    1. Bom dia Giovanna,

      Você pode adquirir todos os materiais na nossa loja: http://www.filipeflop.com

      – Placa Uno
      – Jumpers macho-macho
      – Protoboard 400 pontos
      – Sensor de álcool MQ-3
      – Display Oled Azul/Amarelo

      Abraço!

      Adilson – Equipe FILIPEFLOP

  15. o que acontece caso pouco ar seja expelido? tem como colocar algum tipo de aviso ou algo do tipo??

  16. Implementei o projeto de vocês para a matéria de transdutores com a professora Daniela Suziki da UFSC!
    Sou graduando de engenharia eletrônica e agradeço pelos posts precisos e úteis do blog.
    Vídeo do projeto: https://www.youtube.com/watch?v=oTZowT13zJQ&t=4s

    1. Bom dia Vitor,

      Nós que agradecemos! 🙂

      Abraço.

      Adilson – Equipe FILIPEFLOP

  17. gostaria de saber com inserir a biblioteca U8GLIB no programa sou relativamente novo e não sei como se faz

  18. boa tarde
    Teria com estabilizar para zero?
    E colocar uma porta como saída analógica no Arduíno quando o valor for mair que zero 5vcc?
    pode me ajudar

  19. Existe algum sensor com uma precisão maior que esse? Se sim, onde comprar?

  20. Primeiramente gostei muito desse experimento e gostaria de parabenizar todos da equipe FILIPEFLOP!!
    estou com um problema e espero que vocês me ajudassem o meu display não esta ligando a programação esta certa só que o display não esta funcionando o que ha de errado?

  21. Olá ,
    Primeiramente parabéns pelo blog.
    O sensor que estou usando é um MQ-3 da Flying Fish, e o mesmo possui um trimpot na parte de traseira… Gostaria de saber como a regulagem desse resistor ajustável interfere na leitura da concentração.
    Desde já agradeço,
    ATT. Lucas

  22. Boa tarde.
    Gostaria de saber qual é a variação do sinal analógico, se de 0V ~ 5V ou menos ?
    Obrigado.

  23. O display não esta funcionando e não aparece mensagem de erro! Qual versão da biblioteca é a correta? Poderiam me enviar por email?

    lucasfreitas.contatos@gmail.com

  24. Boa tarde, comprei os materiais necessários com vcs, e ao implementar tudo, meu display não funcionou… o arduino está ok, o código compila normal, mas não aparece nada no display. Preciso de ajuda.

  25. é possível usar um oled SSD1306 de 7 pinos no lugar do de 4 pinos?
    Grato!

  26. Qual a relação de por parte por milhão, de onde esses valores foram tirados?

    1. Olá Leandro!

      Partes por milhão é uma forma comum de expressar concentração na química.

      Esses valores foram retirados do datasheet do sensor.

      Abraços!

      André – Equipe FilipeFlop

  27. Boa noite, gostaria de pedir a ajuda para resolver um problema.
    Estou usando o MQ-3, porém não estou conseguindo alcançar o resultado esperado. O que quero é que após o tempo de aquecimento o sensor leia e libere ou não a passagem de corrente para um led, mas sempre o led liga antes dos 5 minutos de aquecimento. Segue o código utilizado abaixo.
    Agradeço de antemão.
    (o led que quero que ligue de acordo a leitura do sensor é o que está conectado ao pino 8)

    int tempo_aquecimento = 300;
    int valor_sensor = 0;
    unsigned long time;
    int status = 1;
    String estado;
    int posicao1;

    void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);
    pinMode(A1, INPUT);
    pinMode(8,OUTPUT);
    pinMode(9,OUTPUT);
    pinMode(7,OUTPUT);
    }

    void loop() {
    // put your main code here, to run repeatedly:
    if (time <= tempo_aquecimento){
    time = map(time, 0, tempo_aquecimento, 0, 30);
    status = 1;
    }
    else
    {
    status = 0;
    }
    if (time = 400){
    digitalWrite(8,LOW);
    }
    else {
    digitalWrite(8,HIGH);

    }

    }

    1. Olá João,

      Você poderia colocar seu problema no nosso fórum? https://www.filipeflop.com/forum/
      Lá o pessoal pode te ajudar mais no seu projeto!

      Abraço!
      Rosana – Equipe FilipeFlop

  28. Olá equipe do FilipeFlop
    Gostaria de confirmar se o tempo de aquecimento do MQ3 é realmente 5 min
    Em outras pesquisas encontrei relatos de que tempo é 15 min, e por isso fiquei na dúvida.
    Desde já grato
    Abraços

    1. Olá Paulo,

      Acredito que 5 minutos seja o suficiente.

      Abraço!
      Rosana – Equipe FilipeFlop

  29. Olá.

    Estou montando um projeto que consiste no bafômetro acionar um relé caso identifique a menssagem “Você não bebeu”. E não acionar um relé caso identifique outra menssagem.

    Poderias me ajudar na programação?

    1. Olá Luan,

      Dê uma olhadinha nesse post: https://www.filipeflop.com/blog/sensor-de-luz-ldr-com-rele/
      Esse post demonstra como acionar um relé usando o sinal de um LDR. Você pode adaptá-lo para usar o sensor de gás.

      Abraço!
      Rosana – Equipe FilipeFlop

  30. a gente conseguiu carregar o codido mas os valores iniciais eles não fica zerado

    1. Olá Wesley,

      Você fez todas as conexões corretamente e aguardou o tempo de aquecimento?
      Qual é o valor inicial que aparece?

      Abraço!
      Rosana – Equipe FilipeFlop

  31. Parabéns pelo projeto muito legal, fiz e funcionou corretamente, gostaria que zerasse após o tempo de aquecimento poderia me ajudar no código para que isso ocorra. após tempo de aquecimento fica em 84

    1. Cabana,

      Nesse trecho do código:
      // Leitura do valor do sensor
      valor_sensor = analogRead(A1);
      time = millis() / 1000;
      u8g.firstPage();

      Adicione antes de tudo: valor_sensor = 0;

      Veja se funciona 🙂

      Abraços!
      Diogo – Equipe FilipeFlop

      1. coloquei mas ainda não funcionou

        eu comentei //analogRead(A1);
        zerou porem também não marca a leitura do sensor so fica zero.

        tentei colocar valor_sensor = analogRead(A1); quando a leitura do sensor for <99 mas tambem não deu

      2. consegui asiim zerar quando o valor for <de 99

        if (valor_sensor <= 99)
        {
        valor_sensor = 0;
        estado = "Voce pode Assoprar…";

        }

        1. Marcio,

          Você queria zerar apenas com menos 99 então?

          Abraços!
          Diogo – Equipe FilipeFlop

  32. outra dúvida, fiz o teste tomando uma cachaça e marcou direitinho ,porém apos 15 minutos depois de comer umas bolachas não mais acusou o álcool.

  33. Poderiam me informar qual a relação de Volts para mg/L desse sensor?

    Eu estou em dúvida porque alguns utilizam ppm outros g/dl, porém no meu projeto preciso o valor de mg/l em teoria olhando o datasheet do MQ-3 ele faz a leitura de mg/l, só não sei como fazer a conversão correta.

    1. David,

      Dê uma olhada nesse link aqui, ele explica como analisar isso: https://www.teachmemicro.com/mq-3-alcohol-sensor/
      Pelo datasheet, você deve calcular usando um resistor de carga para ter essa relação.

      Abraços!
      Diogo – Equipe FilipeFlop

  34. Olá boa noite,

    Poderia me mandar codigo com Display de 7 Segmentos 4 Dígitos Ânodo Comum.

    E com e com 4 led indicação nivel.

Trackbacks and Pingbacks

  1. […] informação do índice UV. Esse display é o mesmo que utilizamos recentemente no nosso projeto de Bafômetro com Arduino. A saída do módulo UV (pino OUT) será ligada ao pino analógico A0 do […]