Ir ao conteúdo
  • Cadastre-se

Projetos com Avr : Design, Programação em Basic e Assembly


Ir à solução Resolvido por aphawk,

Posts recomendados

  • 5 meses depois...

         ANALISADOR DE ESPECTRO REAL COM 10 BANDAS

 

Segue um projeto completo de um analisador de espectro de áudio de baixo custo com 10 bandas, usando os MSGEQ7, e que segue as frequências originais de utilização de um analisador de espectro clássico. Para uma visualização bem legal, utilizei dois módulos  de matriz de Leds com o ci MAX7219.

 

Estes módulos são bem baratos e voce encontra no Mercado Livre.

 

Essa maneira de usar vários MSGEQ7 com diferentes sintonias foi uma ideia que tive a partir do datasheet dele, e deu certo na bancada. Com isso, em vez de ficar preso às 7 originais , que não seguem o padrão para um analisador de espectro real, eu uso vários deles, e com isso consigo pegar as 10 frequências utilizadas na prática.

 

Como padrão em meu tutorial, o programa fonte está escrito em Basic do Bascom, e como microprocessador utilizei um Arduíno Uno.

A saída é visualizada em duas matrizes de LED 8x8 tipo catodo comum, colocadas uma ao lado da outra.
O Link para download de todo o projeto segue abaixo :

http://www.4shared.com/rar/AFjTGR8a/ANALISADOR_DE_ESPECTRO_SIMPLES.html

Boa diversão.

Paulo

post-464954-1388496631139_thumb.png

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois...

Fervolt,

Obrigado pelas suas palavras, e bem-vindo ao mundo dos AVR's !

Já ví uma questão sua em outro tópico sobre linguagem C, e sei que você pode começar pelo Basic para se familiarizar com os detalhes do hardware dos AVR.

Embora eu tenha escrito o tutorial baseado em um simples CI, é melhor voce utilizar um Arduíno Uno R3, assim você tem a vantagem de poder utilizar a porta serial para enviar dados entre o seu computador e o Arduíno.

Se tiver alguma dúvida é só postar, ok ?

Paulo

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...
Pessoal,

Comprei um sensor baratinho ( R$ 13,00 ) de umidade do ar e temperatura, que é o DHT-11, chegou ontem, e não tive tempo de incluir o projetinho no tutorial.

Só depois que ele chegou é que ví que embora ele seja do tipo 1-Wire, o protocolo é proprietário, isto é, não segue nenhum padrão !!! Tive de baixar o PDF dele e procurar mais dicas na NET para fazer isso funcionar.....

Só agora conseguí terminar o projetinho, ficou simples e funcional; vou postar aqui o projetinho completo com o programa para quem precisar.

O esquema eletrônico é exatamente o mesmo que eu usei no Tutorial para o Controle de Cooler com 1-Wire, a única diferença é a troca do sensor pelo DHT-11.

Eu encontrei esse programa práticamente pronto na Net, reproduzo aqui , modificando para o meu caso, e acrescentei os comentários para explicar o programa. O site que encontrei foi o AVRproject.ru .

Mais informações sobre o funcionamento do DHT-11 no link abaixo :

http://embedded-lab.com/blog/?p=4333


$regfile = "m48pdef.dat"
$crystal = 8000000


Config Lcd = 16 * 2
Config Lcdpin = Pin , Rs = Portc.0 , E = Portc.1 , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5
Cursor Off
Cls


Declare Sub Get_th(t As Byte , H As Byte)

'vamos ligar o sensor no pino B.0
Dht_put Alias Portb.0 ' aqui usamos como saída
Dht_get Alias Pinb.0 ' e aqui usamos como entrada !
Dht_io_set Alias Ddrb.0 ' aqui mudamos entrada < - > saída

Dim T As Byte 'Temperatura
Dim H As Byte 'Umidade
Dim Crc As Byte 'CRC do medidor
Dim Mybyte As Byte
Dim Sensor_data As String * 40 'buffer para os 5 bytes
Dim Tmp_str8 As String * 8 'string temporária para receber 8 bits
Dim Count As Byte 'contador para os bits recebidos

Enable Interrupts

Set Dht_io_set
Set Dht_put

Lcd "AVRproject.ru"
Lowerline
Lcd "DHT11 sensor"

Do
Waitms 1500
Call Get_th(t , H)
Cls
Lcd "TMP: " ; T ; "C"
Lowerline
Lcd "PHP: " ; H ; "%"

Loop

Sub Get_th(t As Byte , H As Byte)

Count = 0
Sensor_data = ""
Set Dht_io_set 'vira saída
Reset Dht_put 'nivel 0 na saída
Waitms 25 'tempo de espera pro dht11 25mseg

Set Dht_put 'volta nivel 1 na saída
Waitus 40 'espera 40 useg
Reset Dht_io_set 'vira entrada
Waitus 40 'espera mais 40 useg
If Dht_get = 1 Then 'se continua 1 tem algo errado
H = 1 'pois deveria estar em 0 !
Exit Sub
End If


Waitus 80 'espera 80 useg
If Dht_get = 0 Then 'agora tem de estar 1 !
H = 2 'se tiver 0 , deu erro
Exit Sub
End If


While Dht_get = 1 : Wend 'espera iniciar transmissão

Do
While Dht_get = 0 : Wend 'começou a transmissão
Waitus 30 'voltou a nivel 1, espera 30 useg
If Dht_get = 1 Then 'se apos 30 useg continua 1, então o bit é 1
Sensor_data = Sensor_data + "1" 'coloca 1 no buffer de dados
While Dht_get = 1 : Wend 'espera esse bit 1 terminar
Else 'se apos 30 useg virou 0, então o bit é 0
Sensor_data = Sensor_data + "0" 'coloca zero no buffer
End If
Incr Count ' incrementa contador de bits
Loop Until Count = 40 ' repete para 40 bits totais

Set Dht_io_set
Set Dht_put



Tmp_str8 = Left(sensor_data , 8) 'os primeiros 8 bits são a umidade
H = Binval(tmp_str8) 'Vamos transformar para valor numérico

Tmp_str8 = Mid(sensor_data , 17 , 8) 'estes 8 são a temperatura
T = Binval(tmp_str8)

Tmp_str8 = Right(sensor_data , 8) 'os ultimos 8 são o CRC
Crc = Binval(tmp_str8) '


Mybyte = T + H ' o CRC é a soma da umidade + temperatura
If Mybyte <> Crc Then ' considerando 8 bits
H = 3 ' se não bateu, erro !
End If

End Sub 'final da subrotina




Paulo

Tenho um RHT-22 que é um pouco diferente no formato dos dados que o DHT-11, e tive que fazer alguns pequenos ajustes para funcionar, abaixo a rotina num Arduino Mega 1280, espero que isto seja útil:


Sub Get_th_rht22(t_ent As Single , H_ent As Single)

Count = 0
Sensor_data = ""
Set Dht_io_set ' vira saída
Reset Dht_put ' nível 0 na saída
Waitms 25 ' tempo de espera pro dht11 25mseg
Set Dht_put ' volta nivel 1 na saída
Waitus 40 ' espera 40 useg
Reset Dht_io_set ' vira entrada
Waitus 40 ' espera mais 40 useg
If Dht_get = 1 Then ' se continua 1 tem algo errado
H_ent = 1 ' pois deveria estar em 0 !
Exit Sub
End If
'???? ?????? ??????? ? ?????? ???? ? ????? ?????????? ??????
Waitus 80 ' espera 80 useg
If Dht_get = 0 Then ' agora tem de estar 1 !
H_ent = 2 ' se tiver 0 , deu erro
Exit Sub
End If
'???? ??? ????????? ? ?????? ??????? ?????????, ????? ??????????
While Dht_get = 1 : Wend ' espera iniciar transmissão
Do
While Dht_get = 0 : Wend ' começou a transmissão
Waitus 30 ' voltou a nivel 1, espera 30 useg
If Dht_get = 1 Then ' se ápos 30 useg continua 1, então o bit é 1
Sensor_data = Sensor_data + "1" ' coloca 1 no buffer de dados
While Dht_get = 1 : Wend ' espera esse bit 1 terminar
Else ' se apos 30 uSeg virou 0, então o bit é 0
Sensor_data = Sensor_data + "0" ' coloca zero no buffer
End If
Incr Count ' incrementa contador de bits
Loop Until Count = 40 ' repete para 40 bits totais
Set Dht_io_set
Set Dht_put
'???????? ???????????? ?????????? ??????
Tmp_str16 = Left(sensor_data , 16) ' os primeiros 16 bits são a umidade
H_cal = Binval(tmp_str16) ' Vamos transformar para valor numérico
H_ent = H_cal
H_ent = H_ent / 10
Tmp_str16 = Left(sensor_data , 8)
Mybyte = Binval(tmp_str16)
Myword = Mybyte
Tmp_str16 = Mid(sensor_data , 9 , 8)
Mybyte = Binval(tmp_str16)
Myword = Myword + Mybyte

Tmp_str16 = Mid(sensor_data , 18 , 15) ' os próximos 15 são a temperatura sem o sinal.
T_cal = Binval(tmp_str16)
T_ent = T_cal
T_ent = T_ent / 10
Tmp_str16 = Mid(sensor_data , 17 , 8)
Mybyte = Binval(tmp_str16)
Myword = Myword + Mybyte
Tmp_str16 = Mid(sensor_data , 25 , 8)
Mybyte = Binval(tmp_str16)
Myword = Myword + Mybyte
Tmp_str16 = Right(sensor_data , 8) ' os últimos 8 são o CRC
Crc = Binval(tmp_str16) '
Tmp_str16 = Mid(sensor_data , 17 , 1) ' bit de sinal da temperatura
If Tmp_str16 = "1" Then
T_ent = 0 - T_ent
End If
Myword = Myword And &B11111111
Mybyte = Myword ' o CRC é a soma dos bytes da umidade e temperatura
If Mybyte <> Crc Then ' considerando 8 bits menos significativos
H_ent = 3 ' se não bateu, erro !
End If
End Sub ' final da subrotina

'--------------------------------------------------------------------------------------

Depois coloco aqui a minha tentativa (infrutífera) de fazer a leitura de um PT100 (sensor de temperatura) usando um ADS-1115 da Texas, para ver se alguém tem ideia onde foi que eu errei.

Link para o comentário
Compartilhar em outros sites

Intrudera6,

Obrigado pelo código, e bem-vindo ao Fórum !

Mais um desses sensores com padrão esquisito.... Mas agora que você já descobriu como tratar, vai ajudar outros usuários com certeza !

Pode postar o seu código do PT100 pra gente dar uma olhada.

Paulo

Este seu trabalho neste seu tutorial foi fantástico, me inspirou e inspirou muita gente, aprendi muito com este seu tutorial. Agora eu quero ajudar e dar uma pequena contribuição, e aprender um pouco mais também.

Mas para postar o código aqui, filtrei o meu código, para que não fique confuso demais pois no meio dele tem muitas outras coisas, como por exemplo o acesso a um RTC de precisão (DS3231), simulação de um RTC por código e etc, e outras coisas que fiz num Arduino MEGA para aprender a programar em Bascom, o que fez com que tenha muita coisa nele sem muita utilidade como fazer piscar LEDs e outras coisas. Por sinal o código acabou tão grande que acabei comprando o soft Bascom AVR, não aguentei mais me restringir a escrever códigos limitados a 4kb.

O ADS1115, é um ADC de 16bits I2C com 4 entradas AD de 16 bits multiplexadas com taxa máxima de 860 conversões por segundo. Encontrei vários exemplos de programação em C, o que não seria algo tão terrível assim, se o código não fizesse referência a uma biblioteca, o que faz ficar bem mais difícil entender como é que ele faz a comunicação com o controlador. Para ir mais além necessito desenhar (e postar aqui) o circuito que interfaceia com o ADS1115 (resistência de referência, PT100, portas AD usadas do ADC e etc.) para que fique entendível para as outras pessoas. A noite vou ver se consigo postar o desenho do circuito.

Abaixo vai o meu código (podado dos extras que não tem nada a ver com o PT100 ou com o ADS1115).


$regfile = "m1280def.dat" ' specify the used micro
$crystal = 16000000 ' Frequência do Cristal em Hz
$loadersize = &H1000 ' Bootloader de 4096 bytes
'$baud = 19200 ' use baud rate
$baud = 57600 ' use baud rate
$hwstack = 64 ' default use 32 for the hardware stack
$swstack = 128 ' default use 10 for the SW stack
$framesize = 256 ' default use 40 for the frame space
$map ' Informação para Debug
'$lib "stackcheck.lib"



$initmicro

Const Valor_prescale_int3 = 256
Const Interrupcoes_por_segundo_int3 = 10
Const Preload_int3 = 65535 - _xtal \(valor_prescale_int3 * Interrupcoes_por_segundo_int3) + 1

Const Valor_prescale_int4 = 256
Const Interrupcoes_por_segundo_int4 = 100
Const Tempo_aguardando = Interrupcoes_por_segundo_int4 * 2 ' Tempo em segundos
Const Preload_int4 = 65535 - _xtal \(valor_prescale_int4 * Interrupcoes_por_segundo_int4) + 1
Const T_acerta_segundos = 60 * 10 ' intervalo de tempo em segundos para acertar o relógio pelo RTC
Const T_acerta = Interrupcoes_por_segundo_int4 * T_acerta_segundos

'Endereço do ADS1115 (END=>GND), conversor ADC de 16 bits
Const Ads1115w = &B10010000 ' Endereço de escrita do ADC ADS1115
Const Ads1115r = &B10010001 ' Endereço de leitura do ADC ADS1115

Config_i2c:
'configure the scl and sda pins
Config Sda = Portd.1
Config Scl = Portd.0
Config I2cdelay = 2 ' para 500 kHz (aproximadamente)
'Config I2cdelay = 10 ' para 100 kHz
I2cinit

......
......
......


Dim I_pt100 As Double , E_pt100 As Double , R_pt100 As Double , T_pt100 As Double
Dim I_pt100_single As Single , E_pt100_single As Single , R_pt100_single As Single , T_pt100_single As Single
Dim Linha3 As String * 160

......
......
......

Gosub Getadc_pt100
If Err = 0 Then
Linha3 = ""
Else
Linha3 = "erro"
End If

If Linha3 <> "erro" Then
I_pt100_single = I_pt100
E_pt100_single = E_pt100
R_pt100_single = R_pt100
T_pt100_single = T_pt100
Linha3 = "ADS1115 (PT100)=> I = "
Linha3 = Linha3 + Fusing(i_pt100_single , "#.#########")
Linha3 = Linha3 + "A E = "
Linha3 = Linha3 + Fusing(e_pt100_single , "#.#######")
Linha3 = Linha3 + "V R = "
Linha3 = Linha3 + Fusing(r_pt100_single , "#.#####" )
Linha3 = Linha3 + "oHms T ="
Linha3 = Linha3 + Fusing(t_pt100_single , "#.###")
Linha3 = Linha3 + "ºC "
End If

Print Linha2
If Linha3 <> "erro" Then
Print Linha3
End If
If Mostra_com2 > 0 Then
Print #1 , Linha2
If Linha3 <> "erro" Then
Print #1 , Linha3
End If
End If

