Sensor de nivel utilizando hcsr04

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Re: Sensor de nivel utilizando hcsr04

Mensagempor ze » 31 Jul 2014 09:28

caro calucio, desconheço o componente mas voce deve ter se equivocado quando teclou 0,3mm, não? se não... bacana este cara. acho que vou comprar 1. sério.
andré, eu particularmente a-d-o-r-e-i aquela fórmula. se puder/quiser, me (nos) informe como chegou ao valor 47. de fato uso algo semelhante mas com potência de 10 o que humanamente é mais fácil pra nós, mas 'microcontroladoramente' nem tanto.
abç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 31 Jul 2014 11:01

Ze, corigindo a precisão e de 0,3cm.

Voce tambem havia me dito para fazer uma tabela. Mas olhando na internet acabei confirmando os meus calculos e agora obtendo resultado com mais precisão

Formula para saber quantos litros cabem em 1cm e 1mm:

V = Pi x r² x h onde:
V= volume em m³
Pi = 3,14
r² = raio ao quadrado
h = altura

Sendo assim com os dados de altura de 60cm e diamtro de 50cm ficou:

V= 3,14 x 0,25(cm)² x 0,01(cm) --------------->>> para saber quantos litros cabem em 1cm
V= 0,00196 x 1000 ------>>> para transformar em m³
V = 1,96 litros / cm ou 0,196litros por mm

Andre peço ate desculpas por ter calculado errado mas qualquer coisa utilizo o valor repassado anteriormente.

Andre tambem tentei a formula repassada anteriormente, mas acho que agora tem alguma coisa errada no codigo nesta parte abaixo :

Código: Selecionar todos

void exibe_distancia(unsigned int16 distancia)//Rotina responsavel por converter em caracter e enviar a distância
   {
   unsigned int16 x;//declara uma váriavel auxiliar
   
   x = distancia / 10000;//Pega a dezena de milhar(Ex: 12345, pega apenas o '1') Inteiro de 12345/10000
   x = x + 48; //Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   
   x = distancia / 1000;//Pega a Dezena e Unidade de Milhar (Ex: 12345, pega '12') Inteiro de 12345/1000
   x = x % 10; //Pega a Unidade de milhar (Ex: 12345, pega apenas '2') resto da divisão 12/10
   x = x + 48; //Converte em caracter ASCII
   caracter_lcd(x); //Envia para o LCD
   
   x = distancia / 100; //Pega dezena, unidade de milhar e a centena (Ex:12345, pega '123') Inteiro de 12345/100
   x = x % 10; //Pega a centena (Ex: 12345, pega apenas '3') o resto da divisão 123/10
   x = x + 48; //Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   
   x = distancia / 10; //Pega dezena e unidade de milhar, centena e desena (Ex: 12345, pega '1234') Inteiro de 12345/10
   x = x % 10; //Pega a dezena (Ex: 12345, pega apenas '4') o resto da divisão 1234/10
   x = x + 48;//Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   
   x = distancia % 10;//Pega a unidade (Ex: 12345, pega apenas '5')  Resto de 12345/10
   x = x + 48;//Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   caracter_lcd('m');
   caracter_lcd('m');//Exibe mm   
   }





Sera que a conversão tambem não teria que ser alterada? Precisaria da ajuda de voces para agora testar com a formula anterior que andre tinha repassado
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 31 Jul 2014 11:20

Os dados da formula acima foram adquiridos do seguinte endereço.

bombeiroswaldo.blogspot.com.br/2012/07/como-calcular-o-volume-de-uma-caixa_08.html

Andre em outros testes que vi aqui pode ser que o jeito de mostra o valor esta errado.
Quantos o tanque estiver zerado ele deve mostrar 0 litros e pelo que vejo e testei vai mostrar o valor total dos litros quando estiver zerado.

Ex:
Balde vazio = 0 litros e não os 110 litros com testei aqui e vi.

Sera que é a formula? 47 >> 8 ?
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor andre_luis » 31 Jul 2014 13:00

carlucio escreveu:Andre em outros testes que vi aqui pode ser que o jeito de mostra o valor esta errado.
Quantos o tanque estiver zerado ele deve mostrar 0 litros e pelo que vejo e testei vai mostrar o valor total dos litros quando estiver zerado.

Ex:
Balde vazio = 0 litros e não os 110 litros com testei aqui e vi.


Nesse caso, voce terá de calibrar a fórmula, pois realmente estamos medindo o tanque vazio, e não cheio.
Para resolver isso, basta você aplicar a fórmula abaixo, mas substituindo o valor K pelo valor lido pelo sensor quando o tanque estiver cheio.
Código: Selecionar todos
exibe_distancia( (  ( K - ler_US() * 47 ) >> 8 ) ) ;




