L06 Medidor de nível para botijão de gás

Dispositivo para medir o nível de botijões de gás, ele mede de 30 a 1000mm, este tópico e a continuação do Medidor de consumo de gás para aba energia

Download dos arquivos.

Video explicativo:

4 curtidas

Valeu amigo. Só o download dos arquivos vc precisa autorizar lá, obrigado.

@kelvinrafaeli liberei, tente ai por favor.
Havia me esquecido de liberar o acesso para todos com o link.

1 curtida

muito bacana , mas não consegui fazer funcionar so fica como indisponivel

Nível botijão de gás Indisponível
Temperatura Indisponível
pode ajudar ?

@cfernandes

O “ângulo” e “força do ultrassom” também estão indisponíveis? O “sensor status” está definido como “Problema”? Se estiverem significa que o ESP não está conseguindo se comunicar com o L06.

Seu L06 é UART mesmo? Se for I2C ou RS485 não irá funcionar, pois o código não foi feito para esses protocolos de comunicação.

Se ele de fato for UART confira as conexões, RX e TX podem estar invertidos:
image

L06     ESP
RX   >  TX
TX   >  RX

Você pode conectar o ESP no USB do seu computador, abrir o platform IO e ir na barra lateral platform IO > Monitor, irá abrir o monitor serial (pode usar qualquer outro que você tenha familiaridade, PutTTY, Arduino, etc.) o ESP enviará via Serial tudo que está acontecendo, daí você saberá o problema, seria uma outra tentativa.

Quando testar responda se conseguiu, por favor, caso haja algum bug no código eu altero ele.

sim fica tudo indisponivel chequei novamente e o meu é o l062mtw (uart controlled).

vou tentar outro esp para ver se não e problema na porta serial do ESP32. e lhe informo

Se for possível conecte o ESP na porta USB e monitore ele via serial (usando qualquer monitor serial) e veja o que ele envia, daí será possível saber onde está o problema.

coloquei alguns debugs a mais no seu codigo
para ver o que acontece e tenho o seguinte no terminal
coloquei na funcao start_reading para imprimir o que esta chegando. e tenho isto que fica se repetindo . e pelo que estou entendendo ele nunca entra na função reading_complete()

Iniciando leitura botijao principal.
Sensor botijao principal nao responde.

Iniciando leitura botijao principal.
255
255
253
0
249
0
0
6
211
205
Sensor botijao principal nao responde.

[edit]
Os dados que você postou é o pacote que o L06 envia. Talvez o tempo de timeout está baixo, apesar de que eu em nenhum momento tive esse problema, usando dois L06. Estranho, tente aumentar o l06_timeout no arquivo definições de 900 para 10000, veja se dá certo. Onde você adicionou o serial.println no código poste o trecho por favor, seu L06 está respondendo sim, posye o trecho onde adicionou o debug.

[edit]

Interessante, você já começou a entender o código!

A função start_reading somente limpa o buffer de entrada serial e manda o caractere “@” (pode ser qualquer um) para o L06 com isso ele entende a solicitação de início de leitura e começa a ler o nível do botijão, a função start_reading não gera dado algum.

start_reading
  void start_reading() {
    while(stream.available() > 0)
      dummy = stream.read();

    stream.print("@");
  }

Após isso o ESP espera um tempo (de acordo com a constante l06_timeout(900mS)).

e pelo que estou entendendo ele nunca entra na função reading_complete()

De fato repare que o código chama a função reading_complete ele não entra nela:

if(l06.reading_complete()) {

Caso haja l06_frame_size(10) bytes no buffer serial quer dizer que o ESP recebeu os dados do L06, então essa função retornará True, caso contrário quer dizer que o L06 não enviou os dados então a função retornará False então o ESP entende que o L06 não está se comunicando por isso as variáveis ficam Indisponíveis.

l06.reading_complete()
bool reading_complete() {
    if(stream.available() >= l06_frame_size) {

      readBytes(dadosRecebidos, l06_frame_size);

      frameHeader = dadosRecebidos[l06_frame_header];

      liquidLevel = (unsigned int)dadosRecebidos[l06_data_h]<<8;
      liquidLevel |= dadosRecebidos[l06_data_l];

      temperature = (unsigned int)dadosRecebidos[l06_temp_h]<<8;
      temperature |= dadosRecebidos[l06_temp_l];

      signalStrength = (unsigned int)dadosRecebidos[l06_rssi_h]<<8;
      signalStrength |= dadosRecebidos[l06_rssi_l];

      horizontalInclination = (unsigned int)dadosRecebidos[l06_angle_h]<<8;
      horizontalInclination |= dadosRecebidos[l06_angle_l];

      receivedSum = dadosRecebidos[l06_sum];

      calculatedSum = 0;
      for(aux=0; aux<9; aux++) {
        calculatedSum += (unsigned int)dadosRecebidos[aux];
      }
      calculatedSum &= 0x00FF;    

      return true;  
    }
    else
      return false;;
  }

Considerando que as ligações estão corretas e que o L06 é UART existe a possibilidade de ele estar defeituoso.

Para matar todas as dúvidas crie um código do zero, configure a serial 2 para para 115200, envie qualquer caractere para o L06 aguarde 1 segundo então imprima todos os valores recebidos no monitor, se nada for impresso confirmaremos que seu L06 não está se comunicando.

Exemplo
Serial2.print("@"); // Inicia a leitura
delay(1000); // espera um segundo
if(Serial2.available() > 0) { // verifica se ha dados recebidos na serial2
  while(Serial2.available() > 0)
    Serial.println(Serial2.read()); // Se houver imprimi todos os dados (10 bytes no toal)
}
else
  Serial.println("Nenhum dado recebido"); // se nao houver informa na Serial

A comunicação com o L06 UART é basicamente isso, o resto é só tratamento dos dados, imagem abaixo é do manual do L06:
image

bacana ,
fiz o seguinte codigo

if(l06.reading_complete()) {

  #ifdef DEBUG
    Serial.println("");
    Serial.println("Botijao principal:");
    Serial.print("Frame header: "); Serial.println(l06.frameHeader, HEX);
    Serial.print("Nivel do liquido: "); Serial.print(l06.liquidLevel); Serial.println("mm");
    Serial.print("Temperatura: "); Serial.print((float)l06.temperature/10); Serial.println("gC");
    Serial.print("Forca do ultrassom: "); Serial.print(l06.signalStrength); Serial.println("mV");
    Serial.print("Inclinacao horizontal: "); Serial.print((float)l06.horizontalInclination/10); Serial.println(" graus");
    Serial.print("Soma recebida: "); Serial.println(l06.receivedSum);
    Serial.print("Soma calculada: "); Serial.println(l06.calculatedSum);
  #endif

e tive a seguinte resposta

Botijao principal:
Frame header: FF
Nivel do liquido: 65533mm
Temperatura: 20.00gC
Forca do ultrassom: 0mV
Inclinacao horizontal: 6.70 graus
Soma recebida: 6
Soma calculada: 6
###############################################

Botijao principal:
Frame header: FF
Nivel do liquido: 65533mm
Temperatura: 20.00gC
Forca do ultrassom: 0mV
Inclinacao horizontal: 7.00 graus
Soma recebida: 9
Soma calculada: 9
###############################################

Botijao principal:
Frame header: FF
Nivel do liquido: 65533mm
Temperatura: 20.00gC
Forca do ultrassom: 0mV
Inclinacao horizontal: 6.80 graus
Soma recebida: 7
Soma calculada: 7

então acho que o problema esta aqui

if((bottijao.leituraEmAndamento) && (millis()-bottijao.tempoSolicitaoInicioLeitura > l06_timeout)) {

Ué mas então você não alterou nada, o debug já está dentro do if olha o código original como esta, poste seu arquivo funcoes.c completo para eu entender onde você colocou seu debug, na verdade poste todos os documentos em que você fez alguma alteração, não estou em casa e não conseguirei compilar mas preciso entender onde você adicionou o código para entender o que esta acontecendo.

Codigo Original
if((bottijao.leituraEmAndamento) && (millis()-bottijao.tempoSolicitaoInicioLeitura > l06_timeout)) {
    if(l06.reading_complete()) {
      
      #ifdef DEBUG
        Serial.println("");
        Serial.println("Botijao principal:");
        Serial.print("Frame header: "); Serial.println(l06.frameHeader, HEX);
        Serial.print("Nivel do liquido: "); Serial.print(l06.liquidLevel); Serial.println("mm");
        Serial.print("Temperatura: "); Serial.print((float)l06.temperature/10); Serial.println("gC");
        Serial.print("Forca do ultrassom: "); Serial.print(l06.signalStrength); Serial.println("mV");
        Serial.print("Inclinacao horizontal: "); Serial.print((float)l06.horizontalInclination/10); Serial.println(" graus");
        Serial.print("Soma recebida: "); Serial.println(l06.receivedSum);
        Serial.print("Soma calculada: "); Serial.println(l06.calculatedSum);
      #endif

      if((byte)l06.calculatedSum == l06.receivedSum) {
        #ifdef DEBUG
          Serial.println("Frame Ok.");
        #endif
        bottijao.leituraEmAndamento = false;

        // Status
        strcpy(myMQTT.topic, "diy/binary_sensor/L06_gas_level/status_nivel_gas/state");
        strcpy(myMQTT.payload, "OFF");
        homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);

        // Temperatura
        strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/temperatura_sensor/state");
        bottijao.temperatura = (float)l06.temperature/10;
        sprintf(myMQTT.payload, "%.2f", bottijao.temperatura);
        homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);

        // Angulo
        strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/angulo_sensor/state");
        bottijao.angulo = (float)l06.horizontalInclination/10;
        sprintf(myMQTT.payload, "%.2f", bottijao.angulo);
        homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);

        // Nivel
        strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/nivel_gas/state");
        sprintf(myMQTT.payload, "%u", l06.liquidLevel);      
        homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);  
        
        // Forca do ultrassom
        strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/RSSI_sensor/state");
        sprintf(myMQTT.payload, "%u", l06.signalStrength);      
        homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);
      }
      else {
        #ifdef DEBUG
          Serial.println("Frame corrompido, realizando nova leitura botijao principal.");
        #endif
        l06.start_reading();
        bottijao.leituraEmAndamento = true;
        bottijao.tempoSolicitaoInicioLeitura = millis();
        bottijao.tempoProximaAtualizacao = millis() + tempoAtualizacaoNivelBotijoes;

        strcpy(myMQTT.topic, "diy/binary_sensor/L06_gas_level/status_nivel_gas/state");
        strcpy(myMQTT.payload, "OFF");      
        homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);
      }
      #ifdef DEBUG
        Serial.println("");
      #endif
    }
    else { // Sensor nao respondeu enviar problema ao home assistant
      #ifdef DEBUG
        Serial.println("Sensor botijao principal nao responde.");
        Serial.println("");
      #endif

      strcpy(myMQTT.topic, "diy/binary_sensor/L06_gas_level/status_nivel_gas/state");
      strcpy(myMQTT.payload, "ON");      
      homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);  

      bottijao.leituraEmAndamento = false;
    }