Pula:
End If


......
......
......


Getadc_i_pt100:
Dim Msbadc As Byte , Lsbadc As Byte
Dim Valoradc As Word At Msbadc Overlay

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B01001010 ' MSB do registrador
' 0 : No effect
' 100 : AINP = AIN0 and AINN = GND
' (================ fora ============ 101 : AINP = AIN1 and AINN = GND =================)
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cwbyte Ads1115r ' Enviando endereço de leitura do ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura do ADC (ADS1115) via i2c
I_pt100 = Valoradc
I_pt100 = I_pt100 * 7.81273842585528e-8 ' * 0.256 / (32767 * 100) => Valor da corrente no PT100 em Amperes
End If
Return


Getadc_pt100:

Gosub Getadc_i_pt100

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita no ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B00111010 ' MSB do registrador
' 0 : No effect
' 011 : AINP = AIN2 and AINN = AIN3
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cwbyte Ads1115r ' Enviando endereço de leitura no ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura ADC (ADS1115) via i2c
E_pt100 = Valoradc
E_pt100 = E_pt100 * 7.81273842585528e-6 ' * 0.256 / 32767 => Valor em Volts
R_pt100 = E_pt100 / I_pt100 ' Valor da resistência no PT100 em Ohms
T_pt100 = 100 - R_pt100
T_pt100 = T_pt100 * 2.32078e-4
T_pt100 = T_pt100 + 0.152726203204
T_pt100 = Sqr(t_pt100)
T_pt100 = 0.390802 - T_pt100
T_pt100 = T_pt100 / 1.16039e-4 ' Valor da temperatura no PT100 em ºC
End If
Return

O resultado foi que obtive overflow (FFFFh) nas duas leituras do ADS1115, independentemente dos valores das variáveis medidas.

Abaixo vai o circuito simplificado:

f4jo.png

No AIN0 eu leio a tensão sobre a minha resistência de referência (100 oHms +/- 0,01% de precisão) em relação ao terra.

No AIN2 e no AIN3 leio o valor sobre o PT100 que eu montei com 4 pernas sendo que 2 para circular corrente (que deve ser por volta de 1 mA), e as outras 2 pernas são para medir a tensão (praticamente sem queda de tensão).

Com estes valores seria só dividir o valor lido da tensão (entrada diferencial AIN2 e AIN3 no ADS1115) pela corrente (AIN0 no ADS1115), que nessa configuração compensa os erros na referência de tensão e na medição da resistência e tensão anulando os desvios, que tendem a se reproduzir nas duas medições (isto se tivesse dado certo e eu conseguisse ler o ADS1115 teria um erro estimado menor que +/- 0,01 °C , acho que conseguiria isso ou melhor se calibrasse o PT100).

Link para o comentário
Compartilhar em outros sites

Pessoal, segue um pequeno tutorial sobre usos do PCF8574 com o Bascom, inclusive transformando displays LCD's comuns em I2C !

 

Possui exemplos de uso, circuitos, arquivos de simulação do Proteus.

 

Um dos exemplos é o uso de dois displays em um simples ATTINY85 de 8 pinos !

 

Segue o link para download :

http://www.4shared.com/rar/HHyJbhj4/tutorial_PCF8574_BASCOM.html

 

Paulo

 

Em tempo :

 

Intrudera6,

Estou olhando o datasheet, percebí algumas coisas por enquanto :

1 - Faça a comunicação a 100 Khz mesmo..... evite usar 500 Khz pois está especificado que sem ser feita nenhuma configuração especial, ele funciona até 400 Khz ! Se quiser aumentar um pouco , use I2CDELAY=6.

2 - Sua rotina Getadc_i_pt100 : antes do WAITMS 2, tem de ter um comando I2CSTOP. O mesmo vale também para Getadc_pt100 .

3 - Quando você quer ler o ADC, você acessa o poiter register,; esta operação também tem de terminar com um I2CSTOP.

4 - E para ler o register de conversão, você tem de iniciar com I2CSTART novamente.

Ou seja, para cada tipo de registro, você tem de começar e terminar ela, antes de partir para um outro tipo de registro.

Creio que o CI não estava sendo inicializado corretamente, e talvez seja isso o motivo das leituras com overflow.

Vou ver mais um pouco o código e se achar algo posto aqui.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Mudei a velocidade do i2c para 100khz (I2CDELAY=10) e coloquei alguns I2cstop e I2cstart conforme o código abaixo, mas os valores estão variando sem sentido agora.


Getadc_i_pt100:
Dim Msbadc As Byte , Lsbadc As Byte
Dim Valoradc As Word At Msbadc Overlay

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B01001010 ' MSB do registrador
' 0 : No effect
' 100 : AINP = AIN0 and AINN = GND
' (================ fora ============ 101 : AINP = AIN1 and AINN = GND =================)
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura do ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura do ADC (ADS1115) via i2c
I_pt100 = Valoradc
I_pt100 = I_pt100 * 7.81273842585528e-8 ' * 0.256 / (32767 * 100) => Valor da corrente no PT100 em Amperes
End If
Return

Getadc_pt100:

Gosub Getadc_i_pt100

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita no ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B00111010 ' MSB do registrador
' 0 : No effect
' 011 : AINP = AIN2 and AINN = AIN3
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura no ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura ADC (ADS1115) via i2c
E_pt100 = Valoradc
E_pt100 = E_pt100 * 7.81273842585528e-6 ' * 0.256 / 32767 => Valor em Volts
R_pt100 = E_pt100 / I_pt100 ' Valor da resistência no PT100 em Ohms
T_pt100 = 100 - R_pt100
T_pt100 = T_pt100 * 2.32078e-4
T_pt100 = T_pt100 + 0.152726203204
T_pt100 = Sqr(t_pt100)
T_pt100 = 0.390802 - T_pt100
T_pt100 = T_pt100 / 1.16039e-4 ' Valor da temperatura no PT100 em ºC
End If
Return

Link para o comentário
Compartilhar em outros sites

Acho que ainda não ficou correto.

Tente separar totalmente as operações em cada registro com o I2CSTOP na rotina GETADC_I_PT100, igual você fez nas rotinas seguintes. Afinal, ela que é responsável pela inicialização do CI.

Aproveita e já faz um teste :

Tira o PT100 , tudo , e coloca um resistor de 100 ohms no lugar do pt100 naquele seu esquema que você postou.

Assim teremos um circuito série com os tres resistores, e tem de dar sempre o mesmo resultado nas leituras.

Veja o que acontece.

Paulo

Link para o comentário
Compartilhar em outros sites

Acho que ainda não ficou correto.

Tente separar totalmente as operações em cada registro com o I2CSTOP na rotina GETADC_I_PT100, igual você fez nas rotinas seguintes. Afinal, ela que é responsável pela inicialização do CI.

Aproveita e já faz um teste :

Tira o PT100 , tudo , e coloca um resistor de 100 ohms no lugar do pt100 naquele seu esquema que você postou.

Assim teremos um circuito série com os tres resistores, e tem de dar sempre o mesmo resultado nas leituras.

Veja o que acontece.

Paulo