+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 31 Jul 2014 22:56

Andre,

Não entendi a formula, ficaria assim:

Código: Selecionar todos

exibe_distancia( (  ([b]109[/b] - ler_US() * 47 ) >> 8 ) ) ;



La nos defines devera ser declarado vamos dizer " valor limite" utilizando o k :

#define k 109

É isso ?
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor ze » 01 Ago 2014 10:17

ze escreveu:... como chegou ao valor 47. de fato uso algo semelhante mas com potência de 10 o que humanamente é mais fácil pra nós, mas 'microcontroladoramente' nem tanto.
abç

k=0.183
256*k=~47
k=~47/256 --->x*k=(x*47)/256
grato
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Sensor de nivel utilizando hcsr04

Mensagempor andre_luis » 01 Ago 2014 10:35

Faltou o parenteses na subtração, que deve ser feita antes da multiplicação.
Seria como abaixo:

#DEFINE K 109
exibe_distancia( ( ( (K- ler_US() ) * 47 ) >> 8 ) ) ;




+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 01 Ago 2014 16:35

Andre,

Fiz o que voce pediu, antes alterei os dados para ficar da altura da mesa no qual estou utilizando e veja o que acontece





O que esta de errado agora?
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor andre_luis » 02 Ago 2014 08:28

Me parece que o valor de 0,182 que você havia passado anteriormente não representa exatamente a calibração correta. Nesse caso, sugiro então você inserir mais uma constante na fórmula, mas agora não para o ajuste do Zero, mas também para a multiplicação.

O primeiro ajuste será do Kvazio, devendo esse ser feito para o valor mais baixo do tanque.
Depois, deverá ir calibrando Kcheio, devendo esse ser feito para o valor mais alto do tanque.

#DEFINE K_vazio 109
#DEFINE K_cheio 47
exibe_distancia( ( ( (K_vazio - ler_US() ) * K_cheio ) >> 8 ) ) ;

Mais uma vez, recomento você fazer os testes não utilizando a mão, mas algum aparato que seja um pouco mais confiável, ou seja, que possa reproduzir o mesmo resultado para as mesmas medidas, como por exemplo voce colocando objetos fixos abaixo do sensor ( ex.: cadeira alta, cadeira baixa, etc... ), pois a água no reservatório em principio terá um comportamento bastante estável.


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 02 Ago 2014 23:04

Esqueci de dizer e fiz algo errado.
Lembrei q por causa de ter mudado o lugar para fazer testes a altura da mesa (sensor) ate o chão esta dando em torno de 71cm.
Refazendo os calculos ficou assim para testes usando o mesmo diametro:

V = Pi x r² x h
V = 3,14 x 0,25(cm) x 0,71(cm)
V = 3,14 x 0,0625 x 0,71
V = 0,139 x 1000
V = 139 litros

Então :

Código: Selecionar todos
#include <16F877A.h>
#device *=16
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=4000000)

#ZERO_RAM

#define k 139 ----------------------------->>>> constante
#include <LCD_MSS.h>



E na formula:

Código: Selecionar todos

 while(1)//Loop infinito do programa
      {
      linha_1_lcd(10);//Imprime a distância apartir do caracter 10
     
      delay_ms(250); //Garante o tempo minimo para aquisição de nova distancia (O fabricante exige minimo 50ms)
      exibe_distancia((((k-ler_US())*50)>>8));//Chama a rotina que exibe a distancia no LCD, e passa como parametro a distancia lida em ler_US()

O 50 acima é o valor de 0,196 litros / mm que achei dividido pelo 256 conforme sua formula anterior, não sei se esta certo. Esta ?





No caso da formula nova que voce repassou me gerou 2 duvidas:

1º - O valor de k_cheio e podera ir ate quanto? Como o valor apresentado é de 8 bits (não sei porque pois se ler o codigo vera que ler_us foi declarado como variavel de 16bits e no display conforme video acima o valor vai so ate 255lt, não entendi porque)

2º - Na nova formula, todas as outras contas não deveriam ser feitas primeiras e por ultimo subtrair de k ?


o codigo completo esta abaixo :

Código: Selecionar todos

#include <16F877A.h>
#device *=16
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=4000000)

#ZERO_RAM