Essa função l06.reading_complete() só é verdadeira se o L06 enviou os 10 bytes do pacote em menos de 900mS, há alguma coisa que não estou conseguindo entender, somente encontrei uma coisa as duas virgulas no código abaixo:

else
  return false;;

Deixe somente uma

else
  return false;

então modifiquei completamente o seu codigo
coloque a função nivelBotijao desta forma porque nunca entra neste
“if((bottijao.leituraEmAndamento) && (millis()-bottijao.tempoSolicitaoInicioLeitura > l06_timeout)) {”

void nivelBotijao() {
if (millis() >= bottijao.tempoProximaAtualizacao) {
bottijao.leituraEmAndamento = true;
bottijao.tempoSolicitaoInicioLeitura = millis();
bottijao.tempoProximaAtualizacao = millis() + tempoAtualizacaoNivelBotijoes;
Serial2.print(“@”);
delay(1);
if (Serial2.available()){
if(Serial2.available() >= l06_frame_size) {
if(l06.reading_complete()) {
#ifdef DEBUG
Serial.println(“Iniciando leitura botijao principal.”);
Serial.println(“”);
Serial.println(“Botijao principal:”);
Serial.print("Frame header: "); Serial.println(l06.frameHeader, HEX);
Serial.print("Nivel do liquido: "); Serial.print(l06.liquidLevel); Serial.println(“mm”);
Serial.print("Temperatura: "); Serial.print((float)l06.temperature/10); Serial.println(“gC”);
Serial.print("Forca do ultrassom: "); Serial.print(l06.signalStrength); Serial.println(“mV”);
Serial.print(“Inclinacao horizontal: “); Serial.print((float)l06.horizontalInclination/10); Serial.println(” graus”);
Serial.print("Soma recebida: "); Serial.println(l06.receivedSum);
Serial.print("Soma calculada: "); Serial.println(l06.calculatedSum);
#endif
if((byte)l06.calculatedSum == l06.receivedSum) {
#ifdef DEBUG
Serial.println(“Frame Ok.”);
#endif
bottijao.leituraEmAndamento = false;

          // Status
          strcpy(myMQTT.topic, "diy/binary_sensor/L06_gas_level/status_nivel_gas/state");
          strcpy(myMQTT.payload, "OFF");
          homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);

          // Temperatura
          strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/temperatura_sensor/state");
          bottijao.temperatura = (float)l06.temperature/10;
          sprintf(myMQTT.payload, "%.2f", bottijao.temperatura);
          homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);

          // Angulo
          strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/angulo_sensor/state");
          bottijao.angulo = (float)l06.horizontalInclination/10;
          sprintf(myMQTT.payload, "%.2f", bottijao.angulo);
          homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);

          // Nivel
          strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/nivel_gas/state");
          sprintf(myMQTT.payload, "%u", l06.liquidLevel);      
          homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);  
          
          // Forca do ultrassom
          strcpy(myMQTT.topic, "diy/sensor/L06_gas_level/RSSI_sensor/state");
          sprintf(myMQTT.payload, "%u", l06.signalStrength);      
          homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);   
        }
      } 
    }else{
            #ifdef DEBUG
            Serial.println("Sensor botijao principal nao responde.");
            Serial.println("");
          #endif

          strcpy(myMQTT.topic, "diy/binary_sensor/L06_gas_level/status_nivel_gas/state");
          strcpy(myMQTT.payload, "ON");      
          homeAssistantMQTT.publish(myMQTT.topic, myMQTT.payload, true);  

          bottijao.leituraEmAndamento = false;

    
    }
  }
    
  }
}

Então funcionou para você né? Show de bola… Não realizarei alterações no código pois os problemas relatados por você não ocorreu durante os meus testes (utilizando dois L06) vou deixar mais pessoas montarem o projeto para que eu tenha mais amostras e então modificarei o código disponibilizado de acordo…

Só uma coisa, o código é todo interligado, alterar onde uma função é executa pode gerar bugs em outros pontos.

Do jeito que você alterou o ESP irá enviar os dados para o home assistant mesma sem estar conectado a ele, dependendo isso pode fazer com que o ESP fique travado por cerca de 20 segundos (percebi durante alguns teste), repare a quantidade de delays que o código possui…

vou fazer mais testes aqui e tentar verificar o que pode estar acontecendo e tambem pretento colocar um sensor de fazemento de gas . vamos testando

Blza assim que chegar em casa vou recompilar gravar e tentar reproduzir o erro que aconteceu com você.