Liguei primeiro numa alimentação estável (fonte de 9V) que a placa do Arduino baixou para 5,02V (antes estava pela USB, o que deixa a tensão mais baixa e menos estável), e continuou oscilando (indicando 0,004A e as vezes 0,0006A, o que eu verifiquei com um multímetro Fluke 87 (4 e 1/2 dígitos) na escala de mA e estava em 1,001mA, a tensão no PT100 estava em 112,2mV. Medi a minha resistência de referência e ela estava em exatos 100 oHms. O PT100 estava com 110,19 oHms, o valor encontrado estava variando muito mais .

Troquei o PT100 por uma resistência de 100 oHms, e os resultados não alteraram muita coisa. Continuou lendo lixo.

Antes de postar a 1ª mensagem aqui no fórum eu já tinha tentado trocar o meu ADS1115 por outro por suspeita de problema, depois disso eu passei a achar que o problema é mesmo de programação.

Pelos valores retornados os valores medidos devem estar todos negativos (último bit em 1), o que o meu programa não está preparado para lidar pois não era para ocorrer valores negativos em nenhuma hipótese. Fiz um gatilho na minha rotina para trocar os valores em complemento de 2 de negativo para positivo, e os valores continuaram estranhos.

Coloquei mais Stop e Starts:


Getadc_i_pt100:
Dim Msbadc As Byte , Lsbadc As Byte
Dim Valoradc As Word At Msbadc Overlay

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B01001010 ' MSB do registrador
' 0 : No effect
' 100 : AINP = AIN0 and AINN = GND
' (================ fora ============ 101 : AINP = AIN1 and AINN = GND =================)
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura do ADS1115
' ===================== Inserido ==========================
I2cstop
I2cstart
' ===================== Inserido ==========================
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura do ADC (ADS1115) via i2c
I_pt100 = Valoradc
I_pt100 = I_pt100 * 7.81273842585528e-8 ' * 0.256 / (32767 * 100) => Valor da corrente no PT100 em Amperes
End If
Return

Getadc_pt100:

Gosub Getadc_i_pt100

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita no ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B00111010 ' MSB do registrador
' 0 : No effect
' 011 : AINP = AIN2 and AINN = AIN3
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura no ADS1115
' ===================== Inserido ==========================
I2cstop
I2cstart
' ===================== Inserido ==========================
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura ADC (ADS1115) via i2c
E_pt100 = Valoradc
E_pt100 = E_pt100 * 7.81273842585528e-6 ' * 0.256 / 32767 => Valor em Volts
R_pt100 = E_pt100 / I_pt100 ' Valor da resistência no PT100 em Ohms
T_pt100 = 100 - R_pt100
T_pt100 = T_pt100 * 2.32078e-4
T_pt100 = T_pt100 + 0.152726203204
T_pt100 = Sqr(t_pt100)
T_pt100 = 0.390802 - T_pt100
T_pt100 = T_pt100 / 1.16039e-4 ' Valor da temperatura no PT100 em ºC
End If
Return

Era isso que você sugeriu ?

Os valores lidos para I (tensão sobre 100 oHms) = 65483 (valor binário), e tensão sobre o PT100 = 65503 (valor binário)

Com resistência de 100 oHms no lugar do PT100

Os valores lidos para I (tensão sobre 100 oHms) = 65483 (valor binário), e tensão sobre o PT100 = 65483 (valor binário)

Eu realmente não tenho a menor ideia do que pode estar acontecendo.

Link para o comentário
Compartilhar em outros sites

Bom, com certeza falta transformar o resultado de sua leitura em complemento de 2 !

Lí atentamente o datasheet, e olha só : o resultado que você está obtendo do ADC está EM COMPLEMENTO DE 2 !!!!!!

Tem de converter para o normal , porisso que você está obtendo leituras negativas !

Não me lembro como transformar o complemento de dois de 16 bits...... vai ter de pesquisar !

E o datasheet especifica que tem de usar sempre os ACK na comunicação, logo após voce passar o endereço. Assim, modifiquei o seu programa para o que eu acho correto, só falta voce fazer a conversão do formato de complemento de 2 !


Getadc_i_pt100:
Dim Msbadc As Byte , Lsbadc As Byte
Dim Valoradc As Word At Msbadc Overlay

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B01001010 ' MSB do registrador
' 0 : No effect
' 100 : AINP = AIN0 and AINN = GND
' (================ fora ============ 101 : AINP = AIN1 and AINN = GND =================)
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
waitms 1
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura do ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop

If Err = 0 Then ' Err = 0 => não houve erro na leitura do ADC (ADS1115) via i2c

' AQUI voce TEM DE TRANSFORMAR O COMPLEMENTO DE 2 EM NORMAL !

I_pt100 = Valoradc
I_pt100 = I_pt100 * 7.81273842585528e-8 ' * 0.256 / (32767 * 100) => Valor da corrente no PT100 em Amperes
End If
Return

Getadc_pt100:

Gosub Getadc_i_pt100

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita no ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B00111010 ' MSB do registrador
' 0 : No effect
' 011 : AINP = AIN2 and AINN = AIN3
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
waitms 1
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura no ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura ADC (ADS1115) via i2c

' AQUI voce TEM DE TRANSFORMAR O COMPLEMENTO DE 2 EM NORMAL !


E_pt100 = Valoradc
E_pt100 = E_pt100 * 7.81273842585528e-6 ' * 0.256 / 32767 => Valor em Volts
R_pt100 = E_pt100 / I_pt100 ' Valor da resistência no PT100 em Ohms
T_pt100 = 100 - R_pt100
T_pt100 = T_pt100 * 2.32078e-4
T_pt100 = T_pt100 + 0.152726203204
T_pt100 = Sqr(t_pt100)
T_pt100 = 0.390802 - T_pt100
T_pt100 = T_pt100 / 1.16039e-4 ' Valor da temperatura no PT100 em ºC
End If
Return

Acerta agora o teu código, faça a conversão da leitura de complemento de 2 da sua variável VALORADC para o normal ANTES DE FAZER QUALQUER CONTA e informe os resultados.

Observação : a menos que voce tenha um layout super profissional, tipo aquele utilizado em medidores cardíacos, voce vai ter de ignorar pelo menos uns 5 bits de suas leituras !

Tem de usar uma referência de tensão super-precisa para o conversor, e mesmo assim um simples ruído de 1 milivolt em qualquer entrada já leva sua precisão no conversor para 12 bits significativos..... E olha que 1 milivolt é algo que é muito, mas muito difícil de eliminar, imagine 0,1 milivolt !!! voce mesmo já disse que a sua tensão de alimentação varia bastante, muito mais do que 1 milivolt, então adeus referência precisa !

Elimine esses 5 bits de suas contas, e veja se estabilizou.

Paulo

Link para o comentário
Compartilhar em outros sites

Consegui fazer funcionar.

O problema era a variável Valoradc que eu estava fazendo ovelay no formato invertido e com isto os valores estavam oscilando de forma bastante severa (sem ter número significativo). Foi só inverter as variáveis Lsbadc e Msbadc de ordem para que a variável Valoradc ficasse com os valores corretos (o certo era o número menos significativo vir antes).

O ADS1115 realmente fornece os resultados em complemento de 2, mas os números em complemento de 2 são exatamente iguais quando são números positivos. Eles só são diferentes quando os valores são negativos, e para convertê-los para positivo é só, no caso de variável de 16 bits, subtrair -1 do valor e inverter os bits (subtrair o valor final de 65535).

Fiz uns testes e os valores oscilam um pouco (o que era esperado), talvez de para conseguir estabilizar melhor o valor, que não precisa ser preciso em 5V para que funcione, mas tem que ser estável ou pelo menos tem que variar lentamente. Vou estudar como é que eu vou fazer isso.

Li o datasheet do ADS1115 e o tempo necessário entre um Stop e um Start é de apenas 600ns e não 1 ms.

Vai abaixo a rotina final.


Getadc_i_pt100:
Dim Lsbadc As Byte , Msbadc As Byte
Dim Valoradc As Word At Lsbadc Overlay

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B01001010 ' MSB do registrador
' 0 : No effect
' 100 : AINP = AIN0 and AINN = GND
' (================ fora ============ 101 : AINP = AIN1 and AINN = GND =================)
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
Waitus 1
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura do ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura do ADC (ADS1115) via i2c
I_pt100 = Valoradc
I_pt100 = I_pt100 * 7.81273842585528e-8 ' * 0.256 / (32767 * 100) => Valor da corrente no PT100 em Amperes
End If
Return

Getadc_pt100:

Gosub Getadc_i_pt100

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita no ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B00111010 ' MSB do registrador
' 0 : No effect
' 011 : AINP = AIN2 and AINN = AIN3
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
Waitus 1
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura no ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura ADC (ADS1115) via i2c
E_pt100 = Valoradc
E_pt100 = E_pt100 * 7.81273842585528e-6 ' * 0.256 / 32767 => Valor em Volts
R_pt100 = E_pt100 / I_pt100 ' Valor da resistência no PT100 em Ohms
T_pt100 = 100 - R_pt100
T_pt100 = T_pt100 * 2.32078e-4
T_pt100 = T_pt100 + 0.152726203204
T_pt100 = Sqr(t_pt100)
T_pt100 = 0.390802 - T_pt100
T_pt100 = T_pt100 / 1.16039e-4 ' Valor da temperatura no PT100 em ºC
End If

Return

Resultados observados:


12/08/13 22:08:46.07 26.75ºC TH => 26.7ºC 71.7% 1012.8mB 3.81mts 26.5ºC
ADS1115 (PT100)=> I = 0.001022274A E = 0.1126675V R = 110.21017oHms T =26.228ºC
12/08/13 22:08:47.06 26.75ºC TH => 26.7ºC 71.7% 1012.8mB 3.81mts 26.5ºC
ADS1115 (PT100)=> I = 0.001020845A E = 0.1127065V R = 110.40025oHms T =26.719ºC
12/08/13 22:08:48.07 26.75ºC TH => 26.7ºC 71.7% 1012.7mB 4.59mts 26.5ºC
ADS1115 (PT100)=> I = 0.001022337A E = 0.1126753V R = 110.20938oHms T =26.226ºC
12/08/13 22:08:49.06 26.75ºC TH => 26.7ºC 71.7% 1012.7mB 4.59mts 26.5ºC
ADS1115 (PT100)=> I = 0.001021798A E = 0.1126987V R = 110.29131oHms T =26.438ºC
12/08/13 22:08:50.07 26.75ºC TH => 26.7ºC 71.7% 1012.7mB 4.38mts 26.5ºC
ADS1115 (PT100)=> I = 0.001022396A E = 0.1126440V R = 110.17039oHms T =26.126ºC
12/08/13 22:08:51.06 26.75ºC TH => 26.7ºC 71.7% 1012.7mB 4.38mts 26.5ºC
ADS1115 (PT100)=> I = 0.001022155A E = 0.1125346V R = 110.08866oHms T =25.915ºC

Estes resultados (na linha do PT100) são influenciados pela imprecisão da tensão de referência do ADS1115 (que não é citado no datasheet) e que faz com que a corrente sobre o resistor de referência varie e também afeta a medição no PT100 (que também é afetado pela tensão sobre as resistências de 100 + 4.7k + PT100), erro do amplificador operacional interno no ganho de 16 vezes, efeito do aquecimento provocado no PT100 pela corrente de referência (1,02mA), variação da tensão de polarização (que não é muito precisa nem muito estável), e outros fatores como interferência eletromagnética que deve ser significativa com tensões baixas e outros.

Finalmente aprendi como usar o ADS1115, agora dá para brincar mais a sério. Quem sabe eu tente também com um ADS1248, que é bem mais preciso (24bits), tem mais portas AD, é mais rápido, tem recursos para compensação que permitem ler os RTDs como um PT100 com muito mais precisão, independentemente da tensão de alimentação. Mas ainda dependo de resistências de alta precisão para ter uma tensão de referência decente. Mas não dá para comunicar com ele da mesma forma que o 1115, ele não é i2c (mais um aprendizado).

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...

Antunes,

Obrigado, eu preferí fazer desta maneira, bem pessoal, e publicar para todos poderem ver e aprender, do que fazer um livro.

O objetivo foi justamente desmitificar o uso dos microcontroladores, pois em tudo que é fórum quando um iniciante pergunta como programar um Pic ou AVR aparece a turma do " tem de ser em C" ou a do " assembler é o melhor" ..., o que acaba desencorajando um monte de gente, que poderia se divertir em poucos dias utilizando o velho e bom Basic.... E acho que é muito importante ensinar a fazer a simulação de projetos com o Isis do Proteus, afinal a gente perde um tempão gravando, testando, gravando, testando .......... Se simular, só precisaremos gravar quando estiver quase totalmente corrigido.

E sempre que tiver alguma novidade, postarei aqui para todos.

Um abraço.

Paulo

Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois...

 RÁDIO FM COM CONTROLE DE TONALIDADE E AMPLIFICADOR

 

Pessoal, terminei o meu novo projeto, ficou simples e bem barato, pois os módulos principais podem ser comprados no Ebay ou no Mercado Livre.

 

Custo aproximado :

Modulo Fm TEA5767 - US$ 2,00

Amplificador stereo 10+10 W - US$ 6,50

Display LCD Backlite 4 x 20 - US$ 6,50

Atmega 328 - US$ 3,50 ( mas serve um Atmega8, Atmega88 , atmega16, Arduino, etc... )

Fonte de parede de 12v por 2A - US$ 6,50

 

Falta ainda algo muito importante : um CI controlador de Audio TDA8425 que pode ser adquirido aqui no Brasil mesmo, em SP na Santa Ifigênia sai por R$ 6,50 !!! Esse CI controla volume, graves, agudos, e ainda pode criar efeitos tipo Estéreo Espacial ou Pseudo-estéreo. E utiliza a interface I2C !

 

Ainda precisamos de alguns resistores, capacitores, regulador 7805 e 4 push-buttons, que custam mais uns R$ 20,00 tudo.

 

Como podem ver, podemos construir apenas uma plaquinha para o Atmega328 e o TDA8425, e aproveitar os outros módulos completos.

 

Ou fazer uma única placa para tudo, usando um CI amplificador de áudio tipo Classe D de baixa potência.

 

Eu montei um Frankstein usando alguns módulos que eu tinha aqui, e o resultado ficou legal.

 

O interessante é que o programa em Bascom que controla tudo com apenas 4 push-buttons de contato momentâneo e pode utilizar qualquer processador, desde um Atmega8 até um Atmega328, ou até mesmo pode ser facilmente modificado para utilizar um Arduino como controlador !

 

Segue o programa fonte em Bascom :

 

 
        '-----------------------------------------------------------------------
        ' Nome       : TEA5767 HOME AUDIO.bas
        ' Revisão    : 1.0   02.09.2013
        ' Controller : AVR ATmega16
        ' Autor      : Antonio Paulo Hawk com trechos de
        '            : Thomas Palluthe (www.tp-homesoft.de)
        ' Compilador : BASCOM-AVR   Rev. 2.0.7.6
        '
        '
        '---[ Detalhes do TEA5767 ]-------------------------------------
        '         ESCRITA
        ' Softmute : bit 3 do byte 4    1=ligado
        ' High Cut : bit 2 do byte 4    1=ligado
        ' Stereo Noise Canceler : bit 1 do byte 4    1=ligado
        ' Mute : bit 7 byte 1  1=mute
        ' Hi/Lo Injection : bit 4 do byte 3   1=hi Side Inj
        ' Stereo/Mono  :  bit 3 do byte 3    1=Mono
        '
        '          LEITURA
        ' Stereo : bit 7 do byte 3     1=stereo
        ' Freq. Intermed. : bit 6-0 do byte 3
        ' Nivel Sinal : bit 7-4 do byte 4
        ' PLL : bit 5-0 byte 1   13-8
        ' PLL : bit 7-0 byte 2    7 - 0
        '
        '---[ Detalhes do TDA8425 ]-------------------------------------
        '
        ' Endereço escrita :  082h
        ' Endereço Leitura :  083h
        ' Formato escrita =  STA/CHIP/REG/VL/VR/BA/TR/S1/STOP
        ' Registros e funções :
        ' REG :0
        ' VL = 11VL5VL4VL3VL2VL1VL0  = 2 DB ( +6 ATÉ -80(27 ATÉ 0) )
        ' VR = 11VR5VR4V33VR2VR1VR0  = 2 DB ( +6 ATÉ -80(27 ATÉ 0) )
        ' BA = 1111BA3BA2BA1BA0 = 3DB ( +15/15/15/15/12...-12/-12/-12 )
        ' TR = 1111TR3TR2TR1TR0 = 3DB ( +12/12/12/12/9....-12/-12/-12 )
        ' SW = 11/MU/EFL/STL/M1/M0/IS onde
        '      MU = Mute ( 1=ligado )
        '      EFL=0 STL=1 -  ESTEREO_NORMAL
        '      EFL=1 STL=1  -  ESTEREO_ESPACIAL
        '      EFL=1 STL=0  -  PSEUDO_ESTEREO
        '      EFL=0 STL=0  -  MONO
        '
        '      ML1=1 ML0=1 IS=0  -  STEREO CANAL 1

        '
        ' FORMATO DISPLAY
        ' LINHA 1->VLM  BAS  TRB  ST NM ( PODE SER ST SP OU MONO)
        ' LINHA 2->-30  -3   -3   RAD 1 ( pode ser AUD )
        ' LINHA 3->RA   AU   +F   -F    ( PODE SER +M -M )
        ' linha 4->F=109.2 STEREO SI=8
        '
        ' TABELAS :
        ' TB_VL VAI DE 20 ATÉ 63 ( -80 A +6 )
        ' TB_BA VAI DE 2 ATÉ 11  ( -12 A +15)
        ' TB_TR VAI DE 2 ATÉ 10  ( -12 A +12)
        '
        ' MAQUINA DE ESTADOS :
        ' MODO=0 Indica tratamento de RADIO. A cada aperto de bot1 muda a fase
        '
        ' FASE=1 Indica bot3 e bot4 mudar frequencias
        ' FASE=2 Indica bot3 muda mono/stereo
        '
        ' MODO=1 Indica tratamento de AUDIO. A cada aperto de bot2 muda a fase
        '
        ' FASE=1 Indica bot3 e bot4 a dim / aumentar o volume
        ' FASE=2 Indica bot3 e bot4 a dim / aumentar os graves
        ' FASE=3 Indica bot3 e bot4 a dim / aumentar os agudos
        ' FASE=4 Indica bot3 mudar ST/SP/MN/PS


$regfile = "m328Pdef.dat"
$crystal = 8000000                                          '8 MHz Oszillator
' SE FOR USAR UM ARDUINO, MUDAR O CRYSTAL PAR 16000000
$hwstack = 128
$swstack = 128
$framesize = 200

Config Sda = Portc.4                                        'I²C
Config Scl = Portc.5
$lib "I2C_TWI.LIB"
$lib "double.lbx"
Declare Sub Init_audio
Declare Sub Init_radio
Declare Sub Sintonia
Declare Sub Leitura_radio
Declare Sub Ajusta_audio
Declare Sub Comunica_audio
Declare Sub Aumenta_volume
Declare Sub Abaixa_volume
Declare Sub Aumenta_grave
Declare Sub Abaixa_grave
Declare Sub Aumenta_agudo
Declare Sub Abaixa_agudo


'---(LCD)-----------------------------------------------------------------------
Config Lcd = 20 * 4
Config Lcdpin = Pin , Db4 = Pd.5 , Db5 = Pd.4 , Db6 = Pd.3 , Db7 = Pd.2 , E = Pd.6 , Rs = Pd.7



'---( hardware)-----------------------------------------------------------------

Config Portb.0 = Input
Config Portb.1 = Input
Config Portb.2 = Input
Config Portc.0 = Input
                                         'Pullup
Set Portb.0
Set Portb.1
Set Portb.2
Set Portc.0

Botao1 Alias Pinb.0
Botao2 Alias Pinb.1
Botao3 Alias Pinb.2
Botao4 Alias Pinc.0


Dim Flag_mudou_radio As Bit
Dim Flag_mudou_audio As Bit
Dim Primeiro As Bit
Dim Flag_botao As Bit
Dim Pllfrequenz As Word
Dim Old_pll As Word
Dim Adresse As Byte
Dim 1st As Byte
Dim 2nd As Byte
Dim 3rd As Byte
Dim 4th As Byte
Dim 5th As Byte

Dim R1st As Byte
Dim R2nd As Byte
Dim R3rd As Byte
Dim R4th As Byte
Dim R5th As Byte
Dim State_radio As Byte

Dim Pll As Single
Dim Freq_desejada As Single
Dim Freq_temp As Single

Dim A1st As Byte
Dim A2nd As Byte
Dim A3rd As Byte
Dim A4th As Byte
Dim A5th As Byte
Dim State_audio As Byte
Dim Vl As Byte
Dim Vr As Byte
Dim Tr As Byte
Dim Ba As Byte
Dim Modo_audio As Byte
Dim Rvl As String * 3
Dim Rvr As String * 3
Dim Rtr As String * 3
Dim Rba As String * 3

Dim Modo As Byte
Dim Fase As Byte
Dim Tam As Byte
Dim Nspaces As Byte


Modo = 0                                                    ' RADIO
Fase = 1
                                                    'INICIO
'Dim Freq_memory(42) As Single
Dim Sender As Byte
Dim I As Byte
Dim W As String * 5
Dim J As Byte
Dim Sinal As Byte
Dim Flag_stereo As Bit
Dim Flag_leitura_stereo As Bit

Dim Linha1 As String * 20
Dim Linha2 As String * 20
Dim Linha3 As String * 20
Dim Linha4 As String * 20
'Dim Copia_linha1 As String * 20
'Dim Copia_linha2 As String * 20
'Dim Copia_linha3 As String * 20
'Dim Copia_linha4 As String * 20
Dim Str_rascunho As String * 4

Const Xtal_tea5767 = 32768
Const Freq_int = 225000
Const Tea5767w = &HC0
Const Tea5767r = &HC1
Const Tda8425w = &H82
Const Tda8425r = &H83
Const Estereo_normal = 1
Const Estereo_espacial = 3
Const Pseudo_estero = 2
Const Mono = 0
Const Incremento = 0.2

Modo_audio = Estereo_normal                                 'AUDIO EM ESTEREO
Flag_stereo = 1                                             ' RADIO EM ESTEREO
Freq_desejada = 87.5

'--- INICIO PROGRAMA -----------------------------------------------------------
Waitms 500
Initlcd
Cls
Cursor Off
Lcd "FM Stereo Radio"
Lowerline
Lcd "Paulo DEV.R1"
Wait 3
Cls
I2cinit
Config Twi = 70000


Init_radio
Init_audio
Waitms 50




Vl = 45
Rvl = Lookupstr(vl , Tb_vl)
Ba = 6
Rba = Lookupstr(ba , Tb_ba)
Tr = 6
Rtr = Lookupstr(tr , Tb_tr)
Ajusta_audio
Primeiro = 1
Do
Flag_botao = 1
If Botao1 = 0 Then
   Flag_botao = 1
   Goto Proc1
End If

If Botao2 = 0 Then
   Flag_botao = 1
   Goto Proc2
End If

If Botao3 = 0 Then
   Flag_botao = 1
   Goto Proc3
End If

If Botao4 = 0 Then
   Flag_botao = 1
   Goto Proc4
End If

If Flag_botao = 1 Or Primeiro = 1 Then
   Primeiro = 0
   Leitura_radio
   Goto Saida
Else
   Leitura_radio
   Linha4 = "F=" + Rtrim(w)
   If Len(linha4) = 6 Then
     Linha4 = Linha4 + " "
   End If
   If Flag_leitura_stereo = 1 Then
     Linha4 = Linha4 + " St   Si="
   Else
     Linha4 = Linha4 + " Mon  Si="
   End If
   Str_rascunho = Str(sinal)
   Linha4 = Linha4 + Trim(str_rascunho)
   Tam = Len(linha4)
   If Tam < 20 Then
     Nspaces = 20 - Tam
     Linha4 = Linha4 + Space(nspaces)
   End If
   Locate 4 , 1
   Lcd Linha4
   Goto Saida_final
End If
Saida_final:
If Modo = 1 And Fase = 1 Then
  Waitms 20
End If
If Modo = 0 And Fase = 1 Then
  Waitms 30
End If
Loop

' --------  PROCESSAMENTO DO BOTAO 1 --------------------------
Proc1:
Waitms 5
If Botao1 = 0 Then
  Waitms 15
  Goto Proc1
End If
If Modo = 1 Then
 Modo = 0
 Fase = 1
Else
 Incr Fase
 If Fase = 3 Then
   Fase = 1
 End If
End If
Goto Saida

' --------  PROCESSAMENTO DO BOTAO 2 --------------------------
Proc2:
Waitms 5
If Botao2 = 0 Then
  Waitms 15
  Goto Proc2
End If
If Modo = 0 Then
 Modo = 1
 Fase = 1
Else
 Incr Fase
 If Fase = 5 Then
   Fase = 1
 End If
End If
Goto Saida

' --------  PROCESSAMENTO DO BOTAO 3 --------------------------
Proc3:
Waitms 5
If Modo = 0 And Fase = 1 Then
  Goto Proc3a
Elseif Modo = 1 And Fase = 1 Then
  Goto Proc3a
End If
If Botao3 = 0 Then
  Waitms 15
  Goto Proc3
End If
Proc3a:
If Modo = 0 Then
   If Fase = 1 Then
      Freq_desejada = Freq_desejada - Incremento
      If Freq_desejada < 87.5 Then
         Freq_desejada = 108.1
      End If
   Else
      Toggle Flag_stereo
   End If
   Flag_mudou_radio = 1
Else
  If Fase = 1 Then
     Abaixa_volume
  Elseif Fase = 2 Then
     Abaixa_grave
  Elseif Fase = 3 Then
     Abaixa_agudo
  Elseif Fase = 4 Then
     Incr Modo_audio
     If Modo_audio > 3 Then
        Modo_audio = 0
     End If
  End If
  Flag_mudou_audio = 1
End If
Goto Saida

' --------  PROCESSAMENTO DO BOTAO 4 ---------------------------
Proc4:
Waitms 5
If Modo = 0 And Fase = 1 Then
   Goto Proc4a
Elseif Modo = 1 And Fase = 1 Then
  Goto Proc4a
End If
If Botao4 = 0 Then
  Waitms 15
  Goto Proc4
End If
Proc4a:
If Modo = 0 Then
   If Fase = 1 Then
      Freq_desejada = Freq_desejada + Incremento
      If Freq_desejada > 108.1 Then
         Freq_desejada = 87.5
      End If
   End If
   Flag_mudou_radio = 1
Else
  If Fase = 1 Then
     Aumenta_volume
  Elseif Fase = 2 Then
     Aumenta_grave
  Elseif Fase = 3 Then
     Aumenta_agudo
  End If
  Flag_mudou_audio = 1
End If
Goto Saida


'---- ROTINA DE DISPLAY -------------------------------------------------------
Saida:
If Flag_mudou_radio = 1 Then
  Sintonia
  Flag_mudou_radio = 0
  End If
If Flag_mudou_audio = 1 Then
  Ajusta_audio
  Flag_mudou_audio = 0
End If
Leitura_radio                                               ' LER O SINAL
' aqui temos de fazer o tratamento do display
Linha1 = "VLM  BAS  TRB  "
If Modo_audio = 0 Then
  Str_rascunho = "Mono"
Elseif Modo_audio = 1 Then
  Str_rascunho = "StNm"
Elseif Modo_audio = 2 Then
  Str_rascunho = "PsSt"
Else
  Str_rascunho = "StSp"
End If
Linha1 = Linha1 + Str_rascunho
Linha2 = Rvl + Space(2)
Linha2 = Linha2 + Rba
Linha2 = Linha2 + Space(2)
Linha2 = Linha2 + Rtr
Linha2 = Linha2 + Space(2)
If Modo = 0 Then
  Str_rascunho = "RAD"
Else
  Str_rascunho = "AUD"
End If
Linha2 = Linha2 + Trim(str_rascunho)
Linha2 = Linha2 + " "
Str_rascunho = Str(fase)
Linha2 = Linha2 + Trim(str_rascunho)
Linha3 = "RAD  AUD  "
If Modo = 0 Then
  If Fase = 1 Then
    Linha3 = Linha3 + "-F   +F"
  Else
    Linha3 = Linha3 + "Mo/St  "
    If Flag_stereo = 1 Then
      Str_rascunho = "St"
    Else
      Str_rascunho = "Mn"
    End If
    Linha3 = Linha3 + Trim(str_rascunho)
  End If
Else
  If Fase = 1 Then
    Linha3 = Linha3 + "-V   +V"
  Elseif Fase = 2 Then
    Linha3 = Linha3 + "-B   +B"
  Elseif Fase = 3 Then
    Linha3 = Linha3 + "-T   +T"
  Else
    Linha3 = Linha3 + "Efeito "
  End If
End If
 W = Fusing(freq_desejada , "#.#")
'Str_rascunho = Str(freq_temp)
'Linha4 = "F=" + Trim(str_rascunho)
Linha4 = "F=" + Rtrim(w)
If Len(linha4) = 6 Then
  Linha4 = Linha4 + " "
End If
If Flag_leitura_stereo = 1 Then
  Linha4 = Linha4 + " St   Si="
Else
  Linha4 = Linha4 + " Mon  Si="
End If
Str_rascunho = Str(sinal)
Linha4 = Linha4 + Trim(str_rascunho)
'agora, acertar os espacos
Tam = Len(linha1)
If Tam < 20 Then
  Nspaces = 20 - Tam
  Linha1 = Linha1 + Space(nspaces)
End If
Tam = Len(linha2)
If Tam < 20 Then
  Nspaces = 20 - Tam
  Linha2 = Linha2 + Space(nspaces)
End If
Tam = Len(linha3)
If Tam < 20 Then
  Nspaces = 20 - Tam
  Linha3 = Linha3 + Space(nspaces)
End If
Tam = Len(linha4)
If Tam < 20 Then
  Nspaces = 20 - Tam
  Linha4 = Linha4 + Space(nspaces)
End If
Locate 1 , 1
Lcd Linha1
Locate 2 , 1
Lcd Linha2
Locate 3 , 1
Lcd Linha3
Locate 4 , 1
Lcd Linha4
Goto Saida_final


'---------  SUB ROTINAS  -------------------------------------------------------
Sub Init_radio
Sintonia
End Sub

Sub Sintonia
Pll = Freq_desejada * 1000000
Pll = Pll + Freq_int
Pll = Pll * 4
Pll = Pll / Xtal_tea5767
Pllfrequenz = Int(pll)
1st = High(pllfrequenz)
Reset 1st.6
Reset 1st.7
2nd = Low(pllfrequenz)
3rd = &B00010000
If Flag_stereo = 1 Then
  3rd.3 = 1
Else
  3rd.3 = 0
End If
4th = &B00011010
5th = &B01000000
I2cstart
I2cwbyte Tea5767w
I2cwbyte 1st
I2cwbyte 2nd
I2cwbyte 3rd
I2cwbyte 4th
I2cwbyte 5th
I2cstop
End Sub

Sub Leitura_radio
I2cstart
I2cwbyte Tea5767r
I2crbyte R1st , Ack
I2crbyte R2nd , Ack
I2crbyte R3rd , Ack
I2crbyte R4th , Ack
I2crbyte R5th , Nack
I2cstop
Sinal = R4th And &B11110000
Shift Sinal , Right , 4
If R3rd.7 = 1 Then
  Set Flag_leitura_stereo
Else
  Reset Flag_leitura_stereo
End If
End Sub



Sub Init_audio
'INICIALIZA O CHIP TDA8425
'Modo = Stereo Normal
'Canal = 1
' MUTE=LIGADO
' VL=VR=-30DB 45
'TR = BA = 0DB 6
A1st = 45 Or &B11000000
A2nd = A1st
A3rd = 6 Or &B11110000
A4th = A3rd
A5th = &B11001110
Comunica_audio
End Sub

Sub Comunica_audio
I2cstart
I2cwbyte Tda8425w
I2cwbyte 0
I2cwbyte A1st
I2cstart
I2cwbyte Tda8425w
I2cwbyte 1
I2cwbyte A2nd
I2cstart
I2cwbyte Tda8425w
I2cwbyte 2
I2cwbyte A3rd
I2cstart
I2cwbyte Tda8425w
I2cwbyte 3
I2cwbyte A4th
I2cstart
I2cwbyte Tda8425w
I2cwbyte 8
I2cwbyte A5th
I2cstop
End Sub



Sub Ajusta_audio
A1st = Vl Or &B11000000
A2nd = A1st
A3rd = Ba Or &B11110000
A4th = Tr Or &B11110000
A5th = Modo_audio
Shift A5th , Left , 3
A5th = A5th Or &B11000110
Comunica_audio
End Sub

Sub Aumenta_volume
Incr Vl
If Vl > 63 Then Vl = 63
Rvl = Lookupstr(vl , Tb_vl)
End Sub

Sub Abaixa_volume
Decr Vl
If Vl < 20 Then Vl = 20
Rvl = Lookupstr(vl , Tb_vl)
End Sub

Sub Aumenta_grave
Incr Ba
If Ba > 11 Then Ba = 11
Rba = Lookupstr(ba , Tb_ba)
End Sub

Sub Abaixa_grave
Decr Ba
If Ba < 2 Then Ba = 2
Rba = Lookupstr(ba , Tb_ba)
End Sub

Sub Aumenta_agudo
Incr Tr
If Tr > 10 Then Tr = 10
Rtr = Lookupstr(tr , Tb_tr)
End Sub

Sub Abaixa_agudo
Decr Tr
If Tr < 2 Then Tr = 2
Rtr = Lookupstr(tr , Tb_tr)
End Sub


End
'----- FINAL DO PROGRAMA -------------------------------------------------------

Tb_vl:
Data "-80" , "-80" , "-80" , "-80" , "-80" , "-80" , "-80" , "-80"
Data "-80" , "-80" , "-80" , "-80" , "-80" , "-80" , "-80" , "-80" , "-80"
Data "-80" , "-80" , "-80" , "-80" , "-78" , "-76" , "-74" , "-72" , "-70"
Data "-68" , "-66" , "-64" , "-62" , "-60" , "-58" , "-56" , "-54" , "-52"
Data "-50" , "-48" , "-46" , "-44" , "-42" , "-40" , "-38" , "-36" , "-34"
Data "-32" , "-30" , "-28" , "-26" , "-24" , "-22" , "-20" , "-18" , "-16"
Data "-14" , "-12" , "-10" , "-8 " , "-6 " , "-4 " , "-2 " , "0  " , "+2 "
Data "+4 " , "+6 "

Tb_ba:
Data "-12" , "-12" , "-12" , "-9 " , "-6 " , "-3 " , "0  " , "+3 " , "+6 "
Data "+9 " , "+12" , "+15" , "+15" , "+15" , "+15" , "+15"

Tb_tr:
Data "-12" , "-12" , "-12" , "-9 " , "-6 " , "-3 " , "0  " , "+3 " , "+6 "
Data "+9 " , "+12" , "+12" , "+12" , "+12" , "+12" , "+12"

Para quem quer aprender mais sobre controles digitais em som, este projeto é uma ótima oportunidade, pois hoje em dia tudo funciona de maneira semelhante, por exemplo uma TV, um rádio moderno ( com DSP ), um home teather, etc.

 

Funcionamento :

 

O botão 1 seleciona as funções de rádio, isto é, quando apertado permite que os botões 3 e 4 façam a diminuição ou o aumento da frequência sintonizada. Se apertar novamente o botão 1, o botão 3 permite a mudança de sinal de Estéreo para Mono e vice versa.

 

O botão 2 seleciona as funções de áudio, ou seja, inicialmente permite que os botões 3 e 4 façam a diminuição do volume ou o aumento. Ao ser apertado novamente, os botões 3 e 4 fazem a diminuição ou o aumento dos graves, e se o botão 2 for apertado de novo, permite mudar o nível dos agudos. Finalmente, apertando mais uma vez o botão 2, faz com que o botão 3 mude o processamento de áudio, trocando ciclicamente de Estéreo Normal para Estéreo Espacial, em seguida Mono, e finalmente Pseudo Estéreo.

 

O display acompanha essa troca de funções, e também mostra o nível do sinal recebido, além de todas as informações sobre a frequência, nível de volume, de graves, de agudos e também o tipo de processamento de áudio.

 

Segue o esquema :

 

PROJETO.png.8334dc88d4faa2338ce2b15e379d74c5.png

 

Segue uma foto da "aranha":

 

vlcsnap-2019-06-06-22h18m15s777.png.f3c8ecc8ac8eeac6bd5a2ab4212ccca2.png

 

Para terminar, conforme prometí, segue o link com o arquivo .hex para gravar o seu ATMEGA328, e o próprio programa-fonte do Bascom :

http://www.4shared.com/rar/VUBGWpWb/radio_tea5767.html

Paulo

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Paulo,

Você já me ajudou muito com o ADS1115, agora estou com alguns problemas novos:

1. Ampliando o meu programa esbarrei neste erro.

back jump out out of range

Não consigo entender bem o porque deste erro, o programa só está usando 15% da memoria do AVR 1280. O que eu estou fazendo de errado e o que eu devo fazer para evitar este erro de compilação ?

2. Eu estou querendo comunicar mais rápido (high speed mode) com o ADS1115. Pelo datashit diz que eu devo enviar para um endereço especial um byte 00001xxx (to activate high-speed mode, send a special address byte of 00001xxx following the START condition, where xxx are bits unique to the Hs-capable master). Texto que fica na página 17 do datashit (ADS1115.pdf).

Eu realmente não entendi o que tenho que fazer para ativar o modo high speed de comunicação I2C do ADS1115.

Ainda tenho muito que aprender com o uso do Bascom e também nos microcontroladores AVR.

Link para o comentário
Compartilhar em outros sites

Oi Intruder,

1 - Nunca ví esse erro.... mas faz o seguinte, normalmente a gente coloca as sub-rotinas no final, experimente espalhar elas no meio do programa.

Uma vez tive um problema com uma tabela no final do programa, dava um erro doido também, tive de mudar o programa, o trecho que chamava essa tabela estava bem no iníçio, mudei ele e coloquei no meio do programa e resolveu....

2 - Vou pesquisar o datasheet e posto depois.

Paulo

Link para o comentário
Compartilhar em outros sites

Pessoal,

Segue um programa bem interessante, muito útil para aqueles casos onde você quer usar vários CI's I2C's porém usam o mesmo endereço.... e claro que neste caso não tem como !

A solução é utilizar um CI demultiplex específico para I2C, mas o tal CI é naqueles formatos SMD e ainda é meio carinho e difícil de achar, porém ......

Se você tiver pinos sobrando, pode usar pares de pinos para simular novos Bus I2C e colocar um CI em cada par, e ainda assim pode controlar todos independentes !

No meu caso, onde preciso usar 3 CI's TDA8425 e dois PCF8574, tive de criar 3 novos Buses I2C, e fiquei com 4 no total, pois existe o nativo no hardware dos Atmegas e nesse eu coloquei os dois PCF8574 cada um em um endereço diferente, e pronto !

Nada impede de aumentar esse número, basta existirem pinos livres !

Como acho que esse programa pode ser útil para outros malucos , posto aqui o código :


'-------------------------------------------------------------------------------
' PROGRAMA PARA USAR 4 BUS I2C INDEPENDENTES
' VELOCIDADE DE COMUNICAÇÃO = 36 KHZ APROXIMADO para os 3 Bus por software
' e 100 Khz para o Bus nativo por hardware
'
'Fiz este programa pois estou montando uma central de som para o meu carro
'onde tenho 6 canais de áudio independentes ( 5.1 ) e gostaria de reforçar
'o áudio com 6 controles independentes de graves e agudos, além de poder
'rotear qualquer canal de entrada para qualquer saída !
'Para isto estou usando 3 TDA8425 e 6 cd4051. O problema é que os TDA's
'possuem o mesmo endereço, então não consigo colocar todos no mesmo Bus.
'
'Este programa é a solução, onde criei 3 bus independentes controlados por
'software, onde colocarei os 3 TDA's, e ainda tenho o bus nativo livre para
'usar um controlador de display com um PCF8574 e mais um PCF8574 para ler os
'botões de controle.
'Segue aqui como exemplo a quem precisar de algo semelhante.
'-------------------------------------------------------------------------------



$regfile = "m328pdef.dat"
$crystal = 16000000 '16 MHz

$hwstack = 128
$swstack = 128
$framesize = 128

Config Submode = New

'
' CONFIGURA O BUS POR HARDWARE NATIVO
Config Sda = Portc.4 'I²C
Config Scl = Portc.5
$lib "I2C_TWI.LIB"

'
' ---- CONFIGURA OS 3 BUS I2C POR SOFTWARE
Const I2c_maxdata = 10 'MAXIMO DE BYTES A RECEBER
' BUS 1
Scl1 Alias Portb.0
Sda1 Alias Portb.1
Sda1_in Alias Pinb.1
' BUS 2
Scl2 Alias Portc.0
Sda2 Alias Portc.1
Sda2_in Alias Pinc.1
' BUS 3
Scl3 Alias Portc.2
Sda3 Alias Portc.3
Sda3_in Alias Pinc.3

' CONFIGS GERAIS DOS 3 BUS POR SOFTWARE
Config Sda1 = Input
Config Sda2 = Input
Config Sda3 = Input
Config Scl1 = Input
Config Scl2 = Input
Config Scl3 = Input
Dim I_data(i2c_maxdata) As Byte '10 BYTES PARA RECEBER
Dim I_num As Byte
Dim I_type As String * 4


'-------------------------------- SUBROTINAS -------------------------
Sub Init_all_i2c
Scl1 = 1
Config Scl1 = Output
Scl2 = 1
Config Scl2 = Output
Scl3 = 1
Config Scl3 = Output
Config Sda1 = Input
Config Sda2 = Input
Config Sda3 = Input
Waitus 10
End Sub

Sub Sda_high(byval I_num As Byte)
Local T1 As Byte
T1 = I_num
Select Case T1
Case 1 : Config Sda1 = Input
Case 2 : Config Sda2 = Input
Case 3 : Config Sda3 = Input
End Select
End Sub

Sub Sda_low(byval I_num As Byte)
Local T1 As Byte
T1 = I_num
Select Case T1
Case 1
Sda1 = 0
Config Sda1 = Output
Case 2
Sda2 = 0
Config Sda2 = Output
Case 3
Sda3 = 0
Config Sda3 = Output
End Select
End Sub

Sub Scl_high(byval I_num As Byte)
Local T1 As Byte
T1 = I_num
Select Case T1
Case 1 : Config Scl1 = Input
Case 2 : Config Scl2 = Input
Case 3 : Config Scl3 = Input
End Select
End Sub

Sub Scl_low(byval I_num As Byte)
Local T1 As Byte
T1 = I_num
Select Case T1
Case 1
Scl1 = 0
Config Scl1 = Output
Case 2
Scl2 = 0
Config Scl2 = Output
Case 3
Scl3 = 0
Config Scl3 = Output
End Select
End Sub

Sub I2c_start(byval I_num As Byte)
Local T2 As Byte
T2 = I_num
Call Scl_high(t2)
Waitus 4
Call Sda_low(t2)
Waitus 5
Call Scl_low(t2)
Call Sda_high(t2)
Waitus 5
End Sub

Sub I2c_stop(byval I_num As Byte)
Local T2 As Byte
T2 = I_num
Call Scl_low(t2)
Waitus 1
Call Sda_low(t2)
Waitus 2
Call Scl_high(t2)
Waitus 4
Call Sda_high(t2)
Waitus 5
End Sub

Sub I2c_wbyte(byval I_num As Byte , Byval I_value As Byte)
Local T3 As Byte
Local I_dummy1 As Byte
Local I_dummy2 As Byte
Local I_dummy As Byte
T3 = I_num
I_dummy1 = I_value
Call Scl_low(t3)
For I_dummy = 1 To 8
I_dummy2 = I_dummy1 And &B10000000
Shift I_dummy1 , Left , 1
If I_dummy2 = 128 Then
Call Sda_high(t3)
Else
Call Sda_low(t3)
End If
Waitus 1
Call Scl_high(t3)
Waitus 6
Call Scl_low(t3)
Next I_dummy
Call Sda_high(t3)
Waitus 3
Call Scl_high(t3)
Waitus 3
Select Case T3
Case 1
I_dummy = Sda1_in
Case 2
I_dummy = Sda2_in
Case 3
I_dummy = Sda3_in
End Select
If I_dummy = 0 Then
I_type = "NACK"
Else
I_type = "ACK "
End If
Waitus 3
End Sub

Sub I2c_rbyte(byval I_num As Byte , Byval I_value As Byte , Byval I_type As String)
Local I_dummy As Byte
Local I_dummy1 As Byte
Local I_dummy2 As Byte
Local I_str As String * 4
Local I_x As Byte
Local I_read As Byte
I_dummy = I_num
I_dummy1 = I_value 'AONDE ARMAZENAR
I_read = 0
I_str = I_type
I_str = Trim(i_str)
I_dummy2 = 0
Call Scl_low(i_dummy)
Waitus 5
For I_x = 1 To 8
Shift I_dummy2 , Left , 1
Call Scl_high(i_dummy)
Waitus 3
Select Case I_dummy
Case 1
I_read = Sda1_in
Case 2
I_read = Sda2_in
Case 3
I_read = Sda3_in
End Select
I_dummy2 = I_dummy2 + I_read
Waitus 2
Call Scl_low(i_dummy)
Waitus 5
Next
If I_type = "ACK" Then
Call Sda_low(i_num)
Waitus 2
Call Scl_high(i_dummy)
Waitus 6
Call Scl_low(i_dummy)
Call Sda_high(i_num)
Waitus 6
Call Scl_high(i_dummy)
Waitus 6
Else
End If
I_data(i_dummy1) = I_dummy2
End Sub

'------------------- FINAL DAS SUBS ----------------------------------

' Aqui começa o programa mesmo....

I2cinit
'
Config Twi = 100000 ' inicializa o i2c nativo hardware
Init_all_i2c ' inicializa os 3 i2cs soft

de novo:
'o comando abaixo faz o i2cstart no bus 1
Call I2c_start(1) 'bus 1
'veja a sintaxe do comando abaixo, onde 1 é o bus e 85 é o endereço
Call I2c_wbyte(1 , 75)
'veja a sintaxe abaixo, onde 1 é o bus, 2 é o endereço na matrix i_data()
'onde o dado lido vai ser guardado, e o ACK significa que continua leitura
Call I2c_rbyte(1 , 2 , "ACK")
' abaixo veja que usamos NACK para sinalizar final de leitura
Call I2c_rbyte(1 , 3 , "NACK")
Call I2c_stop(1)
Waitms 10

Call I2c_start(2) 'bus 2
Call I2c_wbyte(2 , 73)
Call I2c_rbyte(2 , 4 , "ACK")
Call I2c_rbyte(2 , 5 , "NACK")
Call I2c_stop(2)
Waitms 10

Call I2c_start(3) 'bus 3
Call I2c_wbyte(3 , 71)
Call I2c_rbyte(3 , 6 , "ACK")
Call I2c_rbyte(3 , 7 , "NACK")
Call I2c_stop(3)
Waitms 10

I2cstart 'bus 4
I2cwbyte 69
I2crbyte I_data(8) , Ack
I2crbyte I_data(9) , Nack
I2cstop
Waitms 10
Goto de novo


End

Paulo

Link para o comentário
Compartilhar em outros sites

Oi Intruder,

1 - Nunca ví esse erro.... mas faz o seguinte, normalmente a gente coloca as sub-rotinas no final, experimente espalhar elas no meio do programa.

Uma vez tive um problema com uma tabela no final do programa, dava um erro doido também, tive de mudar o programa, o trecho que chamava essa tabela estava bem no iníçio, mudei ele e coloquei no meio do programa e resolveu....

2 - Vou pesquisar o datasheet e posto depois.

Paulo

Já tentei alguma coisa, mas se pelo menos eu soubesse o que realmente está acontecendo e porque, seria mais fácil contornar.

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...

Opa, legal mesmo, seria muito bom contar com você também nos Avrs !

Estou fazendo mais uma atualização da apostila, com alguns exemplos dos modos de baixo consumo, expansores I2c, e pequenas correções. Tudo com o Bascom.

Se tiver alguma dúvida, não hesite, pergunte !

Um abraço e boa diversão, Mr. Nintendo !

Paulo

Link para o comentário
Compartilhar em outros sites

Intruder,

Experimente usar o Config Submode= New , você tem de colocar todas as suas subrotinas logo no início do programa, e o compilador faz a realocação na compilação.

Se mesmo assim não funcionar, mande o fonte para mim, vou tentar dar umas mexidas.

Paulo

Eu ainda não testei, estou com tempo curto. Quando finalmente mexer no programa digo o que foi que ouve.

Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois...
aphawk disse:
Intruder,

Experimente usar o Config Submode= New , você tem de colocar todas as suas subrotinas logo no início do programa, e o compilador faz a realocação na compilação.

Se mesmo assim não funcionar, mande o fonte para mim, vou tentar dar umas mexidas.

Paulo

Demorei para testar, mas acabou não dando certo. O que eu quis fazer foi colocar mais umas 3 operações em ponto flutuante (para fazer um arredondamento) e passou a dar este erro (Backward jump out of range), o pior é que não acho nada na Internet que explique este erro. Tentei mudar todas as rotinas para o inicio do programa e também não deu certo.

Passo abaixo o meu programa (completo), acho que vai dar um trabalho enorme para você entender (são quase 1500 linhas). Fiz muita coisa de forma não muito eficiente mas com o objetivo de aprender a usar o Bascom AVR. Eu pendurei muita coisa do Adruino MEGA 1280, a maior parte com objetivo didático, quem sabe algum dia eu faça algo prático com ele. Se pelo menos eu soubesse que diabos de erro é este talvez desse para contornar

E imaginar que no passado distante, bem distante, já programei em assembler (Z80, 6502, 8088, e alguma coisa de co-processador aritmético) e hoje não consigo e nem tenho mais saco de aprender C, mas Bascom é simples demais, é quase brincadeira usar o Bascom. Eu já tinha perdido totalmente o tesão de programar, mas brincar com microcrontrolador é realmente divertido, pricipalmente quando se pode fazer em Basic (mesmo sendo a versão capada de basic do Bascom).

Spoiler

$regfile = "m1280def.dat" ' specify the used micro
$crystal = 16000000 ' Frequência do Cristal em Hz
$loadersize = &H1000 ' Bootloader de 4096 bytes
'$baud = 19200 ' use baud rate
$baud = 57600 ' use baud rate
$hwstack = 64 ' default use 32 for the hardware stack
$swstack = 128 ' default use 10 for the SW stack
$framesize = 256 ' default use 40 for the frame space
$map ' Informação para Debug
'$lib "stackcheck.lib"

Config Submode= New



$initmicro

Const Valor_prescale_int3 = 256
Const Interrupcoes_por_segundo_int3 = 10
Const Preload_int3 = 65535 - _xtal \(valor_prescale_int3 * Interrupcoes_por_segundo_int3) + 1

Const Valor_prescale_int4 = 256
Const Interrupcoes_por_segundo_int4 = 100
Const Tempo_aguardando = Interrupcoes_por_segundo_int4 * 2 ' Tempo em segundos
Const Preload_int4 = 65535 - _xtal \(valor_prescale_int4 * Interrupcoes_por_segundo_int4) + 1
Const T_acerta_segundos = 60 * 10 ' intervalo de tempo em segundos para acertar o relógio pelo RTC
Const T_acerta = Interrupcoes_por_segundo_int4 * T_acerta_segundos

'Endereço do DS3231
Const Ds3231w = &HD0 ' Endereço de escrita do RTC Ds3231
Const Ds3231r = &HD1 ' Endereço de leitura do RTC Ds3231

'Endereço do ADS1115 (END=>GND), conversor ADC de 16 bits
Const Ads1115w = &B10010000 ' Endereço de escrita do ADC ADS1115
Const Ads1115r = &B10010001 ' Endereço de leitura do ADC ADS1115

Config_i2c:
'configure the scl and sda pins
Config Sda = Portd.1
Config Scl = Portd.0
'Config I2cdelay = 2 ' para 500 kHz (aproximadamente)
Config I2cdelay = 5 ' para 200 kHz (aproximadamente)
'Config I2cdelay = 10 ' para 100 kHz
I2cinit

Config Spi = Soft , Din = Pinb.3 , Dout = Portb.2 , Ss = Portb.0 , Clock = Portb.1
'Dim var As Byte
Spiinit ' Init SPI state and pins.
'SPIOUT var , 1 'send 1 byte

Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc 'Now give power to the chip

Config Lcdpin = Pin , Db4 = Portg.5 , Db5 = Porte.3 , Db6 = Porth.3 , _
Db7 = Porth.4 , Rs = Porth.5 , E = Porth.6
Config Lcd = 16 * 2 ' Configurando o LCD

'Config Pinb.0 = Input ' Configura porta B0 para entrada
'Config Pinb.1 = Input ' Configura porta B1 para entrada
'Set Pinb.0 ' Liga resistência interna do AVR (valor é forçado a 1 se não está apertado)
'Set Pinb.1 ' Liga resistência interna do AVR (valor é forçado a 1 se não está apertado)

'S2 Alias Pinb.0 ' Define que porta B0 é S2
'S1 Alias Pinb.1 ' Define que porta B1 é S1

Buzzer:
Config Portd.7 = Output ' Define porta D7 para saída (Buzzer)
Buzzer Alias Portd.7 ' Define que porta D7 é saída para o Buzzer
Pino38 Alias Portd.7

Led:
Config Portb.7 = Output
Led Alias Portb.7

Config Porta.0 = Output
Config Porta.1 = Output
Config Porta.2 = Output
Config Porta.3 = Output
Config Porta.4 = Output
Config Porta.5 = Output
Config Porta.6 = Output
Config Porta.7 = Output
Led1 Alias Porta.0
Led2 Alias Porta.1
Led3 Alias Porta.2
Led4 Alias Porta.3
Led5 Alias Porta.4
Led6 Alias Porta.5
Led7 Alias Porta.6
Led8 Alias Porta.7

Pino22 Alias Porta.0
Pino23 Alias Porta.1
Pino24 Alias Porta.2
Pino25 Alias Porta.3
Pino26 Alias Porta.4
Pino27 Alias Porta.5
Pino28 Alias Porta.6
Pino29 Alias Porta.7
Porta = &HFF ' define que os leds estão apagados (bit = 1 apagado)


Com2:
'Config Com2 = 19200 , Synchrone = 0 , Parity = None , Stopbits = 1 , _
'Config Com2 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , _
Config Com2 = 115200 , Synchrone = 0 , Parity = None , Stopbits = 1 , _
Databits = 8 , Clockpol = 0

Config Clock = User ' we use I2C for the clock
Config Date = Dmy , Separator = /

Timer0_label: ' Usando para temporização do buzzer
Config Timer0 = Timer , Prescale = 1024 ' 61 interrupções por segundo
On Timer0 Tim0_isr

Timer3_label: ' Usado para fazer piscar o Led 5 vezes por segundo.
Config Timer3 = Timer , Prescale = Valor_prescale_int3 ' Valores possíveis para Prescale => 1|8|64|256|1024
On Timer3 Tim3_isr ' Executa rotina Tim3_usr nas interrupções do Timer3
Timer3 = Preload_int3
Enable Timer3

Timer4_label:
Config Timer4 = Timer , Prescale = Valor_prescale_int4 ' Valores possíveis para Prescale => 1|8|64|256|1024
On Timer4 Tim4_isr ' Executa rotina Tim4_usr nas interrupções do Timer4
Timer4 = Preload_int4
Enable Timer4

Enable Interrupts ' As interrupções são habilitadas

Rht22:
Declare Sub Get_th_rht22(t_ent As Single , H_ent As Single)
' vamos ligar o sensor no pino L.7
Dht_put Alias Portl.7 ' aqui usamos como saída
Dht_get Alias Pinl.7 ' e aqui usamos como entrada !
Dht_io_set Alias Ddrl.7 ' aqui mudamos entrada < - > saída
Pino 42 Alias Portl.7

Dim T As Single ' Temperatura
Dim H As Single ' Umidade
Dim T_cal As Word
Dim H_cal As Word
Dim Crc As Byte ' CRC do medidor
Dim Mybyte As Byte
Dim Myword As Word
Dim Sensor_data As String * 40 ' buffer para os 5 bytes
Dim Tmp_str16 As String * 16 ' string temporária para receber 16 bits
Dim Count As Byte ' contador para os bits recebidos
Dim Mostra_rht22 As Byte : Mostra_rht22 = 0

Set Dht_io_set
Set Dht_put

Bosh_bmp085:

Dim T1 As Single
Const Bmp085_read = &HEF ' BMP085 Read Address
Const Bmp085_write = &HEE ' BMP085 Write Address
'---BMP085 Variables------------------------------------------------------------
Dim I2c_send_buf(5) As Byte
Dim I2c_receive_buf(5) As Byte
'Calibration data variables
'Overlay used for easy access
Dim Calibration_data(22) As Byte
Dim Ac1 As Integer At Calibration_data(1) Overlay
Dim Ac2 As Integer At Calibration_data(1) + 2 Overlay
Dim Ac3 As Integer At Calibration_data(1) + 4 Overlay
Dim Ac4 As Word At Calibration_data(1) + 6 Overlay
Dim Ac5 As Word At Calibration_data(1) + 8 Overlay
Dim Ac6 As Word At Calibration_data(1) + 10 Overlay
Dim B1 As Integer At Calibration_data(1) + 12 Overlay
Dim B2 As Integer At Calibration_data(1) + 14 Overlay
Dim Mb As Integer At Calibration_data(1) + 16 Overlay
Dim Mc As Integer At Calibration_data(1) + 18 Overlay
Dim Md As Integer At Calibration_data(1) + 20 Overlay
Dim C3 As Single
Dim C4 As Single
Dim B11 As Single
Dim C5 As Single
Dim C6 As Single
Dim Mc1 As Single
Dim Md1 As Single
Dim X0 As Single
Dim X1 As Single
Dim X2 As Single
Dim Y0 As Single
Dim Y1 As Single
Dim Temp As Single
Dim P0 As Single
Dim P1 As Single
Dim P2 As Single
Dim Y2 As Single
Dim Alfa As Single
Dim Temp1 As Single
Dim S As Single
Dim X As Single
Dim Y As Single
Dim Z As Single
Dim Tu As Single
Dim Pu As Single
'Dim Pv As Long
Dim Pv As Single
Dim P_corrv As Long
'Dim Tv As Long
Dim Tv As Single
' --------------------------------------------
' | | | Temp_high | Temp_low | Type: LONG
' --------------------------------------------
Dim U_temperatur As Long
Dim U_temp_low As Byte At U_temperatur Overlay
Dim U_temp_high As Byte At U_temperatur + 1 Overlay
Dim T_bosh As Single
' ---------------------------------------------------------------------
' | | U_pressure_high | U_pressure_mid | U_pressure_low | Type: LONG
' ---------------------------------------------------------------------
Dim U_pressure As Long
Dim U_pressure_low As Byte At U_pressure Overlay
Dim U_pressure_mid As Byte At U_pressure + 1 Overlay
Dim U_pressure_high As Byte At U_pressure + 2 Overlay
Dim P_bosh As Single
'absolute altitude
Dim Altitude As Double , Alt As Single
Dim P_corr As Single
'-----BMP085 SUB's--------------------------------------------------------------
Declare Sub Bmp085_read_calibration_data()
Declare Sub Bmp085_initiate_measurement(byval Measurement_type As Byte)
'Measurement_type = 1 --> Temparature Measurement
'Measurement_type = 2 --> Ultra Low Power Pressure Measurement (OSS = 0)
'Measurement_type = 3 --> Standard Pressure Measurement (OSS = 1)
'Measurement_type = 4 --> High Resolution Pressure Measurement (OSS = 2)
'Measurement_type = 5 --> Ultra High Resolution Pressure Measurement (OSS = 3)
Declare Sub Bmp085_read_u_temp() 'Read uncompensated Temp Value
Declare Sub Bmp085_read_u_press() 'Read uncompensated Pressure Value
Declare Sub Bmp085_calc_temp() 'Calculate Temperature
Declare Sub Bmp085_calc_pressure()


' Fornece o número máximo de dias do mês na variável Global NDias
Declare Sub Diasmes(ano_ent As Word , Mes_ent As Byte )

' Formata a saída com dois dígitos e separador retornando na variável Entrada_Texto
Declare Sub Formata(entrada As Byte , Entrada_texto As String * 80 , _
Byval Complemento As String * 1)

Com2_config:
'Config Serialin1 = Buffered , Size = 20 , Bytematch = 65
'Config Serialin = Buffered , Size = 20
Config Serialout = Buffered , Size = 20
Config Serialout1 = Buffered , Size = 255
Open "COM2:" For Binary As #1

Dim B_com2 As Byte ' Entrada de dados Serial 2 (bluetooth)
Dim Cont As Dword , Cont_ant As Dword
Dim Contador As Dword , Contador2 As Dword , Contador_ant As Dword
Dim Var1dword As Dword , Var2dword As Dword
Dim Var1word As Word , Var2word As Word
Dim Var1byte As Byte , Var2byte As Byte
Dim Posicao As Byte , Buzzer_aux As Byte
Dim Acerta As Bit , Tecla_left_apertado As Bit , Tecla_right_apertado As Bit , _
Bissexto As Bit , Status_teclas As Bit , Tecla_left_aux As Bit , _
Tecla_right_aux As Bit , Mostra As Bit
Dim Centesimo As Byte , Segundo As Byte , Minuto As Byte , Hora As Byte
Dim Dia As Byte , Mes As Byte , Ano As Word , Ano2 As Word , Anoaux As Byte
Dim Ndias As Byte
Dim Tecla_aux As Word ' variável de retorno do ADC(0)
Dim Tecla As Byte
Tecla_right Alias Tecla.7
Tecla_up Alias Tecla.6
Tecla_down Alias Tecla.5
Tecla_left Alias Tecla.4
Tecla_select Alias Tecla.3

'Dim W As Word


Dim Laco As Bit
Dim Mostra_com2 As Bit : Mostra_com2 = 1 ' Mostra_com2 é variável que indica que deve mostra ou não Status na Com2
Dim Teclado_adc As Bit : Teclado_adc = 1 ' se 1 executa pega Gosub Pega_tecla_adc.
Dim Pisca_led As Byte : Pisca_led = 1 ' Pisca_led = (0) Apagado, (1) Piscando, (2) Aceso

Dim Linha1 As String * 80 , Linha2 As String * 80 , Aux As String * 1

'dim the used variables
Dim Lvar1 As Long , Mday As Byte , Bweekday As Byte , Strweekday As String * 10
Dim Strdate As String * 8 , Strtime As String * 8
Dim Bsec As Byte , Bmin As Byte , Bhour As Byte
Dim Bday As Byte , Bmonth As Byte , Byear As Byte
Dim Lsecofday As Long , Wsysday As Word , Lsyssec As Long , Wdayofyear As Word

Dim Temperatura As Single , Temp_msb As Byte , Temp_lsb As Byte
Dim Sec_alarme1 As Byte , Min_alarme1 As Byte , Hour_alarme1 As Byte
Dim Weekday_alarme1 As Byte , Day_alarme1 As Byte
Dim Min_alarme2 As Byte , Hour_alarme2 As Byte
Dim Weekday_alarme2 As Byte , Day_alarme2 As Byte

Dim Ds3231_control As Byte , Ds3231_control_status As Byte , Ds3231_aging_offset As Byte

Dim I_pt100 As Double , E_pt100 As Double , R_pt100 As Double , T_pt100 As Double
Dim I_pt100_single As Single , E_pt100_single As Single , R_pt100_single As Single , T_pt100_single As Single
Dim Linha3 As String * 160

'$hwcheck 'hw stack check on
'$framecheck
'$softcheck

Goto_inicio:
Goto Inicio

_init_micro:
'Set Ddrc.3
'Reset Portc.3 'LCD: R/W low
Return

' ==============================================================================

Sub Get_th_rht22(t_ent As Single , H_ent As Single)

Count = 0
Sensor_data = ""
Set Dht_io_set ' vira saída
Reset Dht_put ' nível 0 na saída
Waitms 25 ' tempo de espera pro dht11 25mseg
Set Dht_put ' volta nivel 1 na saída
Waitus 40 ' espera 40 useg
Reset Dht_io_set ' vira entrada
Waitus 40 ' espera mais 40 useg
If Dht_get = 1 Then ' se continua 1 tem algo errado
H_ent = 1 ' pois deveria estar em 0 !
Exit Sub
End If
'???? ?????? ??????? ? ?????? ???? ? ????? ?????????? ??????
Waitus 80 ' espera 80 useg
If Dht_get = 0 Then ' agora tem de estar 1 !
H_ent = 2 ' se tiver 0 , deu erro
Exit Sub
End If
'???? ??? ????????? ? ?????? ??????? ?????????, ????? ??????????
While Dht_get = 1 : Wend ' espera iniciar transmissão
Do
While Dht_get = 0 : Wend ' começou a transmissão
Waitus 30 ' voltou a nivel 1, espera 30 useg
If Dht_get = 1 Then ' se ápos 30 useg continua 1, então o bit é 1
Sensor_data = Sensor_data + "1" ' coloca 1 no buffer de dados
While Dht_get = 1 : Wend ' espera esse bit 1 terminar
Else ' se apos 30 uSeg virou 0, então o bit é 0
Sensor_data = Sensor_data + "0" ' coloca zero no buffer
End If
Incr Count ' incrementa contador de bits
Loop Until Count = 40 ' repete para 40 bits totais
Set Dht_io_set
Set Dht_put
'???????? ???????????? ?????????? ??????
Tmp_str16 = Left(sensor_data , 16) ' os primeiros 16 bits são a umidade
H_cal = Binval(tmp_str16) ' Vamos transformar para valor numérico
H_ent = H_cal
H_ent = H_ent / 10
Tmp_str16 = Left(sensor_data , 8)
Mybyte = Binval(tmp_str16)
Myword = Mybyte
Tmp_str16 = Mid(sensor_data , 9 , 8)
Mybyte = Binval(tmp_str16)
Myword = Myword + Mybyte

Tmp_str16 = Mid(sensor_data , 18 , 15) ' os próximos 15 são a temperatura sem o sinal.
T_cal = Binval(tmp_str16)
T_ent = T_cal
T_ent = T_ent / 10
Tmp_str16 = Mid(sensor_data , 17 , 8)
Mybyte = Binval(tmp_str16)
Myword = Myword + Mybyte
Tmp_str16 = Mid(sensor_data , 25 , 8)
Mybyte = Binval(tmp_str16)
Myword = Myword + Mybyte
Tmp_str16 = Right(sensor_data , 8) ' os últimos 8 são o CRC
Crc = Binval(tmp_str16) '
Tmp_str16 = Mid(sensor_data , 17 , 1) ' bit de sinal da temperatura
If Tmp_str16 = "1" Then
T_ent = 0 - T_ent
End If
Myword = Myword And &B11111111
Mybyte = Myword ' o CRC é a soma dos bytes da umidade e temperatura
If Mybyte <> Crc Then ' considerando 8 bits menos significativos
H_ent = 3 ' se não bateu, erro !
End If
End Sub ' final da subrotina

'--------------------------------------------------------------------------------------
'subrotina para ler o sensor de pressão BMP085
Sub Bmp085_read_calibration_data()
'Read Calibration Data from Sensor (11x 16Bit Values)
'for optional Error checking --> None of the Values are &H0000 or &HFFFF
Calibration_data(1) = &HAA
I2creceive Bmp085_write , Calibration_data(1) , 1 , 22
'We need to swap High Byte with Low Byte of all integers
Swap Ac1
Swap Ac2
Swap Ac3
Swap Ac4
Swap Ac5
Swap Ac6
Swap B1
Swap B2
Swap Mb
Swap Mc
Swap Md
' agora é que vem a doideira.... faremos os cálculos em
' PONTO FLUTUANTE, pois o programa ficou BEM MENOR do que
' se fizéssemos os cálculos do Datasheet da Bosch, que
' são todos com variáveis tipo LONG, e tem um montão de
' cálculos intermediários, ocupando muito mais do que
' a memória disponível no ATMEGA48.
' Consulte o documento BMP085-Calcs.PDF
'
C3 = 0.004882812499 * Ac3
C4 = 0.000000030517 * Ac4
B11 = 0.00002384186 * B1
C5 = 0.000000190734 * Ac5
C6 = Ac6
Mc1 = 0.08 * Mc
Md1 = Md / 160.0000121
X0 = Ac1
X1 = 0.019531250 * Ac2
X2 = 0.000762939453 * B2
Y0 = 32768 * C4
Y1 = C4 * C3
Y2 = C4 * B11
P0 = 2.36437500
P1 = 0.9929838181
P2 = 0.000004420872
End Sub

'-----------------------------------------------------------------------------------
Sub Bmp085_initiate_measurement(byval Measurement_type As Byte)
Local M_type As Byte , Wait_time As Byte
Select Case Measurement_type
Case 1: ' 1 = Temperature Measurement
M_type = &H2E
Wait_time = 5 ' ms
Case 5:
M_type = &HF4 ' 5 =Ultra High Resolution Pressure (OSS = 3)
Wait_time = 26 ' ms
End Select
I2cstart
I2cwbyte Bmp085_write
I2cwbyte &HF4
I2cwbyte M_type
I2cstop
' Wait_time = between 5 and 26ms depending on above selected measurement method
Waitms Wait_time
End Sub

'-----------------------------------------------------------------------------
Sub Bmp085_read_u_temp()
I2cstart
I2cwbyte Bmp085_write
I2cwbyte &HF6
I2crepstart
I2cwbyte Bmp085_read
I2crbyte U_temp_high , Ack
I2crbyte U_temp_low , Nack
I2cstop
Tu = U_temperatur
End Sub

'----------------------------------------------------------------------------
Sub Bmp085_read_u_press()
I2c_receive_buf(1) = &HF6
I2creceive Bmp085_write , I2c_receive_buf(1) , 1 , 3
Pu = 256 * I2c_receive_buf(1)
Pu = Pu + I2c_receive_buf(2)
Temp = I2c_receive_buf(3) / 256
Pu = Pu + Temp
End Sub

'------------------------------------------------------------------------------
Sub Bmp085_calc_temp()
' Calculate true Temperature
Alfa = Tu - C6
Alfa = Alfa * C5
Temp = Alfa + Md1
Temp = Mc1 / Temp
T_bosh = Alfa + Temp
Tv = T_bosh
End Sub

'-----------------------------------------------------------------------------
Sub Bmp085_calc_pressure()
' Calculate true pressure
S = T_bosh - 25
X = X1 * S
X = X + X0
Temp = S * S
Temp = Temp * X2
X = X + Temp
Y = Y1 * S
Y = Y + Y0
Temp = S * S
Temp = Y2 * Temp
Y = Y + Temp
Z = Pu - X
Z = Z / Y
P_bosh = P1 * Z
P_bosh = P_bosh + P0
Temp = Z * Z
Temp = Temp * P2
Pv = P_bosh + Temp
P_corrv = P_bosh * 1.09328 ' FATOR CORREÇÃO PARA ALTURA=746 MTS
Altitude = Pv
Altitude = Altitude / 1013.25
Altitude = Log(altitude)
Altitude = Altitude * 0.19029495718
Altitude = Exp(altitude) ' Altitude ^ 0.19029495718
Altitude = 1 - Altitude
Altitude = 44330 * Altitude ' altitude em relação ao nível do mar em metros
Alt = Altitude
End Sub

' ==============================================================================

' Fornece o número máximo de dias do mês na variável NDias

Sub Diasmes(ano_ent As Word , Mes_ent As Byte )

Local Div4 As Word

Div4 = Ano_ent And 3 ' equivalente a Mod 4, e se é maior que 0 não é divisível

If Div4 > 0 Then
Reset Bissexto
Else
Set Bissexto
Var2word = Ano_ent Mod 400 ' se é maior que 0 não é divisível
Var1word = Ano_ent Mod 100 ' se é maior que 0 não é divisível
If Var1word = 0 And Var2word > 0 Then
Reset Bissexto
End If
End If
If Mes_ent = 2 Then
Ndias = 28 + Bissexto
Else
Var1byte = Mes_ent And &B00001001
If Var1byte = &B00001000 Or Var1byte = &B00000001 Then
Ndias = 31
Else
Ndias = 30
End If
End If

End Sub

' ==============================================================================

' Formata a saída com dois dígitos e separador retornando na variável Entrada_Texto

Sub Formata(entrada As Byte , Entrada_texto As String * 80 , _
Byval Complemento As String * 1)

If Entrada < 10 Then
Entrada_texto = Entrada_texto + "0"
End If
Entrada_texto = Entrada_texto + Str(entrada)
Entrada_texto = Entrada_texto + Complemento

End Sub

' ==============================================================================

'only when we use I2C for the clock we need to set the clock date time

'called from datetime.lib
Dim Weekday As Byte
Getdatetime:
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte 0 ' Endereço no Ds3231

I2cstart ' Generate start code
I2cwbyte Ds3231r ' Enviando endereço de leitura no Ds3231
I2crbyte _sec , Ack
I2crbyte _min , Ack ' MINUTES
I2crbyte _hour , Ack ' Hours
I2crbyte Weekday , Ack ' Day of Week
I2crbyte _day , Ack ' Day of Month
I2crbyte _month , Ack ' Month of Year
I2crbyte _year , Nack ' Year
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura no relógio RTC via i2c
_sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour)
_day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year)
Else ' ou usando o relógio via Timer1
_sec = Segundo : _min = Minuto : _hour = Hora
_day = Dia : _month = Mes : Var2word = Ano Mod 100 : _year = Var2word
End If
Return