#define k 139 -------------------------------------------------------------------------->>>>>>>>>>>>>>> a constante
#include <LCD_MSS.h>
/******************************************************************************
*  Ligações do LCD                                                            *
*   D7 -> RD7 (PORTD 7)                                                       *
*   D6 -> RD6 (PORTD 6)                                                       *
*   D5 -> RD5 (PORTD 5)                                                       *
*   D4 -> RD4 (PORTD 4)                                                       *
*   RS -> RD3 (PORTD 3)                                                       *
*   EN -> RD2 (PORTD 2)                                                       *
*   R/W -> Deve ser conectado ao GND                                          *
*   VCC -> Deve ser conectado ao +5V                                          *
*   GND -> Deve ser conectado ao GND                                          *
*   VO -> Deve ser conectado ao potenciômetro/trimpot de ajuste de brilho     *
******************************************************************************/

/******************************************************************************
* Ligações do Sensor HC-SR04                                                  *
*  Trig -> Pino RC0 do PORTC                                                  *
*  Echo -> Pino RC1 do PORTC                                                  *
*  VCC -> Deve ser conectado ao +5V                                           *
*  GND -> Deve ser conectado ao GND                                           *
******************************************************************************/
 
#use fast_io(c)//O Controle de direção (Entrada/Saida) dos pinos será feito no programa
#use fast_io(d)//O Controle de direção (Entrada/Saida) dos pinos será feito no programa

#byte PORTC = 0x07//Endereço do PORTC
#byte PORTD = 0x08//Endereço do PORTD

#bit Trig = PORTC.0 //pino que dispara o ultrasom
#bit Echo = PORTC.1 //pino que lê a resposta


//Declaração de funções
//const float k = 182; // 109 litros (capacidade) / 600mm = 0,182 por isso utilizei 182 /10 = 0,182litros a constante para 1 mm
unsigned int16 ler_US(void); //função que lê e retorna a distância em mm -------------->>>>> declarado com variavel 16bits
void exibe_distancia(unsigned int16);//rotina que converte a distância em caracteres e envia para o LCD

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_2);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   // TODO: USER CODE!!
   
   //Os Pinos RD2 a RD7 são usados pelo LCD, os pinos RD0 e RD1 estão livre para uso
   set_tris_d(0b00000000);//Configurando todos os pinos como saída
   //Os pinos Trig e Echo estão conectados no PORTC, Trig -> RC0 e Echo -> RC1
   set_tris_c(0b00000010);//Pino RC1 como entrada e o restante como saída
   
   PORTC = 0;//Inicia com todos os pinos que forem saída em zero
   PORTD = 0;//Inicia com todos os pinos que forem saída em zero
 
   configura_lcd();//Chama a rotina que faz as configurações básica para o LCD funcionar
   inicio_lcd();//Coloca o cursor no inicio
   limpa_lcd();//Limpra o LCD
   
   linha_1_lcd(3);//Começa a escrever apartir do caracter 4 na primeira linha
   caracter_lcd('N');
   caracter_lcd('I');
   caracter_lcd('V');
   caracter_lcd('E');
   caracter_lcd('L');
   caracter_lcd(':');
   caracter_lcd(' ');
 
   while(1)//Loop infinito do programa
      {
      linha_1_lcd(10);//Imprime a distância apartir do caracter 10
     
      delay_ms(250); //Garante o tempo minimo para aquisição de nova distancia (O fabricante exige minimo 50ms)
      exibe_distancia((((k-ler_US())*50)>>8));//Chama a rotina que exibe a distancia no LCD, e passa como parametro a distancia lida em ler_US()
      }

}

unsigned int16 ler_US(void)//Esta rotina realiza a leitura da distancia e a retorna em mm
   {
   unsigned int16 vl_timer = 0;//Variavel para armazenar o tempo
   unsigned int16 distancia = 0;//Armazena a distancia convertida
   Trig = 1;//Dispara o Ultrasom
   delay_us(20);//Aguarda um tempo (minimo de 10us)
   Trig = 0;//Volta para 0 (zero)
   
   while(!Echo){}//Aguarda começar a enviar a resposta
   
   set_timer1(0);//Reinicia o TIMER1
         
   while(Echo){}//Fica parado até receber a resposta
   
   vl_timer = get_timer1();//Le o tempo em que ficou recebendo a resposta (Tempo de instrução / 2 em uS)

   distancia = (((((vl_timer * 2) * 10) / 58) + 10));//Como o divisor do TIMER1 estar 1:2, multiplicamos por 10, passo para mm (x 10) e converto ( / 58)
   return distancia;//A função retorna o valor convertido em mm
   }

