-
Posts
8.316 -
Cadastrado em
-
Última visita
Tipo de conteúdo
Artigos
Selos
Livros
Cursos
Análises
Fórum
Tudo que aphawk postou
-
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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. -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Seguem os trechos de código que interessam : ' A seguir, a declaração da frequência do cristal : Const Xtal = 12500000 ' This is the CPU clock frequency 12.5 Mhz $crystal = Xtal ' Agora, a seguir, a configuração do timer0 com prescaler de 1024 : Config Timer0 = Timer , Prescale = 1024 ' configure the timer On Ovf0 Tim0_isr ' Define ISR handler for clock Enable Timer0 ' Enable timer 0 interrupt Dim Bres As Long ' --This is the timer value Enable Interrupts ' enable global Interrupts ' E agora, a seguir, a rotima de interrupção do timer0, repare que a variável Brea é o tal de contador de ciclos de clock que falei no post acima : Tim0_isr: Bres = Bres + 262144 ' 262144 = prescaler:1024 * timer0:256 If Bres > Xtal Then ' = xtal frequency Bres = Bres - Xtal Incr L2 ' Increment system seconds End If Return Simples e muito funcional, espero que lhe ajude. Uma coisa muito importante : no seu programa, não suspenda a interrupção do timer em nenhum momento ! Se precisar desabilitar alguma das outras interrupções, faça manualmente uma a uma, em vez de desabilitar TODAS as interrupções, pois é muito importante que nada suspenda a interrupção desse Timer ! Paulo
-
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
-
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
-
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
-
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
-
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Circuito com AMP-OP L272M para alimentação de uma bomba D'água 24v
aphawk respondeu ao tópico de nelsondantas em Eletrônica
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 -
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
-
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
-
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
-
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
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
-
Controlando motor de passo com potenciometro
aphawk respondeu ao tópico de Evertton Laddaga em Microcontroladores
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 -
Controlando motor de passo com potenciometro
aphawk respondeu ao tópico de Evertton Laddaga em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
Projetos com Avr : Design, Programação em Basic e Assembly
aphawk respondeu ao tópico de aphawk em Microcontroladores
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 -
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
-
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
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