Weekdays:
Data "Segunda" , "Terça" , "Quarta" , "Quinta" , "Sexta" , "Sábado" , "Domingo"

Setdate:
_day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year)
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte 4 ' Endereço no Ds3231
I2cwbyte _day ' Send Data to dia
I2cwbyte _month ' Month
I2cwbyte _year ' Yesr
I2cstop
Return

Setdate_aux:
Var1word = Ano Mod 100
_year = Var1word
_month = Mes
_day = Dia
Gosub Setdate
Return

Settime:
_sec = Makebcd(_sec) : _min = Makebcd(_min) : _hour = Makebcd(_hour)
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte 0 ' Endereço no Ds3231
I2cwbyte _sec ' Send Data to SECONDS
I2cwbyte _min ' MINUTES
I2cwbyte _hour ' Hours
I2cstop
Return

Settime_aux:
_hour = Hora
_min = Minuto
_sec = Segundo
Gosub Settime
Return

Getalarme1:
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte &H07 ' Endereço Alarme1 no Ds3231

I2cstart ' Generate start code
I2cwbyte Ds3231r ' Enviando endereço de leitura no Ds3231
I2crbyte Sec_alarme1 , Ack ' Segundos Alarme1
I2crbyte Min_alarme1 , Ack ' Minutos Alarme1
I2crbyte Hour_alarme1 , Ack ' Horas Alarme1
I2crbyte Weekday_alarme1 , Ack ' Dia da Semana Alarme1
I2crbyte Day_alarme1 , Nack
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura no relógio RTC via i2c
Sec_alarme1 = Makedec(sec_alarme1) : Min_alarme1 = Makedec(min_alarme1) ' Dia do Mês Alarme1
Hour_alarme1 = Makedec(hour_alarme1) : Day_alarme1 = Makedec(day_alarme1)
End If
Return