void exibe_distancia(unsigned int16 distancia)//Rotina responsavel por converter em caracter e enviar a distância
   {
   unsigned int16 x;//declara uma váriavel auxiliar
   
   x = distancia / 10000;//Pega a dezena de milhar(Ex: 12345, pega apenas o '1') Inteiro de 12345/10000
   x = x + 48; //Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   
   x = distancia / 1000;//Pega a Dezena e Unidade de Milhar (Ex: 12345, pega '12') Inteiro de 12345/1000
   x = x % 10; //Pega a Unidade de milhar (Ex: 12345, pega apenas '2') resto da divisão 12/10
   x = x + 48; //Converte em caracter ASCII
   caracter_lcd(x); //Envia para o LCD
   
   x = distancia / 100; //Pega dezena, unidade de milhar e a centena (Ex:12345, pega '123') Inteiro de 12345/100
   x = x % 10; //Pega a centena (Ex: 12345, pega apenas '3') o resto da divisão 123/10
   x = x + 48; //Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   
   x = distancia / 10; //Pega dezena e unidade de milhar, centena e desena (Ex: 12345, pega '1234') Inteiro de 12345/10
   x = x % 10; //Pega a dezena (Ex: 12345, pega apenas '4') o resto da divisão 1234/10
   x = x + 48;//Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   
   x = distancia % 10;//Pega a unidade (Ex: 12345, pega apenas '5')  Resto de 12345/10
   x = x + 48;//Converte em caracter ASCII
   caracter_lcd(x);//Envia para o LCD
   caracter_lcd('l');
   caracter_lcd('t');//Exibe mm   
   }




No aguardo de uma orientação.
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor andre_luis » 02 Ago 2014 23:28

Não há problema algum em mudar o K de lugar e o tirar de dentro da formula, mas o procedimento de calibração continua sendo o mesmo: Primeiro ajustar o Zero e depois ajustar o Maximo.

Quanto á refazer a fórmula com 16 bits não tem problema, tendo apenas que substituir o >>8 por >>16.



+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 03 Ago 2014 00:03

Essa escala agora e a minha dor de cabeça.

com k_cheio em 113 e k_vazio em 139 consegui que meu minimo (caixa vazia) ficasse em 001 lt e não consegui zerar no k_cheio se altero para 114 ultrapassa o zero ficando em 6lt aprox. se coloco abaixo disso estoura e vai para 255 para tras. O estranho e que o range esta oscilando de 0 a 139 em um espaço de 20 cm ou menos.(Quando deveria oscilar no espaço de 71 cm).

Qualquer alteração que faço em K_vazio acima de 139 altera o valor minimo de K_cheio que deveria ser 0, mais vai subindo conforme aumento o valor de k_vazio e range fica sempre proximo a esse 20cm.

Onde esta o erro que eu não entendi o que tenho que fazer?
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor andre_luis » 03 Ago 2014 00:41

Ao menos, em se tratando de caixa dágua, em operação normal ela não atinge o topo, pois existe o dreno do "ladrão", para evitar que transborde. Também, para o fundo, não deve alcançar, pois a saída deve estar sempre um pouco acima do fundo, para evitar que a sugeira decantada entre na tubulação. Com essas premissas ( e considerando que sua caixa atende á essas regras ) você pode evitar a calibração das 2 constantes proximo dessas zonas limite.

Ou seja, se não conseguimos uma solução, mudamos o problema.
Pode não ser a resposta que voce queria, mas espero que sirva de consolo... :mrgreen:


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Sensor de nivel utilizando hcsr04

Mensagempor carlucio » 03 Ago 2014 14:29

Infelizmente, nem de consolo serve pois a medida desta maneira que esta não atende.
Cada centimetro da maneira correta deveria equivaler a aproximadamente 1,96l (para 71cm) mas da maneira que esta cada centimetro esta na ordem de mais de quase 10litros ou seja não vai funcionar assim.

Vejo que o caminho é esse ou perto desse. Talves na formula devera se achar novamente um detalhe. Se não me engano no codigo original o valor de ler_us retorna o valor em mm sera que não deveria transformar a mesma em litros primeiro para depois calcular o restante da formula ?
carlucio
Byte
 
Mensagens: 118
Registrado em: 05 Jan 2014 15:07

Re: Sensor de nivel utilizando hcsr04

Mensagempor andre_luis » 03 Ago 2014 14:37

Se a medida tem de ser precisa, considero que o sensor de ultrassom não seja uma boa escolha, pois na verdade estamos medindo o volume vazio, e não cheio.
Não poderia contornar esse problema trabalhando com uma escala menos precisa ? Tipo conceito de bargraf, como o abaixo:

PrimeLED LED Bargraphs




+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

AnteriorPróximo

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x