Ir ao conteúdo

aphawk

Membro Pleno
  • Posts

    8.316
  • Cadastrado em

  • Última visita

Tudo que aphawk postou

  1. CIS, É a mesma coisa que contar os ciclos de clock ! Um timer de 8 bits só pode contar de 0 a 255, ou seja , 256 contagens. E cada timer possui um prescaler, que nada mais é que um divisor da frequência do clock do oscilador. Usando um precaler de 1024 é a mesma coisa que dizer que a cada 1024 ciclos do clock do oscilador é aplicado 1 pulso ao timer de 8 bits, ou seja, se o seu cristal for de 1.024 Mhz , será aplicado ao timer uma frequência de exatos 1 KHz. Vamos fazer um exemplo completo para você entender melhor. Suponha que temos um cristal oscilador de 1.048576 Mhz. Se programarmos o prescaler para 1024, teremos aplicado ao timer a frequência de exatos 1024 Hz. Agora, se simplesmente deixarmos o timer trabalhar sem recarregar nenhum valor, ele vai gerar UMA interrupção a cada 256 ciclos do clock aplicado a ele. então, teremos 1024 / 256 = 4 interrupções por segundo, certo ? Dentro da rotina de interrupção do timer, fazemos um contador, que a cada vez que ocorre essa interrupção somamos a ele o valor de 262.144 (1024 x 256 ). E sempre comparamos esse valor ao valor do cristal oscilador, que é 1.048.576 . Quando o valor da nossa contagem for maior ou igual ao do cristal, significa que já se passou um segundo com certeza, e podemos incrementar o nosso contador de segundos. E ao mesmo tempo, recarregamos o nosso contador, com os ciclos que tenham ultrapassado a frequência do cristal, que por acaso, devido aos valores que escolhí para o cristal, na quarta vez que ocorre a interrupção a contagem chega a 1.048.576, e a diferença resulta em zero ! Ou seja, o contador vai começar novamente todo o processo a partiz do valor zero. Caso a nossa contagem seja menor do que o valor do cristal, simplesmente saímos da interrução sem fazer nada ! Repare que isto equivale a contar os ciclos de clock do cristal oscilador ! E como nunca interferimos no valor do timer, ou seja, sempre ele vai contar 256 ciclos antes de gerar uma interrupção, temos um relógio tão preciso quanto for o cristal utilizado no clock. Se quiser um exemplo de programação, posso postar um código simples que utilizo em Basic do Bascom. E quanto ao estudo, voce tem mesmo de estudar o funcionamento dos periféricos de um microcontrolador Pic para entender como eles funcionam. O resto são pequenos truques de programação que a gente vai aprendendo com os outros, e vamos incorporando à nossa biblioteca mental... Paulo
  2. CIS, Meio atrasado,mas quem sabe ainda ajuda.... Existe uma técnica bem interessante, que é deixar o Timer estourar, sem recarregar o valor do timer! É muito usada quando se usa linguagem de alto nível. Só precisamos criar uma variável para usar como contador de ciclos de clock, assim usaremos apenas um cristal, que é o que vai gerar o clock do Pic. Vou supor aqui o caso do Timer0, como 8 bits, e com um divisor de 1024. A cada vez que se passarem 256 x 1024 ciclos de clock, o timer gera uma interrupção, e voce vai simplesmente incrementar um contador de exatos 256 x 1024 ! Após isso, você compara com a frequência do cristal em Hertz, e se for maior ou igual, significa que já passou um segundo, e neste caso voce vai recomeçar o contador com a sobra da conta (256x1024) - Frequência do cristal. Quando acontecer isto, voce seta um flag, para que o seu programa principal saiba que já se passou um segundo. E zera o flag. Ou pode fazer a rotina de incrementar segundos, minutos, etc, dentro da própria interrupção, mas eu costumo fazer no programa principal. Caso o contador seja menor do que a frequência do cristal, você simplesmente sai da interrupção. Desta maneira, a longo prazo o seu relógio vai estar matemáticamente exato , tão preciso quanto for o seu cristal oscilador. Pode usar qualquer frequência de cristal, 4Mhz, 20Mhz, qqr um que você quiser, como clock do Pic. O truque é justamente não interferir no contador, assim não temos o problema de achar o momento exato de recarregar o timer com um numero exato, o que é simplesmente impossivel sem usar o Assembler. Paulo
  3. Vtrx, O desenho que o Márcio postou é mais um dos milhares de tutoriais que você vai encontrar na Net,e se baseia no modelo mais tradicional, ou seja, obedeçe à pinagem que o Proteus também utiliza. Até uns 10 anos atrás, realmente quase todos os displays obedeciam a essa pinagem, mesmo sem ser um padrão. E hoje em dia, tem tanta fábrica disso na China que não dá para confiar apenas verificando que tem 16 pinos sem ler o datasheet.... E é esse o caso do seu display ! Mas pode confiar no que te falei, esse seu modelo possui uma outra pinagem, basta voce conferir no datasheet dele. Pode ligar de acordo com o datasheet sem medo ! Se você tentar ligar da maneira que o Márcio postou, pode dizer adeus ao display, isso no mínimo... Paulo
  4. Vtrx, Realmente , a pinagem do datasheet não confere com a pinagem do Proteus. Conferí a sua foto, e parece mesmo que os pinos de alimentação estão mesmo nos pinos 13 e 14 do display, e bate com a pinagem do datasheet ! Neste caso, confie no datasheet, e use a descrição dos sinais na montagem física. O pino 1 desse display é o DB7, o 2 é o DB6 e assim em diante, conforme o datasheet. Uma vez, comprei 95 displays de cores diferentes de uma mesma fábrica na China, e recebi 3 modelos com pinagens diferentes uns dos outros..... Tive de fabricar 3 modelos de placas por causa disso ! Paulo
  5. 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
  6. Nelson, O problema é que o motor de uma bomba de água consome mais do que os 0,7A que esse componente pode oferecer ! Quando usamos um motor, temos grandes problemas com correntes de pico devido à carga altamente indutiva do motor. O restante é fácil. Paulo
  7. Oi, Vtrx, não quis dizer nada sobre se existe algum erro seja de quem for ! Heheheh isto é uma discussão conceitual kkkkk ! O problema do CIS é o maldito oscilador interno ! Se fosse para temporizar um periodo pequeno, até dá para usar o oscilador interno; mas para SETE dias, os erros vão se acumulando e compromete o resultado, a menos que seja em ambiente de temperatura constante. Se fizer isto, independente da linguagem utilizada, através da estatística pode-se ajustar o loop de tempo no software, sem utilizar interrupção do timer, seja em C ou em ASM. O que eu quis deixar bem claro é o seguinte : se tem um timer no hardware, porque não usar ele ??????????????? Assim não precisa ficar contando ciclo de máquina, que convenhamos , enche o saco ! Concordo que a matemática continua sendo exata, só que o oscilador interno não tem nada de exato ! Agora, se usar um cristal oscilador, vai ter a precisão necessária, e já que o CIS usa o C, basta fazer a interrupção do timer , e pronto, problema resolvido , e eu acredito que ele vai achar isto bem mais fácil do que aprender a programar em ASM. Estou olhando do lado prático, não quis dizer nada sobre vantagens de linguagens, mas sem conhecer os periféricos do PIC fica difícil fazer um programa um pouco mais sofisticado... Paulo
  8. Cis, voce tem dois caminhos : estudar o ASM , ou estudar melhor o hardware de um Pic ! Conhecendo como funciona um Timer, você faz um programinha de menos de 15 linhas em C e resolve o seu problema da maneira mais simples e rápida. Se escolher o caminho do ASM, vai ter de ficar calculando ciclos de máquina por instrução, e vai continuar sem aprender o mais importante, que é saber utillizar todos os periféricos embutidos em um PIC. E, me desculpe pela sinceridade, vai continuar não entendendo quase nada sobre um microcontrolador, vai virar uma calculadora burra de somar ciclo de máquina... E o pior, vai sempre levar muito mais tempo para conseguir um resultado que pode ser conseguido muitas vezes em menos de um décimo do tempo que levaria se utilizasse uma linguagem de alto nível. Deixe o ASM para quem realmente precisa do ASM, seja prático ! Minha opinião é que voce deve estudar o hardware melhor, ver como funciona um Timer de um PIC, e implementar em C mesmo. Vai te abrir um novo horizonte em seus projetos. Só para definir isto de vez.... NAO EXISTE PRECISÃO USANDO CLOCK INTERNO para um período tão grande de tempo, seja em ASM ou em qualquer linguagem! Paulo
  9. Cis, Calma.... problema bem simples de resolver. Abandone o laço DO WHILE, faça por Hardware, já existente nos Pic's !!!! Primeiro e mais importante : use um oscilador a cristal para gerar o clock, ou até mesmo pode usar o clock interno, mas utilize um cristal de relógio de 32 Khz para o Timer do PIC. Programe o Timer1 para utilizar um cristal de relógio de 32.768 Hz, incremente um contador a cada interrupção do timer, e pronto, voce terá uma base de tempo digitalmente correta. Claro, isto se voce puder abrir mão de dois pinos de I/O.... senão só usando o clock interno, que não tem precisão nem estabilidade para isso. Se voce só puder abrir mão de 1 pino de I/O, terá de usar um oscilador a cristal externo, e aplicar o clock diretamente no pino do PIC. Só vai depender da precisão e estabilidade de temperatura do cristal oscilador, que normalmente permite um erro máximo de uns 15 segundos por dia. voce pode comprar também um cristal oscilador super-preciso, mas vai custar bem caro. Enquanto voce utilizar o oscilador RC interno, esquece qualquer precisão, pois ele varia bastante com a temperatura, além de não haver nenhuma garantia da frequência exata pelo fabricante. Não entendo nadinha de C, mas aqui temos membros "feras", com certeza algum pode te passar essa programação do Timer1 e a rotina de interrupção para base de tempo de 1 segundo. Alguém se habilita ? Paulo
  10. Oi ASP40, bem-vindo ao Fórum ! Olha, temos de esperar que o fabricante do Proteus inclua os componentes em uma próxima atualização....... E olha que já esperei um monte deles e nenhum foi incluido até agora. Infelizmente o negócio é comprar os danados e mandar bala por conta própria. Mas sugiro voce pesquisar no EBAY, hoje em dia eu compro tudo pelo Ebay mesmo e acaba ficando bem, mais barato do que na Sparkfun. Claro que a placa é sempre diferente, mas é só questão de adaptar os pinos de ligações. Boas pesquisas na Internet ! Paulo
  11. Olá Nailson, bem-vindo ao Fórum ! Eu já usei os dois. O DS1302 eu fiz uma rotininha de escrita e uma de leitura, fazendo a sinalização "na marra", isto é, colocando os pinos nos níveis alto e baixo pelos tempos determinados no protocolo. Mas alguma boa alma fez algo melhor, criou até uma library para uso no Bascom !!! Segue o link do post para voce se divertir : http://www.mcselec.com/index2.php?option=com_forum&Itemid=59&page=viewtopic&t=8905&highlight=ds1302 O ACS758 eu usei também, mas eu comprei ele da Sparkfun, que já vem com um amp-op e um trim-pot de ganho que nunca funcionou direito e tive de alterar toda a plaquinha que acabou ficando um monstro de gambiarra.... o melhor mesmo é montar o seu ACS758 com um bom amp-op rail to rail moderno, com ajustes independentes de ganho e de off-set que fica uma beleza ! Pode postar os seus projetos , a turma agradeçe , e qualquer dúvida, pode perguntar aqui, eu também faço tudo com o Bascom, mas estou utilizando como plataforma de desenvolvimento os hardwares padrão Arduíno. É uma baita mão na roda ! Um abraço ! Paulo
  12. Karen, Eu posso te ajudar nas informações de funcionamento do motor, chips que você vai utilizar, e como fazer o programa para cada o controle, eu fiz um programa em BASCOM que controla qualquer tipo de motor, seja unipolar, bipolar, 2 fases, 3 fases, etc. Veja o que que você precisa , me informe qual a linguagem que você vai usar, ok ? Paulo
  13. Evertton, Meu código está em Bascom em um projeto de controladora para 8 motores, vou separar ele e postarei aqui. A ideia é simples, olha o jeito que o Matheus explicou o conceito de "distância", repare que é uma função linear, isto é, se a distância é de 1 volt, os steps são , por exemplo, 30 steps por minuto; se a distância aumentar para 2 volts, os steps seriam 60 por minuto, certo ? Repare que isso é uma função LINEAR. O que eu fiz foi assim : Se o potenciometro estiver em um dos extremos, os steps feitos serão o máximo que o meu motor aguenta. Imagine que o meu motor trabalha com o máximo de 500 steps por minuto. Então temos uma função linear do tipo : Se o potenciometro estiver a meio caminho, isto é , na metade entre um dos extemos e a posição central, o resultado é que serão aplicados 250 steps por minuto, certo ? Pois é uma função linear ! Criei uma tabela de correspondencia entre esses resultados que são obtidos pela função linear, e coloquei um valor que segue uma funçao tipo X ao quadrado. Usei uma tabela exatamente para poder ajustar os valores na mão para ficar mais natural. Veja se entendeu o conceito ! Paulo
  14. Matheus, Caramba, voltei uns 30 anos lendo esse post .... VETOR , na minha época, era uma entidade demonstrativa de força, diferente de MATRIZ, que é uma entidade dimensional. Não sabia que esse termo se aplica à programação de hoje em dia ! Tá vendo só , ficar velho é uma M.... !!!!! P.S. - Quanto à sua solução, eu fiz quase a mesma coisa que voce.... funcionou, mas também achei que podia funcionar melhor, e eu incluí um sistema de "aceleração do STEP" não linear ( ficou numa tabela ) em função da diferença da tensão medida em relação aos 2.5 volts. Ficou um pouco mais "redondo" o movimento do step motor. Um abração, Matheus ! Paulo
  15. Jpsek, Tenho dois projetos que ainda quero fazer, um deles é o balancing bot , e o outro é um pêndulo perpétuo que ví na revista Elektor, ambos são muito interessantes na ciência aplicada ao funcionamento. Mas só de pensar já dá dor de cabeça .... Se voce puder postar esse seu ultimo projeto com o transceiver, pode ajudar outras pessoas, certo ? Um abraço, Jpsek ! Paulo
  16. Olha só.... Hoje me lembrei que o BASCOM possui uma função própria para medir a largura de um pulso aplicado em um pino de I/O, e que fornece uma contagem que incrementa uma unidade a cada exatos 10 microsegundos !!!! O nome dessa função é PULSEIN . Ou seja, isso resolve todo o problema que tive de resolver "na bancada" com o programa anterior. Resolví postar ele aqui, pois este programa funcionou de cara sem precisar nenhum ajuste "prático". '------------------------------------------------------------------------------- ' usando um ARDUINO UNO R3 para mostrar o funcionamento do HC-SR04 ' SENSOR ULTRA-SONICO HC-SR04 - versão 2 do programa ! ' Trigger - ligado no pino DIGITAL 2 ' Echo - ligado no pino DIGITAL 3 ' Usando a função PULSEIN do BASCOM, que mede a largura de um pulso ' Com resolução de 10 microsegundos, que já é suficiente ! $regfile = "m328pdef.dat" ' MICRO uno $crystal = 16000000 ' xtal uno $baud = 9600 ' baud rate '------------------------------------------------------------------------------- $loadersize = &H200 $hwstack = 32 $swstack = 32 $framesize = 32 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 Dim X As Byte Dim Tempo As Word Dim Tempo1 As Word Dim Dist As Single Config Portd.2 = Output Config Pind.3 = Input Set Pind.3 ' LIGA PULL-UP ' VAMOS ESPERAR O SENSOR ESTABILIZAR, E DEPOIS MANDAR O PULSO DE TRIGGER Portd.2 = 0 Waitms 100 Tempo = 0 Do 'VAMOS MEDIR 4 VEZES E FAZER A MÉDIA Dist = 0 For X = 1 To 4 Portd.2 = 1 ' AQUI GERAMOS O TRIGGER DE 10 MICROSEGUNDOS APROXIMADO Waitus 10 Portd.2 = 0 Tempo = 0 Tempo1 = 0 'AGORA, USAR A FUNÇÃO PULSEIN , QUE TEM RESOLUÇÃO DE 10 MICROSEGUNDOS ' E ELA VAI COMEÇAR A CONTAR O TEMPO ' E TERMINAR A CONTAGEM QUANDO RECEBER A BORDA DE DESCIDA Pulsein Tempo1 , Pind , 3 , 1 'VAMOS ESPERAR UM POUCO PARA DAR TEMPO DE O ECO CHEGAR Waitms 50 ' SE O ECO DEMOROU MUITO, DEFINIR LIMITE DE +- 4 METROS Tempo = Tempo1 If Tempo > 2400 Then Tempo = 2400 Dist = Dist + Tempo Waitms 50 Next X Tempo = Dist / 4 ' AGORA, OUTRO TRUQUE INTERESSANTE : ' USEI UMA EQUAÇÃO PARA CALCULAR A VELOCIDADE DO SOM PARA A ALTITUDE ' EM QUE ME ENCONTRO ( 750 METROS ) , E RESULTOU V=338 M/SEG OU 33800 CM/SEG Dist = 33800 * Tempo ' LEMBRAMOS QUE O TEMPO MEDIDO É PARA O DOBRO DA DISTÂNCIA ( IDA E VOLTA ) ! ' PORISSO QUE TEMOS DE DIVIDIR POR 200000 EM VEZ DE 100000 ' E PORQUE 200000 EM VEZ DE 2000000 ? ' LEMBRE QUE A NOSSA BASE DE TEMPO É UMA CONTAGAM PARA CADA 10 MICROSEGUNDOS ! ' E NÃO 1 MICROSEGUNDO .... Dist = Dist / 200000 Print "Distancia = " ; Dist Print Waitms 700 Loop End Boa diversão ! Paulo
  17. Pessoal, recentemente peguei um sensor de ultrasom desses disponíveis no Mercado Livre ou no EBAY, o HC-SR04 . Falam tão bem deles que comprei duas peças, e chegaram ontem. Hoje, usei o IDE do Arduíno, montei exatamente seguindo os posts de quem já tinha usado, e me decepcionei com o resultado. As medidas de distância eram bem fora da realidade, com erros acima de 15% ! Troquei o sensor pelo outro, e as medidas continuaram malucas. Como não entendo patavina nenhuma de C, não adiantava nada insistir ... Aí, resolví ir para o campo que domino, que é o Basic do Bascom, e ver se conseguia um resultado melhor do que usando a IDE do Arduíno. Esses sensores de ultrasom funcionam asim : damos um pulso de início no pino de Trigger, e na saída ECHO teremos um pulso positivo, cuja duração em microsegundos é exatamente o tempo que demorou para o som voltar refletido pelo objeto. Simples demais para dar errado ! Aí, olhando o Datasheet, ele tem a seguinte fórmula : dividindo o tempo desse pulso em microsegundos por 58 já dá o resultado em centímetros ! Tentei usar essa fórmula primeiro, e nada, continuava errado. Começei a pensar no funcionamento do programa : Clock do Arduíno Uno = 16 Mhz. Tempo a ser gerado pela rotina de Timer, para servir como base de tempo : 1 microsegundo .... Pera aí ..... isso quer dizer UMA interrupção de Timer a cada 16 ciclos de clock ..... só o tempo necessário para atender a interrupção e salvar o contexto já é maior do que 20 ciclos de clock, essa base de tempo ia ficar totalmente errada ! Então pensei que seria melhor usar uma base de tempo de 10 microsegundos, teria 160 ciclos de clock entre duas interrupçoes do Timer. Isso daria tempo para fazer tudo. ( depois percebí que não ..... ) Então, fiz o programa, usando o TIMER1 para gerar a base de tempo de 10 microsegundos. E o resultado das medidas continuou totalmente errado, mais de 40% de erro agora .... Me lembrei que a velocidade do som é 340 m/seg AO NIVEL DO MAR ! Como estou a 750 metros de altitude, deve ser outro valor. Pesquisando na Internet, achei uma fórmula, e o resultado é de 338 metros por segundo... A diferença é muito pequena, mas mesmo assim mudei o programa para esse valor. O erro continuava enorme .... Aí bateu um pouco luz .... troquei a base de tempo para 100 microsegundos, e não é que o erro diminuiu prá menos de 10% !!! Imaginei que os erros de tempo entre atender a interrupção, incrementar a variável de tempo, repor o valor do timer1 e sair da interrupção estavam fazendo com que o tempo fosse maior do que os 10 microsegundos que eu tinha planejado. Então, usei o osciloscópio digital para medir o tempo Exato do TIMER1, e adivinhe só : em vez de 10 microsegundos, media sempre algo entre 15 e 16 microsegundos ! Isto se deve ao Bascom salvar vários registradores na entrada e na saída da interrupção, e isso consome tempo ! Existe uma opção NOSAVE na declaração da interrupção, mas ela não pode ser utilizada quando a interrupção faz algumas coisas complexas. Até poderia ter utilizado, mas preferi a maneira da gambiarra ! Então, resolvi fazer a velha "abordagem empírica" : fui mudando o valor de TIMER1 , até que o tempo chegasse em 10 microsegundos ! Acabei usando um valor 8 unidades maior do que o calculado, e gerava um tempo um pouquinho só maior do que os 10 microsegundos. Na verdade, medindo na tela do osciloscópio, tinha 8,15 divisões quando deveria ter 8 divisões exatas, então introduzi no cálculo de tempo uma correção usando esses valores. Após tudo isso feito, conseguí a precisão que queria ! Uma distância exata de 114 centímetros, e a medida resultante foi de 113,8 ! Aí, fui para o outro extremo : Uma distância exata de 15 centímetros resultou na medida de 15,1 ! Como o sensor tem precisão de 0,3 centímetros, para mim está ótimo ! Segue o programa feito , para que vocês possam montar esse sensorzinho, que realmente funciona muito bem ! '------------------------------------------------------------------------------- ' usando um ARDUINO UNO R3 para mostrar o funcionamento do HC-SR04 ' SENSOR ULTRA-SONICO HC-SR04 ' Trigger - ligado no pino DIGITAL 2 ' Echo - ligado no pino DIGITAL 3 $regfile = "m328pdef.dat" ' MICRO uno $crystal = 16000000 ' xtal uno $baud = 9600 ' baud rate '------------------------------------------------------------------------------- $loadersize = &H200 $hwstack = 32 $swstack = 32 $framesize = 32 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 Dim X As Byte Dim Tempo As Word Dim T_mat(4) As Word Dim Dist As Single Dim Dist1 As Single Config Portd.2 = Output Config Pind.3 = Input Set Pind.3 ' LIGA PULL-UP ' VAMOS ESPERAR O SENSOR ESTABILIZAR, E DEPOIS MANDAR O PULSO DE TRIGGER Portd.2 = 0 Waitms 100 Tempo = 0 ' E VAMOS PREPARAR UM TIMER PARA TERMOS CONTAGEM A CADA 10 MICROSEGUNDOS (UAU) Config Timer1 = Timer , Prescale = 8 ' VALOR DE TIMER1 OBTIDO EXPERIMENTALMENTE COM OSCILOSCÓPIO DIGITAL ! ' POIS O CALCULADO ERA 65516 PARA 10 MICROSEGUNDOS , MAS VAMOS USAR 65524 ! ' A LATENCIA DA INTERRUPÇÃO DO TIMER1 , BEM COMO SALVAR OS ' REGISTRADORES, GASTA A DIFERENÇA DE +- 8 * 8 = 64 CICLOS DE CLOCK ! ' AINDA FICA UM PEQUENO ERRO, POIS TENTEI 65525 E FICOU PIOR QUE 65524 ' VOU ACERTAR ESSE TEMPO EXATO ABAIXO ! ' REPAREM O FATOR 815 E 800 ..... Timer1 = 65524 On Timer1 Sample_isr Nosave 'DIMINUIR A LATENCIA ... Enable Timer1 Enable Interrupts Stop Timer1 Do 'VAMOS MEDIR 4 VEZES E FAZER A MÉDIA For X = 1 To 4 Portd.2 = 1 ' AQUI GERAMOS O TRIGGER DE 10 MICROSEGUNDOS APROXIMADO Waitus 10 Portd.2 = 0 Tempo = 0 Espera: If Pind.3 = 0 Then Goto Espera Start Timer1 Espera1: If Pind.3 = 1 Then Goto Espera1 Stop Timer1 ' SE NÃO VEIO ECO DENTRO DO ESPERADO, DEFINIR LIMITE DE +- 4 METROS If Tempo > 2400 Then Tempo = 2400 ' FATOR DE CORREÇAO OBTIDO EXPERIMENTALMENTE MEDINDO O TEMPO ' EXATO DO TIMER1 COM UM OSCILOSCÓPIO DIGITAL ' TINHA 8,15 DIVISÕES QUANDO DEVERIA TER 8 EXATAS !!! Dist = Tempo * 815 Dist = Dist / 800 Tempo = Dist T_mat(x) = Tempo Waitms 50 Next X Tempo = T_mat(1) + T_mat(2) Tempo = Tempo + T_mat(3) Tempo = Tempo + T_mat(4) Tempo = Tempo / 4 ' AGORA, OUTRO TRUQUE INTERESSANTE : ' USEI UMA EQUAÇÃO PARA CALCULAR A VELOCIDADE DO SOM PARA A ALTITUDE ' EM QUE ME ENCONTRO ( 750 METROS ) , E RESULTOU V=338 M/SEG OU 33800 CM/SEG Dist = 33800 * Tempo ' LEMBRAMOS QUE O TEMPO MEDIDO É PARA O DOBRO DA DISTÂNCIA ( IDA E VOLTA ) ! ' PORISSO QUE TEMOS DE DIVIDIR POR 200000 EM VEZ DE 100000 ' E PORQUE 200000 EM VEZ DE 2000000 ? ' LEMBRE QUE A NOSSA BASE DE TEMPO É UMA CONTAGEM PARA CADA 10 MICROSEGUNDOS ! ' E NÃO 1 MICROSEGUNDO .... Dist = Dist / 200000 Print "Distancia = " ; Dist Print "Tempo = " ; Tempo Waitms 800 Loop Sample_isr: Pushall Timer1 = 65524 Incr Tempo Popall Return End Boa diversão ! Paulo
  18. Algo que é pouco divulgado é que podemos usar o BASCOM como um IDE de desenvolvimento com a plataforma Arduíno ! Se configurarmos diretinho o tipo de programador do BASCOM, utilizando o AVRDUDE presente na IDE do Arduíno, podemos fazer o programa no BASCOM, compilar e passar para o Arduino e utilizando o terminal serial do Bascom, podemos interagir com o nosso programa ! Para isso, temos de dizer ao BASCOM que deve gerar o nosso programa para rodar através do BOOTLOADER do Arduíno, e isso é um endereço que varia conforme o Arduíno utilizado ! Para o Arduino que eu uso, que é o UNO Rev 3, o endereço de carregamento é o $H200. Basta informar isto ao compilador pela diretiva $loadersize, conforme o programa apresentado aqui abaixo. Antes da listagem, se voce leu o post acima, vai ver que eu adaptei um programa em C para rodar no Bascom, e desta maneira conseguí fazer com que os três modelos diferentes de Rotary Encoder que comprei funcionassem sem problema. Para isto, uso três pinos do Arduíno, e programo a interrupção por mudança de nível nesses 3 pinos, e trato a interrupção. Só tem um probleminha ao fazer isto : o que eu preciso é apenas uma interrupção que funcione na DESCIDA do sinal, portanto eu preciso checar para ver se a interrupção gerada foi por uma descida ou por uma subida; se foi subida, eu simplesmente ignoro ! Desta maneira, voce pode utilizar interrupções EM QUASE TODO PINO DE I/O dos ATMEGA, simplesmente habilitando os pinos desejados e as PCINT's correspondentes a esses pinos, e na rotina de tratamento, filtrar de alguma maneira qual é a interrupção que voce quer tratar. No meu caso, eu simplesmente guardo o estado dos pinos ANTES de uma interrupção, e quando ela ocorre, eu leio novamente o estado dos pinos e comparo com o anterior ! Assim fica simples detectar, certo ? Segue o programa : '------------------------------------------------------------------------------- ' usando um ARDUINO UNO R3 para mostrar o funcionamento ' ligamos o rotary aos pinos ANALOG 0,1 e 2 do Arduino, sendo : ' Pino A0= botão do Rotary ' Pinos A1 e A2 = Sinais de direção do Rotary ' e por ultimo, o pino comum do rotary ligar ao terra $regfile = "m328pdef.dat" ' MICRO uno $crystal = 16000000 ' xtal uno $baud = 9600 ' baud rate '------------------------------------------------------------------------------- $loadersize = &H200 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 Config Serialin = Buffered , Size = 250 Config Serialout = Buffered , Size = 50 Dim X_enc As Byte Dim Dado As Byte Dim Old_val As Byte Dim Flag_enc_novo As Bit Dim Flag_enc_apert As Bit Dim Half_left As Bit Dim Half_right As Bit Dim Flag_dir_h As Bit Config Pinc.0 = Input Config Pinc.1 = Input Config Pinc.2 = Input Rotaryp0 Alias Pinc.2 ' um pino do rotary switch Rotaryp1 Alias Pinc.1 ' outro pino do rotary switch Rotarypb Alias Pinc.0 'pino do botão do rotary switch ' o pino comum do rotary switch é ligado ao terra ! Set Rotaryp0 'liga resistor pull-up Set Rotaryp1 Set Rotarypb X_enc = 0 Dado = Pinc Old_val = Dado Pcmsk1 = &B00000111 ' enable pin change interrupt em pinC.0 - pinC.2 Pcicr.1 = 1 ' enable PCINT1 vector On Pcint1 Isr_pcint1_encoder ' define a ISR para tratar Enable Pcint1 Enable Interrupts 'pronto, ints estão ligadas 'agora é só esperar pelos flags setados pela interrupção Do If Flag_enc_novo = 1 Then ' temos rotação ? If Flag_dir_h = 1 Then Print X_enc ; " direita" Else Print X_enc ; " esquerda" End If Flag_enc_novo = 0 'já mostramos, resetar End If If Flag_enc_apert = 1 Then 'temos botão apertado ? Print "Encoder Apertado" Flag_enc_apert = 0 'já mostramos, resetar End If Loop ' ISR on PCINT1 for encoder status changes Isr_pcint1_encoder: Dado = Pinc 'novo valor nas entradas c ' VAMOS TESTAR SE FOI POR DESCIDA DE NÍVEL If Old_val.2 = 1 And Dado.2 = 0 Then Goto A_pin2 End If If Old_val.1 = 1 And Dado.1 = 0 Then Goto A_pin1 End If If Old_val.0 = 1 And Dado.0 = 0 Then Goto A_pinb End If ' SE FOI POR SUBIDA ATUALIZAR VALOR E TERMINAR If Old_val.2 = 0 And Dado.2 = 1 Then Old_val.2 = 1 Goto Isr1_fim End If If Old_val.1 = 0 And Dado.1 = 1 Then Old_val.1 = 1 Goto Isr1_fim End If If Old_val.0 = 0 And Dado.0 = 1 Then Old_val.0 = 1 Waitms 5 End If Isr1_fim: Return 'TRATAMENTO DOS PINOS MUDADOS PELO ENCODER A_pin1: Waitms 1 If Rotaryp1 = 0 Then If Rotaryp0 = 1 And Half_right = 0 Then Set Half_right End If If Rotaryp0 = 0 And Half_left = 1 Then Reset Half_left Decr X_enc Reset Flag_dir_h Set Flag_enc_novo End If Old_val.1 = 0 End If Goto Isr1_fim A_pin2: Waitms 1 If Rotaryp0 = 0 Then If Rotaryp1 = 1 And Half_left = 0 Then Set Half_left End If If Rotaryp1 = 0 And Half_right = 1 Then Reset Half_right Incr X_enc Set Flag_dir_h Set Flag_enc_novo End If Old_val.2 = 0 End If Goto Isr1_fim A_pinb: Set Flag_enc_apert ' encoder apertado Waitms 5 Old_val.0 = 0 Goto Isr1_fim End Boa diversão ! Paulo
  19. Oi Jagoris, obrigado pelo elogio ! Conforme eu vou encontrando problemas, vou solucionando e tento passar essa experiência para quem está iniciando. Ainda acredito que o velho Basic facilita muito o entendimento, e vou continuar postando mais dicas por aqui, ok ? Quanto a escrever um livro... Só de pensar eu fico cansado hehehehe ! Mais uma vez, obrigado e espero que esses tutoriais lhe sejam muito úteis. Aproveitando a resposta, Pessoal, recentemente eu comprei um rotary switch ( também conhecido como Encoder ) , e levei uma baita surra dele .... O Bascom tem uma função própria para ler esse rotary, que é a função Encoder() . Mas não consegui fazer funcionar direito. Fui a uma outra loja e comprei um outro encoder, diferente do primeiro. E o resultado continuou o mesmo : nada ! Finalmente, encontrei um encoder igual ao que a Sparkfun vende, e novamente não funcionou. O gozado era que cada um deles tinha um funcionamento diferente dos outros, mesmo sendo todos errados. Fui pesquisar nos fóruns do Bascom, e ví que muita gente reclamava que também não conseguiam fazer funcionar. Pesquisando mais, achei um site onde um cara escreveu uma rotina em C que ele afirmava funcionar perfeitamente, mesmo em alta velocidade. Estudei o funcionamento da rotina dele, e fiz uma rotina no Bascom baseado na rotina do cara, e não é que funcionou com TODOS os meus 3 encoders diferentes ???? A rotina nova será detalhada no próximo post. Paulo
  20. Oi test man, faz tempo mesmo hein ???? Eu comprei o DHT11 no ML, paguei uns R$ 12,00, e realmente funcionou muito bem. Aliás, comprei 2, e ambos deram exatamente as mesmas leituras tanto em temperatura como em umidade. Mas a precisão não é das maiores, a umidade é +- 5% e a temperatura creio que é +- 2 graus. Paulo
  21. Eu usei o DHT-11, que mede temperatura e umidade do ar, e comprei ele no Mercado Livre, bem baratinho. É um sensor do tipo 1-Wire ( mas não é padrão exato ! ), não tem uma precisão enorme, mas para uso simples funciona muito bem. Comparei a temperatura com um LM35, e a diferença sempre foi menor do que 1 grau, entre 0 e 50 graus. Se quiser ver como ele funciona, eu usei ele no Tutorial com Basic, e expliquei bastante para facilitar aos iniciantes, segue o link para te facilitar, ok ? http://forum.clubedohardware.com.br/showpost.php?p=5553520&postcount=1 E o melhor de tudo para voce é que pode utilizar qualquer PIC, pois o protocolo tipo 1-Wire ( é parecido com 1-Wire mas não segue o padrão ... ) é simulado com qualquer pino, e o código-fonte que usei em Basic pode ser passado pro PIC facilmente. Bons usos ! Paulo
  22. Pessoal, Acabei de colocar para download uma atualização do tutorial, com mais projetos e dicas de utilização para componentes mais "especiais" , como sensores de pressão, sensores de umidade, etc. Por favor, baixem a nova versão, que já chegou a 169 páginas .... É o mesmo link que está no primeiro post do tópico. Boa diversão ! Paulo
  23. Pessoal, Segue o programa que fiz para utilizar o BMP085 . É um programa que permite o uso bem sofisticado dos 3 sensores envolvidos, e mostra 4 informações diferentes. Já está compensado para a altura média na cidade de São Paulo, mostrando a pressão relativa ao nível do mar para facilitar a interpretação da variação de pressão. Segue o esquema do circuito : Segue o programa : ' ---------------------------------------------------------------- ' ESTAÇÃO METEOROLÓGICA COMPENSADA ' ' Permite obter a Temperatura Real, a Umidade Real, ' a Temperatura do Ponto de Orvalho Real, e finalmente ' obtém a Pressão Real Relativa ao Nível do Mar. ' Para a medida de pressão, levewi em conta a elevação em minha ' residência, que é de 746 metros acima do nível do mar. ' ' E estou usando para monitorar as minhas pescas !!! ' ' Embora não fosse necessário utilizar o DS18B20, pois o DHT11 faz ' as medidas de Umidade e Temperatura, acabei utilizando para ' demonstrar o poder do Bascom, ao utilizar 3 interfaces diferentes ' ao mesmo tempo. E a segunda razão é que o sensor DHT11 não é preciso ' nas leituras de temperatura, tendo uma variação muito maior do que o ' DS18B20. Mesmo assim, poderia utilizar a temperatura do sensor ' BMP085, que mede tanto a pressão como a temperatura com uma boa ' precisão. Mas ..... pelo bem da didática, usei os 3 sensores ! ' ' Este programa é um apanhado dos programas anteriores do Tutorial ' sobre o uso do DS1820 e DHT11 ( este está aqui no tópico mesmo ) ' e usei boa parte do código feito por um usuário do Fórum do BASCOM ' para tratar o BMP085, mas o código dele contém um erro, e eu já ' corrigí aqui nesta versão. ' Como uma boa dica , ilustro o uso do I2C sem os resistores de ' PULL-UP internos , assim posso utilizar dois resistores de ' PULL-UP externos, mas ligados à alimentação do sensor BMP085 ' que é de aproximadamente 3.3 Volts, assim elimino qualquer ' tipo de circuito conversor de nível de tensão entre 5V e 3.3V . ' Vale lembrar que este truque só funciona para velocidades baixas ' de I2C, abaixo de 200 Khz, que é o padrão do BASCOM. ' Lembrando que o BASCOM pode mudar a velocidade do I2C, indo desde ' os famosos 10Khz para até 500 Khz sem dificuldade. ' ---------------------------------------------------------------- $regfile = "m88Pdef.dat" $crystal = 8000000 $hwstack = 40 $swstack = 16 $framesize = 32 Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2 Config Lcd = 16 * 2 Config 1wire = Portc.0 ' DS18B20 on pin 12 Config Sda = Portc.4 ' BMP 085 Sensor de pressão I2C Config Scl = Portc.5 Declare Sub Read1820 Declare Sub Temperature Declare Sub Orvalho Declare Sub Get_th(t As Byte , H As Byte) 'vamos ligar o sensor DHT-11 no pino PORTC.2 Dht_put Alias Portc.2 ' aqui usamos como saída Dht_get Alias Pinc.2 ' e aqui usamos como entrada ! Dht_io_set Alias Ddrc.2 ' aqui mudamos entrada < - > saída Portc.4 = 0 ' Truque para desabilitar o Pull-Up interno Portc.5 = 0 ' Assim não precisamos converter de 3.3 para 5V Dim Tdht As Byte 'Temperatura Dim Hdht 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 Dim Bd(9) As Byte Dim I As Byte , Tmp As Byte Dim Tempc As Single , 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 ' -------------------------------------------- ' | | | 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 X1 As Long ' variáveis auxiliares para cáculos BMP085 Dim X21 As Long Dim X22 As Long Dim X2 As Long Dim B5 As Long Dim T As Long Dim Temperatur As String * 6 ' --------------------------------------------------------------------- ' | | 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 B6 As Long 'mais variáveis auxiliares BMP085 Dim X3 As Long Dim B3 As Long Dim Oss As Word ' will be set in Sub Bmp085_initiate_measurement(byval Measurement_type As Byte) Dim B4 As Dword ' mais variáveis auxiliares BMP085 Dim B7 As Dword Dim P As Long Dim Pcomp As Single Dim Pvarx As Single Dim Pressure As String * 6 Dim Ph As Long 'absolute altitude 'Dim Altitude_var1 As Single 'Dim Altitude As Single 'Dim P_single As Single 'Const Pressure_at_see_level = 101325 ' Pa Dim X As Byte Dim Idw As Dword '-----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() Declare Sub Bmp085_absolute_altitude() Cursor Off Noblink Cls Locate 1 , 1 : Lcd "BAROMETRO PESCAS" Set Dht_io_set ' prepara interface com o DHT-11 Set Dht_put I2cinit ' Inicializa bus I2C, mas com PULL-UP Interno ! Portc.4 = 0 ' temos de desativar eles novamente ! Portc.5 = 0 ' assim protegemos nosso sensor que usa 3.3 V ! ' Vamos ler os dados de calibração do BMP 085 Call Bmp085_read_calibration_data() Do Temperature ' leitura precisa de temperatura do DS18B20 Waitms 2000 Call Get_th(tdht , Hdht) ' leitura precisa de umidade do DHT-11 ' Agora, vamos medir a pressão do BMP085. Para isso : ' É bem complicado, temos primeiro de ler a temperatura sem compensação ' e depois calcular a compensação ! Call Bmp085_initiate_measurement(1) '1 = Temperatur Measurement Call Bmp085_read_u_temp() Call Bmp085_calc_temp() 'Calculate Compensated Temperature 'Temperatur = Str(t) ' Agora, vamos medir a pressão sem compensação , e depois calcular a ' compensação, com cálculos bem chatinhos ! Call Bmp085_initiate_measurement(5) 'Very High Resolution Pressure Measurement (OSS=3) ' ^ type in Measurement_type !!!! <<<<<---------------------------------------- Call Bmp085_read_u_press() Call Bmp085_calc_pressure() ' Agora, temos tudo para calcular o Ponto de Orvalho Call Orvalho ' Pronto, tudo calculado , é só mostrar ! Cls Locate 1 , 1 Lcd "T= O= " ' Temperatura e Orvalho na primeira linha Locate 1 , 3 Lcd Fusing(tempc , "##.#") Locate 1 , 10 Lcd Fusing(pcomp , "##.#") Locate 1 , 15 Lcd Chr(223) ; "C" Locate 2 , 1 Lcd "P= U=" ' Pressão Corrigida E Umidade Na Segunda Locate 2 , 3 Lcd Ph Lcd "mB" Locate 2 , 12 Lcd Hdht Lcd " %" Loop End '////////////////////////////////////////////////////////////////////////////// Sub Temperature ' actual measuring 1wreset 1wwrite &HCC 1wwrite &H44 ' start measure Waitms 1000 Read1820 ' read 9 bytes End Sub '////////////////////////////////////////////////////////////////////////////// Sub Read1820 ' reads sensor ans calculate ' T for 0.1 C 1wreset ' reset the bus 1wwrite &HCC ' read internal RAM 1wwrite &HBE ' read 9 data bytest Bd(1) = 1wread(9) Waitms 1 1wreset ' reset the bus Bd(6) = Bd(2) And &B10000000 ' não usamos para nada mesmo .... Tmp = Bd(1) And &B00001111 T1 = Tmp / 16 Bd(1) = Bd(1) And &B11110000 Bd(1) = Bd(1) / 16 Bd(2) = Bd(2) And &B00000111 Bd(2) = Bd(2) * 16 Tempc = Bd(1) + Bd(2) Tempc = Tempc + T1 If Bd(6) = 128 Then Tempc = Tempc - 256 Else End If End Sub '-------------------------------------------------------------------------------------- ' SUB-ROTINA PARA LER O DHT-11 Sub Get_th(tdht As Byte , Hdht 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 Hdht = 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 ! Hdht = 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 Hdht = Binval(tmp_str8) 'Vamos transformar para valor numérico Tmp_str8 = Mid(sensor_data , 17 , 8) 'os próximos 8 são a temperatura Tdht = Binval(tmp_str8) Tmp_str8 = Right(sensor_data , 8) 'os ultimos 8 são o CRC Crc = Binval(tmp_str8) ' Mybyte = Tdht + Hdht ' o CRC é a soma da umidade + temperatura If Mybyte <> Crc Then ' considerando 8 bits Hdht = 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 End Sub '------------------------------------------------------------------------------------------------------- Sub Bmp085_initiate_measurement(byval Measurement_type As Byte) Local M_type As Byte , Wait_time As Byte If Measurement_type < 1 Or Measurement_type > 5 Then Ac1 = Ac1 ' achei melhor por alguma coisa do que deixar vazio Else Select Case Measurement_type Case 1: '1 = Temparature Measurement M_type = &H2E Wait_time = 5 'ms Case 2: M_type = &H34 '2 = Ultra Low Power Pressure Measurement (OSS = 0) Wait_time = 5 'ms Oss = 0 Case 3: M_type = &H74 '3 = Standard Pressure Measurement (OSS = 1) Wait_time = 8 'ms Oss = 1 Case 4: M_type = &HB4 '4 = High Resolution Pressure Measurement (OSS = 2) Wait_time = 14 'ms Oss = 2 Case 5: M_type = &HF4 '5 =Ultra High Resolution Pressure Measurement (OSS = 3) Wait_time = 26 'ms Oss = 3 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 If 'If Measurement_type < 1 Or Measurement_type > 5 Then 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 End Sub '---------------------------------------------------------------------------------------------------- Sub Bmp085_read_u_press() I2c_receive_buf(1) = &HF6 I2creceive Bmp085_write , I2c_receive_buf(1) , 1 , 3 U_pressure_high = I2c_receive_buf(1) U_pressure_mid = I2c_receive_buf(2) U_pressure_low = I2c_receive_buf(3) Select Case Oss Case 0: Shift U_pressure , Right , 8 Case 1: Shift U_pressure , Right , 7 Case 2: Shift U_pressure , Right , 6 Case 3: Shift U_pressure , Right , 5 End Select End Sub '--------------------------------------------------------------------------------------- Sub Bmp085_calc_temp() ' Calculate true Temperature 'X1 = X1 = U_temperatur - Ac6 X1 = X1 * Ac5 Shift X1 , Right , 15 'X2 = X21 = X1 + Md X22 = 2 ^ 11 X22 = X22 * Mc X2 = X22 \ X21 'Integer division is denoted by the backslash (\). 'B5 = B5 = X1 + X2 'T = T = B5 + 8 Shift T , Right , 4 '4 End Sub '---------------------------------------------------------------------------------------- Sub Bmp085_calc_pressure() ' Calculate true pressure B6 = B5 - 4000 'X1 = X21 = 2 ^ 12 X22 = B6 * B6 X1 = X22 \ X21 X1 = X1 * B2 Shift X1 , Right , 11 'X2 = X21 = 2 ^ 11 X22 = Ac2 * B6 X2 = X22 \ X21 'X3 = X3 = X1 + X2 'B3 = X21 = Ac1 * 4 X22 = X21 + X3 Shift X22 , Left , Oss X22 = X22 + 2 B3 = X22 \ 4 'X1 = X21 = 2 ^ 13 X22 = Ac3 * B6 X1 = X22 \ X21 'X2 = X21 = 2 ^ 12 X2 = B6 * B6 X2 = X2 \ X21 X2 = B1 * X2 Shift X2 , Right , 16 'X3 = X21 = 2 ^ 2 X3 = X1 + X2 X3 = X3 + 2 X3 = X3 \ X21 'B4 = B4 = X3 + 32768 B4 = Ac4 * B4 Shift B4 , Right , 15 'B7 = X21 = 50000 Shift X21 , Right , Oss B7 = U_pressure - B3 B7 = B7 * X21 If B7 < &H80000000 Then Idw = B7 * 2 Idw = Idw \ B4 P = Idw Else Idw = B7 \ B4 Idw = P * 2 P = Idw End If 'X1 = X21 = 2 ^ 8 X1 = P \ X21 X1 = X1 * X1 'X1 = X21 = 2 ^ 16 X1 = X1 * 3038 X1 = X1 \ X21 'X2 = X21 = 2 ^ 16 X2 = -7357 * P X2 = X2 \ X21 'p = X21 = 2 ^ 4 X22 = X1 + X2 X22 = X22 + 3791 X22 = X22 \ X21 P = P + X22 Pcomp = P * 1.0896 'FATOR CORREÇÃO PARA ALTURA=746 MTS P = Pcomp Ph = P \ 100 End Sub '------------------------------------------------------------------------------ Sub Orvalho ' CALCULA O PONTO DE ORVALHO 'Vamos usar a mesma variável real Pcomp para economizar ... Pcomp = Hdht / 100 Pcomp = Pcomp ^ 0.125 Pvarx = Tempc * 0.9 Pvarx = Pvarx + 112 Pcomp = Pvarx * Pcomp Pvarx = 0.1 * Tempc Pcomp = Pcomp + Pvarx Pcomp = Pcomp - 112 End Sub Paulo
  24. Pessoal, achei um Bug na simulação do Proteus 7. E é daqueles que deixa a gente doido ! Estava testando o novo projetinho do medidor de pressão, e como resolví fazer algo bem ilustrativo, estou usando 3 sensores ao mesmo tempo : o DS18B20 que é 1-Wire, o DHT-11 que é um tipo de 1-Wire proprietário, e o Bosh BMP085, que é I2C a 3.3 Volts. Como o sensor de tensão é relativamente trabalhoso em termos de cálculos com ponto flutuante, o programa inteiro não coube mais no ATMEGA48 que estava utilizando. Aí, como eu tinha um ATMEGA168, troquei o processador no programa, e continuei fazendo. Logo de cara, compilei e carreguei no ISIS, apenas trocando o ATMEGA48 pelo ATMEGA168 . E a partir daí as leituras com o DS18B20 começaram a dar errado. Bom, isso era sábado, umas 3 horas da tarde. Fiquei procurando um erro no programa até umas 7 horas da noite. E nada ! O pior é que o osciloscópio virtual , ligado na linha de dados do DS18B20, mostrava um sinal doido, que não tinha nada a ver. Aí, começou o desespero. Mexí no programa, tirei pedaços e pedaços, até ficar quase idêntico ao programa do Tutorial, que utiliza o DS18S20. E continuava a doidera do sinal de dados. Como não funcionava, já na madrugada, resolví pegar o programa do Tutorial, que utiliza o DS18S20, e troquei apenas o processador, para um ATMEGA168. Compilei, e quando fui simular no ISIS, aconteceu o mesmo erro que eu estava tendo no novo programa ! Resolví tirar a dúvida, troquei no programa pelo ATMEGA168P , e o erro permaneceu. Mas .... quando troquei para o ATMEGA88, funcionou direitinho novamente..... Mudei novamente para o ATMEGA328, e também funcionou direitinho. Resolví testar mais : troquei a porta onde o DS18S20 estava ligado, recompilei, e não adiantou nada. O erro continuava dando APENAS no ATMEGA168 e ATMEGA168P ! Resolví tirar a prova dos nove : Montei o circuito real no protoboard, primeiro com o ATMEGA48P , e funcionou direitinho. Aí, recompilei o programa para o ATMEGA168 que tenho, gravei, e coloquei no protoboard. Advinhem : também funcionou direitinho ! Ou seja, o problema não é o ATMEGA168, e nem com o compilador BASCOM, pois o hardware real funciona, mesmo com a simulação do ISIS dizendo que não funcionaria... O problema está no modelo do ATMEGA168 e no ATMEGA168P do PROTEUS. Como dica, fiz um teste que funcionou direitinho : No ISIS, padronizei o processador ATMEGA328, pois consigo carregar nele sem nenhum problema os programas compilados para os ATMEGA48, ATMEGA88 e ATMEGA168. Não preciso alterar nada , é só simular e pronto ! CUIDADO COM O MODELO DO ATMEGA168 e ATMEGA168P. Obs : bug foi corrigido na versão 8 do Proteus ! Paulo
  25. Pessoal, Acabei de receber um sensor de pressão barométrica relativamente barato,o BMP085 da BOSCH, paguei R$ 18,00 , vou fazer um programinha para ter um aparelho que mostre Pressão Atmosférica, Temperatura , Umidade Relativa do Ar e Ponto de Orvalho, para me ajudar nas minhas pescarias ...... até domingo postarei o projetinho. Paulo ATUALIZAÇÃO - Estou incluindo no Tutorial o uso do DHT-11, e também um projetinho simples de uso do BMP085, mostrando apenas a pressão e a temperatura. Motivo - o programa que fiz e vou postar aqui no tópico ficou grande demais, pois utilizei 3 sensores com interfaces diferentes para ilustrar um uso mais sofisticado do Bascom; e acabou precisando de um ATMEGA88 para caber tudo, mas a versão demo do Bascom não consegue compilar, pois passa de 4 Kb. Porisso, estou fazendo esse novo projetinho apenas para o Tutorial, que irá permitir utilizar o ATMEGA48 e a versão demo do Bascom. Logo postarei o Tutorial Atualizado.

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

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!