Setalarme1:
Sec_alarme1 = Makebcd(sec_alarme1) : Min_alarme1 = Makebcd(min_alarme1)
Hour_alarme1 = Makebcd(hour_alarme1) : Day_alarme1 = Makebcd(day_alarme1)
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte &H07 ' Endereço Alarme1 no Ds3231
I2cwbyte Sec_alarme1 ' Send Data to SECONDS
I2cwbyte Min_alarme1 ' MINUTES
I2cwbyte Hour_alarme1 ' Hours
I2cwbyte Weekday_alarme1
I2cwbyte Day_alarme1
I2cstop
Return

Getalarme2:
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte &H0B ' Endereço Alarme2 no Ds3231

I2crbyte Min_alarme2 , Ack ' Minutos Alarme2
I2crbyte Hour_alarme2 , Ack ' Horas Alarme2
I2crbyte Weekday_alarme2 , Ack ' Dia da Semana Alarme2
I2crbyte Day_alarme2 , Nack ' Dia do Mês Alarme2
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura no relógio RTC via i2c
Min_alarme2 = Makedec(min_alarme2) : Hour_alarme2 = Makedec(hour_alarme2)
Day_alarme2 = Makedec(day_alarme2)
End If
Return

Setalarme2:
Min_alarme2 = Makebcd(min_alarme2) : Hour_alarme2 = Makebcd(hour_alarme2)
Day_alarme2 = Makebcd(day_alarme2)
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte &H0B ' Endereço Alarme2 no Ds3231
I2cwbyte Min_alarme2 ' MINUTES
I2cwbyte Hour_alarme2 ' Hours
I2cwbyte Weekday_alarme2
I2cwbyte Day_alarme2
I2cstop
Return

