Como fazer um Bafômetro com Arduino 75

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: MakerHero

#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.

Faça seu comentário

Acesse sua conta e participe

75 Comentários

  1. Olá eu sou novato ainda na parte do arduino e nos comandos na linha 18 fala “Comandos graficos para o display devem ser colocados aqui” onde eu posso encontrar esses comandos e de que forma é que se aplica isso nos comandos?

    1. Olá.

      No caso essa frase comentada apenas indica que abaixo dessa linha tem as indicações no gráfico, que seriam o “bafometro” e “Aguarde”, além da animação da caneca.

      É opcional que seja alterado as indicações de gráfico no display. Ou seja, já está funcional a forma como está o código.

      Att.
      Vitor Mattos.
      Suporte Técnico MakerHero.

  2. Boa tarde, tudo bem? Achei o projeto bem interessante, mas fiquei com uma dúvida e já va desculpando minha falta de conhecimento. Mas não entendi porque não utiliza nenhum resistor no projeto. Porque ele não foi necessário? Obrigado

    1. Olá.

      Resistores no geral são utilizados em componentes passivos (como um LED por exemplo) para limitar a corrente. É utilizado também para divisão de tensão em determinados sensores.

      Nesse caso, tanto o display quanto o sensor são elementos ativos, então não é necessário utilizar resistor.

      Att.
      Vitor Mattos.
      Suporte Técnico MakerHero.

  3. Boa tarde, baixei a biblioteca u8glib 1.19.1, compilei o programa com ela e passei para o arduino, mas a tela não acende, tudo acende e parece funcionar, menos ela, devo abaixar alguma outra biblioteca ou só assim já devia funcionar?

    Obs: no meu Display está escrito SCK ao invés de SCL

    1. Olá.

      Pode ser algum detalhe na ligação elétrica do seu display.

      Antes de executar esse projeto, tente usar outro exemplo da própria biblioteca do display para apenas mostrar alguma informação na tela.

      Att.

      Vitor Mattos.
      Suporte Técnico MakerHero.

  4. Boa tarde, poderia me informar por onde montou o demonstrativo? Tentei fazer no Tinkercad, mas não encontro os sensores necessários.

    1. Olá,

      Foi feito no Fritzing.

      Abraços!
      Vinícius – Equipe MakerHero

  5. É possível identificar se a pessoa não bebeu nada (resultado = 0) ou se ela simplesmente não assoprou o bafômetro (resultado =0). ???

  6. 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.

  7. 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 MakerHero

  8. 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.

  9. 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 MakerHero

      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 MakerHero

  10. 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 MakerHero

  11. 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.makerhero.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 MakerHero

  12. Olá equipe do MakerHero
    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 MakerHero

  13. 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);

    }

    }

  14. 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 MakerHero

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

  16. 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.

  17. 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?

    [email protected]

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

  19. 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

  20. Primeiramente gostei muito desse experimento e gostaria de parabenizar todos da equipe MakerHero!!
    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. Existe algum sensor com uma precisão maior que esse? Se sim, onde comprar?

  22. 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

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

  24. 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 MakerHero

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

  26. 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

    1. Bom dia Giovanna,

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

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

      Abraço!

      Adilson – Equipe MakerHero

  27. 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.

  28. 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 MakerHero

      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 MakerHero

    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)

  29. 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 [email protected]

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

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

  30. 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);
    }
    }

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

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

  33. 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.

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

    1. Boa tarde Vinicius,

      Estamos aguardando a chegada do display.

      Abraço.

      Adilson – Equipe MakerHero

  35. Olá,

    Parabéns pelo blog.

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

  36. 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 MakerHero

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

  38. 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 MakerHero

  39. 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 MakerHero

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 […]