Gettemp:
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte &H11 ' Endereço Temperatura no Ds3231

I2cstart ' Generate start code
I2cwbyte Ds3231r ' Enviando endereço de leitura no Ds3231
I2crbyte Temp_msb , Ack
I2crbyte Temp_lsb , Nack
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura no relógio RTC via i2c
Rotate Temp_lsb , Right , 6
Temperatura = Temp_lsb / 4
Temperatura = Temperatura + Temp_msb
End If
Return

Getstatus:
I2cstart ' Generate start code
I2cwbyte Ds3231w ' Enviando endereço de escrita no Ds3231
I2cwbyte &H0E ' Endereço do Status no Ds3231

I2cstart ' Generate start code
I2cwbyte Ds3231r ' Enviando endereço de leitura no Ds3231
I2crbyte Ds3231_control , Ack
I2crbyte Ds3231_control_status , Ack
I2crbyte Ds3231_aging_offset , Nack
I2cstop
Return

Pega_hora_rtc:
Reset Laco
Do
Gosub Getdatetime ' Pega a Data e Hora do RTC

If Err > 0 Then ' se o RTC não está conectado pula e usa os valores padrão
Exit Do
End If
If _sec <> Segundo And Laco = 1 Then
Segundo = _sec : Centesimo = 0 : Minuto = _min : Hora = _hour
Dia = _day : Mes = _month : Ano = _year + 2000
Exit Do
Else
Laco = Not Laco
End If
Loop
Return


Dim Tecla_aux2 As Word , Conta_tecla As Byte
Pega_tecla_adc0:
Conta_tecla = 0
Do
Waitms 1
Tecla_aux = Getadc(0)
If Tecla_aux <> Tecla_aux2 Then
Tecla_aux2 = Tecla_aux
Conta_tecla = 0
Else
Incr Conta_tecla
If Conta_tecla > 5 Then
Exit Do
End If
End If
Loop
Pega_tecla_simula_lcd:
Tecla = &B11111000 ' Tecla_right, Tecla_up, Tecla_down, Tecla_left, Tecla_Select
If Tecla_aux < 800 Then
'Locate 2 , 10
'Lcd Tecla_aux ; " "
Select Case Tecla_aux
Case Is < 50 :
Reset Tecla_right
Case Is < 150 :
Reset Tecla_up
Case Is < 350 :
Reset Tecla_down
Case Is < 550 :
Reset Tecla_left
If Teclado_adc = 0 And Acerta = 0 Then
Reset Acerta
Posicao = 1
Reset Status_teclas
End If
Case Is < 800 :
Reset Tecla_select
End Select
End If
Return


Mostrahora:
'Home
'Lowerline
Locate 1 , 1

If Err = 0 Then
Lcd Time$
Else
Linha1 = ""
Call Formata(hora , Linha1 , ":")
Call Formata(minuto , Linha1 , ":")
Call Formata(segundo , Linha1 , "")
Lcd Linha1 ' usando o RTC Ds3231 ou o relógio via Timer1
End If
Return


Mostradata:
'Lowerline
Locate 2 , 1
If Err = 0 And Mostra = 1 Then
Gosub Gettemp
End If
If Acerta = 0 And Mostra = 1 And Err = 0 Then
'Lcd Str(temperatura) ; " C" ; " "
Lcd Fusing(temperatura , "##.##") ; Chr(223) ; "C "
Else
If Err = 0 Then
Lcd Date$
Else
Ano2 = Ano Mod 100
Anoaux = Ano2
Linha2 = ""
Call Formata(dia , Linha2 , "/")
Call Formata(mes , Linha2 , "/")
Call Formata(anoaux , Linha2 , "")
Lcd Linha2
End If
End If
Return

Getadc_i_pt100:
Dim Lsbadc As Byte , Msbadc As Byte
Dim Valoradc As Word At Lsbadc Overlay

Dim Cont_pt100 As Byte
Dim I_dw_pt100 As Dword , E_dw_pt100 As Dword
Const Nmedia = 16 ' Quantidade de valores para fazer a média

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B01001010 ' MSB do registrador
' 0 : No effect
' 100 : AINP = AIN0 and AINN = GND
' (================ fora ============ 101 : AINP = AIN1 and AINN = GND =================)
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
Waitus 1
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura do ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura do ADC (ADS1115) via i2c
Var1dword = Valoradc
I_dw_pt100 = I_dw_pt100 + Var1dword
If Cont_pt100 = Nmedia Then
I_dw_pt100 = I_dw_pt100 / Nmedia
I_pt100 = I_dw_pt100

'I_pt100 = Valoradc
I_pt100 = I_pt100 * 7.81273842585528e-8 ' * 0.256 / (32767 * 100) => Valor da corrente no PT100 em Amperes
End If
End If
Return

Getadc_pt100:

I_dw_pt100 = 0
E_dw_pt100 = 0
For Cont_pt100 = 1 To Nmedia ' Calcula a média das leituras

Gosub Getadc_i_pt100

I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita no ADS1115
I2cwbyte &B00000001 ' Registrador de configuração
I2cwbyte &B00111010 ' MSB do registrador
' 0 : No effect
' 011 : AINP = AIN2 and AINN = AIN3
' 101 : FS = ±0.256V
' 0 : Continuous conversion mode
I2cwbyte &B11100011 ' LSB do registrador
' 111 : 860SPS
' 0 : Traditional comparator with hysteresis (default)
' 0 : Active low (default)
' 0 : Non-latching comparator (default)
' 11 : Disable comparator (default)
I2cstop
Waitms 2 ' Espera 2 ms

' Lê valor do ADC
I2cstart ' Generate start code
I2cwbyte Ads1115w ' Enviando endereço de escrita do ADS1115
I2cwbyte &B00000000 ' Registrador de conversão
I2cstop
Waitus 1
I2cstart
I2cwbyte Ads1115r ' Enviando endereço de leitura no ADS1115
I2crbyte Msbadc , Ack ' Valor mais significativo do ADC
I2crbyte Lsbadc , Nack ' Valor menos significativo do ADC
I2cstop
If Err = 0 Then ' Err = 0 => não houve erro na leitura ADC (ADS1115) via i2c
Var1dword = Valoradc
E_dw_pt100 = E_dw_pt100 + Var1dword
If Cont_pt100 = Nmedia Then
E_dw_pt100 = E_dw_pt100 / Nmedia
E_pt100 = E_dw_pt100

'E_pt100 = Valoradc
E_pt100 = E_pt100 * 7.81273842585528e-6 ' * 0.256 / 32767 => Valor em Volts
R_pt100 = E_pt100 / I_pt100 ' Valor da resistência no PT100 em Ohms
T_pt100 = 100 - R_pt100
T_pt100 = T_pt100 * 2.32078e-4
T_pt100 = T_pt100 + 0.152726203204
T_pt100 = Sqr(t_pt100)
T_pt100 = 0.390802 - T_pt100
T_pt100 = T_pt100 / 1.16039e-4 ' Valor da temperatura no PT100 em ºC
End If
End If
Next Cont_pt100

Return


'------------------------------------------------------------------
' Sub-rotina de timer0, chamada para marcar o tempo do Buzzer tocando.
'
Tim0_isr:
If Buzzer_aux < 6 Then
Incr Buzzer_aux
Else
Reset Buzzer ' Desliga o Buzzer
Disable Timer0
End If
Return

'------------------------------------------------------------------
' Sub-rotina de timer3, chamada para fazer o led piscar.
'
Tim3_isr:
Timer3 = Preload_int3
Led = Not Led
'Toggle Led
Return

'------------------------------------------------------------------
' Sub-rotina de timer4, chamada 100 vezes por segundo, dependendo da Constante Interrupções_por_segundo
'
Tim4_isr:

Timer4 = Preload_int4

Incr Contador
If Centesimo < 99 Then
Incr Centesimo
Else
Centesimo = 0
If Segundo < 59 Then
Incr Segundo
Else
Segundo = 0
If Minuto < 59 Then
Incr Minuto
Else
Minuto = 0
If Hora < 23 Then
Incr Hora
Else
Hora = 0
If Dia < Ndias Then
Incr Dia
Else
Dia = 1
If Mes < 12 Then
Incr Mes
Else
Mes = 1
Incr Ano
End If
Call Diasmes(ano , Mes)
End If
End If
End If
End If
Incr Cont
End If

Return

'------------------------------------------------------------------

Inicio:

Contador = 0
Cont = 0
Centesimo = 00
Segundo = 00
Minuto = 30
Hora = 12
Dia = 01
Mes = 01
Ano = 2012


Gosub Pega_hora_rtc
Call Diasmes(ano , Mes)
Cont_ant = 1 ' força que mostre no LCD

Cls

Set Tecla_left_apertado ' = 1 se o botão esquerdo não foi apertado
Set Tecla_right_apertado ' = 1 se o botão direito não foi apertado
Posicao = 0
Reset Acerta ' = 0 se não está em modo de edição
Reset Mostra ' = 1 mostra Temperatura (se o RTC está conectado).

Reset Buzzer
Buzzer_aux = 0

' Vamos ler os dados de calibração do BMP 085
Call Bmp085_read_calibration_data()

Comeca_loop:
Do
If Teclado_adc = 1 Then
Gosub Pega_tecla_adc0
Else
Gosub Pega_tecla_simula_lcd
Set Teclado_adc
End If
Tecla_left_aux = Tecla_left
Tecla_right_aux = Tecla_right
If Tecla_right_aux = 0 Then
If Tecla_right_apertado = 1 Then
Buzzer_aux = 0
Set Buzzer ' Liga o Buzzer.
Enable Timer0
End If
Else
Disable Timer0
Reset Buzzer ' Desliga o Buzzer.
End If
If Tecla_left_aux = 1 And Tecla_left_apertado = 1 Then Status_teclas = 0
If Acerta = 0 And Tecla_right_aux = 0 Then ' se Tecla_right (botão direito) está apertado mostra Temperatura ou não mostra (permuta)
Reset Status_teclas
If Tecla_right_apertado = 1 Then
Reset Tecla_right_apertado
Mostra = Not Mostra
End If
Else
If Acerta = 0 And Tecla_right_apertado = 0 And Tecla_right_aux = 1 Then
Set Tecla_right_apertado
End If
If Acerta = 0 And Tecla_left_aux = 0 Then ' Botão da esquerda (Tecla_left=0) apertado entra em modo de edição (Acerta => 1)
Reset Tecla_left_apertado
If Status_teclas < 1 Then
Set Status_teclas
Contador_ant = Contador ' Começa a contar o tempo até 2 segundos
Else
Var1dword = Contador - Contador_ant
If Var1dword >= Tempo_aguardando Then ' Até ser maior ou igual a 2 segundos
Posicao = 1
End If
End If
Else
If Acerta = 0 And Posicao = 1 And Tecla_left_aux = 1 Then
Set Acerta
Set Tecla_left_apertado
Reset Status_teclas
Else
If Tecla_left_aux = 0 And Tecla_right_aux = 1 Then ' Botão da esquerda (Tecla_left=0) apertado e Botão da direita (Tecla_right=1) não apertado
If Tecla_left_apertado = 1 Then
Reset Tecla_left_apertado
If Posicao < 6 Then
Incr Posicao
Else
Posicao = 0
Reset Acerta
Reset Status_teclas
End If
End If
Elseif Tecla_left_aux = 1 And Tecla_left_apertado = 0 Then
Set Tecla_left_apertado
End If
End If
End If
End If

If Posicao > 0 And Posicao <= 6 Then ' colocar o cursor piscando na posição de edição
If Posicao < 4 Then
Var1byte = Posicao - 1
Var1byte = Var1byte * 3
Var1byte = Var1byte + 1
Locate 1 , Var1byte ' Linha 1 do LCD
Else
Var1byte = 6 - Posicao
Var1byte = Var1byte * 3
Var1byte = Var1byte + 1
Locate 2 , Var1byte ' Linha 2 do LCD
End If
Cursor On Blink
Else
Posicao = 0
Reset Acerta
Cursor Off Blink
End If

Acerta_hora:
If Tecla_left_aux = 1 Then ' Botão da esquerda (Tecla_left=1) não apertado
If Posicao > 0 And Acerta = 1 Then
If Tecla_right_aux = 0 And Tecla_right_apertado = 1 Then ' Botão da direita (Tecla_right=0) apertado
Reset Tecla_right_apertado
Select Case Posicao
Case 1 :
If Hora < 23 Then
Incr Hora
Else
Hora = 0
End If
Gosub Settime_aux
Gosub Mostrahora
Case 2 :
If Minuto < 59 Then
Incr Minuto
Else
Minuto = 0
End If
Gosub Settime_aux
Gosub Mostrahora
Case 3 :
If Segundo >= 30 Then
If Minuto < 59 Then
Incr Minuto
Else
Minuto = 0
End If
End If
Timer4 = Preload_int4
Centesimo = 0
Segundo = 0
Gosub Settime_aux
Gosub Mostrahora
Case 4 To 5 :
If Posicao = 4 Then
Var1word = Ano Mod 100
If Var1word < 99 Then
Incr Ano
Else
Ano = Ano - Var1word
End If
Else
If Mes < 12 Then
Incr Mes
Else
Mes = 1
End If
End If
Call Diasmes(ano , Mes)
If Dia > Ndias Then Dia = Ndias
Gosub Setdate_aux
Gosub Mostradata
Case 6 :
If Dia < Ndias Then
Incr Dia
Else
Dia = 1
End If
Gosub Setdate_aux
Gosub Mostradata
End Select
Cont_ant = 0
Elseif Tecla_right_aux = 1 And Tecla_right_apertado = 0 Then ' Botão da direita (Tecla_right=1) não apertado
Set Tecla_right_apertado
End If
Elseif Tecla_left_apertado = 0 Then
Set Tecla_left_apertado
End If
End If

Mostra_no_lcd:
Dim Segundos_dia As Dword
Dim Segundos_dia_ant As Dword

Gosub Getdatetime
Segundos_dia = Secofday()

If Cont_ant <> Cont And Err > 0 Or Err = 0 And Segundos_dia <> Segundos_dia_ant Then
If Err = 0 Then
Segundos_dia_ant = Segundos_dia
End If
Cont_ant = Cont
If Contador > Contador2 Then
Contador2 = Contador + T_acerta ' tempo em segundos para acertar o relogio automaticamente pelo RTC
Gosub Pega_hora_rtc ' acerta o relógio interno pelo RTC
End If
Gosub Mostrahora
Gosub Mostradata

If Mostra_rht22 = 2 Then
Call Get_th_rht22(t , H)
If H > 3 Then
Locate 1 , 10
Lcd Fusing(t , "##.#") ; Chr(223) ; "C "
Locate 2 , 9
Lcd " " ; Fusing(h , "##.#") ; "% "
Else
Locate 1 , 10
Lcd " "
Locate 2 , 9
Lcd " "
End If
Mostra_rht22 = 1
Else
Call Bmp085_initiate_measurement(1) ' 1 = Temperature Measurement
If Err = 0 Then ' se não ocorreu erro
Call Bmp085_read_u_temp()
Call Bmp085_initiate_measurement(5) ' Very High Resolution Pressure Measur. (OSS=3)
' ^ type in Measurement_type !!!! <<<<<-----------
Call Bmp085_read_u_press()
Call Bmp085_calc_temp() ' Calculate calibrated Temperature
Call Bmp085_calc_pressure() ' Calculate calibrated Pressure

Locate 1 , 10
Lcd Fusing(tv , "##.#") ; Chr(223) ; "C "
Locate 2 , 9
Lcd Fusing(pv , "##.#") ; "mB "
End If

Incr Mostra_rht22
End If

Mostra_pt100:

Gosub Getadc_pt100
If Err = 0 Then
Linha3 = ""
Else
Linha3 = "erro"
End If

'W = _hwstackstart - _hw_lowest
'Locate 1 , 10 : Lcd "H" ; W ; " "
'Print _fw_highest
'If _fw_highest > 0 Then
'W = _frame_high - _fw_highest
'Lcd "F" ; W ; " "
'End If
'Print _sw_lowest
'W = _hwstack_low - _sw_lowest
'Locate 2 , 10 : Lcd "SW" ; W

'Print #1 , "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
'Goto Pula

Ano2 = Ano Mod 100
Anoaux = Ano2
Linha2 = ""
Call Formata(dia , Linha2 , "/")
Call Formata(mes , Linha2 , "/")
Call Formata(anoaux , Linha2 , " ")
Call Formata(hora , Linha2 , ":")
Call Formata(minuto , Linha2 , ":")
Call Formata(segundo , Linha2 , ".")
Call Formata(centesimo , Linha2 , "")
Linha2 = Linha2 + " "
Gosub Gettemp ' Pega temperatura do RTC DS3231
Linha2 = Linha2 + Fusing(temperatura , "#.##")
Linha2 = Linha2 + "ºC "
'Fusing(temperatura , "#.##") ; Chr(223) ; "C "
Linha2 = Linha2 + "TH => "
Linha2 = Linha2 + Fusing(t , "#.#")
Linha2 = Linha2 + "ºC "
Linha2 = Linha2 + Fusing(h , "#.#")
Linha2 = Linha2 + "% "
Linha2 = Linha2 + Fusing(pv , "#.#")
Linha2 = Linha2 + "mB "
Linha2 = Linha2 + Fusing(alt , "#.##")
Linha2 = Linha2 + "mts "
Linha2 = Linha2 + Fusing(tv , "#.#")
Linha2 = Linha2 + "ºC"



If Linha3 <> "erro" Then
I_pt100_single = I_pt100
E_pt100_single = E_pt100
R_pt100_single = R_pt100
T_pt100_single = T_pt100
Linha3 = "ADS1115 (PT100)=> I = "
Linha3 = Linha3 + Fusing(i_pt100_single , "#.#########")
Linha3 = Linha3 + "A E = "
Linha3 = Linha3 + Fusing(e_pt100_single , "#.#######")
Linha3 = Linha3 + "V R = "
Linha3 = Linha3 + Fusing(r_pt100_single , "#.#####" )
Linha3 = Linha3 + "ohms T ="
'Linha3 = Linha3 + Fusing(t_pt100_single , "#.###")

T_pt100_single = T_pt100_single * 20
T_pt100_single = Round(t_pt100_single)
T_pt100_single = T_pt100_single / 20

Linha3 = Linha3 + Fusing(t_pt100_single , "#.##")
Linha3 = Linha3 + "ºC "
End If

Print Linha2
If Linha3 <> "erro" Then
Print Linha3
End If
If Mostra_com2 > 0 Then
Print #1 , Linha2
If Linha3 <> "erro" Then
Print #1 , Linha3
End If
End If

Pula:
End If
B_com2_pega_tecla:
B_com2 = Inkey(#1)
If B_com2 <> 0 Then
'Print #1 , Str(b_com2)
Select Case B_com2
Case "1" : ' Led1
Led1 = Not Led1
Case "!" :
Set Led1 ' apaga o Led1

Case "2" : ' Led2
Led2 = Not Led2
Case "@" :
Set Led2 ' apaga o Led2

Case "3" : ' Led3
Led3 = Not Led3
Case "#" :
Set Led3 ' apaga o Led3

Case "4" : ' Led4
Led4 = Not Led4
Case "$" :
Set Led4 ' apaga o Led4

Case "5" : ' Led5
Led5 = Not Led5
Case "%" :
Set Led5 ' apaga o Led5

Case "6" : ' Led6
Led6 = Not Led6
Case "¨" :
Set Led6 ' apaga o Led6

Case "7" : ' Led7
Led7 = Not Led7
Case "&" :
Set Led7 ' apaga o Led7

Case "8" : ' Led8
Led8 = Not Led8
Case "*" :
Set Led8 ' apaga o Led8

Case "<" : ' Simula tecla LEFT do LCD
Reset Teclado_adc
Tecla_aux = 400
Case "," :
Reset Teclado_adc
Tecla_aux = 400

Case ">" : ' Simula tecla RIGHT do LCD
Reset Teclado_adc
Tecla_aux = 20
Case "." :
Reset Teclado_adc
Tecla_aux = 20

Case "P" : ' Para de mostrar STATUS na COM2 - (P)ara
Reset Mostra_com2
Case "p" :
Reset Mostra_com2

Case "C" : ' Continua a mostrar STATUS na COM2 - (C)ontinua
Set Mostra_com2
Case "c" :
Set Mostra_com2

Case "L" : ' Pisca Led
Pisca_led = 1
Case "l" :
Pisca_led = 1

Case "K" : ' Acende Led
Pisca_led = 2
Case "k" :
Pisca_led = 2

Case "J" : ' Apaga o Led
Pisca_led = 0
Case "j" :
Pisca_led = 0
End Select

Select Case Pisca_led
Case 1 : ' Pisca Led
Enable Timer3
Case 0 :
Disable Timer3 ' Apaga Led
Reset Led
Case 2 : ' Acende Led
Disable Timer3
Set Led
End Select
End If
Loop

'End 'end program

 

 

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...