ekit - kit de apoio à aprendizagem de sinais, circuitos e ... · an´alise de circuitos. iv. ......

117
Ekit - Kit de Apoio à Aprendizagem de Sinais, Circuitos e Sistemas Electrónicos Nuno Filipe Maia Lucas Dissertação para obtenção do grau de Mestre em Engenharia Electrotécnica e Computadores Júri Presidente: Prof. Carlos Jorge Ferreira Silvestre Orientador: Prof. Dr. José António da Cruz Pinto Gaspar Co-Orientador: Prof. Dr. João Fernando Cardoso Silva Sequeira Vogais: Prof. Dr. João Miguel Raposo Sanches Setembro 2008

Upload: dinhxuyen

Post on 04-Nov-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

Ekit - Kit de Apoio à Aprendizagem de Sinais, Circuitos e Sistemas Electrónicos

Nuno Filipe Maia Lucas

Dissertação para obtenção do grau de Mestre em

Engenharia Electrotécnica e Computadores

Júri

Presidente: Prof. Carlos Jorge Ferreira Silvestre

Orientador: Prof. Dr. José António da Cruz Pinto Gaspar

Co-Orientador: Prof. Dr. João Fernando Cardoso Silva Sequeira

Vogais: Prof. Dr. João Miguel Raposo Sanches

Setembro 2008

Agradecimentos

Agradeco a todos que directa ou indirectamente contribuıram para a realizacao desta tese.Ao incansavel Professor Jose Gaspar, nao so pelo apoio e acompanhamento ao longo do trabalho, mas tambem

e sobretudo por me despertar quando eu adormecia no caminho,Ao Professor Joao Sequeira pela ajuda e supervisao ainda que a distancia,Aos colegas que gentilmente contribuıram como cobaias nas experiencias inicias,A Catarina por me aturar nos piores momentos,Aos meus pais pela paciencia e confianca inabalaveis, sem as quais nao teria conseguido alcancar estes objec-

tivos,Um Muitıssimo Obrigado!!!

ii

Resumo

A crescente mobilidade dos estudantes na Europa, e outros paıses, bem como a recente uniformizacao dossistemas de ensino superior, imposta por Bolonha, veio trazer a necessidade de aumentar a cooperacao entre uni-versidades, de forma a desenvolver modulos educacionais assentes numa base comum.[7]Com a entrada em vigor de Bolonha, o processo de auto-aprendizagem, conduziu a abolicao de muitas cadeiras

experimentais nos cursos superiores de engenharia.Esta dissertacao descreve um projecto cujo objectivo maior, reside na capacidade de proporcionar ao aluno,

uma ferramenta de aprendizagem autonoma.O Ekit visa a aquisicao de conhecimentos praticos, atraves da experiencia, que proporcionam um completo su-

plemento aos conhecimentos apenas leccionados em teoria, nomeadamente, sinais, circuitos, e sistemas electronicos.Recorrendo apenas a um equipamento simples de manusear e facil de adquirir torna possıvel realizar experienciasde medicao de resistencias, condensadores, parametros de motor DC e resposta em frequencia de sistemas dinamicos.

Palavras-chave: Microcontrolador USB, Conversao analogico-digital, Conversao digital-analogica, e-Learning,Analise de circuitos.

iv

Abstract

The increase of student mobility in Europe and in other countries, and the recent attempt to harmonise Europeancurricula at the graduation and post-graduation levels lead towards an increasing co-operation among universitiesto develop educational modules with a common background [7] .With Bolonha coming into effect in most universities the self-learning processes lead to the abolition of many

experimental classes in the electronic graduations courses.This thesis describes a project which aims to provide the students an independent learning tool .The Ekit seeks to acquire practical knowledge through experience, which provides a complete supplement to

the knowledge offered only in theory, in particular, signals, circuits and electronic systems.Using only one equipment simple to handle and easy to acquire, it is possible to carry out experiments on

measuring resistors, capacitors, DC motor parameters and frequency responses of dynamic systems.

Keywords: Microcontroller based interfaces, Analog to digital conversion, Digital to analog conversion, e-Learning,Circuit analysis.

vi

Conteudo

Agradecimentos i

Resumo iii

Abstract v

1 Introducao e Enquadramento 11.1 Ponto de Vista dos Alunos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Ponto de Vista dos Docentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Ponto de Vista da Instituicao de Ensino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4 Objectivos e Estrutura da Tese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 Hardware 52.1 Interface USB para ligacao PC-Microcontrolador . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.1.1 Versoes USB e Barramento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.1.2 Protocolo USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.1.3 Aplicacao ao Ekit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.2 Kit completo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.2.1 Modulo DLP-2232PB-G . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.2.2 Hardware de USB, circuito integrado FT2232D . . . . . . . . . . . . . . . . . . . . . . . 92.2.3 O microcontrolador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.2.4 Conversao D/A, circuito integrado MCP4822 . . . . . . . . . . . . . . . . . . . . . . . . 11

2.3 Desempenho do Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3 Software 153.1 PC-driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.1.1 Funcionalidades pretendidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.1.2 Camadas de software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.1.3 Inicializacao, deteccao de modulos USB . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.1.4 Protocolo de comunicacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.1.5 Interface generico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

3.2 Firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203.2.1 Firmware original . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

viii CONTEUDO

3.2.2 Firmware implementado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.3 Testes do software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4 Aplicacoes Didaticas 254.1 Medicao de resistencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.2 Medicao de condensadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.3 Parametros do motor DC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284.4 Diagramas de Bode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

5 Conclusoes e Trabalho Futuro 35

Bibliografia 37

A Especificacoes do PIC16F877A 39

B Modulo USB comercial DLP-2232PB-G 47

C Software de interface para PC 49

D Software do microcontrolador 51

E Guias das experiencias 53

F Forum e web page 55

Lista de Figuras

2.1 Esquematico de Hardware. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.2 Topologia USB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.3 Sequencia de frames do protocolo USB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.4 Conexao do adaptador USB ao microcontrolador. . . . . . . . . . . . . . . . . . . . . . . . . . . 92.5 Diagramas temporais do adaptador USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.6 Protocolo SPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.7 Comunicacao SPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.8 Modulo DLP e DAC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.9 Onda sinusoidal gerada a frequencia maxima . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.10 Onda sinusoidal adquirida a frequencia maxima . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.1 Ligacao do PC ao dispositivo USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2 Camadas de software para comunicacao USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3 Discrepancia de tempos na aquisicao de amostras . . . . . . . . . . . . . . . . . . . . . . . . . . 223.4 Ondas geradas e adquiridas pelo modulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.5 Funcionamento do software em ambiente MS Visual Studio 2005. . . . . . . . . . . . . . . . . . 233.6 Fluxograma do firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4.1 Experiencia de medicao de resistencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.2 Setup do circuito RC serie para medicao do condensador C. . . . . . . . . . . . . . . . . . . . . 264.3 Experiencia de medicao do condensador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.4 Driver de potencia (esquerdo), o motor e sensores (direito). . . . . . . . . . . . . . . . . . . . . . 284.5 Constante de tempo vs Ganho estatico do motor DC . . . . . . . . . . . . . . . . . . . . . . . . . 294.6 Constante de tempo vs Ganho estatico do motor DC . . . . . . . . . . . . . . . . . . . . . . . . . 314.7 Setup para obtencao do diagrama de Bode de um circuito RC. . . . . . . . . . . . . . . . . . . . 314.8 Entrada e saıda de um circuito RC em resposta a uma onda sinusoidal a varias frequencias. . . . . 324.9 Diagrama de Bode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

A.1 Pinos do microcontrolador PIC16F877A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40A.2 Arquitectura interna do PIC16F877A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41A.3 Organizacao da memoria do programa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41A.4 Mapa de memoria do arquivo de registos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

x LISTA DE FIGURAS

A.5 Diagrama de blocos do conversor A/D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44A.6 Configuracoes possıveis dos pinos do conversor A/D . . . . . . . . . . . . . . . . . . . . . . . . 44

F.1 Forum de ajuda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55F.2 Site com guias e software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

Capıtulo 1

Introducao e Enquadramento

Numa era em que a tecnologia abunda, e a electronica e quase omnipresente, esta latente a urgencia de formarbons alunos em engenharia electrotecnica e computadores, para tal, a prioridade, mais que teoriza-los e abandona-los ao ensaio da auto-aprendizagem, consiste em guia-los de forma a potencializar a individualidade e colmatar asfalhas do ensino desacompanhado.A Reestruturacao academica conduzida pelo processo de Bolonha, deixou de parte uma importante compo-

nente da engenharia electronica, nomeadamente, a interaccao laboratorial com os mais elementares dispositivoselectronicos.Com o objectivo de promover a igualdade de ensino e qualificacoes na uniao europeia e outros paıses aderentes,

o processo de Bolonha veio trazer uma nova forma de abordar a aprendizagem, o e-learning , um sistema de auto-aprendizagem cujo objectivo maior consiste em capacitar o aluno para a auto-aquisicao de conhecimentos numespaco/meio mais amplo do que a sala de aula tradicional, atraves da internet e com o auxılio de ferramentasinteractivas. O Ekit vem trazer vantagens a alunos, Professores e ate a propria Instituicao de Ensino.

1.1 Ponto de Vista dos Alunos

O Ekit e um projecto com o objectivo de facilitar a auto-aprendizagem pratica dos alunos na area de analise decircuitos, tem como principais vantagens a facilidade de utilizacao; o baixo custo; as capacidades do hardware.Uma vez que os alunos de primeiro ano nao estao familiarizados com o manuseamento de componentes

electronicos, o facto dos utilizados neste projecto serem de facil utilizacao sao uma mais-valia, mas nao a unica,pois o Ekit e um projecto apelativo em tres parametros distintos. Para alem da acessibilidade de utilizacao supra-mencionada, temos ainda o facto de com um setup mınimo conseguir reproduzir uma geracao e aquisicao de sinaisidentica a proporcionada por equipamentos dispendiosos e mais difıceis de manusear por utilizadores inexperien-tes, como fontes de alimentacao, osciloscopios e geradores de sinais, existentes nos extintos laboratorios o que setraduz numa outra mais-valia, que se resume ao baixo custo dos componentes necessarios a este projecto.Pretende-se que o conjunto mınimo de hardware acima mencionado seja disponibilizado, por emprestimo, aos

alunos de primeiro ano de engenharia electrotecnica e computadores a frequentar a cadeira de analise de circuitos,pela propria instituicao de ensino, podendo no entanto, os alunos com interesse pessoal na utilizacao do Ekit ou porhobby quer por curiosidade, ainda que nao preencham os requisitos necessarios ao emprestimo, podem facilmente

2 Introducao e Enquadramento

adquirir o conjunto de hardware a custo reduzido (aproximadamente o custo de um livro de consulta).Sao sem duvida os alunos quem mais tem a ganhar nesta equacao, pois gracas ao Ekit adquirir conhecimentos

praticos e realizar experiencias no ambito da materia leccionada da cadeira de analise de circuitos, com recurso aoseu computador pessoal e a um conjunto mınimo de hardware. Podendo ainda usufruir de um forum de esclareci-mento, suporte e discussao, moderado por alunos, bem como um site onde se disponibilizam os drivers, softwaree manuais de instalacao, tudo isto sem necessitar de supervisao docente. A pre-visualizacao de ambos os espacosencontra-se disponıvel no anexo F

1.2 Ponto de Vista dos Docentes

Do ponto de vista do docente a vantagem reside na componente pratica que o Ekit proporciona ao aluno e quefacilita e complementa a compreensao da materia teorica leccionada sem que para tal o docente despenda o seutempo. Encontrando-se o mesmo apenas presente atraves da avaliacao interactiva no sistema e-learning.O e-learning e mais do que colocar um conjunto de pdf’s na internet e responder a duvidas de alunos por correio

electronico[2], este responsabiliza o aluno pela sua educacao passando o mesmo a controlar diversos aspectos doprocesso, como a escolha e o acesso as fontes de informacao, os momentos e locais desse acesso e ate os processosde interaccao com os outros participantes[5]. O e-learning atribui ao professor o trabalho de avaliar e dirigir o alunono processo de aprendizagem cognitivo, proporcionando ao docente um metodo individualizado de avaliacao, poisessa nao se limita ao espaco e decurso temporal de uma aula teorica. Concede assim ao docente a oportunidade deavaliar personalizadamente cada aluno com recursos a ferramentas interactivas[9].Constatamos entao que para o docente o Ekit se transforma numa ferramenta complementar de avaliacao indi-

vidual, ou seja, disponibiliza um metodo de avaliacao dos conhecimentos teoricos elevados a pratica.

1.3 Ponto de Vista da Instituicao de Ensino

Resta-nos analisar a perspectiva da Instituicao de Ensino, sendo que e ela a base de todo o projecto, estaodepositadas a seu cargo as competencias de facultar ao aluno o melhor metodo de aprendizagem disponıvel. Destemodo, e tambem a Instituicao de Ensino que cabe proporcionar ao aluno as ferramentas fundamentais para usufruirtao amplamente quanto possıvel dessa mesma aprendizagem. Ao longo do projecto, a Instituicao de Ensino,assume multiplos e diferenciados papeis, todos eles de extrema importancia, ainda que em cenarios distintos.Num primeiro momento a Instituicao de Ensino, foi a Mentora do projecto, sendo que dela partiu a iniciativa

de proposta da criacao do mesmo, de notar que apenas estando atenta as necessidades academicas dos alunosa Instituicao de Ensino, detectou uma lacuna flagrante deixada por Bolonha e procurou uma forma elementar eeconomica de a colmatar.Esta ultima caracterıstica da resolucao do problema, a economia, transporta-nos para outro dos papeis da

Instituicao de Ensino, o de Financiadora do projecto, e ela quem suporta os custos quer na execucao do projecto,quer posteriormente na aquisicao e disponibilizacao do hardware aos alunos no ambito do projecto, uma vez que aestes sera ”emprestado”mediante o pagamento de uma caucao.O que nos leva a outro papel, o Pedagogico, na medida em que assenta no aproveitamento pratico e directo do

projecto para fins de avaliacao individual, concretamente, o fim imediato para que o projecto foi concebido, propor-cionar um suplemento de auto-aprendizagem de cariz pratico aos alunos, de modo a potenciar os conhecimentos

1.4 Objectivos e Estrutura da Tese 3

teoricos ja leccionados.Por ultimo, mas nao menos importante, abordemos o papel Promovedor, pois e da Instituicao de Ensino de

quem se espera a difusao e promocao deste projecto junto de outras entidades, nao so das academicas, visandoa apresentacao enquanto ferramenta pedagogica, mas tambem a promocao do projecto na area empresarial, eoutras das tarefas que cabem a Instituicao de Ensino. Para tal, a mesma, estabelece especificacoes de hardwarenecessarias ao projecto e avalia a validade/qualidade das propostas apresentadas pelas empresas, nomeadamente,se sao propostas aceitaveis e se estao de acordo com as especificacoes. Assim o custo e mınimo para a Instituicao(podendo receber algo pela avaliacao das propostas) e ainda se garante o interesse das empresas na criacao denovos produtos de hardware. Abordadas as competencias da Instituicao de Ensino, analisemos agora de que formapode esta, prolongar a longevidade do projecto. Durante a execucao deste projecto surgiu a oportunidade desubmeter um artigo cientifico de apresentacao do projecto Ekit nas Quartas Jornadas de Engenharia de Electronicae Telecomunicacoes e de Computadores.A longevidade de um projecto, e directamente proporcional a sua flexibilidade. Nao basta ao projecto que tenha

qualidade, e necessario, que este seja abrangente e permanentemente actual, para tal, necessita de um interfacegenerico que proporcione uma utilizacao basica de todas as potencialidades do microcontrolador e que garantauma utilizacao em microcontroladores mais recentes e/ou sofisticados num futuro proximo. A nao esquecer quepara tal ha que assegurar, uma actualizacao constante, com vista a que nao se perca o trabalho desenvolvido ate adata pela Instituicao de Ensino.

1.4 Objectivos e Estrutura da Tese

O principal proposito da tese, desta dissertacao, reside precisamente na projeccao/execucao de uma ferramentainovadora, para os alunos de primeiro ano de analises de circuitos. Visando a possibilidade destes realizarem umconsideravel numero de experiencias padrao na area de analise de circuitos, outrora apenas possıveis em labo-ratorio, de uma forma agora economica e quase autonoma.Esta dissertacao encontra-se organizada da seguinte forma, no capıtulo 2 surge a composicao e caracterısticas

principais do hardware utilizado no projecto, seguindo-se no capıtulo 3 o desenvolvimento de software parautilizacao do hardware, no capıtulo 4 encontram-se algumas experiencias didaticas realizadas com recurso aoEkit, e finalmente apresentam-se nao so as conclusoes finais, como tambem alguns projectos para o futuro.

4 Introducao e Enquadramento

Capıtulo 2

Hardware

O objectivo principal do trabalho desta dissertacao reside na construcao de um kit de apoio a aprendizagem desinais, circuitos e sistemas electronicos. Para que isso fosse possıvel foi necessario, nao so uma procura intensivade componentes de hardware adequados, como a criacao de software eficaz.O avanco tecnologico despoletou um decrescimo dos precos do material electronico, a prova-lo, a grande

maioria dos alunos possuı actualmente um computador pessoal. O mesmo avanco proporcionou tambem, oaparecimento, na ultima decada, de micro controladores de compra acessıvel possuindo muito bons converso-res, analogico-digitais e digitais-analogicos, que quando aliados a um dispositivo com ligacao USB permitem aobtencao de uma excelente solucao: o micro controlador consegue gerar e adquirir sinais enviando-os posterior-mente para o computador. O computador desempenha o papel de gerador, fornecendo alimentacao aos dispositivos,bem como de osciloscopio permitindo a visualizacao dos sinais resultantes.Ao iniciar o processo de edificacao do Ekit estabeleceu-se como prioridade a escolha do microcontrolador mais

adequado tendo em conta o menor custo e a versatilidade. Sob a premissa de criar um dispositivo que seja robusto,compacto e resistente visando a sua finalidade, ser utilizado por multiplos utilizadores, procurou encontrar-se umdispositivo com conversores AD/DA e conexao a um PC via USB(figura [ 2.1]).

Figura 2.1: Esquematico de Hardware.

No ınicio do trabalho foram especificados objectivos mınimos a nıvel do desempenho do hardware, este ne-cessitaria de possuir: canais analogicos de entrada e saıda; conversores com resolucao mınima de 8 bits; umafrequencia amostral suficiente para dispositivos mecanicos (1kHz a 2kHz), para futuramente poder ser utilizadoem experiencias tıpicas (controlo de motores DC) de outras cadeiras do curso, como por exemplo, Controlo do

6 Hardware

terceiro ano; facilidade de interface (ligacao USB). Relembrar que a aquisicao deste hardware deve ter em contao preco, para poder ser uma alternativa barata para a Instituicao de Ensino, e no caso de interesse pessoal, para ospropriosalunosSeleccionaram-se para o desenvolvimento deste projecto o modulo DLP-2232PB-G e o DAC MCP 4822 pois

sao os dispositivos que melhor preencheram os requisitos de hardware estabelecidos e tem um preco de aproxima-damente 50 euros .O modulo DLP-2232PB-G e composto por um adaptador USB FT2232D e ummicrocontroladorPIC 16F877A embebidos.O adaptador USB FT2232D funciona como um interface de comunicacao entre o micro-controlador e o PC.

2.1 Interface USB para ligacao PC-Microcontrolador

O USB e um barramento que suporta a troca de dados entre um computador (Host) e um grande numero deperifericos. O barramento permite que os perifericos sejam conectados, configurados, utilizados e desconectadossem ser necessario reiniciar o computador. Os dispositivos conectados dividem a banda de transmissao segundouma ordem imposta pelo Host.

2.1.1 Versoes USB e Barramento

Uma das primeiras versoes USB foi a 1.0 com velocidade de 1,5Mbs (Low-speed), logo em seguida foi con-cebida a 1.1 com velocidades que vai de 1,5Mbps a 12Mbps. Essa versao e conhecida com Full-speed. Nofinal de 2000 foi lancada a versao 2.0 (high-speed), compatıvel com as versoes anteriores, mas com algunsaperfeicoamentos que vao desde a topologia a velocidade de trafego de dados, atingindo velocidades de 480Mbps.Num sistema USB apenas pode existir um Host que e definido por um Host controller. A este Host controller

esta associado um root hub que proporciona uma ou mais portas. A topologia (figura [ 2.2]) do barramento USBpode ser composta por ate 127 dispositivos, entre hubs e funcoes. Os hubs aumentam a quantidade de dispositivosque podem ser conectados ao barramento adicionando mais portas. No entanto, e definido pela especificacao queum dispositivo pode ser conectado com o maximo 5 nıveis de hubs entre ele e o root hub.

Figura 2.2: Topologia USB.

2.1 Interface USB para ligacao PC-Microcontrolador 7

O termo endpoint (”node”na figura [ 2.2]) e utilizado para descrever um ponto de entrada ou saıda de dadosde um sistema USB. O conjunto de um ou mais endpoints que implementam uma conexao com o mundo real echamado de interface. Cada interface esta associada a um device driver no Host atraves de um pipe, ou canal. Umdispositivo pode ter mais de uma interface e todas elas funcionam em paralelo, cada uma com seu respectivo driver.O barramento fısico USB e composto por quatro condutores: VCC, D+, D- e GND. Os dados sao transmi-

tidos de forma diferencial pelos condutores D+ e D-. O sinal VCC e responsavel por fornecer alimentacao aosdispositivos.

2.1.2 Protocolo USB

O protocolo USB, tem como finalidade a comunicacao entre o Host do computador e um ou mais dispositivos,so que num formato diferente da comunicacao de uma porta paralela ou serie, que utiliza sinais electricos atravesde seus pinos. Na comunicacao USB o protocolo esta presente tanto no Host como no dispositivo. No primeiro, oprotocolo apresenta-se sob formato de drivers, no dispositivo, encontra-se na memoria de um microcontrolador ounum chip (FTDI neste caso).A comunicacao entre o Host e um dispositivo USB e feita atraves de pacotes. Os pacotes sao constituıdos por,

no mınimo, tres campos: um de sincronizacao, chamado de SYNC, um de identificacao do pacote chamado dePID (Packet IDentificator) e o EOP (End Of Packet) indicando o fim do pacote. Entre o campo de PID e o campoEOP pode haver um campo de dados de no maximo 8 bytes para um dispositivo low-speed, 1023 bytes para umfull-speed e 1024 bytes para um high-speed.Existem tres tipos de pacotes: Token, Data e Handshake. A comunicacao inicia-se pelo pacote Token, gerado

pelo Host, com o intuito de descrever o que vira no proximo pacote, e se e uma escrita ou leitura. Segue-se o pacoteData, que possui todos os dados que serao lidos ou escritos e por ultimo o pacote Handshake, que informa se houvefalha ou sucesso na transaccao. Ao conjunto de pacotes Token, Data e/ou Handshake chama-se transaccao.As especificacoes USB definem transaccao como a entrega de um servico a um endpoint. Servico tanto pode

ser o Host a enviar informacao a um dispositivo, como o Host a pedir e receber informacao do dispositivo. O Hoste responsavel por controlar o fluxo de dados no barramento. Multiplos dispositivos podem querer transferir dadosao mesmo tempo, para que tal nao ocorra, o Host controller divide a largura de banda disponıvel em frames deum milissegundo (ou microframes de 125 micro segundos para USB High Speed). Cada frame e iniciada com umpacote SOF (Start of frame) seguido de transaccoes (figura [ 2.3]) para endpoints especıficos de cada dispositivo,ou transferencias de dados destes endpoints para o Host (o pacote SOF serve igualmente para sincronizar os hubscom o Host).

Figura 2.3: Sequencia de frames do protocolo USB.

8 Hardware

O numero de transaccoes possıveis dentro de cada frame depende do tipo de transferencia (Controlo, Bulk,Interrupt, Assıncrona). Uma transaccao deve ocorrer dentro de um unico frame e quando iniciada nao pode serinterrompida por outras transaccoes ate o seu termino[6].

2.1.3 Aplicacao ao Ekit

O nosso adaptador USB FT2232D e compatıvel com USB 1.1 e 2.0 (embora somente em modo Full Speed).Um pedido ao modulo USB e enviado numa transaccao, numa determinada frame, sendo que a resposta provenientedo modulo para o Host ja se encontra na frame seguinte. Uma vez que no modo Full Speed, cada novo frame temınicio a cada milissegundo, tal implica uma frequencia de amostragem (pedido e recepcao de dados) inferior a 1KHz. Para superar esta limitacao de comunicacao USB exige-se trabalho de software, nomeadamente buffering,com o objectivo de se conseguir colocar o maior numero de dados num unico frame e nao se estar dependente de umnovo pedido do PC. Como o USB impoe um milissegundo de comunicacao e necessita-se de maiores frequencias,sera necessario o desenvolvimento de software.

2.2 Kit completo

O kit completo e o conjunto de dispositivos utilizados para adquirir e gerar sinais e posteriormente envia-lospara o PC. Este conjunto e constituıdo pelo modulo DLP-2232PB-G e pelo DAC MCP4822. Utilizaram-se doisdispositivos porque o modulo DLP que contem o adaptador USB e o PIC16F877A so possuı conversores analogico-digitais. Tal inviabilizava a geracao de sinais, problema esse que foi resolvido adicionando o DAC MCP4822, umconversor digital-analogico, que comunica com o modulo atraves do protocolo SPI.Recentemente surgiram novos microcontroladores de 16bit da famılia dsPIC33FJ, com 28 e 44 pinos, que pela

primeira vez dispoem de dois canais de conversao DAC com 16bit de resolucao mantendo nestes novos modelos, osconversores ADC de 10bit ou de 12bit. Espera-se que estes novos microcontroladores substituam com sucesso osantigos, mantendo as funcionalidades e sobretudo melhorando taxas de aquisicao e geracao de sinais (ADC/DAC).Apesar de ja estarem a ser desenvolvidos novos prototipos, a maior parte das experiencias da tese foram realizadascom base na solucao DLP-2232PB-G, que sera por isso a solucao descrita e detalhada nas seccoes e capıtulosseguintes.

2.2.1 Modulo DLP-2232PB-G

O modulo DLP e composto pelo circuito integrado adaptador para USB (FT2232D) e pelo microcontroladorPIC 16F877A. A ligacao dos dois componentes e realizada por um barramento de 8 bits, utilizando para o efeitoo porto D do microcontrolador (pinos D0 a D7). No anexo B encontra-se a descricao das funcoes associadas aospinos do modulo DLP.Abordando omodulo como um dispositivo unico encontram-se disponıveis as seguintes funcionalidades/potencialidades:

• Alimentacao do modulo (5v) e de alguns circuitos a partir do USB (esta opcao pode ser desactivada paracriacao de sistemas autonomos)

• Envio e recepcao de dados via USB para um PC ate 2 megabits por segundo. Compatibilidade com USB 1.1e USB2.0.

2.2 Kit completo 9

• 16 pins I/O digitais (5 podem ser configurados como entradas A/D)

• 5 entradas A/D de 10 bits.

• Microcontrolador com 8kB de FLASH ROM e 368 Bytes de RAM.

• Alimentacao via USB.

2.2.2 Hardware de USB, circuito integrado FT2232D

O circuito integrado FT2232D e uma interface USB que incorpora as funcionalidades de dois circuitos inte-grados FTDIs da segunda geracao num unico dispositivo. Uma unica porta de saıda USB e convertida para doiscanais I/O que podem ser individualmente configurados como um interface UART FT232BM, ou um interfaceFIFO FT245BM, sem a necessidade de adicionar um hub USB.Optou-se por configurar o adaptador como um interface FIFO FT245BM que sucintamente consiste num FIFO

de leitura e de escrita que resulta na pratica num porto bidireccional de 8 bits de leitura e escrita com memoria.Este dispositivo nao requer a utilizacao de memorias para armazenar os dados a serem enviados para o PC umavez que possui um buffer FIFO de transmissao de 384 bytes e tambem um buffer FIFO de recepcao de 128 bytes.O desenvolvimento da aplicacao no PC pode ser efectuada utilizando um driver de COM virtual (VCP) ou via

biblioteca de interface (DLL). No primeiro caso o PC ve o modulo com se fosse uma porta serie, o software eescrito como se tratasse de uma aplicacao na porta serie. No segundo caso e necessario conhecer as especificacoesdas funcoes implementadas pela biblioteca dinamica (DLL).Neste projecto recorre-se a primeira forma, ou seja, como uma porta serie em que foi necessario usar os drivers

fornecidos pelo fabricante.As taxas de transferencia podem chegar ate 2 Megabits por segundo, sendo o metodo FIFO uma mais valia para

criar o interface com um microcontrolador, atraves das portas de I/O, pois assim consegue-se controlar o envio e arecepcao de palavras (de 1 byte) ao PC.

Ligacao ao Microcontrolador - Na figura [ 2.4] estao patentes quais as linhas de controlo do adaptador USB(FT2232D) que o microcontrolador deve controlar para que seja executado o processo de leitura/escrita.

Figura 2.4: Conexao do adaptador USB ao microcontrolador.

Para tal, basta efectuar o controlo das duas entradas, TXE# e RXF#, e de duas saıdas, WR e RD#.

10 Hardware

Ciclos de Leitura e Escrita - Os diagramas temporais de escrita e leitura no adaptador USB, estao representadosna figura [ 2.5].

Figura 2.5: ciclo de escrita (esquerda), ciclo de leitura (direita).

Para enviar dados, basta colocar os dados disponıveis nas 8 linhas de dados do adaptador (D[7..0]). QuandoTXE = 0, um impulso de 0 para 1 na linha de controlo WR faz com que os dados sejam guardados no buffer de 384bytes do adaptador. Quando a linha TXE = 1, significa que o buffer de envio esta cheio, logo nao se pode enviardados. Os dados sao posteriormente retirados do buffer pelo PC realizando-se desta forma varios ciclos de leitura.

A recepcao dos dados enviados pelo PC so pode ser feita quando a linha de controlo RXF = 0. Quando for0, esta linha indica que o buffer de recepcao tem dados enviados pelo PC. Neste caso, apenas e necessario umimpulso de 1 para 0 na linha de controlo RD para que os 8 bits fiquem disponıveis em D [7..0].

2.2.3 O microcontrolador

A maioria das funcionalidades disponıveis no modulo DLP-2232PB-G sao garantidas pelo microcontrolador.E neste dispositivo que se interpretam as instrucoes enviadas do PC atraves do adaptador USB. Cabe igualmente aeste dispositivo realizar o buffering (atraves de software) necessario para ultrapassar a limitacao USB, bem comocontrolar qualquer dispositivo que se pretenda adicionar.

Os microcontroladores sao cada vez mais sofisticados, baratos e surgem diariamente com novas funcionalida-des. Os microcontroladores sao dispositivos compostos por varios componentes num unico modulo de circuitointegrado, a CPU (unidade central de processamento), RAM (memoria de acesso aleatorio), EPROM (ou variantesEEPROM, ROM, PROM , memoria somente de leitura, I/O (entradas e saıdas digitais e analogicas), TEMPORI-ZADORES (contadores e temporizadores) e Interrupts.[4]

Os microcontroladores da serie PIC16F87X sao maquinas RISC. Isto significa que sao maquinas com umreduzido conjunto de instrucoes (total de 35 instrucoes cada uma ocupando uma palavra, 14bits) As suas principaiscaracterısticas sao: uma frequencia de relogio de 20MHz (perıodo 200ns); 8K x 14 palavras de Memoria dePrograma de FLASH; 368 x 8 bytes de Memoria de Dados (RAM); 256 x 8 bytes de EEPROM Dados Memoria;3 TIMERs; um conversor A/D de 8 canais de 10 bits; porta serie sıncrona; modulo PWM; Watchdog timer; modoeconomico de energia (SLEEP);

O PIC16F877A e formada por 44 pinos, sendo que a maioria possuı mais que uma funcao. A sua estruturainterna e composta por 5 modulos: um modulo logico e de controlo, modulos de memoria RAM e ROM, portas deI/O e o modulo de perifericos, onde se localizam o Watchdog, Timers, USART e outros perifericos. No anexo Aaprofundam-se detalhadamente as especificacoes deste microcontrolador.

2.2 Kit completo 11

2.2.4 Conversao D/A, circuito integrado MCP4822

Para o modulo DLP ser uma solucao completa necessitava de conversores digitais analogicos incorporados(para se poder realizar a geracao de sinais e ondas sinusoidais).Uma vez que nao existe ainda um modulo robusto e pratico com essa funcionalidade extra, optou-se por co-

nectar ao modulo, um conversor digital analogico que permitisse comunicacao Interface Periferica Serie (SPI). Oconversor DACMCP4822 e um conversor digital-analogico de 12 bits, tensao de referencia interna e interface SPI.SPI e um protocolo (Figura [ 2.6]) que permite a comunicacao do microcontrolador com diversos outros com-

ponentes, formando uma rede. Em modo slave, o microcontrolador comporta-se como um componente da rede,recebendo o sinal de relogio. Em modo master, o microcontrolador gera um sinal de relogio e deve ter um pino deI/O para habilitacao de cada periferico. O protocolo SPI e composto por 4 sinais:

Figura 2.6: Protocolo SPI

• Sinais de dados: MOSI (Master data Output, Slave data Input) e MISO (Master data Input, Slave dataOutput) sao responsaveis pela transferencia de dados entre o master e o slave.

• Sinais de controle: SCLK (Serial Clock) e /SS (Slave Select).

A comunicacao (Figura [ 2.7]) entre o dispositivo master e varios dispositivos slave utilizando o protocolo SPIe possıvel gracas ao pino /SS, no caso da comunicacao de um master com diversos dispositivos slaves, requeremdo microcontrolador um grande numero de pinos de seleccao.

Figura 2.7: Comunicacao SPI

O protocolo de comunicacao e muito simples, nao requerendo uma programacao complicada. Por isso mesmo,este protocolo permite uma mais alta velocidade de comunicacao que o I2C.Apos a conexao do modulo DLP com o DAC obtemos finalmente uma solucao completa, barata e simples para

geracao e aquisicao de sinais com ligacao a um PC (Figura [ 2.8]).

12 Hardware

Figura 2.8: Diagrama (direita) e setup real (esquerda) do modulo DLP e DAC.

2.3 Desempenho do Hardware

O desempenho do hardware e a grande contribuicao do capıtulo, especialmente porque cumpriu as especificacoespretendidas. Foram efectuados testes e medicoes para comprovar o alcancar dos objectivos.Para testar a frequencia maxima de geracao de sinais colocou-se o Ekit a gerar uma onda sinusoidal composta

por noventa e seis amostras por perıodo. Na figura [ 2.9] pode-se ver a onda sinusoidal gerada pelo Ekit e adquiridapor um osciloscopio analogico Kikusui COS5020 20 MHz, e pela placa de aquisicao da National Instruments NIPCI-6221 (possuı conversores analogicos digitais de 12 bits).

0 5 10 15 20 250

0.5

1

1.5

2

2.5

3

3.5

4

4.5

tempo [miliseg]

y [v

olt]

Figura 2.9: Onda sinusoidal gerada a frequencia maxima e adquirida por um osciloscopio (esquerda) e pela placada NI (direita)

O sinal foi adquirido pelo osciloscopio e pela placa da NI para confirmar os resultados obtidos. Se fosse soutilizado o osciloscopio, este poderia encontrar-se descalibrado, perdendo-se a precisao temporal. Observando comalgum pormenor as imagens, especialmente a referente ao osciloscopio, nota-se que a escala de divisao temporal

2.3 Desempenho do Hardware 13

encontra-se a 1 milissegundo por divisao e que a onda sinusoidal ocupa aproximadamente 4,6 divisoes (perıodode 4.6 milissegundos), ou seja, a onda sinusoidal tem uma frequencia aproximada de 217.391304 Hz. Tendo emconta que o modulo gera 96 amostras em cada perıodo, a frequencia de geracao de amostras (96 ∗ 217 = 20869) eaproximadamente 20 kHz.No que diz respeito a frequencia maxima de aquisicao de sinais, colocou-se a placa da NI a gerar uma onda

sinusoidal com 1V de amplitude, 1V de offset, uma frequencia de 10Hz, e adquiriu-se com o Ekit. Na figura[ 2.10] pode-se ver a aquisicao do sinal a frequencia maxima conseguida, em funcao das amostras e em funcao dotempo.

0 500 1000 1500 2000 25000

0.5

1

1.5

2

2.5Onda sinusoidal gerada pela placa NIDAQ

Numero de amostras

Tens

ão [V

]

0 0.05 0.1 0.15 0.2 0.250

0.5

1

1.5

2

2.5Onda sinusoidal gerada pela placa NIDAQ

Tempo [seg]

Tens

ão [V

]

Figura 2.10: Onda sinusoidal adquirida a frequencia maxima em funcao das amostras (esquerda) e do tempo(direita). Os cırculos azuis sao os pontos utilizados na deteccao de um perıodo do sinal

Na onda sinusoidal em funcao do tempo, foram utilizados os timers internos do microcontrolador para conse-guir o instante temporal de cada amostra. Selecionou-se um perıodo do sinal em funcao do tempo e calculou-sea media das diferencas dos intantes temporais nesse perıodo, obtendo-se uma frequencia maxima de aquisicaode 10469 Hz. Para a onda sinusoidal em funcao das amostras, selecionou-se novamente um perıodo do sinal, edeterminou-se quantas amostras estavam contidas nesse perıodo. Sabendo que a frequencia do sinal gerado e 10Hze o numero de amostras num perıodo, calculou-se a frequencia de aquisicao retornando o valor de 10470 Hz. Adiferenca de resultados entre os dois metodos, que nao e significatica, pode dever-se a quatro factores: alguma im-precisao na frequencia do sinal gerado (podia nao ser exactamente 10Hz); ao facto de na vizinhanca dos cırculos(pontos escolhidos para determinar o perıodo do sinal) existirem seis amostras consecutivas com o mesmo valor; ao facto da diferenca dos instantes temporais no primeiro metodo ter uma variancia de 0.75 micro segundos; aexistencia de ruıdo associado aos conversores.Pode-se entao garantir com seguranca que o conjunto de hardware possibilita aquisicoes de amostras a 10KHz e

geracoes de amostras a 20KHz tendo todos os conversores mais que 8 bits de resolucao. Na tabela [ 2.1] encontram-se as especificacoes alcancadas com o conjunto de hardware escolhido.No capıtulo seguinte apresenta-se uma solucao de software que permite usufruir de todas as potencialidades

deste hardware.

14 Hardware

dispositivo Modulo USB + microcontrolador DAC MCP4822DLP 2232PB-G

Gama do sinal 0 - 5.12 V 0 - 4.096 VResolucao dos conversores ADC 10 bits DAC 12 bits

Corrente maxima nos pinos I/O 25 mA 25mAFrequencia max de aquisicao/geracao 10 kHz 20 kHz

Fonte de alimentacao USB 2.7 - 5.5V (alimentado pelo modulo- 5.12V)Numero de canais analogicos 5 2Numero de canais digitais 11 -

Tabela 2.1: Especificacoes do ekit

Capıtulo 3

Software

O software desenvolvido para o projecto encontra-se dividido em firmware e PC-driver. Na figura [ 3.1] po-demos ver o esquematico da ligacao do PC ao dispositivo USB. No PC encontramos o PC-driver, o softwareresponsavel por controlar e gerir a comunicacao com os dispositivos conectados atraves de uma ligacao USB.O dispositivo USB , neste caso o PIC16F877A com adaptador USB, e controlado pelo firmware, software quecontrola directamente o hardware.

Figura 3.1: Ligacao do PC ao dispositivo USB

3.1 PC-driver

O PC-driver ou software do lado do PC foi desenvolvido em C++. Um objectivo importante do Ekit e adefinicao de uma solucao de interface generico que servisse tanto para o modulo DLP usado neste projecto, comopara futuros modulos com mais potencialidades, partindo da premissa que todos terao que conseguir gerar e ad-quirir amostras. Com microcontroladores mais avancados beneficiamos somente de melhores tempos de aquisicaoe maiores resolucoes, que obviamente vao depender das especificacoes de cada microcontrolador.

3.1.1 Funcionalidades pretendidas

Pretende-se com o desenvolvimento deste software criar um interface generico com funcoes simples de uti-lizar que permita uma comunicacao do PC com o hardware de geracao e aquisicao de sinais. A facilidade decomunicacao e a transmissao de dados no menor tempo possıvel sao aspectos cruciais desta implementacao. Derealcar igualmente a validade da comunicacao, ou seja, deve estar prevista a deteccao e correccao de eventuaisfalhas ou erros na comunicacao.

16 Software

3.1.2 Camadas de software

Para uma aplicacao comunicar com o dispositivo USB tem que passar por uma serie de camadas de software(figura [ 3.2]).

Figura 3.2: Camadas de software para comunicacao USB

A primeira camada e a chamada a funcoes API (Application Programming Interface) para gerar o pedido decomunicacao. Quando uma aplicacao chama uma determinada funcao de API, esta chama rotinas do driver Clientedo periferico USB instalado. Este driver traduz os comandos da API para comandos USB. O driver Cliente egeralmente parte do sistema operacional, ou e disponibilizado pelo fabricante. No nosso caso, a FTDI fornecetodas as drivers necessarias para os diversos sistemas operativos.

O driver Cliente encaminha o pedido as camadas de driver mais baixas, o driver USB (USBD), camada res-ponsavel por tornar o acesso ao controlador Host mais amigavel, definindo um grupo de rotinas a serem chamadaspelo driver Cliente.

A camada seguinte e o driver do controlador Host (HCD), que funciona a nıvel de Kernel do sistema operaci-onal. O HCD disponibiliza o nıvel de software entre o hardware do controlador Host e o USBD. E esta camadaque realiza os acessos de I/O necessarios para a operacao do dispositivo USB. O HCD interpreta as chamadas doUSBD e constroi uma lista de estruturas, um descritor de transferencias, uma fila principal e um buffer de dadospara o controlador Host.

Existem tambem duas camadas de hardware. A primeira e o Controlador Host (HC), que e o circuito onde seraofeitas as conexoes de todos os dispositivos USB. Este circuito executa electronicamente os comandos programadaspelo HCD, alem de registar o estado das transaccoes do USB. A camada final e constituıda pelo conjunto deDispositivos USB conectados, que sao os perifericos que usam esse tipo de barramento.

A FT2232D embutida no modulo DLP facilita a comunicacao via USB pois trata de todos os protocolos decomunicacao USB, sem ser necessario o desenvolvimento de algoritmos ou outros protocolos. Possui uma EE-PROM externa que permite o armazenamento de USB VID (Vendor ID), PID (Product ID), numero de serie edescritor.

3.1 PC-driver 17

3.1.3 Inicializacao, deteccao de modulos USB

A deteccao do modulo USB e crucial. Antes de uma aplicacao comunicar com o dispositivo, ela deve identificaro dispositivo e obter algumas informacoes do mesmo. Para tal e necessario realizar uma serie de chamadas dasfuncoes de APIs. Ha funcoes de APIs que fornecem informacoes sobre cada um dos dispositivos. Ha que examinaressas informacoes e escolher as caracterısticas que melhor identificam o modulo DLP.Inicialmente a aplicacao descobre quais os dispositivos fısicos que estao conectados ao sistema. Destes so

pesquisa mais informacoes se forem do tipo ”USB Serial Port”uma vez que optou-se por utilizar os drivers VCP(Virtual Port COM), que permitem ao sistema ver o modulo com se fosse uma porta serie.A procura seguinte e pelos numeros especıficos de identificacao do Fabricante e do Produto (VID e PID), uma

vez que os dispositivos FTDI (como o que existe no modulo) tem associado um PID e VID caracterısticos. Estesnumeros de identificacao sao enviados ao Host num descritor de dispositivo.Depois de encontrar e abrir conexao com o dispositivo, a aplicacao pode finalmente comunicar, enviando e

recebendo dados.As funcoes de API usadas para comunicar com o sistema operacional no Host, tem o codigo executavel lo-

calizado em bibliotecas dinamicas chamadas Dynamic Linked Library (DLL), que sao ficheiros fornecidos peloWindows. As funcoes API utilizadas nesta fase foram:

• SetupDiGetClassDevs - que retorna informacoes sobre todos dispositivos conectados da classe especificadaou de todos as classes presentes.

• SetupDiEnumDeviceInfo - que retorna informacoes para cada dispositivo da classe especificada.

• SetupDiGetDeviceRegistryProperty - que retorna propriedades do dispositivo especificado.

• SetupDiClassNameFromGuid - que retorna o nome da classe associado a estrutura GUID (estrutura queidentifica objectos tais como interfaces).

• SetupDiEnumDeviceInterfaces - que retorna informacoes para cada dispositivo com a interface especificada.

• SetupDiGetDeviceInterfaceDetail - que retorna o caminho do dispositivo especificado.

• SetupDiDestroyDeviceInfoList - que libera os recursos utilizados por SetupDiGetClassDevs.

Todas estas funcoes encontram-se implementadas na biblioteca DLL Setupapi.dll.Depois de se obter o caminho do dispositivo (retornado por SetupDiGetDeviceInterfaceDetail), pode-se abrir

uma conexao, para tal, usa-se a funcao de API “CreateFile” da qual se ira falar mais adiante. Ha que perceberagora que tipo de comunicacao faz o PC com o microcontrolador, e qual e o formato das mensagens que saoenviadas/recebidas do modulo.

3.1.4 Protocolo de comunicacao

Para o PC comunicar com o microcontrolador foi implementado um protocolo de comunicacao baseado numbuffer de dados de tamanho fixo. Este buffer e enviado via USB ao microcontrolador que posteriormente retornauma resposta da correcta ou ma recepcao do mesmo, tal permite verificar se os dados nao sofreram alteracoes e por-tanto nao estao corrompidos. O buffer transmitido tem dois bytes de controlo para garantir a correcta comunicacao.

18 Software

O primeiro byte corresponde ao numero de bytes que vao ser enviados ao microcontrolador e o ultimo byte e umachecksum ou soma de verificacao, que corresponde a um XOR (Ou exclusivo) bit a bit de todos os bytes enviadosnesse buffer. Com estes dois bytes de controlo consegue-se garantir a correcta comunicacao de dados entre o PCe o microcontrolador, bem como a deteccao de erros. Os dados transmitidos entre PC e microcontrolador, ou seja,os valores passados no buffer, sao do tipo hexadecimal, byte.

3.1.5 Interface generico

Numa fase em que ja se assegurou a comunicacao do PC com o microcontrolador pode-se agora identificare explicar o porque das funcoes escolhidas que compoem este interface. O interface generico e composto pelasseguintes funcoes:

//metodos de comunicacao

bool connect(const char* porta);

std::vector<string> listDevices(void);

string deviceHandler(const char* desc);

//escrita digital de um pin ou porto no PIC

bool digitalOutput(unsigned char v, unsigned char channel);

//leitura digital de um pin ou porto no PIC

int digitalInput(int channel);

//pede uma leitura ADC do canal

double ADC(int channel);

//coloca o valor "value" como saıda analogica no canal

int DAC(int channel,double value);

//receber pelos ADC’s um array de valores.

int inputADCArray(int channel, double* buffer,

int bufflen, double Ts, int flags);

int inputADCTimeArray(int channel, double* buffer,

double*bufferTempos, int bufflen, double Ts, int flags);

int input2ADCArray(int channel, double* buffer,

double* buffer2, int bufflen, double Ts, int flags);

//gerar sinal com os DAC em background com perıodo Ts

int outputDACArray(int channel, double* buffer,

int bufflen, double Ts, int nTimes, int flags);

//parar a geracao do sinal com STOP

int outputDACArrayStop();

3.1 PC-driver 19

Todo o codigo relativo a este interface encontra-se no anexo C, assim como um ficheiro teste que conteminumeros exemplos da aplicacao de cada uma das funcoes. Este ficheiro teste pode funcionar como um pequenotutorial com o objectivo de facilitar a utilizacao das mesmas. O ficheiro teste foi feito para compilacao em Matlab(ferramenta de programacao muito usada na engenharia e que e amplamente utilizada ao longo do curso de enge-nharia electrotecnica e computadores), pois permite um facil processamento dos dados sem grandes conhecimentosde programacao.As funcoes podem subdividir-se em tres grupos: funcoes de comunicacao, funcoes digitais, funcoes analogicas.

Funcoes de comunicacao - Como ja foi acima [ 2.1] referido, foi adoptada uma comunicacao serie com odispositivo. Foi utilizado um driver disponibilizado pelo fabricante que cria um porto COM virtual (VCP) no PC.Este porto pode ser acedido da mesma forma que os outros portos COM do PC. Para comunicar com a porta COMsao necessarias as funcoes API (Application Programming Interface) disponibilizadas pela biblioteca dinamicaDLL Kernel32.dll.A funcao connect conecta-se ao dispositivo utilizando algumas funcoes do API do Windows[1]:

• CreateFile - Utilizada para abrir a porta serie.

• CloseHandle - Utilizada para fechar a porta serie.

• GetCommState e SetCommState - Utilizadas para obter e alterar as configuracoes da porta serie(velocidade,numero de bits de dados, paridade, numero de stop de bits).

• GetCommTimeouts e GetCommTimeouts - Utilizadas para obter e alterar os parametros actuais de timeoutsassociados as funcoes ReadFile e WriteFile.

Contudo e necessario um caminho(chave), um descritor, de onde o dispositivo se encontra conectado [ 3.1.3].A atribuicao da COM e feita automaticamente pelo sistema operativo aquando da conexao de um novo dispo-sitivo contudo o Windows so tem como palavras reservadas as COM’s de 1 a 9. Quando a COM atribuıda esuperior a 9 tem que se ir buscar a HKEY_LOCAL_MACHINE, esta chave e onde se encontram armazenadas amaior parte das configuracoes do sistema: programas instalados, toda a configuracao de hardware, configuracoesde seguranca, etc. A funcao deviceHandler faz exactamente isso, enumera todos os dispositivos de hardware edevolve a HKEY_LOCAL_MACHINE associada ao dispositivo pretendido.Se se tiver mais que um dispositivo FTDI (adaptador USB do modulo) conectado ao PC, e possıvel diferencia-

los e criar uma ligacao para cada um. A funcao listDevices faz exactamente isso, procura todos os dispositivosconectados ao PC atraves de um adaptador USB FTDI.Para permitir uma utilizacao mais simples do modulo, para os utilizadores que nao se encontrem muito a

vontade com strings e descritores, a chamada a funcao connect(NULL) efectua a conexao automatica ao primeirodispositivo FTDI encontrado, poupando muito trabalho aos alunos mais inexperientes em programacao.Apos a ligacao ao modulo as restantes funcoes(digitais e analogicas) tem uma programacao de acordo com

os dados esperados no microcontrolador. Sem entrar em grande pormenor, basicamente o PC envia um bufferde bytes ao microcontrolador de acordo com a finalidade pretendida e com o protocolo de comunicacao adoptado.Este envio/recepcao de dados faz uso de mais duas funcoes da API, ReadFile eWriteFile, que recebem e enviam osdados (bytes) respectivamente. E importante referir que estas duas funcoes necessitam de um HANDLE, retornadopela funcao CreateFile(que efectua a conexao), para conhecerem o dispositivo com o qual estao a trocar dados.

20 Software

Funcoes digitais - As funcoes digitais sao as mais simples de manusear, sucintamente pode-se ler/escrever umporto(8 bits) ou um pino do microcontrolador. Quando se impoe um pino a ”1”o modulo coloca 5.12 V (tensao dealimentacao) nesse pino. Nao e possıvel gerar outros valores de tensao a menos que opte por exemplo por fazerum divisor de tensao com resistencias.

Funcoes analogicas - As funcoes analogicas sao as mais usadas nas experiencias. Os valores analogicos sao lidose gerados por conversores analogico-digitais e digitais-analogicos, respectivamente. A frequencia de aquisicao egeracao destes sinais encontra-se limitada pela capacidade do microcontrolador, tanto a nıvel de memoria como declock. Para a aquisicao foram implementas quatro funcoes:

• ADC - aquisicao de um valor analogico no pino correspondente

• inputADCArray - aquisicao de uma sequencia de leituras analogicas a determinada frequencia.

• inputADCTimeArray - aquisicao de duas sequencias, uma de leituras analogicas e outra com os respectivostempos dos timers internos do microcontrolador a determinada frequencia.

• input2ADCArray - para a aquisicao em ”simultaneo”de 2 pinos diferentes a determinada frequencia

Para a geracao foi implementada a funcao outputDACArray que permite gerar um sinal com 96 entradas(limitacao do microcontrolador na RAM). Estas 96 entradas, ou menos, sao as amostras de um perıodo do si-nal e sao definidas pelo proprio utilizador de forma a possibilitar a geracao da forma da onda pretendida. Quantomenor o numero de entradas escolhidas para o sinal, maior a frequencia a que se podera gerar um perıodo desinal. A paragem de geracao do sinal por parte dos DAC e feita recorrendo a funcao outputDACArrayStop pois eimportante conseguir cessar a geracao para fins experimentais e para libertar recursos da CPU do microcontroladorpara experiencias que exijam aquisicoes, por exemplo, a altas frequencias. Se a geracao do sinal nao requer altasfrequencias, ou apenas se esta interessado em gerar um unico valor, foi implementada uma solucao simples emboraobsoleta. A funcao DAC permite exactamente isso, realizar uma unica geracao analogica mediante a chamada afuncao. Embora pareca obsoleta a primeira vista, visto que se pode utilizar a funcao outputDACArray colocandouma unica entrada no array que se pretende gerar, na verdade a utilizacao desta funcao implica libertar recursos nomicrocontrolador, que caso contrario, estariam em uso.Explicada a comunicacao com o microcontrolador assim como o interface generico implementado e necessario

agora perceber o funcionamento do microcontrolador atraves do seu firmware.

3.2 Firmware

Tendo em conta as funcionalidades requeridas ao conjunto modulo DLP mais DAC e necessario dotar o micro-controlador de alguma ”inteligencia”para desempenhar todas as tarefas desejadas. A programacao do microcon-trolador e feita em C recorrendo ao compilador CCS. Para realizar o upload de firmware para o microcontrolador,a arquitectura do modulo DLP-2232PB-G possuı o porto A do microcontrolador conectado, exclusivamente, paraupload de novos programas atraves de uma aplicacao disponibilizada pelos fabricantes DLP Design. Esta aplicacaopermite reprogramar o microcontrolador em apenas quatro segundos e sem necessidade de hardware adicional.Esta e uma caracterıstica igualmente motivadora para os alunos desenvolverem os seus proprios programas cri-ando novas funcionalidades e aplicacoes para este tipo de dispositivos.

3.2 Firmware 21

3.2.1 Firmware original

O modulo DLP vem, de fabrica, com um firmware instalado, o Token I/O firmware que permitia utilizar asfuncoes basicas do microcontrolador, como por exemplo, leitura e escrita digital ou conversao analogico-digital.Contudo esta solucao nao permitia aquisicoes a altas frequencias nem geracao de sinais analogicos. Uma vez quea taxa de transmissao de dados via USB para um PC e somente ate 2 megabits por segundo, se a isto aliarmos otempo de processamento e de conversao dos ADC do microcontrolador, ficava-se limitado a uma frequencia deaquisicao baixa. Contudo estas nao sao as grandes limitacoes temporais desta implementacao. Relembrando comofunciona o interface USB [ 2.1] verifica-se que a comunicacao de dados entre o PC e os perifericos esta limitadapela calendarizacao do Host USB que necessita de dois frames para uma comunicacao de envio e recepcao dedados (envio e recepcao devido ao protocolo [ 3.1.4] pois e necessario conhecer a validade dos dados transmiti-dos). Tal significa que apenas seria possıvel fazer chegar pedidos ao microcontrolador em intervalos de tempo dedois milissegundos. Foi entao necessario proceder-se a implementacao de um novo firmware tendo por base o jaexistente.

3.2.2 Firmware implementado

As opcoes tomadas na implementacao do firmware tiveram em conta o protocolo de comunicacao utilizadoassim como as limitacoes de hardware (comunicacao USB a Full Speed, e especificacoes do microcontrolador).Partindo do codigo do firmware ja existente e aproveitando todas as suas funcionalidades foi somente ne-

cessario criar funcoes que colmatassem as limitacoes acima referidas.

Exactidao de instancia temporal - Emmuitas experiencias e importante conhecer os tempos exactos de aquisicaode cada amostra. Se nos basearmos num timer do tempo de chegada da amostra ao PC, pode existir uma grandediscrepancia entre o tempo real de aquisicao e o tempo de recepcao da amostra no PC. O USB possuı o seu propriodiagrama temporal, o que provoca alguns erros significativos de discretizacao temporal. Visto que o microcontro-lador possuı tres timers, foi implementada a solucao, de alem de retornar o valor da aquisicao, retornar igualmenteo valor temporal associado ao timer utilizado.

Conversao AD temporizada - Para fazer face ao problema de limitacao da frequencia de aquisicao, a solucaofoi programar o microcontrolador para mediante uma instrucao pre-definida, realizar um determinado numero deaquisicoes e envia-las para o adaptador USB (FT2232D). Assim que fosse possıvel mais uma comunicacao dedados entre o PC e o modulo, as aquisicoes guardadas no FIFO do adaptador eram entao enviadas ao PC.O microcontrolador so possuı 368 bytes de RAM, logo a solucao de armazenar as amostras adquiridas no

microcontrolador e envia-las posterior e lentamente para o PC teve que ser igualmente posta de parte. Os novosDsPIC nao padecem deste problema pois possuem 16 Kbytes de RAM que permitem uma solucao mais rapida quea implementada, visto que se poupava o tempo de envio da amostra adquirida para o adaptador USB, permanecendoos dados na memoria RAM.A aquisicao sequencial de valores analogicos de tensao encontra-se implementada com time delays garantindo

que o espacamento temporal entre cada amostra se mantem constante. Devido a diminuta RAM presente nestemicrocontrolador e impossıvel alocar memoria para cada amostra adquirida, tendo pois esta que ser enviada ime-diatamente de volta ao PC. O espacamento temporal constante e baseado na ideia que o microcontrolador demorasempre o mesmo tempo a executar cada conjunto de instrucoes dentro de um ciclo. Foram adquiridas amostras a

22 Software

diferentes frequencias e calculou-se a diferenca entre os instantes de tempo(tempos retornados pelos timers inter-nos do microcontrolador). A figura [ 3.3] mostra a discrepancia dos intervalos de tempo a frequencia maxima deaquisicao (10kHz).

0 50 100 150 200 250 300 350 40094

94.5

95

95.5

96

96.5

97

97.5

98Diferença de instantes de aquisição á frequencia maxima

Numero de amostras

Tem

po [u

seg]

Figura 3.3: Discrepancia de tempos na aquisicao de amostras

Verificou-se que o desvio padrao da diferenca de tempos se mantinha constante indepententemente da frequencia(0.7 a 0.8 micro segundos). Conclui-se que era devido ao tempo que o microcontrolador necessitava para realizarum conjunto de intrucoes. Como o atraso mınimo que se consegue provocar atraves de time delays e de 1 microsegundo, este tipo de falta de precisao so poderia ser corrigida com a utilizacao de ISR (rotinas de servico deinterrupcao). De seguida justificar-se-a o porque da nao utilizacao das mesmas.

Conversao DA temporizada - A comunicacao SPI tambem nao se encontrava implementada no firmware defabrica, foi necessario proceder-se a sua implementacao para possibilitar a comunicacao com o DAC 4822.A geracao sequencial de valores analogicos pelo DAC encontra-se implementada recorrendo a ISR (rotinas de

servico de interrupcao). Estas sao executadas a cada disparo do timer2 garantindo igualmente o equiespacamentoentre geracoes. E de salientar, que a prioridade atribuıda as ISR aliada a baixa capacidade do CPU, podem com-prometer o equiespacamento das amostras adquiridas. A aquisicao sequencial porem nao foi implementada comrecurso as ISR tendo em conta que os PIC’s da famılia 16F nao permitem a priorizacao das interrupcoes, o queresultaria num crash do programa caso estas colidissem.A geracao de sinais sinusoidais e feita recorrendo a um array pre alocado na RAM do microcontrolador e

limitado a 96 entradas. Por outras palavras para gerar, por exemplo, um seno, preenche-se (recorrendo ao softwaredo PC) o array pre alocado com o numero de entradas desejado para o mesmo. Quando se solicita a geracao doseno aos terminais do DAC, o firmware vai percorrer o array preenchido e gerar cada entrada em intervalos detempo equiespacados.

Todo o codigo pode ser encontrado no anexo D mas para se ter uma melhor nocao do firmware desenvolvido afigura [ 3.6] descreve de uma forma simplicista o funcionamento e principais funcionalidades do microcontrolador.Com este firmware esta garantido que o Ekit adquire e gera sinais encontrando-se apenas limitado pela velocidadee capacidade de memoria do microcontrolador.

3.3 Testes do software 23

3.3 Testes do software

Apos a implementacao do PC-driver e firmware importa testar o seu funcionamento em diferentes ambientes.Na figura [ 3.4] podemos comprovar o correcto funcionamento da geracao e aquisicao em simultaneo de uma ondatriangular e de uma onda sinusoidal em ambiente Matlab. Os sinais sao gerados pelo DAC do Ekit e sao adquiridasvarias amostras nos ADC que posteriormente sao enviadas via USB para o PC, e colocadas em matrizes. OMatlab permite facilidade na manipulacao destas matrizes e criacao de graficos sendo uma ferramenta ideal para oprocessamento dos dados provenientes do Ekit.

Figura 3.4: Onda triangular (esquerda) e onda sinusoidal (direita).

A mesma aplicacao usada para a criacao dos graficos foi executada no Microsoft Visual Studio 2005. Comoneste ambiente torna-se ligeiramente mais moroso a criacao de graficos, e como o bom funcionamento do softwareja se encontra testado, foi apenas testado o funcionamento atraves da visualizacao da resposta tıpica da aplicacaoaquando da comunicacao com o Ekit. Na figura [ 3.5] podemos visualizar as strings devolvidas na execucao daaplicacao. As strings retornadas mostram a deteccao do dispositivo conectado ao USB, a correcta conexao aomesmo, e o correcto funcionamento da aplicacao, finalizando esta sem qualquer erro.

Figura 3.5: Funcionamento do software em ambiente MS Visual Studio 2005.

No capıtulo seguinte, aplicacoes didacticas, prova-se entao que recorrendo apenas a um conjunto mınimo dehardware conseguem efectivamente realizar-se experiencias basilares de Analise de Circuitos.

24 Software

Figura 3.6: Fluxograma do firmware

Capıtulo 4

Aplicacoes Didaticas

Este capıtulo desenvolve o objectivo principal do Ekit, nomeadamente ser uma ferramenta didatica que forneceum apoio material a aprendizagem de sinais, circuitos e sistemas electronicos. Propoem-se neste sentido quatroexperiencias a serem detalhadas nas proximas seccoes: (i) medicao de resistencias, usando um simples divisor detensao, (ii) medicao de condensadores com base na funcao de resposta no tempo ao escalao, (iii) medicao do ganhoestatico e constante de tempo de um motor DC, usando tecnicas similares as da medicao do condensador e (iv)calculo do diagrama de Bode baseado na resposta de um sistema a uma onda sinusoidal a diferentes frequencias.Encontram-se no anexo E guias condutores das experiencias (i), (ii) e (iv), criados com o intuito de guiar os

alunos na realizacao destas experiencias. A nao existencia de um guia experimental para (iii) deve-se ao facto de omotor DC utilizado na realizacao da experiencia apenas se encontrar disponıvel nos laboratorios da faculdade. Anecessidade de utilizacao de material de laboratorio contrariaria a premissa de possibilitar aos alunos a utilizacaode material acessıvel.Nas experiencias e usado maioritariamente o microcontrolador com adaptador USBDLP-2232PB-G produzido

pela DLP [3] e o DACMCP4822[8].

4.1 Medicao de resistencias

Considerando um divisor de tensao de uma fonte de alimentacao, Vs atraves de uma resistencia calibrada,Ri e uma resistencia de carga a ser medida, R, a expressao da tensao na carga pode ser expressa como Vr =

VsR/(R + Ri). Conhecendo a priori o valor exacto de Vs e Ri e medindo Vr, e possıvel estimar R simplesmentecomo:

R = RiVr/(Vs − Vr)

Usando os conversores A/D do modulo DLP e simples obter os valores necessarios a experiencia. Na figura 4.1podemos ver o circuito divisor de tensao conectado ao modulo.Foram realizadas experiencias medindo resistencias de 1K, 10K e 100K, usando uma resistencia calibrada de

1K. As experiencias foram repetidas 100 vezes para cada resistencia resultando num desvio padrao de 0.37%,1.09% e 7.95%, respectivamente.

26 Aplicacoes Didaticas

Figura 4.1: Diagrama das conexoes para a medicao de resistencias (direita) e imagem do setup real (esquerda).

Por outras palavras, os resultados mostram que o ruıdo de medicao dos conversores A/D do modulo e suficien-temente pequeno para permitir medir, usando uma resistencia calibrada de 1K, outras resistencias com uma ordemde grandeza superior, com aproximadamente 1% de precisao.

4.2 Medicao de condensadores

Um circuito RC em serie e a forma tıpica de medir um condensador. Pode-se, por exemplo, alimentar o circuitoRC com uma fonte de tensao constante, vs e medir a tensao aos terminais do condensador, vc(t). A tensao vc(t)

permite calcular a constante de tempo, τ , do circuito e no caso de se conhecer o valor real de R consegue-se obterdirectamente o valor do condensador, C.Novamente usando somente os conversores A/D do modulo DLP e facil obter as medidas necessarias. Na

Figura 4.2 podemos ver o modulo DLP conectado ao circuito RC, actuando um pino de saıda para a fonte dealimentacao e um pino conversor A/D, ou seja, gerando vs e lendo vc(t).

Figura 4.2: Setup do circuito RC serie para medicao do condensador C.

Existem diversas formas de calcular o valor do condensador, C atraves da resposta temporal, vc(t) de umcircuito RC alimentado por uma fonte constante. Ira ser detalhado tres formas diferentes para proceder a estimacaode C:(i) atraves de incrementos locais da tensao do condensador e pelo integral da corrente, (ii) como o caso anterior,

mas com perıodos de tempo superiores, (iii) directamente da resposta temporal.Para se poder aplicar os primeiros dois metodos, e necessario estimar a corrente atraves do condensador, ic(t),

que e calculada directamente com a informacao de vs e R como:

4.2 Medicao de condensadores 27

ic(t) =vs − vc (t)

R(4.1)

A corrente atraves do condensador e por definicao a taxa a que a carga e armazenada, ic(t) = C · dvc(t)/dt.Logo a carga sobre o condensador e igual ao integral da corrente em funcao do tempo, obtendo assim: C =∫ t1

t0ic(t)dt/(vc(t1)− vc(t0)) sendo assim possıvel chegar a uma formula local convertendo o tempo de contınuo

para discreto:

C(k) ∼=Ts

2

ic((k + 1)Ts) + ic(kTs)

vc((k + 1)Ts)− vc(kTs)(4.2)

onde Ts e o perıodo de amostragem e k o numero da amostra.No metodo (ii) considera-se um intervalo de tempo superior, portanto, tem que se ter em conta todos os incre-

mentos locais na corrente:

C(k) ∼=Ts

2

k−1∑n=0

ic((k + 1)Ts) + ic(kTs)

vc(kTs)− vc(0). (4.3)

O Metodo (iii) parte do conhecimento da funcao da resposta temporal, isto e, a funcao que descreve a carga docondensador: vc(t) = vs(1− e−t/τ ) que pode ser resolvida explicitamente em ordem a τ , e depois em ordem a C

uma vez que τ = R · C:C(t) =

−t

R · log (1− vc(t)/vs)(4.4)

onde t = kTs.

−0.2 0 0.2 0.4 0.6 0.8 1 1.2

0

1

2

3

4

5

6

Vc

[V]

0 0.5 1−1

0

1

2

3x 10−6

C [F

]

0 0.5 1−1

0

1

2

3x 10−6

0 0.5 1−1

0

1

2

3x 10−6

Figura 4.3: Resposta temporal do circuito RC e estimativas do condensador usando os metodos (i), (ii) e (iii) (vertexto).

A figura 4.3 mostra a resposta temporal do circuito RC a uma tensao de entrada vs = 5.12[V ], e as estimativasde cada um dos tres metodos , para um condensador de valor nominal C = 1μF .E interessante notar que apesar das ruidosas estimativas locais da corrente que percorre o condensador, que tem

um efeito directo nas estimativas de C usando o metodo (i), e possıvel obter bons resultados utilizando o metodo

28 Aplicacoes Didaticas

(ii) desde que o tempo de integracao seja suficientemente grande. O resultado do metodo (ii) e suave ao longo dotempo, devido a forma de integracao, e e interessante mesmo quando comparado com o metodo (iii), onde C deixade ser possıvel de estimar assim que vc(t) se aproxima demasiado de vs. Esta suavidade caracterıstica do metodo(ii) pode ser util se, por exemplo, quisermos implementar um detector de vc(t) ∼= vs.

4.3 Parametros do motor DC

A experiencia do motor DC consiste na estimacao dos parametros do motor em resposta ao escalao. Nestaseccao estamos interessados em encontrar os parametros de um setup de um motor DC didactico, construıdo pelaQuanser, para cadeiras de controlo. Na figura 4.4 podemos ver o driver de potencia e o motor.

Figura 4.4: Driver de potencia (esquerdo), o motor e sensores (direito).

Os metodos para a estimacao dos parametros sao muito parecidos com os usados para o circuito RC, uma vezque tem essencialmente o mesmo modelo. Um motor DC com tensao de entrada, vs e com velocidade angular,ω, de saıda, pode ser aproximadamente descrito por uma funcao de transferencia de primeira ordem G(s) =

k0/(1 + τs), onde τ e a constante de tempo e k0 e o ganho estatico (note-se que no circuito RC k0 = 1).A resposta do sistema com o escalao como entrada e descrita por:

ω(t) = vsk0

(1− e−t/τ

)(4.5)

onde ω(t) e a velocidade do motor medida em tensao pelo taquımetro. Esta resposta, Eq.4.5 pode ser usado comomodelo para estimar os parametros do motor k0 e τ .Apos adquirir a velocidade do motor (Fig. 4.5), o ganho estatico e a constante de tempo podem ser estimados

por dois metodos, invertendo a resposta ao escalao ou usando um algoritmo de aproximacao a curva (curve fitting).

Inversao da resposta ao escalao - Primeiramente e necessario estimar o ganho estatico. Dado que a respostaao escalao e uma funcao monotonica, e possıvel estimar o ganho estatico a partir do valor maximo dessa mesmaresposta. Para fazer face ao ruıdo, na pratica, estimou-se o ganho estatico como a mediana de todos os valores numintervalo de cinco por cento da tensao maxima lida do taquımetro:

k0 = median{ω(t) : ω(t) ≥ 0.95max(ω(t))} (4.6)

A constante de tempo foi entao calculada a partir da Eq.4.5:

τ(t) =−t

log (1− ω(t)/(vsk0))(4.7)

4.3 Parametros do motor DC 29

Com o objectivo de testar o procedimento acima, foram adquiridas varias respostas do motor DC usando omodulo DLP para gerar sinais de referencia (para o driver de potencia do motor) e adquirir a velocidade atraves datensao lida do taquımetro.Para demonstrar as potencialidades deste modulo como dispositivo de aquisicao de dados, esta experiencia foi

igualmente realizada com a placa de aquisicao da National Instruments NI PCI-6221.Utilizando ambos os dispositivos , a experiencia foi realizada 200 vezes para a mesma tensao de entrada

constante e com uma frequencia de amostragem de aproximadamente 500Hz. Veja-se Fig.4.5(a,b).

0 0.05 0.1 0.15 0.20

1

2

3

4

5PIC acquisition

time [sec]

w [v]

0 0.05 0.1 0.15 0.20

1

2

3

4

5NI−daq acquisition

time [sec]

w [v]

(a) (b)

0 0.05 0.1 0.15 0.20

20

40

60

80

Tau

vs t

ime

[mse

c]

0 0.05 0.1 0.15 0.20

20

40

60

80

(c) (d)

3.9 4 4.1 4.2

24

26

28

30

32

Tau

[mse

c] v

s k 0

3.9 4 4.1 4.2

24

26

28

30

32

(e) (f)

Figura 4.5: 200 respostas ao escalao no motor DC (a,b). DLP (coluna esquerda) e placa da NI (coluna direita).Constante de tempo, τ [msec] estimado a partir da Eq.4.7 (c,d). Constante de tempo vs Ganho estaticoK0 (e,f). Ocirculo vermelho representa a mediana de τ e k0 das 200 experiencias.

A constante de tempo foi calculada atraves de todas as amostras temporais de cada experiencia.A figura 4.5(c,d) mostra que o ruıdo das medicoes apenas conduziu a bons resultados nas amostras centrais. De

realcar que a incerteza cresce quando t →∞, pois o motor atingiu o regime estacionario. No caso do modulo DLP,a incerteza e igualmente grande no inıcio devido a inexactidao do relogio do PC por causa do sistema operativo.

30 Aplicacoes Didaticas

Assim, a fim de estimar um unico valor de τ para cada experiencia, seleccionou-se τ := τ(t), sendo t a amostrade tempo onde o desvio padrao de τ(t) e o mınimo considerando as 200 experiencias.A figura 4.5(e,f) mostra as estimativas de (k0, τ) para as 200 experiencias. A incerteza das estimativas deve-se

a alguma incerteza mecanica (a carga do motor DC implica maior friccao nalguns angulos) e ao ruıdo na medicao.Como previsto, o modulo DLP origina maior incerteza devido a menor precisao dos seus conversores analogico-

digitais (10 bits em oposicao aos 12 bits da placa de aquisicao NI).No entanto, deve salientar-se que a diferenca entre os dois dispositivos e inferior a 2% em ambos os parametros,

k0 e τ .

Optimizacao da curva de aproximacao (optimal curve fitting) - O objectivo desta optimizacao e encontrarsimultaneamente a constante de tempo e o ganho estatico para que o modelo teorico (Eq.4.5) se adeque o melhorpossıvel as medicoes. A funcao de custo usada neste algoritmo de optimizacao e simplesmente o metodo dosmınimos quadrados:

(k0, τ)∗

= argk0,τ minN∑

i=1

(ω(ti)− vsk0(1− e−ti/τ )

)2

(4.8)

A optimizacao nao linear e feita a partir da funcao de Matlab fminsearch que encontra o mınimo de umafuncao escalar com diversas variaveis, partindo duma estimativa inicial.A figura 4.6 e a tabela 4.1 mostram as estimativas de τ e k0 utilizando ambos dispositivos de aquisicao. As

estimativas contem mais ruıdo do que as da seccao anterior devido a inexistencia de um mecanismo de seleccaode dados para remover as amostras temporalmente imprecisas (temporizacao feita pelo PC) ou devido ao processode conversao de analogico para digital (a relembrar que o τ na seccao anterior e estimado a partir das amostrascentrais, medicoes mais precisas).A discrepancia obtida de 1ms na estimativa de τ utilizando ambos os dispositivos e justificada sobretudo por

uma imprecisao temporal no PC. De realcar que o USB, possuı o seu proprio diagrama temporal que provocaalguns erros de discretizacao temporal significativos.A tabela 4.1 mostra que globalmente a placa NI PCI-6221 permite obter variancias ligeiramente menores nas

estimativas. No entanto, uma observacao importante e que a medicao dos parametros do motor DC usando omodulo DLP e suficientemente fiavel para a maioria das aplicacoes e uma solucao muito mais economica.

device modulo DLP NI PCI-6221k0 mean 4.033 4.010k0 std 0.0311 0.0241

τ mean [msec] 28.87 27.66τ std 0.6049 0.4301

Tabela 4.1: Comparacao das estimativas do k0 e τ utilizando ambos os dispositivos.

4.4 Diagramas de Bode

O diagrama de Bode disponibiliza informacao acerca da relacao entre entrada e saıda de qualquer sistema, emque a entrada seja uma onda sinusoidal e a saıda possa ser mesuravel.

4.4 Diagramas de Bode 31

3.9 4 4.1 4.2

24

26

28

30

32

Tau

[mse

c] v

s k 0

3.9 4 4.1 4.2

24

26

28

30

32

(a) (b)

Figura 4.6: Estimativas da Constante de tempo τ vs Ganho estaticoK0 usando o procedimento de optimizacao daEq.4.8 com base nos dados do modulo DLP (a) ou na placa da NI (b). O circulo vermelho representa a mediana deτ e k0 das 200 experiencias.

Visando construir uma experiencia didactica para a aquisicao do diagrama de Bode, considerou-se novamenteo circuito RC em serie da seccao 4.2. Utilizou-se o modulo DLP e o DAC para gerar uma onda sinusoidalcomo entrada do circuito RC e adquiriram-se simultaneamente a entrada e saıda do sistema. Na figura 4.7 podevisualizar-se a conexao de ambos os dispositivos ao circuito RC, sendo a onda sinusoidal gerada nos pinos do DACe as duas tensoes de entrada e saıda adquiridas pelos ADC’s do modulo DLP.

Figura 4.7: Setup para obtencao do diagrama de Bode de um circuito RC.

Embora exista um modelo para este sistema, o objectivo aqui e variar a frequencia do sinal de entrada e calculara diferenca de amplitudes maximas e o atraso correspondente entre a entrada e a saıda apos o sistema ter atingido oregime estacionario. Considerando a entrada do sistema Vs(t) = A sin(ωt) + A, com ω a frequencia em rad/sec,A a amplitude da onda sinusoidal e Vc(t) a tensao aos terminais do condensador em regime estacionario, entao a

32 Aplicacoes Didaticas

resposta em frequencia do sistema H(jω), pode ser estimada em amplitude na escala logarıtmica ou dB por:

|H(jω)|dB = 20 log10

(max(Vc(t))−min(Vc(t))

max(Vs(t))−min(Vs(t))

)

sendo a fase representada em escala linear por:

� H(jω) = (ts − tc)× ω ×180o

onde ts e tc sao medicoes de tempo que correspondem aos maximos, da entrada Vs(t) e da saıda Vc(t), respec-tivamente.

0 500 1000 1500 2000 2500 3000 3500 40000

0.5

1

1.5

2

2.5

3

3.5

4

4.5Entrada e saída de um circuito RC

Amostras

Tens

ão [V

]

0 500 1000 1500 2000 2500 3000 3500 40000

0.5

1

1.5

2

2.5

3

3.5

4

4.5Entrada e saída de um circuito RC

Amostras

Tens

ão [V

]

Figura 4.8: Entrada e saıda de um circuito RC em resposta a uma onda sinusoidal a varias frequencias.

A figura 4.8 mostra as tensoes de entrada(azul)e de saıda(vermelho) do circuito RC a uma frequencia de 10 e100 Hz.Foram adquiridas varias amostras a diferentes frequencias e obteve-se o diagrama de Bode (figura 4.9). A am-

plitude do diagrama de Bode mostra duas funcoes, a azul encontram-se as amostras recolhidas experimentalmentee a verde a aproximacao (curve fitting) dessas amostras ao modelo caracterıstico de um sistema de primeira ordemcom ganho estatico unitario:

H(jω) =ωc

jω + ωc

A funcao de custo usada no algoritmo de optimizacao foi:

ω∗c = argωcmin

∑i

(|H(jωi)| −

∣∣∣∣ ωc

jωi + ωc

∣∣∣∣)2

. (4.9)

A experiencia foi realizada com um condensador C = 1μF e uma resistencia, R, de 100kΩ sendo identificadaa frequencia de corte(valor encontrado na descida de -3dB), wc, aproximadamente em 10 rad/sec. Utilizandoo algoritmo de aproximacao (curve fitting) com funcao de custo definida na equacao 4.9, atraves da funcao deMatlab fminsearch obteve-se uma frequencia de corte de 10.44 rad/sec.Considerando que a frequencia de corte ωc, e a constante de tempo τ do circuito RC tem uma relacao inversa:

ωc =1

τ=

1

RC

4.4 Diagramas de Bode 33

10−1 100 101 102 103−30

−25

−20

−15

−10

−5

0Bode Diagram

Frequency (rad/seg)

Mag

nitu

de (d

B)

10−1 100 101 102 103

−120

−100

−80

−60

−40

−20

0

20

Frequency (rad/seg)

Pha

se A

ngle

(º)

Figura 4.9: Diagrama de Bode: Angulo de fase(baixo), Amplitude das amostras experimentais(azul) e aproximacaoda mesma curva ao modelo(verde) (cima)

34 Aplicacoes Didaticas

pode observar-se que a frequencia de corte estimada tem um erro inferior a 5% em relacao a frequencia de cortenominal, ωc,nom = 1/τnom = 1/(1μ × 100k) = 10rad/sec ,ou seja, o inverso da constante de tempo nominalτnom, calculada a partir dos valores nominais dos componentes. Note-se que sendo C = 1

ωcR , e possıvel obteruma estimativa de C muito proxima da conseguida na seccao 4.2.Prova-se assim, que o Ekit permite efectivamente conduzir experiencias didacticas com sistemas dinamicos,

em particular apresentando conceitos e estimando valores de frequencias de corte e constantes de tempo. Asestimativas precisas permitem acima de tudo explorar a relacao tempo-frequencia tao importante em cursos deEngenharia Electrotecnica.

Capıtulo 5

Conclusoes e Trabalho Futuro

Com o processo de auto-aprendizagem imposto por Bolonha, tornou-se imperativo fornecer aos alunos deprimeiro ano de Analise de Circuitos, uma ferramenta autonoma, de simples utilizacao e baixo custo, um meio decompreender o lado pratico da cadeira, atraves da experiencia.Com o projecto Ekit experiencias que anteriormente apenas eram possıveis recorrendo a materiais de labo-

ratorio complexos e indiscutivelmente dispendiosos, podem agora, ser postas em pratica pelos alunos recorrendoapenas ao seu computador pessoal, aliado a um pequeno conjunto de dispositivos de hardware, de simples manuse-amento, compostos por um modulo DLP2232PB-G (microcontrolador com adaptador USB), um DAC MCP4822e que tem por base um interface generico de facil utilizacao.No entanto a importancia deste interface generico nao se esgota na sua descomplexidade de utilizacao, o seu

grande merito reside na generalidade, isto e, a potencialidade que lhe permite ser utilizado com qualquer outromicrocontrolador, requisitando, para tal, apenas que seja feita uma actualizacao de software.Em suma, o potencial destes microcontroladores aliados ao seu baixo custo, fazem do Ekit uma ferramenta

indispensavel aos alunos da cadeira de primeiro ano de analise de circuitos.Tendo em conta a constante exigencia da evolucao (melhoramento e inovacao) que nos coloca a tecnologia, e

imperativo que o projecto Ekit possua uma vertente flexıvel e dinamica tendo em vista, uma importante premissa:nao deixar perder o trabalho ate entao realizado. Exploradas as potencialidades para que foi concebido, comosuprimir a ausencia de ferramentas para abordagem pratica da materia das cadeiras de Analise de Circuitos deprimeiro ano, e chegado o momento de perspectivar o futuro.Assim tendo por base o Ekit, surge a possibilidade de realizar outras experiencias, como por exemplo, identificacao

de filtros, sistemas de controlo (servomecanismos), que possibilitam a extensao deste projecto a outras cadeiras naarea da engenharia.O projecto Ekit e uma excelente e sobretudo barata solucao para a geracao, aquisicao e processamento de

dados e sinais. Que para alem de proporcionar um processo de rapida auto-aprendizagem tambem incentiva futurasaplicacoes bem como estudo avancado de processamento sinal e controlo de sistemas.Nao e demais sublinhar que o interface generico deste projecto, oferece a possibilidade de utilizacao com

outros microcontroladores, mais recentes e com maiores potencialidades, sendo esta uma possibilidade que ja seencontra a ser posta em pratica, com o microcontrolador dsPIC33FJ128GP802 em conjunto com o modulo USBUM245R.O Ekit e um projecto votado ao sucesso, a sua inovacao e uma mais valia, nao apenas para o seu publico alvo

36 Conclusoes e Trabalho Futuro

(alunos de primeiro ano de Analise de Circuitos) mas para como para toda a comunidade de engenharia na area deelectrotecnica e computadores.

Bibliografia

[1] Robertson Bayer. Windows serial port programming. http://www.robbayer.com/files/

/serial-win.pdf, 2008.

[2] M. J. Gomes. E-learning: reflexoes em torno do conceito. http://repositorium.sdum.uminho.pt/handle/1822/2896, 2005.

[3] Future Technology Devices International. Dlp design - dlp-2232pb-g. http://www.ftdichip.com/Products/EvaluationKits/DIPModules.htm#DLP-2232PB-G, 2007.

[4] Solbet Ltda. Tutoriais sobre programacao de microcontroladores. http://www.solbet.com.br, 2007.

[5] G. Moore and G. Kearsley. Distance education: A systems view. Wadsworth Publishing Company, 1996.

[6] Craig Peacock. Usb in a nutshell, beyond logic. http://www.beyondlogic.org/usbnutshell/,2006.

[7] P. Ruffio. Changing the university: The supporting role of the erasmus thematic networks (a three-year pers-pective). Technical report, European Union: Eucen, Brussels, Belgium, Jan. 2000.

[8] Microchip Technology’s. Mcp4821/mcp4822. http://www.microchip.com/wwwproducts/

Devices.aspx?dDocName=en024016, 2007.

[9] Unesco. World declaration on higher education for the twenty-first century: Vision and action. http:

//www.unesco.org/education/educprog/wche/declaration_eng.htm, 1998.

38 BIBLIOGRAFIA

Apendice A

Especificacoes do PIC16F877A

AArquitectura do microcontrolador PIC16F877A - Podemos pensar num microcontrolador como um dispo-sitivo composto por sete partes, clock, interrupts, CPU, portas I/O, memoria de dados, memoria de programa. Osdados dentro de um microcontrolador sao manipulados em unidades chamadas palavras. O PIC16F877A possuipalavras de dados de oito bits de tamanho, e palavras de instrucao de 14 bits. Este comprimento da palavra deinstrucao do PIC16F877A permite que a maioria das instrucoes possa ser executada dentro de um unico ciclo demaquina, um dos motivos da grande velocidade que se consegue nestes microcontroladores.O clock e o responsavel pelo sincronismo entre todas as operacoes de um microcontrolador. Todos os eventos

que ocorrem dentro de um microcontrolador obedecem a uma logica preestabelecida pelo fabricante, e sao pro-cessados em tempos determinados pela frequencia do clock. Normalmente, quanto maior a frequencia de clock deum microcontrolador, mais rapida e a execucao das instrucoes. No caso dos microcontroladores, o clock e tambemutilizado como referencia de tempo para execucao de tarefas que devem ser repetidas a determinado intervalo detempo, como por exemplo a leitura de sinais em interfaces RS232C.A CPU, ou unidade central de processamento, coordena todas as actividades dentro do microcontrolador. Ela

organiza a execucao das instrucoes. E a CPU que realiza as operacoes logicas ou matematicas sobre os dados, eenvia os resultados para os diversos registos ou portas de entrada e saıda.As portas de entrada e saıda sao os pontos atraves dos quais o microcontrolador interage com o meio ambiente.

As portas digitais assumem valores discretos, normalmente referenciados como 0 ou 1, correspondentes a 0 voltsou 5 volts de saıda respectivamente. O valor de tensao correspondente ao nıvel logico 1 normalmente correspondea tensao de alimentacao do microcontrolador.Alem das portas convencionais, que a CPU deve ler sempre que deseja saber sobre o seu estado (0 ou 1),

alguns microcontroladores possuem uma ou mais portas de entrada especiais chamadas de Interrupts. Estas portasnao exigem que a CPU monitorize a ocorrencia de um evento, porque interrompem o programa e sao executadossempre que ocorre um dado evento. Desta forma a CPU pode atender ao evento externo assim que o mesmoocorre, e nao despende tempo a monitorizar inutilmente a ocorrencia do evento na porta. Interrupts sao uma dascaracterısticas mais utilizadas nos projectos em se necessite de uma rapidez de resposta a eventos assıncronos, quepodem ocorrer a qualquer instante.O PIC16F877A possui portas de entradas analogicas, ou seja, portas que podem receber sinais variaveis entre

0 e 5 volts. Internamente estes sinais analogicos sao convertidos em valores digitais entre 0 e 0x3FF (se utilizamosconversores de dez bits), ou 0xFF (se utilizarmos conversores de oito bits).

40 Especificacoes do PIC16F877A

A memoria de dados e normalmente implementada sob forma de RAM (memoria de acesso aleatorio) em quepodemos ler e gravar com facilidade. A leitura e nao destrutiva, ou seja, podemos ler ınumeras vezes o valor deuma posicao de memoria que o valor nao se altera. A gravacao de um dado na RAM e feita pela CPU, respondendoa instrucoes colocadas pelo programador. Os microcontroladores normalmente utilizam pequenas quantidades dememoria de dados, principalmente se comparados com as memorias RAM utilizadas pelos computadores pessoaisactualmente.

A memoria de programa e onde se encontram as instrucoes a ser executadas pela CPU. Num computadorpessoal os programas localizam-se tipicamente em CDs ou discos rıgidos. Nos microcontroladores por sua vez, oprograma deve residir numa memoria somente de leitura. O programa e normalmente gravado uma unica vez e apartir daı o microcontrolador executa apenas esse programa.

A maioria dos microcontroladores utiliza memoria EPROM, que para ser apagada necessita ser exposta a luzultravioleta, ou PROM. No caso da PROM o programa apenas pode ser gravado uma vez. Portanto so e interessantepara os fabricantes de produtos com base nos microcontroladores, porque a PROM e uma memoria de baixo custo.Ja a gravacao de uma EPROM deve ser realizada atraves de equipamento adequado. O ciclo de desenvolvimentonormalmente exige inumeras operacoes de gravacao e eliminacao, para correccoes do programa.

Figura A.1: Pinos do microcontrolador PIC16F877A

Alguns microcontroladores, como o PIC16F877A (Figura A.1), substituıram a EPROMpela EEPROM,memoriaque pode ser apagada por meios electricos. Esta forma de trabalho encurta significativamente o ciclo de desenvol-vimento do programa, e tambem nao exige equipamento sofisticado para gravacao e eliminacao de programas namemoria.

Na figura A.2 podemos ver a arquitectura do microcontrolador utilizado.

A memoria encontra-se organizada em tres blocos. A memoria de programas e memoria de dados localizam-seseparadas, de modo a poderem acontecer acessos simultaneos. E ainda o bloco da memoria EEPROM.

Memoria de Programa - Os dispositivos PIC 16F87XA tem um contador de programa de 13 bits capaz deenderecar um espaco de 8K x 14 de memoria de programa. Nos PIC’s desta famılia a memoria de programautilizada e memoria FLASH. Na Figura A.3 encontra-se um mapa da memoria de programa do PIC 16F877A.

41

Figura A.2: Arquitectura interna do PIC16F877A

Figura A.3: Organizacao da memoria do programa.

42 Especificacoes do PIC16F877A

Memoria de dados - A memoria de dados (Figura A.4) e dividida em multiplos bancos que tem registos depropositos gerais e registos de funcoes especiais. A seleccao dos bancos e feita atraves dos bits RP1 (bit 6 doregisto STATUS) e RP0 (bit 5 do registo STATUS).Os bancos estendem-se ate 7Fh. As localizacoes mais baixas de cada banco sao reservadas para registos de

funcoes especiais. Sobre estes registos e os registos de proposito geral, as implementacoes sao todas feitas namemoria RAM estatica. Toda a implementacao com os bancos contem registos de funcoes especiais.

Figura A.4: Mapa de memoria do arquivo de registos.

Registos de Funcoes Especiais - Os Registos de Funcoes Especiais sao registos usados pela CPU e modulosperifericos para controlar as operacoes desejadas do dispositivo. Estes registos sao implementados na memoriaRAM estatica.Os Registos de Funcoes Especiais podem ser classificados em dois tipos: centrais (CPU) e perifericos. Alguns

dos principais registos sao os seguintes:

• Registo de STATUS - Contem o status das operacoes aritmeticas da ULA, status do RESET e os bits deseleccao dos bancos da memoria de dados;

• Registo OPTION_REG - E um registo de escrita e leitura que contem varios bits de controlo para configurar oprescale doTMR0, o postscale WDT, a interrupcao externa INT, TMR0 e os registos de pull-ups da PORTB;

• Registo INTCON - E um registo de escrita e leitura que contem varios enables e bits de sinalizacao (flags)para o disparo do registo TMR0, mudanca de porta RB e pino de interrupcao externa RB0/INT;

• Registo PIE1 - Contem os bits individuais de habilitacao das interrupcoes de perifericos;

• Registo PIR1 - Contem os bits individuais de sinalizacao (flags) das interrupcoes de perifericos;

• Registo PIE2 - Contem os bits individuais de habilitacao de interrupcao de periferico CCP2, interrupcao decolisao no barramento SSP, interrupcao de operacao de escrita na EEPROM e comparador de interrupcao;

• Registo PIR2 - Contem os bits de sinalizacao de interrupcao do CCP2, interrupcao de colisao no barramentoSSP, interrupcao de operacao de escrita na EEPROM e comparador de interrupcao;

43

• Registo PCON - Registo que contem os bits de sinalizacao que permite diferenciar o reset de Power-on(POR), reset de Brown-out (BOR), o reset do Watchdog (WDT) e um reset externo MCLR.

Memoria EEPROM - A memoria de dados EEPROM permite operacoes de leitura e escrita de bytes sem inter-ferir com a operacao normal do microcontrolador. Quando ha uma passagem para memoria de dados EEPROM,o registo EEADR guarda o endereco para que seja acedida. Dependendo da operacao, o registo EEDATA guardao dado a ser escrito ou o dado lido no endereco em EEADR. Os dispositivos PIC 16f876/877 tem 256 bytes dememoria de dados EEPROM.

Portas I/O - O microcontrolador possui 5 portas, todas podendo ser configuradas como entrada e saıda quandosendo utilizadas como proposito geral. Mas estas portas tambem podem ser configuradas com outras funcoes domicrocontrolador. Para utilizar uma ou outra funcao e necessario uma multiplexacao interna, que e feita comrecurso aos dados colocados nos respectivos registos de controlo, estes determinam por sua vez a actuacao dasportas.O microcontrolador possui uma porta de 6 bits, a porta A, uma de 3 bits, a porta ”E”e tres de 8 bits, as portas

B, C e D.Os registos que armazenam os dados das portas, quer na leitura como na escrita sao PORTA, PORTB, PORTC

e PORTD. A escolha do direccionamento das portas e feita atraves dos seguintes registos: TRISA, TRISB, TRISCe TRISD.Para escolher um pino como entrada ou como saıda basta escrever no bit do registo correspondente ao pino o

valor 0, o que implica configura-lo como saıda, ou o valor 1, correspondendo a configura-lo como entrada.

Conversor A/D - O conversor(Figura A.5) possui tensoes de referencia alta e baixa tabeladas, que sao usadaspara definir os limites mınimos e maximo de tensao e entrada do conversor A/D. Elas sao seleccionadas porsoftware fazendo uma combinacao entre dois dos seguintes pinos VDD, VSS, RA2 e RA3.Possui tambem uma caracterıstica particular, pode operar mesmo quando o microcontrolador esta no modo

SLEEP, sendo que nesse caso o clock do A/D deve ser derivado do oscilador RC interno dos A/D’s.Os registos para controlo e armazenamento de dados sao 4:

• ADRESH - Neste registo e armazenada a parte mais significativa do resultado da conversao.

• ADRESL - Neste registo e armazenada a parte menos significativa do resultado da conversao.

• ADCON0 - Configura o modo de operacao do conversor.

• ADCON1 - Configura as funcoes dos pinos das portas

Atraves do registo ADCON0 e determinado o clock que o conversor ira utilizar nas suas conversoes (a escolhado clock utiliza tambem o bit 6 do registo ADCON1 ou ADCS2), seleccionar o canal que vai fazer a conversao,indicar o andamento da conversao (se ja acabou ou se esta em andamento), e habilitar ou desabilitar o conversorA/D.Atraves do registo ADCON1 e determinado se os 6 bits mais significativos de ADRESH sao considerados 0,

ou se por sua vez sao os 6 bits menos significativos de ADRESL. Isto e feito, tendo em conta que o dado digitale formado por apenas 10 bits. Configuram-se tambem os pinos que serao utilizados pelo conversor como entrada

44 Especificacoes do PIC16F877A

Figura A.5: Diagrama de blocos do conversor A/D

analogica e os pinos que forneceram as tensoes de referencia. Esta configuracao e feita atraves dos bits 0,1,2 e 3,que correspondem respectivamente as funcoes PCFG0, PCFG1, PCFG2, e PCFG3. As combinacoes possıveis saomostradas na figura A.6.

Figura A.6: Configuracoes possıveis dos pinos do conversor A/D. O ”A”na tabela representa configuracao para umsinal analogico e ”D”para um sinal digital.

O conversor possui apenas uma entrada de tensao, sendo que os pinos sao multiplexados. Por este motivo,entre uma conversao e outra e necessario que se de um tempo mınimo de 2TAD (TAD - tempo de conversao porbit), que e um tempo necessario que o valor de um pino seja convertido sem que o valor de outro pino interfira noresultado.

Os Timers - O PIC 16F877A possui tres temporizadores: o TIMER0, o TIMER1 e o TIMER2. Cada um delestrabalha de um modo particular.O TIMER0 pode ser utilizado como um contador ou como um timer, em ambos os casos de 8 bits. Ele pode

usar o clock externo ou interno, sendo que e possıvel dividi-lo por um valor chamado pre-escala que podem serde 2, 4, 8, 16, 32, 64, 128 ou 256. Deste modo divide-se a frequencia do clock utilizado pelo TIMER0. Umainterrupcao pode ser programada para ser gerada a cada disparo de overflow de FFh para 00h. O controlo destasfuncoes e feito atraves do registo OPTION_REG. Para escrever ou ler o valor do timer e atraves do registo TMR0.O TIMER1 tambem pode ser usado como contador e como timer. Tem 16 bits, divididos em dois registos de

8 bits o TMR1H e TMR1L, atraves dos quais e possıvel escrever e ler o valor do TIMER1. O par de registosTMR1 conta de 0000h ate FFFFfh. Pode gerar-se uma interrupcao com disparo de overflow. Quando e utilizadocomo timer, ocorre um incremento em todo ciclo de instrucao. Quando e utilizado como contador, o incrementoe feito no flanco ascendente do clock externo de entrada. O timer possui um RESET interno de entrada que pode

45

ser gerado por qualquer um dos dois modulos CCP (Captura - Comparacao - PWM). Sendo que o TIMER1 apenastrabalha no modo captura e comparacao. O clock utilizado pelo TIMER1 pode ser o externo ou o interno, e podeainda ser dividido pelo prescale que pode ser de 2, 4 ou 8.O TIMER2 e um timer de 8 bits. Pode ser utilizado como timer base para geracao de um sinal PWM no modo

PWM dos modulos CCP. Os valores de prescale para o TIMER2 sao de 1, 4 ou 16. A contagem no TIMER2 difereum pouco dos outros dois TIMER’s, pois inicia-se em 00h, mas para assim que o valor do TIMER2 (registo quecontem o valor actual de contagem do TIMER2) iguala o valor do registo de 8 bits PR2. Este registo contem o valorlimite de contagem do timer, no fim do qual a contagem e reiniciada parando sempre no mesmo valor. Quandoocorre um RESET o valor de PR2 e inicializado a FFh. O TIMER2 tambem possui uma funcao chamada postscale.Esta e utilizada juntamente com a chamada de interrupcao, pois a interrupcao do TIMER2 ocorre apenas quandoo timer acabar a contagem do numero de vezes determinado pelo postscale. Ou seja, se o valor do postscale e 3,significa que uma interrupcao sera chamada somente depois de o timer contar tres vezes ate ao valor de PR2.

Modulo Captura/Comparacao/PWM - OPIC16F877A possui dois modulos Captura/Comparacao/PWM (CCP).Os modulos possuem registos de 16 bits, e podem operar nos seguintes modos:

• Modo captura com o registo de 16 bits;

• Modo comparacao com o registo de 16 bits;

• Modo PWM.

Sao utilizados dois pinos para a geracao dos sinais PWM: CCP1 e CCP2. A resolucao do sinal PWM desaıda e de 10 bits. Ele vai utilizar dois pinos que tambem sao utilizados pela porta C, por isso motivo ocorre umamultiplexacao entre as funcoes, o bit correspondente no registo TRISC devera ser posto a zero.Dos 10 bits de resolucao, 8 bits mais significativos sao escritos no registo CCPR1L e os 2 bits menos signifi-

cativos sao escritos nos bits 4 e 5 do registo CCP1CON.

Porta Serie Sıncrona Mestre (MSSP) - O modulo MSSP e uma interface serie util para comunicacao comoutros perifericos ou com outros microcontroladores. Estes dispositivos perifericos podem ser EEPROM, display,conversor A/D etc. O modulo do MSSP pode operar em dois modos:1) Interface Periferica Serie (SPI);2) Circuito inter-integrado (I2C).

46 Especificacoes do PIC16F877A

Apendice B

Modulo USB comercial DLP-2232PB-G

Neste anexo identificam-se as funcoes dos varios pinos do modulo DLP-2232PB-G, e apresenta-se um esquemadas ligacoes dos varios elementos constituintes do modulo.

V1.6 Page 12 of 15 August 2007

TABLE 1: DLP-2232PB PINOUT DESCRIPTION

Pin # Description

1 GROUND

2 B5 (I/O) Port Pin B5 connected to the 16F877A microcontroller.

3 UPRST (In) 16F877A Reset input. Can be left disconnected if not used.

4 A0 (I/O) Port Pin A0 connected to the 16F877A microcontroller. A/D Channel 0.

5 A1 (I/O) Port Pin A1 connected to the 16F877A microcontroller. A/D Channel 1.

6 A2 (I/O) Port Pin A2 connected to the 16F877A microcontroller. A/D Channel 2.

7 A3 (I/O) Port Pin A3 connected to the 16F877A microcontroller. A/D Channel 3.

8 A4 (I/O) Port Pin A4 connected to the 16F877A microcontroller. Open drain output.

9 A5 (I/O) Port Pin A5 connected to the 16F877A microcontroller. A/D Channel 4.

10 LED (I/O) Port Pin E0 connected to the 16F877A microcontroller. The on-board LED can be driven

by 16F877A microcontroller or by external user electronics if E0 is configured as an input.

11 GROUND

12 NO CONNECT

13 NO CONNECT

14 NO CONNECT

15 DB7 (I/O) Line 7 of the data bus between the 16F877A and the FT2232D USB-FIFO.

16 DB6 (I/O) Line 6 of the data bus between the 16F877A and the FT2232D USB-FIFO.

17 DB5 (I/O) Line 5 of the data bus between the 16F877A and the FT2232D USB-FIFO.

18 DB4 (I/O) Line 4 of the data bus between the 16F877A and the FT2232D USB-FIFO.

19 DB3 (I/O) Line 3 of the data bus between the 16F877A and the FT2232D USB-FIFO.

20 DB2 (I/O) Line 2 of the data bus between the 16F877A and the FT2232D USB-FIFO.

21 DB1 (I/O) Line 1 of the data bus between the 16F877A and the FT2232D USB-FIFO.

22 DB0 (I/O) Line 0 of the data bus between the 16F877A and the FT2232D USB-FIFO.

23 EXTVCC (In) Use for applying main power (4.4 to 5.25 volts) to the module. Connect to

26

1

50

25

V1.6 Page 13 of 15 August 2007

PORTVCC if the module is to be powered by the USB port (typical configuration).

24 PORTVCC (Out) Power from USB port. Connect to EXTVCC if module is to be powered by the

USB port (typical configuration). 500mA is the maximum current available to the DLP-2232PB and

target electronics if the USB device is configured for high power.

25 GROUND

26 GROUND

27 VCCUSB (Out) Filtered power applied to pin 23.

28 SWVCC (Out) Power from EXTVCC (Pin 23) controlled via PWREN of the FT2232D and Q2

MOSFET power switch. R5 and C9 control the power-up rate to help limit inrush current.

29 AC3 (I/O) Port Pin AC3 connected to the FT2232D USB IC.

30 AC2 (I/O) Port Pin AC2 connected to the FT2232D USB IC.

31 AC1 (I/O) Port Pin AC1 connected to the FT2232D USB IC.

32 AC0 (I/O) Port Pin AC0 connected to the FT2232D USB IC.

33 NO CONNECT

34 NO CONNECT

35 NO CONNECT

36 NO CONNECT

37 NO CONNECT

38 NO CONNECT

39 NO CONNECT

40 GROUND

41 C0 (I/O) Port Pin C0 connected to the 16F877A microcontroller.

42 C1 (I/O) Port Pin C1 connected to the 16F877A microcontroller.

43 C2 (I/O) Port Pin C2 connected to the 16F877A microcontroller.

44 C3 (I/O) Port Pin C3 connected to the 16F877A microcontroller.

45 C4 (I/O) Port Pin C4 connected to the 16F877A microcontroller.

46 C5 (I/O) Port Pin C5 connected to the 16F877A microcontroller.

47 C6 (I/O) Port Pin C6 connected to the 16F877A microcontroller.

48 C7 (I/O) Port Pin C7 connected to the 16F877A microcontroller.

49 B0 (I/O) Port Pin B0 connected to the 16F877A microcontroller.

50 GROUND

5 5

4 4

3 3

2 2

1 1

DD

CC

BB

AA

DLP

-223

2PB

MO

DU

LE

B6 (CLK) -->

B7 (DTA) <-->

General

Purpose

I/O

0=run 1=Program

16 Digital I/O to uP -Plus- 8-bit Data bus (24 total)

2 of which are interrupt input

5 of which are analog input

| 4 General Purpose I/O from FT2232C

** DNS **

EE

DA

TA

EE

CS

EE

SK

C1

EXT

VCC

PO

RTV

CC

C0

GN

D

C4

C2

C7

GN

D

C3

C6

C5

B5

UP

RS

T

GN

D

B0

SW

VC

C

VC

CU

SB

EXT

VCC

PO

RTV

CC

RX

F#TX

E#

SI/W

UB

RD

#W

R

BD

5

BD

1

BD

3

BD

7

BD

4

BD

6

BD

0

AC

0A

C1

AC

2A

C3

AC

0

AC

3

AC

1A

C2

BD

5

BD

2B

D1

BD

3

BD

7

BD

4

BD

6

BD

0

GN

D

UP

RS

T

SW

VC

C

VC

CU

SB

VC

CU

SB

SW

VC

C

A0

A5

A3

A1

A2

A4

BD

2

UP

RS

T

C0

BD

3

BD

0

B0

BD

6

TXE#

A0

A5

A1

C6

C3

C5

SI/W

UB C1

BD

2

A3

SW

VC

C

WR

SW

VC

C

B5

BD

4

C2

RX

F#C4

A2

SW

VC

C C7

A4

RD

#

BD

1

BD

5

BD

7

LED

LED

VC

CU

SB

GN

D

GN

D

Y2 6M

Hz

C20

.1uF

CN

1C

N-U

SB

1 2 3 4

5

C1

.01u

F

R12

10K

FB3

12

C2

.1uF

C34

10uF

R4

470

C7

.1uF

C3

.1uF

R9

360

C4

.033

uF

C5

.01u

F

C16

.033

uFR

227

R1

27

C13

47pF

LED

1

LED

C14

47pF

R3

1.5K

C17

18pF

R8 1K

U3

93C

56

1 2 3 4

8 7 6 5

CS SK

DIN

DO

UT

VC

CN

CN

CG

ND

R7

10K

R6

2.2K

R5

2.2K

C12

18pF

JP2

CO

NN

PC

B 2

5x2

8761 2 3 4 5 109 1211 13 1514 1716 18 2019 2524232221

34 33 32 31 30 29 28 27 2640 39 38 37 36 3550 49 48 47 46 45 44 43 42 41

8761 2 3 4 5 109 1211 13 1514 1716 18 2019 2524232221

34 33 32 31 30 29 28 27 2640 39 38 37 36 3550 49 48 47 46 45 44 43 42 41

FB4

FB

12

Q2

IRLM

L640

2

C9

.1uF

C6

.1uF

C8

.1uF

C10

.1uF

U2

FT22

32

5 44 4 48 1 2

45

918

476

46

423

8 7 43

24 23 22 21 20 19 17 16 15 13 12 11 10 40 39 38 37 36 35 33 32 30 29 28 27 26 41

253414

31

RS

TOU

T#

XTO

UT

RE

SE

T#

EE

CS

EE

SK

EE

DA

TA

AGND

GNDGND

TES

T

3V3O

UT

AVCC

VCCVCC

US

BD

M

US

BD

P

XTI

N

AD

0A

D1

AD

2A

D3

AD

4A

D5

AD

6A

D7

AC

0A

C1

AC

2A

C3

SI/W

UA

BD

0B

D1

BD

2B

D3

BD

4B

D5

BD

6B

D7

BC

0B

C1

BC

2B

C3

SI/W

UB

PW

RE

N

GNDGNDVCCIOA

VCCIOB

JP1

Deb

ugge

r Hea

der (

DN

S)

1 2 3 4 5

R13

27

Q3

2N39

04

Q4 2N

3904

C18

18pF

U1 PIC

16F8

77A

TQ

FP

21 22 23 18

29

8 9 10 11

7

313019 20

6

24

37 42 43 44 1272625

38 39 40 41 2 3 4 5

28

143632 35 15 16 17

33341213

RA

2/A

N2/

VR

EF

RA

3/A

N3/

VR

EF+

RA

4/TO

CK

I

MC

LR

Vss

RB

0/IN

TR

B1

RB

2R

B3/

PG

M

VDD

OS

C2/

CLK

OU

TO

SC

1/C

LKIN

RA

0/A

N0

RA

1/A

N1

Vss

RA

5/A

N4/

SS

*

RC

3R

C4

RC

5R

C6

RC

7

E2

E1

E0/

AN

5

D0

D1

D2

D3

D4

D5

D6

D7

VDD

RB

4/IN

T

RC

2

RC

0R

C1

RB

5/IN

TR

B6/

PG

CR

B7/

PG

D

NCNCNCNC

C33

10uF

C11

18pF

R14

27

C19

.1uF

Y1

20M

Hz

R11

10K

C15

.47u

F

R10

1K

48 Modulo USB comercial DLP-2232PB-G

Apendice C

Software de interface para PC

Este software de interface para PC, ou PC-driver, encontra-se divido em tres ficheiros. O myadda.h, ondepodemos encontrar as funcoes do interface generico, o myadda.cpp onde se encontra implementada cada funcaodo interface generico, e o teste.cpp que funciona como um pequeno tutorial, onde se mostra a utilizacao de grandeparte das funcoes, atraves de exemplos, para o ambiente de Matlab.

//myadda.h

//

Interface de comunicação com o modulo DLP-2232PB-G e DAC4822

//

#if

!defined(MYADDA_H)

#define MYADDA_H

#include

<windows.h>

//createfile handlers

#include

<iostream>

//usar namespace std

#include

<string>

//usar strings,

pelo namespace

#include

<setupapi.h>

//devices do windows

#include

<vector>

#include

<cmath>

using

namespace std;

#ifdef

__cplusplus

//se estiver em modo de C++

//codigo em classes C++

class Myadda

{ private:

HANDLE hCom;

bool ADsetup;

//int timer0Div;

//int timer0DivTimeOut;

//metodos

public:

//construtor

&destrutor

Myadda();

~Myadda();

//metodos de comunicação

bool connect(const

char*

porta);

std::vector<string>

listDevices(void);

string deviceHandler(const

char*

desc);

//escrita digital de um pin ou porto no PIC

bool digitalOutput(unsigned

char v,

unsigned

char channel);

//leitura digital de um pin ou porto no PIC

int digitalInput(int channel);

//pede uma leitura ADC do canal

double ADC(int channel);

//coloca o valor "value"

como saida analogica no canal

int DAC(int channel,double value);

//gerar sinal com os DAC em background do pic com periodo Ts e nTimes

//numero de vezes

int outputDACArray(int channel,

double*

buffer,

int bufflen,

double Ts,

int nTimes,

int

flags);

//se nao interessar nTimes ==

NULL,

então parar a geração do sinal com STOP

int outputDACArrayStop();

//receber com ADC's um array de valores.

//com timedelays DAC

int inputADCArray(int channel,

double*

buffer,

int bufflen,

double Ts,

int flags);

//com ISR DAC+tempo

//int inputArray(int channel,

double*

buffer,

double*bufferTempos,

int bufflen,...

//

double Ts,

int flags);

//com timedelays DAC+tempo

int inputADCTimeArray(int channel,

double*

buffer,

double*bufferTempos,

int bufflen,

double Ts,

int flags);

//com timedelays DAC +

DAC

int input2ADCArray(int channel,

double*

buffer,

double*

buffer2,

int bufflen,

double Ts

,int flags);

private:

int recebeBuffer(Myadda*

obj);

void enviaBuffer(Myadda

*obj,const

unsigned

char

*instrucao,int dimensao);

int setupAdc();

//int chooseTimer(double Ts);

};

#else

//codigo em C

#endif

#endif

//myadda.cpp

//includes files

#pragma

comment(lib,

"setupapi.lib")

//disponibiliza as funcoes de devices do windows

#include

"myadda.h"

#define VREF 5.12

#define DACREF 4.096

//comandos para o PIC

#define lineOut 0xA6

#define lineIn 0xA5

#define setupAD 0xA9

#define PortAwrite 0x56

#define PortCwrite 0x5A

#define PortDwrite 0x5C

#define PortAread 0x55

#define PortCread 0x59

#define PortDread 0x5B

//portas/pin do PIC

//PORT A:

4->

9#define PIN_A0 0x28

#define PIN_A1 0x29

#define PIN_A2 0x2A

#define PIN_A3 0x2B

#define PIN_A4 0x2C

#define PIN_A5 0x2D

//PORT C:

41

->

48

#define PIN_C0 0x38

#define PIN_C1 0x39

#define PIN_C2 0x3A

#define PIN_C3 0x3B

#define PIN_C4 0x3C

#define PIN_C5 0x3D

#define PIN_C6 0x3E

#define PIN_C7 0x3F

int Myadda::recebeBuffer(Myadda*

obj){

unsigned

char b;

DWORD BytesLidos;

if

(ReadFile(

obj->hCom, &b,

1, &BytesLidos,

NULL)!=

0)

if

(BytesLidos

>0)

{return

(int)b;

}

return

-1;

}//fim da funcao

void Myadda::enviaBuffer(Myadda

*obj,const

unsigned

char

*instrucao,int dimensao){

DWORD BytesEscritos;

unsigned

char buf[100];

for

(int i=0;i<dimensao;i++)

buf[i] = instrucao[i];

WriteFile(obj->hCom,

buf,

dimensao,&BytesEscritos,NULL);

}//fim da funcao

std::vector<string>

comDetection(const

char*

flag){

HDEVINFO hDevInfo;

SP_DEVINFO_DATA DeviceInfoData;

DWORD i;

char*

pStrTemp;

vector<string>

setStr;

string compare1

="USB Serial Port";

string compare2

="Ports";

//

Create a HDEVINFO with all present devices.

hDevInfo

=SetupDiGetClassDevs(NULL,

0,

//

Enumerator

0,

DIGCF_PRESENT

|DIGCF_ALLCLASSES);

if

(hDevInfo

==

INVALID_HANDLE_VALUE)

{//

Insert error handling here.

printf("\nNo device present\n");

} //

Enumerate through all devices in Set.

DeviceInfoData.cbSize

=sizeof(SP_DEVINFO_DATA);

for

(i=0;SetupDiEnumDeviceInfo(hDevInfo,i,&DeviceInfoData);i++)

{DWORD DataT;

LPTSTR buffer =

NULL;

DWORD buffersize =

0;

/*

Call function with null to begin with,then use the returned buffer size(doubled)

to Alloc the buffer.

Keep calling until success or an unknown failure.

Double the returned buffersize to correct for underlying legacy CM functions that

return an incorrect buffersize value on DBCS/MBCS systems.*/

//*********************************************************************************

//*********************************************************************************

while

(!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_DEVICEDESC,

&DataT,(PBYTE)buffer,buffersize,&buffersize))

{if

(GetLastError() ==

ERROR_INSUFFICIENT_BUFFER)

{//

Change the buffer size.

if

(buffer)

LocalFree(buffer);

//

Double the size to avoid problems on

//

W2k MBCS systems per KB 888609.

buffer

= (LPTSTR)LocalAlloc(LPTR,buffersize

*2);

} else

{//

Insert error handling here.

break;

}} if

(compare1.compare(buffer)!=0){

if

(buffer)

LocalFree(buffer);

continue;

} //printf("Result:[%s]\n",buffer);

if

(buffer)

LocalFree(buffer);

//*********************************************************************************

//*********************************************************************************

buffer

=NULL;

buffersize

=0;

while

(!SetupDiClassNameFromGuid(&DeviceInfoData.ClassGuid,

buffer,

buffersize,&

buffersize))

{if

(GetLastError() ==

ERROR_INSUFFICIENT_BUFFER)

{//

Change the buffer size.

if

(buffer)

LocalFree(buffer);

buffer

= (LPTSTR)LocalAlloc(LPTR,buffersize

*2);

} else

{//

Insert error handling here.

break;

}} if

(compare2.compare(buffer)!=0){

if

(buffer)

LocalFree(buffer);

continue;

} //printf("Result2:[%s]\n",buffer);

//guarda o ClassGuid do dispositivo

GUID InterfaceClassGuid =

DeviceInfoData.ClassGuid;

if

(buffer)

LocalFree(buffer);

//*********************************************************************************

//*********************************************************************************

buffer

=NULL;

buffersize

=0;

while

(!SetupDiGetDeviceInstanceId(hDevInfo,&DeviceInfoData,

buffer,

buffersize,&

buffersize))

{if

(GetLastError() ==

ERROR_INSUFFICIENT_BUFFER)

{//

Change the buffer size.

if

(buffer)

LocalFree(buffer);

buffer

= (LPTSTR)LocalAlloc(LPTR,buffersize

*2);

} else

{//

Insert error handling here.

break;

}} //printf("Result3:[%s]\n",buffer);

//nao contem as strings PID VID e DP ->

continue

if

(!(((string)buffer).find("PID",0) != -1

&&

((string)buffer).find("VID",0) !=-1

&&

((string)buffer).find("DP",0) !=-1)){

if

(buffer)

LocalFree(buffer);

continue;

} //se for so para devolver os dispositivos ligados

if

(flag

==

NULL){

vector<string>

setStr1;

//parse da string para conseguir VID PID e DP

char

*pch;

pch

=strtok((char*)buffer,"\\+");

while

(pch

!=

NULL)

{

if

(((string)pch).find("PID",0) != -1

||

((string)pch).find("VID",0) !=-1

||

((string)pch).find("DP",0) !=-1)

setStr1.push_back((string)pch);

pch

=strtok

(NULL,

"\\+");

} //concatenar VID e PID na mesma string

vector<string>

setStr_aux

=setStr1;

setStr1.clear();

string s[4];

while

(!setStr_aux.empty())

{s[3] = setStr_aux.back();

if

(s[3].find("VID",0) != -1)

s[0] = s[3];

if

(s[3].find("PID",0) != -1)

s[1] = s[3];

if

(s[3].find("DP",0) != -1)

s[2] = s[3];

setStr_aux.pop_back();

} setStr_aux.clear();

setStr1.push_back(s[0].append("+").append(s[1]));

setStr1.push_back(s[2]);

if

(buffer)

LocalFree(buffer);

while

(!setStr1.empty())

{setStr.push_back(setStr1.back());

setStr1.pop_back();

continue;

}} //se nao é porque queremos o registo do FTDI correspondente a flag

else{ //é dispositivo FTDI mas não é o pretendido

if

(!(((string)buffer).find((string)flag,0) != -1))

continue;

if

(buffer)

LocalFree(buffer);

setStr.clear();

//*****************************************************************************

//

devolve o numero da COM

//*****************************************************************************

buffer

=NULL;

buffersize

=0;

DWORD Property =

SPDRP_FRIENDLYNAME;

while

(!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,

Property,

&DataT,(PBYTE)buffer,

buffersize,&buffersize))

{if

(GetLastError() ==

ERROR_INSUFFICIENT_BUFFER)

{//

Change the buffer size.

if

(buffer)

LocalFree(buffer);

buffer

= (LPTSTR)LocalAlloc(LPTR,buffersize

*2);

} else

{//

Insert error handling here.

break;

}} //printf("Result4:[%s]\n",buffer);

pStrTemp

=strchr(buffer,')');

if(NULL==pStrTemp)

continue;

*pStrTemp=0;

pStrTemp

=strchr(buffer,'(');

if(NULL==pStrTemp)

continue;

pStrTemp++;

//printf("ResultFINAL:[%s]\n",pStrTemp);

if

(buffer)

LocalFree(buffer);

//*****************************************************************************

HDEVINFO hdevClassInfo;

//

Retrieve a device information set.

hdevClassInfo

=SetupDiGetClassDevs(&InterfaceClassGuid,

NULL,

NULL,

DIGCF_PRESENT

|DIGCF_DEVICEINTERFACE);

if

(hdevClassInfo

==

INVALID_HANDLE_VALUE)

{printf("\nNo device information set for the device\n");

} //

Initialize variables.

SP_DEVICE_INTERFACE_DATA DeviceData;

DeviceData.cbSize

=sizeof(SP_INTERFACE_DEVICE_DATA);

for

(int nMemberIndex =

0;

TRUE;

nMemberIndex++)

{int nStatus =

SetupDiEnumDeviceInterfaces

(hdevClassInfo,

NULL,

(LPGUID)&InterfaceClassGuid,

nMemberIndex,

&DeviceData);

int nSize;

//

Retrieve the size of the device data.

int nStatus2

=SetupDiGetDeviceInterfaceDetail(hdevClassInfo, &DeviceData,

NULL,

0,

(PDWORD)&nSize,

NULL);

if

(nStatus

!=

TRUE)

break;

//

Allocate memory for the device detail buffer.

PSP_INTERFACE_DEVICE_DETAIL_DATA deviceDetail;

deviceDetail

= (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(nSize);

deviceDetail->cbSize

=sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

if

(deviceDetail

==

NULL)

{printf("\nDeviceDetail is NULL\n");}

//

Initialize variables.

DeviceData.cbSize

=sizeof(SP_INTERFACE_DEVICE_DATA);

int nStatus3

=SetupDiGetDeviceInterfaceDetail(hdevClassInfo, &DeviceData,

deviceDetail,

nSize,

NULL,&DeviceInfoData);

if

(nStatus3

=FALSE)

{printf("\nSetupDiGetDeviceInterfaceDetail is NULL\n

");}

else

{setStr.push_back(deviceDetail->DevicePath);

free

(deviceDetail);

break;

}

} //*****************************************************************************

break;

}//fim do else

}//fim da iteracao sobre todos os dispositivos fisicos

if

(GetLastError()!=NO_ERROR

&&

GetLastError()!=ERROR_NO_MORE_ITEMS

){

//

Insert error handling here.

printf("\nErrors in device detection\n");

setStr.clear();

return setStr;

} //

Cleanup

SetupDiDestroyDeviceInfoList(hDevInfo);

return setStr;

} /////////////////////////////////////////////////////////////////////////////

//

FTDI_COM dialog -

classe de comunicação com a porta COM

/////////////////////////////////////////////////////////////////////////////

class Ftdi_com

{ public:

bool FTDI_Conectado;

HANDLE hCom;

DCB dcb;

COMMTIMEOUTS CommTimeouts;

public:

bool AbrirPorta(const

char

*NomePorta);

bool ConfiguraControle(void);

bool ConfiguraTimeOuts(void);

Ftdi_com();

~Ftdi_com();

};

Ftdi_com::Ftdi_com()

{

FTDI_Conectado

=false;

hCom

=NULL;

} Ftdi_com::~Ftdi_com()

{ } //------------------------------------------------------------------------------

//Abre a Porta Serial COMx

bool Ftdi_com::AbrirPorta(const

char*

NomePorta)

{

hCom

=CreateFile(

NomePorta,

GENERIC_READ

|GENERIC_WRITE,

0,

//

dispositivos comm abertos com acesso exclusivo

NULL,

//

sem atributos de segurança

OPEN_EXISTING,

//

deve usar OPEN_EXISTING

FILE_ATTRIBUTE_NORMAL,

//Entrada e saída sem ovelap.

NULL

//

hTemplate deve ser NULL para comm

);

if(hCom

==

INVALID_HANDLE_VALUE)

{return

false;

} return

true;

} //------------------------------------------------------------------------------

//CONFIGURA PORTA SERIAL.

bool Ftdi_com::ConfiguraControle(void)

{//Retrieves the current control settings for a specified communications device.

if(!GetCommState(hCom, &dcb))

{return

false;

} dcb.BaudRate

=CBR_256000;//CBR_9600;

dcb.ByteSize

=8;

dcb.Parity

=NOPARITY;

dcb.StopBits

=ONESTOPBIT;

//Configures a communications device according to the specifications in a

//device-control block (a DCB structure).

//The function reinitializes all hardware and control settings,

but it does not empty

//output or input queues.

if(

SetCommState(hCom, &dcb) == 0

){

return

false;

} return

true;

} //------------------------------------------------------------------------------

//DEFINE TIMEOUTs

bool Ftdi_com::ConfiguraTimeOuts(void)

{if(

GetCommTimeouts(hCom, &CommTimeouts) == 0

){

return

false;

} //

immediate return if data is available,

wait

1ms otherwise

CommTimeouts.ReadTotalTimeoutConstant

=1;

CommTimeouts.ReadIntervalTimeout

=MAXDWORD;

CommTimeouts.ReadTotalTimeoutMultiplier

=MAXDWORD;

CommTimeouts.WriteTotalTimeoutMultiplier

=5;

CommTimeouts.WriteTotalTimeoutConstant

=5;

if(

SetCommTimeouts(hCom, &CommTimeouts) == 0

){

return

false;

} return

true;

} //*************************************************************************

//implementação de metodos da classe MYADDA

//*************************************************************************

Myadda::Myadda()

{

this->ADsetup

=false;

//this->timer0Div

=128;//ISR

0.5ms

//this->timer0DivTimeOut

=236;

} Myadda::~Myadda()

{CloseHandle(this->hCom);

this->ADsetup

=false;

} bool Myadda::connect(const

char*

porta){

bool Sucesso;

string gate;

//

Criar objecto Ftdi_com

Ftdi_com

*d

=new Ftdi_com;

if

(porta

==

NULL){

string aux;

std::vector<string>

s;

s=

listDevices();

aux

=s.back();

gate

=deviceHandler(aux.c_str());

} elsegate

=porta;

//se tivermos ligacao com o dispositivo

if(d->AbrirPorta(gate.c_str()) == true){

d->FTDI_Conectado

=true;

Sucesso

=d->ConfiguraControle();

Sucesso

=d->ConfiguraTimeOuts();

if(Sucesso

==

false)

{d->FTDI_Conectado

=false;

CloseHandle(d->hCom);

free(d);

return

false;

} //para remover

printf("\n------------------------ESTOU LIGADO----------------------\n");

this->hCom

=d->hCom;

free(d);

return

true;

} else

{free(d);

return

false;

}

} string Myadda::deviceHandler(const

char*

desc){

std::vector<string>

s;

string aux;

s=

comDetection(desc);

aux

=s.back();

s.pop_back();

return aux;

} std::vector<string>

Myadda::listDevices(void){

std::vector<string>

s;

s=

comDetection(NULL);

return s;

} bool Myadda::digitalOutput(unsigned

char v,

unsigned

char channel){

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

if

(channel

==

PortAwrite

||

channel

==

PortCwrite

||

channel

==

PortDwrite){

buff[0] = numBytes

=0x02;

buff[1] = channel;

buff[2] = v;

//checksum

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[3] = checksum;

buff[4] = '\0';

} else{ buff[0] = numBytes

=0x03;

buff[1] = lineOut;

buff[2] = channel;

if

(v)

buff[3]=0x01;

else buff[3]=0x00;

//checksum

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[4] = checksum;

buff[5] = '\0';

} sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

int a;

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85)

return

false;

elsereturn

true;

} int Myadda::digitalInput(int channel){

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

if

(channel

==

PortAread

||

channel

==

PortCread

||

channel

==

PortDread){

buff[0] = numBytes

=0x01;

buff[1] = channel;

//checksum

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[2] = checksum;

buff[3] = '\0';

} else{ buff[0] = numBytes

=0x02;

buff[1] = lineIn;

buff[2] = channel;

//checksum

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[3] = checksum;

buff[4] = '\0';

} sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

int a;

while((a

=recebeBuffer(this)) == -1);

//a

=recebeBuffer(this);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}

return a;

} double Myadda::ADC(int channel){

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

//se ainda nao foi feito o setup AD

if

(!this->ADsetup){

this->setupAdc();

} //

ler AD pin A0:

0x02 0xa9 0x28 0x83

//

ler AD pin A1:

0x02 0xa9 0x29 0x82

//

ler AD pin A2:

0x02 0xa9 0x2A

0x81

//

ler AD pin A3:

0x02 0xa9 0x2B

0x80

//

ler AD pin A4:

0x02 0xa9 0x2C

0x87

buff[0] = numBytes

=0x02;

buff[1] = setupAD;

switch(channel){

case

0:

buff[2] = PIN_A0;

break;

case

1:

buff[2] = PIN_A1;

break;

case

2:

buff[2] = PIN_A2;

break;

case

3:

buff[2] = PIN_A3;

break;

case

4:

buff[2] = PIN_A4;

break;

default:

buff[2] = PIN_A0;

} for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[3] = checksum;

buff[4] = '\0';

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}double out;

while((a

=recebeBuffer(this)) == -1);

out

= (double)a;

while((a

=recebeBuffer(this)) == -1);

out

= ((double)a*256

+out)*(VREF/1023);

return out;

} int Myadda::DAC(int channel,double value){

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

if

(channel

!=0

&&

channel

!=1)

{printf("\nError:

only channel 0

or

1available\n");

return

-1;

} buff[0] = numBytes

=0x02;

buff[1] = 0xB8;

buff[2] = channel;

//converter voltagem de 0

a4.095V para byte.

if

(value

>=

0&&

value

<=

4.095)

buff[3] = (int)((value*4096)/(16*DACREF));

else{ printf("\nError:

voltage between 0

and

4.096V\n");

return

-1;

} for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[4] = checksum;

buff[5] = '\0';

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}

return

1;

} int Myadda::outputDACArray(int channel,

double*

buffer,

int bufflen,

double Ts,

int nTimes,

int flags){

//enviar buffer para o pic.

//definir frequencia do sinal

const

double PICclock =

20000000;

double maxPeriod =

256/(PICclock/4);

double DACtimeDiv =

16;

double samplePeriod;

//periodo de

int postscale =

1;

//definir as ISR do timer2

int prescale =

0;

//definir as ISR do timer2

unsigned

char buffer_aux[97]={0x00};

int i;

if(bufflen

>96){

printf("\nError bufflen:

array dimension exceeded (max

96)\n");

return

-1;

} for(

i=0

;i

<bufflen

;i++,buffer++ )

buffer_aux[i] = (unsigned

char)*buffer;

buffer_aux[++i] = '\0';

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

//envia instruçao para guardar array

buff[0] = numBytes

=0x02;

buff[1] = 0xC2;

buff[2] = (unsigned

char)bufflen;

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[3] = checksum;

buff[4] = '\0';

checksum

=0;

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

} //enviar array

enviaBuffer(this,buffer_aux,bufflen);

double numIsr =

1;

//definir tempos de interrupçoes

samplePeriod

=Ts/bufflen;

while

(1){

if

(samplePeriod

==

0){

printf("\nError Ts:

period too low\n");

return

-1;

} if

(samplePeriod

<=

numIsr*postscale*maxPeriod*DACtimeDiv){

prescale

= (int)((samplePeriod*256)/(numIsr*postscale*maxPeriod*DACtimeDiv)-1);

break;

} postscale++;

if

(postscale

>16){

postscale

=1;

numIsr++;

} if

(numIsr

==

65535){

printf("\nError

:frequency too low.\n");

return

-1;

}

} if

(prescale

<2){

printf("\nError prescale:

frequency too high,

choose a lower freq or reduce the

number of samples per period(Tmax(sample)=50us)\n");

return

-1;

} //enviar tempos de interrupçoes

buff[0] = numBytes

=0x05;

buff[1] = 0xC1;

buff[2] = (unsigned

char)prescale;

buff[3] = (unsigned

char)postscale;

buff[4] = ((unsigned

int)numIsr

&0x00ff);//LSByte first

buff[5] = (((unsigned

int)numIsr

&0xff00)

>>

8);

//MSByte

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[6] = checksum;

buff[7] = '\0';

checksum

=0;

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

} //enviar instruçao de geraçao de sinal

buff[0] = numBytes

=0x01;

buff[1] = 0xB6;

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[2] = checksum;

buff[3] = '\0';

checksum

=0;

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}

//***********************************************************

return

1;

} int Myadda::outputDACArrayStop(){

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

buff[0] = numBytes

=0x01;

buff[1] = 0xB9;

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[2] = checksum;

buff[3] = '\0';

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}

return

1;

} //

int Myadda::inputADCArray(int channel,

double*

buffer,

double*

bufferTempos,

...

//

int bufflen,

double Ts,

int flags){

// //ISR ADC0:

0x02 0xb1 0x28 0x9b

//

double numSamples =

bufflen;//reservar buff 3 4 5 6 para int32

num amostras.

//

unsigned char buff[10]={0x00};

//

unsigned char numBytes,checksum=0;

//

int sizeBuff=0;

//

int a;

//

//

//

// //escolhe o timer correcto para atender ao periodo requerido de amostragem.

//

chooseTimer(Ts);

//

// //se ainda nao foi feito o setup AD

//

if

(!this->ADsetup){

//

this->setupAdc();

//

}//

//

//

buff[0] = numBytes

=0x06;

//

buff[1] = 0xB1;

//

switch(channel){

//

case

0:

//

buff[2] = PIN_A0;

//

break;

//

case

1:

//

buff[2] = PIN_A1;

//

break;

//

case

2:

//

buff[2] = PIN_A2;

//

break;

//

case

3:

//

buff[2] = PIN_A3;

//

break;

//

case

4:

//

buff[2] = PIN_A4;

//

break;

//

default:

//

buff[2] = PIN_A0;

//

}//

//

//

//

buff[3] = ((unsigned int)numSamples

&0x000000ff);//LSByte first

//

buff[4] = (((unsigned int)numSamples

&0x0000ff00)

>>

8);

//

buff[5] = (((unsigned int)numSamples

&0x00ff0000)

>>

16);

//

buff[6] = (((unsigned int)numSamples

&0xff000000)

>>

24)

;//MSByte

//

for(int pn=0;

pn<numBytes+1;

pn++)

//

checksum

^=

buff[pn];

//

buff[7] = checksum;

//

buff[8] = '\0';

//

sizeBuff

=numBytes+2;

//checksum

+\0

//

//

//

//

//

//

enviaBuffer(this,buff,sizeBuff);

//

while((a

=recebeBuffer(this)) == -1);

//

if(a

!=

85){

//

printf("\nCommunication Error\n");

//

return

-1;

//

}// //vou receber 4

vezes numSamples bytes.

//

numSamples

=numSamples*4;

//

//

double iter =

0;

//

int numbyte =

0;

//

//

while

(iter

!=

numSamples){

//

while((a

=recebeBuffer(this)) == -1);

//

numbyte++;

//

//

double tempo;

//

double out;

//

//

switch(numbyte){

//

case

1:

//

out

= (double)a;

//

break;

//

case

2:

//

out

= ((double)a*256

+out)*(VREF/1023);

//

break;

//

case

3:

//

tempo

= (double)a;

//

break;

//

case

4:

//

tempo

= ((double)a*256

+tempo);

//

//

numbyte

=0;

//

break;

//

}//fim do switch

//

//

buffer[(int)floor(iter/4)] = out;

//

bufferTempos[(int)floor(iter/4)] = tempo;

//

//

iter++;

//

}//

//

// //verificar onde ocorreu o overlap dos timers

//

int overlap =

0;

//

for

(int i=0;

i<

numSamples;

i++){

//

if

(i>0)

//

if

(bufferTempos[i-1]

>(bufferTempos[i]+

overlap*65536))

//

overlap

=overlap

+1;

//

bufferTempos[i] = (bufferTempos[i] + overlap*65536);//*0.000001;

//

}//

for

(int i=0;

i<

numSamples;

i++){

//

bufferTempos[i] = bufferTempos[i]*1.6*0.000001;

//

}//

//

return

1;

//

}

//

int Myadda::chooseTimer(double Ts){

//

//

int aux=0;

//

const double PICclock =

20000000;

//

double maxPeriod =

256/(PICclock/4);

//

// //printf("\nentrei chooseTimer\n");

//

//

//

while(1){

//

if

(Ts

==

0){

//mantem o default de div_128

// //printf("\nsai\n");

//

return

1;

//

}//

if

(Ts

<=

maxPeriod){

//

aux

=1;

//

break;}

//

if

(Ts

<= (2*maxPeriod)){

//

aux

=2;

//

break;}

//

if

(Ts

<= (4*maxPeriod)){

//

aux

=4;

//

break;}

//

if

(Ts

<= (8*maxPeriod)){

//

aux

=8;

//

break;}

//

if

(Ts

<= (16*maxPeriod)){

//

aux

=16;

//

break;}

//

if

(Ts

<= (32*maxPeriod)){

//

aux

=32;

//

break;}

//

if

(Ts

<= (64*maxPeriod)){

//

aux

=64;

//

break;}

//

if

(Ts

<= (128*maxPeriod)){

//

aux

=128;

//

break;}

//

if

(Ts

<= (256*maxPeriod)){

//

aux

=256;

//

break;}

//

else{

//

printf("\nError:

period too high [max period=

0.013107

seg]\n");

//

return

-1;

//

}//

break;

//

}//

//

//

//

//

// //se for diferente do actual actualizar no PIC o time division do timer0

//

if

(aux

!=

this->timer0Div){

//

unsigned char buff[10]={0x00};

//

unsigned char numBytes,checksum=0;

//

int sizeBuff=0;

//

//

buff[0] = numBytes

=0x02;

//

buff[1] = 0xB4;

//

buff[2] = (unsigned char)(aux-1);//

//

//

for(int pn=0;

pn<numBytes+1;

pn++)

//

checksum

^=

buff[pn];

//

buff[3] = checksum;

//

buff[4] = '\0';

//

sizeBuff

=numBytes+2;

//checksum

+\0

//

//

//

int a;

//

enviaBuffer(this,buff,sizeBuff);

//

//

//

while((a

=recebeBuffer(this)) == -1);

//

if(a

!=

85){

//

printf("\nCommunication Error\n");

//

return

-1;

//

}//

this->timer0Div

=aux;

//

//

}// //calcular timeroffset baseado no time division

//

//

int timeroffset;

//

//

timeroffset

= (int)(256

- (Ts*256)/(aux*maxPeriod));

//

if

(timeroffset<0)

timeroffset

=0;

//

//

//

// //se for diferente do defauft actualizar no PIC

//

if

(timeroffset

!=

this->timer0DivTimeOut){

//

unsigned char buff[10]={0x00};

//

unsigned char numBytes,checksum=0;

//

int sizeBuff=0;

//

//

buff[0] = numBytes

=0x02;

//

buff[1] = 0xB5;

//

buff[2] = timeroffset;//

//

//

for(int pn=0;

pn<numBytes+1;

pn++)

//

checksum

^=

buff[pn];

//

buff[3] = checksum;

//

buff[4] = '\0';

//

//

sizeBuff

=numBytes+2;

//checksum

+\0

//

//

int a;

//

enviaBuffer(this,buff,sizeBuff);

//

while((a

=recebeBuffer(this)) == -1);

//

if(a

!=

85){

//

printf("\nCommunication Error\n");

//

return

-1;

//

}//

this->timer0DivTimeOut

=timeroffset;

//

}//

//

//

//

//

return

1;

//

}

int Myadda::setupAdc(){

unsigned

char buff[10]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

//printf("\nfiz o setup AD\n");

buff[0] = numBytes

=0x03;

buff[1] = 0xA8;

buff[2] = 0x89;//all analog

buff[3] = 0x87;//ADC_CLOCK_INTERNAL

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[4] = checksum;

buff[5] = '\0';

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

} this->ADsetup

=true;

return

1;

} int Myadda::inputADCTimeArray(int channel,

double*

buffer,

double*

bufferTempos,

int

bufflen,

double Ts,

int flags){

//reservar

://

amostras

= (int16)buffer[3]+(int16)buffer[4]*256;

//

u_delay

= (int16)buffer[5]+(int16)buffer[6]*256;

//

m_delay

= (int16)buffer[7]+(int16)buffer[8]*256;

double numSamples =

bufflen;//reservar buff 3 4

para int16

num amostras.

unsigned

char buff[11]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

double m_delay,u_delay=0;

double instruc_time

=0.000095;//95

if

(!this->ADsetup){

this->setupAdc();

} buff[0] = numBytes

=0x08;

buff[1] = 0xB3;

switch(channel){

case

0:

buff[2] = PIN_A0;

break;

case

1:

buff[2] = PIN_A1;

break;

case

2:

buff[2] = PIN_A2;

break;

case

3:

buff[2] = PIN_A3;

break;

case

4:

buff[2] = PIN_A4;

break;

default:

buff[2] = PIN_A0;

}

//

cout

<<

"NUM DE SAMPLES: " <<

numSamples

<<

endl;

if

(fmod(numSamples,100) != 0){

printf("\nError:

number of samples must be a multiple of 100\n");

return

-1;

} elsenumSamples

=numSamples/100;

//printf("\nAKI\n");

buff[3] = ((unsigned

int)numSamples

&0x00ff);//LSByte first

buff[4] = (((unsigned

int)numSamples

&0xff00)

>>

8);

//MSByte

double o =0;

double*

i=

&o;

Ts

=Ts

-instruc_time;

if

(Ts

<0

)Ts

=0;

//cout

<<

"Ts: " <<

Ts

<<

endl;

u_delay

= (modf((Ts*1000),i))*1000;

m_delay

= (*i);

//

cout

<<

"u_delay"

<<

u_delay

<<

endl;

//

cout

<<

"m_delay"

<<

m_delay

<<

endl;

buff[5] = ((unsigned

int)u_delay

&0x00ff);//LSByte first

buff[6] = (((unsigned

int)u_delay

&0xff00)

>>

8);

//MSByte

buff[7] = ((unsigned

int)m_delay

&0x00ff);//LSByte first

buff[8] = (((unsigned

int)m_delay

&0xff00)

>>

8);

//MSByte

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[9] = checksum;

buff[10] = '\0';

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}//vou receber 4

vezes numSamples bytes.

numSamples

=numSamples*4*100;

double iter =

0;

int numbyte =

0;

while

(iter

!=

numSamples){

while((a

=recebeBuffer(this)) == -1);

numbyte++;

double tempo;

double out;

switch(numbyte){

case

1:

out

= (double)a;

break;

case

2:

out

= ((double)a*256

+out)*(VREF/1023);

break;

case

3:

tempo

= (double)a;

break;

case

4:

tempo

= ((double)a*256

+tempo);

numbyte

=0;

break;

}//fim do switch

buffer[(int)floor(iter/4)] = out;

bufferTempos[(int)floor(iter/4)] = tempo;

iter++;

} numSamples

=numSamples/4;

//verificar onde ocorreu o overlap dos timers

int overlap =

0;

for

(int i=0;

i<

numSamples;

i++){

if

(i>0)

if

(bufferTempos[i-1]

>(bufferTempos[i]+

overlap*65536))

overlap

=overlap

+1;

bufferTempos[i] = (bufferTempos[i] + overlap*65536);//*0.000001;

} for

(int i=0;

i<

numSamples;

i++){

bufferTempos[i] = bufferTempos[i]*1.6*0.000001;

} return

1;

} int Myadda::input2ADCArray(int channel,

double*

buffer,

double*

buffer2,

int bufflen,

double Ts,

int flags){

//reservar

://

amostras

= (int16)buffer[3]+(int16)buffer[4]*256;

//

u_delay

= (int16)buffer[5]+(int16)buffer[6]*256;

//

m_delay

= (int16)buffer[7]+(int16)buffer[8]*256;

double numSamples =

bufflen;//reservar buff 3 4

para int16

num amostras.

unsigned

char buff[11]={0x00};

unsigned

char numBytes,checksum=0;

int sizeBuff=0;

int a;

double m_delay,u_delay=0;

double instruc_time

=0.000095;//95

if

(!this->ADsetup){

this->setupAdc();

} buff[0] = numBytes

=0x08;

buff[1] = 0xB7;

switch(channel){

case

0:

buff[2] = PIN_A0;

break;

case

1:

buff[2] = PIN_A1;

break;

case

2:

buff[2] = PIN_A2;

break;

case

3:

buff[2] = PIN_A3;

break;

case

4:

buff[2] = PIN_A4;

break;

default:

buff[2] = PIN_A0;

} //cout

<<

"NUM DE SAMPLES: " <<

numSamples

<<

endl;

if

(fmod(numSamples,100) != 0){

printf("\nError:

number of samples must be a multiple of 100\n");

return

-1;

} elsenumSamples

=numSamples/100;

buff[3] = ((unsigned

int)numSamples

&0x00ff);//LSByte first

buff[4] = (((unsigned

int)numSamples

&0xff00)

>>

8);

//MSByte

double o =0;

double*

i=

&o;

Ts

=Ts

-instruc_time;

if

(Ts

<0

)Ts

=0;

//cout

<<

"Ts: " <<

Ts

<<

endl;

u_delay

= (modf((Ts*1000),i))*1000;

m_delay

= (*i);

//

cout

<<

"u_delay"

<<

u_delay

<<

endl;

//

cout

<<

"m_delay"

<<

m_delay

<<

endl;

buff[5] = ((unsigned

int)u_delay

&0x00ff);//LSByte first

buff[6] = (((unsigned

int)u_delay

&0xff00)

>>

8);

//MSByte

buff[7] = ((unsigned

int)m_delay

&0x00ff);//LSByte first

buff[8] = (((unsigned

int)m_delay

&0xff00)

>>

8);

//MSByte

for(int pn=0;

pn<numBytes+1;

pn++)

checksum

^=

buff[pn];

buff[9] = checksum;

buff[10] = '\0';

sizeBuff

=numBytes+2;

//checksum

+\0

enviaBuffer(this,buff,sizeBuff);

while((a

=recebeBuffer(this)) == -1);

if(a

!=

85){

printf("\nCommunication Error\n");

return

-1;

}//vou receber 4

vezes numSamples bytes.

numSamples

=numSamples*4*100;

double iter =

0;

int numbyte =

0;

while

(iter

!=

numSamples){

while((a

=recebeBuffer(this)) == -1);

numbyte++;

double out2;

double out;

switch(numbyte){

case

1:

out

= (double)a;

break;

case

2:

out

= ((double)a*256

+out)*(VREF/1023);

break;

case

3:

out2

= (double)a;

break;

case

4:

out2

= ((double)a*256

+out2)*(VREF/1023);

numbyte

=0;

break;

}//fim do switch

buffer[(int)floor(iter/4)] = out;

buffer2[(int)floor(iter/4)] = out2;

iter++;

} return

1;

} int Myadda::inputADCArray(int channel,

double*

buffer,

int bufflen,

double Ts,

int flags){

double*

tempo;

tempo

= (double

*)malloc(sizeof(double)*bufflen);

inputADCTimeArray(channel,

buffer,

tempo,

bufflen,

Ts,

flags);

free(tempo);

return

1;

}

//programa teste

#include

"myadda.h"

#ifdef MATLAB_MEX

#include

"mex.h"

#endif

//extern void main();

using

namespace std;

void comMain(double sample_freq,int numero_de_amostras,double*

V,double*

tempo){

Myadda x;

vector<string>

abd;

string s;

/*

double signal[96]={128,143,159,162,171,174,

188,201,204,206,213,216,

218,234,236,237,242,243,

246,247,248,252,254,255,

255,255,255,252,249,248,

246,240,239,230,224,222,

218,209,206,200,193,185,182,

176,165,162,146,134,

128,115,112,

96,

87,

84,

79,

64,

62,

46,

44,

42,

39,

37,

29,

27,

18,

12,

9,

4,

3,

0,

0,

0,

3,

4,

5,

6,

7,

8,

9,

16,

23,

25,

27,

35,

37,

56,

59,

73,

76,

79,

103,106,109,115,121,124};

*/

double signal[96]={

0,

0,

1,

3,

4,

7,

10,

13,

17,

22,

27,

32,

38,

44,

51,

58,

65,

72,

80,

88,

96,

104,

113,

121,

130,

138,

146,

155,

163,

171,

179,

186,

194,

201,

207,

214,

220,

225,

231,

235,

240,

243,

247,

249,

252,

253,

254,

255,

255,

254,

253,

252,

249,

247,

243,

240,

235,

231,

225,

220,

214,

207,

201,

194,

186,

179,

171,

163,

155,

146,

138,

130,

121,

113,

104,

96,

88,

80,

72,

65,

58,

51,

44,

38,

32,

27,

22,

17,

13,

10,

7,

4,

3,

1,

0,

0};

/*double signal[85]=

{128

,134

,140

,146

,152

,158

,164

,170

,176

,182,

188

,194

,200

,206

,212

,218

,224

,230,

236

,242,

248

,254

,248

,242

,236

,230

,224

,218

,212

,206

,200,

194

,188

,182

,176

,170

,164

,158

,152,

146

,140

,134

,128

,122

,116

,110

,104

,98

,92

,86

,80

,74,

68

,62

,56

,50

,44,

38

,32

,26

,20

,14

,8

,2,

8,

14

,20

,26

,32

,38

,44

,50

,56

,62

,68

,74

,80

,86

,92,

98,

104,

110

,116

,122

,128};*/

/*double signal[4] = {128,255,128,0};*/

//

prealocacao de memoria para as tensoes lidas no ADC e

//

tempos correspondentes

double

*output

=new

double[numero_de_amostras];

double

*tempo_f

=new

double[numero_de_amostras];

//inicializacao dos buffers de memoria

for

(int i=

0;i<numero_de_amostras;i++){

output[i] = 0;

tempo_f[i] = 0;

}

//*************************************************************************************

//*************************************************************************************

//

listDevices() - devolve um vector de strings com os descritores dos dispositivos

//

detectados

//

//

listDevices()

para escolher o dispositivo pretendido no caso de varios dispositivos

//

ligados:

//

devolve por ex: "DPR47P0FB" (difere de dispositivo para dispositivo,

configuravel

//

com o Mprog)

//

ou

"VID_0403+PID_6010" (VID e PID caracteristico das FTDI's)

//-------------------------------------------------------------------------------------

abd

=x.listDevices();

printf("\n");

if

(abd.empty())

return;

for

(vector<string>::const_iterator p =

abd.begin( );p

!=

abd.end( );

++p){

printf

(((string)*p).c_str());

printf("\n");

s= (string)*p;

}printf("\n");

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

connect(const char*) - conecçao com o dispositivo

//

//connect(NULL) ->>

com argumento NULL conecta-se ao 1º dispositivo FTDI encontrado

//connect(const char*

caminho) ->>

conecta-se ao dispositivo definido em "caminho"

// "caminho"

pode ser "COM1"

a"COM9" (palavras reservadas,ver a COMx no gestor de

//

dispositivos do windows)

//

ou a HKEY_LOCAL_MACHINE

(para COMx com x>9)

//"\\?\ftdibus#vid_0403+pid_6010+dpr47p0fb#0000#{4d36e978-e325-11ce-bfc1-08002be10318}"

//

esta HKEY_LOCAL_MACHINE é retornada pela funcao deviceHandler(const char*

desc)

//

onde

"desc"

é uma das strings obtidas por listDevices()

//-------------------------------------------------------------------------------------

//x.connect(NULL);

//-------------------------------------------------------------------------------------

cout

<<

"MAIN descritor do device:"

<<

s<<

endl;

s= (x.deviceHandler(s.c_str()));

cout

<<

"MAIN device handler:"

<<

s<<

endl;

x.connect(s.c_str());

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

//

bool digitalOutput(unsigned char v,

unsigned char channel);

//

//

forçar porto ou pin do PIC a 1

ou

0.

//-------------------------------------------------------------------------------------

/*//256

novo

1 0000 0000

->

ultimos

8bits

cout

<<

"devolveu

: " <<

x.digitalOutput(255,PortCwrite)<<

endl;

//

colocar pinX a 0

ou

1->

converte para 0

ou

1cout

<<

"devolveu

: " <<

x.digitalOutput(0,PIN_A0)<<

endl;

*/ //************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

//

bool digitalInput(unsigned char channel);

//

//

ler porto ou pin do PIC a 1

ou

0.

//-------------------------------------------------------------------------------------

/*

//le

8bits de um porto A C ou D

cout

<<

"devolveu

: " <<

x.digitalInput(PortCread)<<

endl;

cout

<<

"devolveu

: " <<

x.digitalInput(PIN_A1)<<

endl;

//le

1bit/pino

*/

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

//

double ADC(int channel);

//

//

leitura da tensao analogica 0

a5.12V

//-------------------------------------------------------------------------------------

/*cout

<<

"ADC

0: " <<

x.ADC(0)<<

endl;

//pin num 4

cout

<<

"ADC

1: " <<

x.ADC(1)<<

endl;

//pin num 5

cout

<<

"ADC

2: " <<

x.ADC(2)<<

endl;

//pin num 6

cout

<<

"ADC

3: " <<

x.ADC(3)<<

endl;

//pin num 7

cout

<<

"ADC

4: " <<

x.ADC(4)<<

endl;

//pin num 9

(pin

8do DLP não é ADC)

cout

<<

"ADC default: " <<

x.ADC(10)<<

endl;

//default pin num 4

*/

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

//

int DAC(int channel,double value){

//

//

coloca tensao analogica com o conversor DAC channel 0

ou

1,

tensões entre 0

e4.096V

//-------------------------------------------------------------------------------------

/*cout

<<

"DAC

0: " <<

x.DAC(0)<<

endl;

cout

<<

"DAC

1: " <<

x.DAC(1)<<

endl;

*/

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

//int outputDACArray(int channel,

double*

buffer,

int bufflen,

double Ts,int nTimes,...

//

int flags);

//

//

void outputDACArrayStop();

//

// -gerar sinal com os DAC em background do pic com periodo Ts e nTimes numero de vezes

//

// -se nao interessar nTimes ==

NULL,

então parar a geração do sinal com STOP

//-------------------------------------------------------------------------------------

/*

x.outputDACArray(NULL,

signal,

(int)(sizeof(signal)/sizeof(double)),

0.01

,500,

1);

x.outputDACArrayStop();

*/

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//*************************************************************************************

//

//com timedelays DAC

//

int inputADCArray(int channel,

double*

buffer,

int bufflen,

double Ts,

int flags);

//

// //comentado no codigo pois optou-se pela solução com time delays

//

//com ISR DAC+tempo

//

int Myadda::inputADCArray(int channel,

double*

buffer,

double*

bufferTempos,...

//

int bufflen,

double Ts,

int flags);

//

//

//com timedelays DAC+tempo

//

int inputADCTimeArray(int channel,

double*

buffer,

double*bufferTempos,

...

//

int bufflen,

double Ts,

int flags);

//

//

//com timedelays DAC +

DAC

//

int input2ADCArray(int channel,

double*

buffer,

double*

buffer2,

int bufflen,...

//

double Ts,

int flags);

//

//-------------------------------------------------------------------------------------

/*

x.inputADCArray(0,

output,

numero_de_amostras,

0.0005,

0);

//x.inputADCArray(0,

output,

tempo_f,

numero_de_amostras,

0.0005,

0);

//unico com ISR!!

x.input2ADCArray(0,

output,

output2,

numero_de_amostras,

0.00005,

0);

x.inputADCTimeArray(0,

output,

tempo_f,

numero_de_amostras,

0.00005,

0);

*/

//*************************************************************************************

//*************************************************************************************

cout

<<

"numero_de_amostras: "

<<

numero_de_amostras

<<

endl;

cout

<<

"numero de elementos do signal: "

<<

sizeof(signal)/sizeof(double)

<<

endl;

if(x.outputDACArray(NULL,

signal,

(int)(sizeof(signal)/sizeof(double)),

1/(double)

sample_freq

,NULL,

1) != -1){

x.input2ADCArray(0,

output,

tempo_f,

numero_de_amostras,

0.00005,

0);

//x.inputADCTimeArray(0,

output,

tempo_f,

numero_de_amostras,

0.05,

0);

//parar a geração do sinal periodico.

x.outputDACArrayStop();

} //preencher as matrizes com as tensoes e tempos adquiridos

for

(int i=0;

i<

numero_de_amostras;

i++)

V[i] = output[i];

for

(int i=0;

i<

numero_de_amostras;

i++)

tempo[i] = tempo_f[i];

delete[]

output;

delete[]

tempo_f;

cout

<<

"MAIN saida"

<<

endl;

} #ifdef MATLAB_MEX

void mexFunction(int nlhs,

mxArray

*plhs[],int nrhs,

const mxArray *prhs[])

{double

*numero_de_amostras,*V,*tempo;

double

*sample_time;

/*

check for proper number of arguments */

if(nrhs!=2)

mexErrMsgTxt("Sao necessarios dois argumentos de entrada,

ie. [Vc(t),tempo] = teste

(sample_time,numero_de_amostras)");

/*

check to make sure the first input argument is a scalar */

if( !mxIsDouble(prhs[1])

||

mxIsComplex(prhs[1])

||

mxGetN(prhs[1])*mxGetM(prhs[1])!=1

){

mexErrMsgTxt("Segundo argumento tem que ser um escalar");

} sample_time

= (double

*)

mxGetPr(prhs[0]);

numero_de_amostras

= (double

*)

mxGetPr(prhs[1]);

plhs[0] = mxCreateDoubleMatrix((int)*numero_de_amostras,1,

mxREAL);

plhs[1] = mxCreateDoubleMatrix((int)*numero_de_amostras,1,

mxREAL);

V=

mxGetPr(plhs[0]);

tempo

=mxGetPr(plhs[1]);

comMain(*sample_time,(int)*numero_de_amostras,V,tempo);

return;

} #else

//

not defined MATLAB_MEX

:

int main()

{

double numero_de_amostras;

double sample_time;

cout

<<

"introduza o numero amostras:"

<<

endl;

cin

>>

numero_de_amostras;

cout

<<

"introduza a frequencia:"

<<

endl;

cin

>>

sample_time;

double

*V

=new

double[(int)numero_de_amostras];

double

*tempo

=new

double[(int)numero_de_amostras];

comMain(sample_time,(int)numero_de_amostras,V,tempo);

/*

o código que faria o programa funcionar deveria estar aqui */

cout

<<

"press

1and return to end program..."

<<

endl;

int a;

cin

>>

a;

return

0;

}

#endif

50 Software de interface para PC

Apendice D

Software do microcontrolador

Para o PC comunicar com o microcontrolador foi implementado um protocolo de comunicacao baseado numbuffer de dados de tamanho fixo. Este buffer e enviado via USB ao microcontrolador que posteriormente retornauma resposta da correcta ou ma recepcao do mesmo, tal permite verificar se os dados nao sofreram alteracoes e por-tanto nao estao corrompidos. O buffer transmitido tem dois bytes de controlo para garantir a correcta comunicacao.O primeiro byte corresponde ao numero de bytes que vao ser enviados ao microcontrolador e o ultimo byte e umachecksum ou soma de verificacao, que corresponde a um XOR (Ou exclusivo) bit a bit de todos os bytes enviadosnesse buffer. Com estes dois bytes de controlo consegue-se garantir a correcta comunicacao de dados entre o PC eo microcontrolador, bem como a deteccao de erros.

#include

<16F877A.H>

#device ADC=10

#fuses HS,WDT,NOPUT,NOBROWNOUT,LVP,NOWRT,NOPROTECT

#use delay(clock=20000000,restart_wdt)

//#include

<STDLIBM.H>

para mallocs.

#define set_bit(reg,

bit)

reg

|=

bit

#define clear_bit(reg,

bit)

reg

&=

~(bit)

//#byte ADCON0

=0x1F//A/D Control Register 0

//#byte ADCON1

=0x9F//A/D Control Register 1

//#byte ADRESH =

0x1E//A/D data register

//#byte ADRESL =

0x9E//A/D data register

#define WR PIN_B2

#define RD PIN_B1

#define SND PIN_E1

#define TXE PIN_E2

#define RXF PIN_B4

#define LED PIN_E0

#priority timer2,timer0

int8

led_state;

int16

led_count;

volatile int8

buffer[10];

int8

D_Data;

int8

D_Error;

int8

D_Presence;

int8

D_SC;

int8

packet_ready;

int8

d_pin;

volatile int32

contador;

//volatile int32

contador2

=0;

volatile int32

AUX;

//numero de amostras adquiridas ---

passar como parametro

//maximo

254

minimo

0este valor é o default para interrupçoes de 0.5ms

volatile int8

offset_timer

=0;

volatile int8

offset_timer_2

=161;

//offset timer2

para as ISR dos DAC's

int8

postscale

=1;

//default

volatile int16

num_isr

=1;

volatile int16

contador2

=0;

volatile int8

signal[96];

volatile int8

i=

0;

volatile int8

sizelim

=96;

/*volatile int8

signal[96]={128,143,159,162,171,174,

188,201,204,206,213,216,

218,234,236,237,242,243,

246,247,248,252,254,255,

255,255,255,252,249,248,

246,240,239,230,224,222,

218,209,206,200,193,185,182,

176,165,162,146,134,

128,115,112,

96,

87,

84,

79,

64,

62,

46,

44,

42,

39,

37,

29,

27,

18,

12,

9,

4,

3,

0,

0,

0,

3,

4,

5,

6,

7,

8,

9,

16,

23,

25,

27,

35,

37,

56,

59,

73,

76,

79,

103,106,109,115,121,124};

*/

void send(int8

thebyte);

int8

read_usb();

void receive_packet();

int8

Read_byte(void);

void D_Reset(void);

void Write_byte(int8

Data);

void make_low(int8

pin_to_use);

void make_high(int8

pin_to_use);

int8

get_line_in(int8

pin_to_use);

void setup_AD();

void run_AD();

void strobe_SND();

void toggle_led();

void funcao_sample();

void funcao_2adc(int8

channel);

void timer0_isr();

void timer1_isr();

#INT_DEFAULT

//quando ocorre um interrupt nao programado

void time_isr(){

} //gerar o sinal para o DAC

#INT_TIMER2

void timer2_isr(){

int16

aux=0;

disable_interrupts(INT_TIMER2);

contador2++;

if

(contador2

==

num_isr){

aux

= ((int16)signal[i])*16;

//converter

8bits em 12bits

output_low(PIN_C2);

if

(aux

<=

255){

spi_write(16);

spi_write(aux);

}else{

spi_write((int8)((int8)16

+ (int8)(aux

>>

8)));

spi_write((int8)(aux

&0x00ff));

}output_high(PIN_C2);

i++;

if

(i

==

sizelim)

i=

0;

contador2

=0;

} enable_interrupts(INT_TIMER2);

} #INT_TIMER0

void timer0_isr()

{

//static int16

enbia;

static int16

dataword1;

static int16

tempos1;

disable_interrupts(INT_TIMER0);

contador++;

set_timer0(offset_timer

+get_timer0());

dataword1

=read_adc();

while(input(TXE)==1);

output_d((int8)(dataword1

&0x00ff));

output_low(WR);

output_high(WR);

while(input(TXE)==1);

output_d((int8)(dataword1

>>

8));

output_low(WR);

output_high(WR);

tempos1

=get_timer1();

while(input(TXE)==1);

output_d((int8)(tempos1

&0x00ff));

output_low(WR);

output_high(WR);

while(input(TXE)==1);

output_d((int8)(tempos1

>>

8));

output_low(WR);

output_high(WR);

output_low(SND);

output_high(SND);

enable_interrupts(INT_TIMER0);

} //********************************************************************

void main()

{int8

databit,

tt;

//float fret;

//char string[30],

term[3],

*ptr;

//initialize EEPROM locations with data

#rom

0x2100={1,2,3,4,5,6,7,8}

#rom

0x2108={9,10,11,12,13,14,15,16}

#rom

0x2110={17,18,19,20,21,22,23,24}

#rom

0x2118={25,26,27,28,29,30,31,32}

#rom

0x21fe={1,2}

//1111 1111 port A idle state:

7654 3210 1=input

0=output

SET_TRIS_A(

0xff

);//all input

//1111 1111 port B idle state:

7654 3210 1=input

0=output

SET_TRIS_B(

0xff

);//all input

//0011 0000 port C idle state:

7654 3210 1=input

0=output

SET_TRIS_C(

0xff

);

//1111 1111 port D idle state:

7654 3210 1=input

0=output

SET_TRIS_D(

0xff

);//all input

//1111 1111 port E idle state:

7654 3210 1=input

0=output

SET_TRIS_E(

0xff

);//all input

setup_adc_ports(

NO_ANALOGS

);//default to all digital I/O

setup_adc(ADC_OFF

);//disable the A/D converter

output_high(WR);//init USB WR

output_high(RD);//init USB RD

output_high(SND);//init SND

delay_ms(100);

//default's

:setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_128);

setup_wdt(WDT_2304MS);

if(!input(RXF))//purge USB FIFO

{output_low(RD);

output_high(RD);

} for(tt=0;

tt<10;

tt++)

{

RESTART_WDT();

delay_ms(40);

output_high(LED);

delay_ms(40);

output_low(LED);

}//leave the LED on

while(1)

{RESTART_WDT();

toggle_led();

//byte received in FIFO buffer...

if(!input(RXF))

{receive_packet();

//if Line in command...

//**********************************************

if(buffer[1] == 0xA5)

{databit

=get_line_in(buffer[2]);

send(databit);

strobe_SND();//send now

buffer[1] = 0;

continue;

} //if Line out command...

//**********************************************

if(buffer[1] == 0xA6)

{if(buffer[3])//if high requested

make_high(buffer[2]);

else

make_low(buffer[2]);//low requested

buffer[1] = 0;

continue;

} //if Return Board ID command...

//**********************************************

if(buffer[1] == 0xA7)

{send('2');

send('2');

send('3');

send('2');

send('P');

send('B');

strobe_SND();//send now

buffer[1] = 0;

continue;

} //if Setup A/D command...

//**********************************************

if(buffer[1] == 0xA8)

{setup_AD();

buffer[1] = 0;

continue;

} //if run A/D command...

//**********************************************

if(buffer[1] == 0xA9)

{run_AD();

buffer[1] = 0;

continue;

} //if EEPROM Read

//**********************************************

if(buffer[1] == 0xAA)

{send(

read_EEPROM(buffer[2]) );

strobe_SND();//send now

buffer[1] = 0;

continue;

} //if EEPROM Write

//**********************************************

if(buffer[1] == 0xAB)

{write_eeprom(buffer[2],

buffer[3]);

buffer[1] = 0;

continue;

} //if temperature start convert command

//**********************************************

if(buffer[1] == 0xAC)//start convert

{d_pin

=buffer[2];

D_Reset();

if(D_Error

<99)

{send(D_Error);//return error

continue;

} else send(0x63);//return no error (99)

Write_byte(0xcc);//skip rom command

Write_byte(0x44);//Convert temperatures

buffer[1] = 0;

continue;

} //if temperature read command -

//**********************************************

if(buffer[1] == 0xAD)//READ DATA

{d_pin

=buffer[2];

D_Reset();

Write_byte(0xcc);//skip rom command

Write_byte(0xbe);//read scratch pad

delay_us(5);

for(tt=0;

tt<9;

tt++)

send(Read_byte());

strobe_SND();//send now

buffer[1] = 0;

continue;//probably not needed

} //if Loopback test

//**********************************************

if(buffer[1] == 0xAF)

{send(buffer[2]);

strobe_SND();//send now

buffer[1] = 0;

continue;

} //if Port C read

//**********************************************

if(buffer[1] == 0x59)

{send(

input_c() );

buffer[1] = 0;

strobe_SND();//send now

continue;

} //if Port C write

//**********************************************

if(buffer[1] == 0x5A)

{output_c(buffer[2]);

buffer[1] = 0;

continue;

} //if Port A read

//**********************************************

if(buffer[1] == 0x55)

{send(

input_a() );

buffer[1] = 0;

strobe_SND();//send now

continue;

} //if Port A write

//**********************************************

if(buffer[1] == 0x56)

{output_a(buffer[2]);

buffer[1] = 0;

continue;

} //if Port D read

//**********************************************

if(buffer[1] == 0x5B)

{send(

input_d() );

buffer[1] = 0;

strobe_SND();//send now

continue;

} //if Port D write

//**********************************************

if(buffer[1] == 0x5C)

{output_d(buffer[2]);

buffer[1] = 0;

continue;

} //funcao teste ADC com ISR:

input:

contador-num amostras

//

offset_timer-

define tempo entre amostras

//**********************************************

if(buffer[1] == 0xB1)

{

set_adc_channel(

buffer[2] );

//NUMERO DE AMOSTRAS.

AUX

= (int32)buffer[3]+(int32)buffer[4]*256+(int32)buffer[5]*65536+(int32)

buffer[6]*16777216;

contador=0;

delay_us(10);

setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

SET_TRIS_D(

0x0

);//all output

set_timer1(0);

set_timer0(256);

enable_interrupts

(INT_TIMER0);

enable_interrupts(GLOBAL);

while(contador

!=

AUX)

restart_wdt();

//disable_interrupts(GLOBAL);

disable_interrupts(INT_TIMER0);

clear_interrupt(INT_TIMER0);

SET_TRIS_D(

0xff

);//all input

buffer[1] = 0;

buffer[2] = 0;

buffer[3] = 0;

buffer[4] = 0;

buffer[5] = 0;

buffer[6] = 0;

continue;

}

//funcao PWM -

falta conseguir reduzir os timers(reduzir a frequencia)

//**********************************************

/*if(buffer[1] == 0xB2)

{

setup_ccp1(CCP_PWM_PLUS_2);

//

Configure CCP1

as a PWM

setup_ccp2(CCP_PWM_PLUS_2);

//

Configure CCP1

as a PWM

setup_timer_2(T2_DIV_BY_1,

2,

1);

set_pwm1_duty(1);

set_pwm2_duty(1);

buffer[1] = 0;

continue;

} */

//funcao teste ADC multiplos de 100,

num de amostras =

buffer[2]*100

//**********************************************

if(buffer[1] == 0xB3){

int32

count;

int16

i;

int16

amostras;

int16

m_delay;

int16

u_delay;

setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

set_adc_channel(

buffer[2] );

delay_us(10);

amostras

= (int16)buffer[3]+(int16)buffer[4]*256;

u_delay

= (int16)buffer[5]+(int16)buffer[6]*256;

m_delay

= (int16)buffer[7]+(int16)buffer[8]*256;

set_timer1(0);

for(i=1;

i<=amostras;

i++)

for(count=1;

count<=100;

count++)

{ funcao_sample();

if

(count==100){

strobe_SND();//send now

if

(u_delay!=0)

delay_us(u_delay);

if

(m_delay!=0)

delay_ms(m_delay);

} else{

delay_us(10);//compensar SND

if

(u_delay!=0)

delay_us(u_delay);

if

(m_delay!=0)

delay_ms(m_delay);

} }

buffer[1] = 0;

buffer[2] = 0;

buffer[3] = 0;

buffer[4] = 0;

buffer[5] = 0;

buffer[6] = 0;

buffer[7] = 0;

buffer[8] = 0;

continue;

}

//actualizar timer0

division

if(buffer[1] == 0xB4){

if(buffer[2] == 0x00)

setup_timer_0(RTCC_INTERNAL);

if(buffer[2] == 0x01)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_2);

if(buffer[2] == 0x03)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_4);

if(buffer[2] == 0x07)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_8);

if(buffer[2] == 0x0F)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_16);

if(buffer[2] == 0x1F)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_32);

if(buffer[2] == 0x3F)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_64);

if(buffer[2] == 0x7F)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_128);

if(buffer[2] == 0xFF)

setup_timer_0(RTCC_INTERNAL

|RTCC_DIV_256);

buffer[1]=0;

buffer[2]=0;

continue;

} //actualizar timer0

offset

if(buffer[1] == 0xB5){

offset_timer

=buffer[2];

buffer[1]=0;

buffer[2]=0;

continue;

} //funcao teste output DAC

//**********************************************

if(buffer[1] == 0xB6){

output_high(PIN_C2);

setup_spi(spi_master

|spi_h_to_l

|SPI_CLK_DIV_16);

//ensure that the CS line starts high

delay_us(20);

//definir freq de output dos DAC's

setup_timer_2(T2_DIV_BY_16,

offset_timer_2,

postscale);//freq

=312.5

kHz

//gerar

1ª ISR

set_timer2(255);

enable_interrupts(INT_TIMER2);

enable_interrupts(GLOBAL);

buffer[1] = 0;

continue;

} //2

ADC's em "simultaneo" (para o diagrama de bode)

if(buffer[1] == 0xB7){

int32

count;

int16

i;

int16

amostras;

int16

m_delay;

int16

u_delay;

amostras

= (int16)buffer[3]+(int16)buffer[4]*256;

u_delay

= (int16)buffer[5]+(int16)buffer[6]*256;

m_delay

= (int16)buffer[7]+(int16)buffer[8]*256;

set_timer1(0);

for(i=1;

i<=amostras;

i++)

for(count=1;

count<=100;

count++)

{funcao_2adc(buffer[2]);

if

(count==100){

strobe_SND();//send now

if

(u_delay!=0)

delay_us(u_delay);

if

(m_delay!=0)

delay_ms(m_delay);

} else{

delay_us(10);//compensar SND

if

(u_delay!=0)

delay_us(u_delay);

if

(m_delay!=0)

delay_ms(m_delay);

}}

buffer[1] = 0;

buffer[2] = 0;

buffer[3] = 0;

buffer[4] = 0;

buffer[5] = 0;

buffer[6] = 0;

buffer[7] = 0;

buffer[8] = 0;

continue;

} //

DAC de uma amostra sem ISR

if(buffer[1] == 0xB8){

int16

aux;

int8

port;

if(buffer[2] == 0)

port

=16;

//DAC A

else port

=144;

//DAC B

aux

= ((int16)buffer[3])*16;

//converter

8bits em 12bits

output_high(PIN_C2);

setup_spi(spi_master

|spi_h_to_l

|SPI_CLK_DIV_16

);

//ensure that the CS line starts high

delay_us(20);

output_low(PIN_C2);

if

(aux

<=

255){

spi_write(port);

spi_write(aux);

delay_us(1);

}else{

spi_write((int8)((int8)port

+ (int8)(aux

>>

8)));

spi_write((int8)(aux

&0x00ff));

delay_us(1);

}output_high(PIN_C2);

continue;

}

//

parar as interrupçoes dos DAC's

if(buffer[1] == 0xB9){

disable_interrupts(INT_TIMER2);

clear_interrupt(INT_TIMER2);

num_isr

=1;

contador2

=0;

//por a zero

output_high(PIN_C2);

setup_spi(spi_master

|spi_h_to_l

|SPI_CLK_DIV_16

);

//ensure that the CS line starts high

delay_us(20);

output_low(PIN_C2);

spi_write(0);

spi_write(0);

delay_us(1);

output_high(PIN_C2);

buffer[1]=0;

continue;

} //definir tempos de amostragem do sinal gerado

if(buffer[1] == 0xC1){

offset_timer_2

=buffer[2];

postscale

=buffer[3];

num_isr

= (int16)buffer[4]+(int16)buffer[5]*256;

buffer[1]=0;

buffer[2]=0;

buffer[3]=0;

buffer[4]=0;

buffer[5]=0;

continue;

} //preencher o array para gerar o sinal

if(buffer[1] == 0xC2){

int8

num_bytes,pos2;

sizelim

=buffer[2];

while(1){

RESTART_WDT();

//byte received in FIFO buffer...

if(!input(RXF)){

num_bytes

=sizelim;

pos2=0;

while(num_bytes--)

signal[pos2++]=read_usb();

break;

}} buffer[1]=0;

buffer[2]=0;

continue;

}

}//end of if(!RXF)

}//end of while(1)

}//end of main()

//***********************************************************

void toggle_led()

{led_count++;

if(led_count

>60000)

{led_count=0;

//toggle LED

if(led_state==0)

{led_state=1;

output_low(LED);

}else

{led_state=0;

output_high(LED);

}}

} /*

//////////////////////////////////////////////////////////////////

ADC

//

ADC Functions:

SETUP_ADC(),

SETUP_ADC_PORTS() (aka SETUP_PORT_A),

//

SET_ADC_CHANNEL(),

READ_ADC()

//

Constants used for SETUP_ADC()

are:

#define ADC_OFF

0//

ADC Off

#define ADC_CLOCK_DIV_2 0x10000

#define ADC_CLOCK_DIV_4 0x4000

#define ADC_CLOCK_DIV_8 0x0040

#define ADC_CLOCK_DIV_16 0x4040

#define ADC_CLOCK_DIV_32 0x0080

#define ADC_CLOCK_DIV_64 0x4080

#define ADC_CLOCK_INTERNAL

0x00c0

//

Internal

2-6us

//

Constants used in SETUP_ADC_PORTS()

are:

#define ALL_ANALOG

0//

A0

A1

A2

A3

A5

E0

E1

E2

#define AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF

1//

A0

A1

A2

A5

E0

E1

E2

VRefh=A3

#define AN0_AN1_AN2_AN3_AN4 2

//

A0

A1

A2

A3

A5

#define AN0_AN1_AN2_AN4_VSS_VREF

3//

A0

A1

A2

A5

VRefh=A3

#define AN0_AN1_AN3 4

//

A0

A1

A3

#define AN0_AN1_VSS_VREF

5//

A0

A1

VRefh=A3

#define NO_ANALOGS

7//

None

#define AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF

0x08

//

A0

A1

A5

E0

E1

E2

VRefh=A3

VRefl=A2

#define AN0_AN1_AN2_AN3_AN4_AN5 0x09

//

A0

A1

A2

A3

A5

E0

#define AN0_AN1_AN2_AN4_AN5_VSS_VREF

0x0A

//

A0

A1

A2

A5

E0

VRefh=A3

#define AN0_AN1_AN4_AN5_VREF_VREF

0x0B

//

A0

A1

A5

E0

VRefh=A3

VRefl=A2

#define AN0_AN1_AN4_VREF_VREF

0x0C

//

A0

A1

A5

VRefh=A3

VRefl=A2

#define AN0_AN1_VREF_VREF

0x0D

//

A0

A1

VRefh=A3

VRefl=A2

#define AN0 0x0E

//

A0

#define AN0_VREF_VREF

0x0F

//

A0

VRefh=A3

VRefl=A2

*/

//**********************************************************************

void setup_AD()//0xA8

{switch

(buffer[2])//selects which I/Os on port A are analog in and which are digital I/O

{ case

137:

setup_adc_ports(

0);//See above for description:0=ALL_ANALOG:A0

A1

A2

A3

A5

E0

E1

E2

break;

case

138:

setup_adc_ports(

1);

break;

case

139:

setup_adc_ports(

2);

break;

case

132:

setup_adc_ports(

3);

break;

case

140:

setup_adc_ports(

4);

break;

case

141:

setup_adc_ports(

5);

break;

case

142:

break;

case

143:

setup_adc_ports(

7);

break;

case

144:

setup_adc_ports(

8);

break;

case

145:

setup_adc_ports(

9);

break;

case

0xa:

setup_adc_ports(

0x0a

);

break;

case

0xb:

setup_adc_ports(

0x0b

);

break;

case

0xc:

setup_adc_ports(

0x0c

);

break;

case

0xd:

setup_adc_ports(

0x0d

);

break;

case

0xe:

setup_adc_ports(

0x0e

);

break;

case

0xf:

setup_adc_ports(

0x0f

);

break;

default:

setup_adc_ports(

0);

} switch

(buffer[3])//selects A/D clock source

{ case

128:

setup_adc(

ADC_OFF

);

break;

case

129:

setup_adc(

ADC_CLOCK_DIV_2

);

break;

case

130:

setup_adc(

ADC_CLOCK_DIV_4

);

break;

case

131:

setup_adc(

ADC_CLOCK_DIV_8

);

break;

case

132:

setup_adc(

ADC_CLOCK_DIV_16

);

break;

case

133:

setup_adc(

ADC_CLOCK_DIV_32

);

break;

case

134:

setup_adc(

ADC_CLOCK_DIV_64

);

break;

case

135:

setup_adc(

ADC_CLOCK_INTERNAL

);

break;

}} //**********************************************************************

void funcao_2adc(int8

channel)//0xB7

{int16

dataword1;

int16

dataword2;

set_adc_channel(

channel

);

delay_us(10);

dataword1

=read_adc();

send((int8)(dataword1

&0x00ff));//LSByte

send((int8)(dataword1

>>

8));//MSByte

set_adc_channel( ++channel

);

delay_us(10);

dataword2

=read_adc();

send((int8)(dataword2

&0x00ff));//LSByte

send((int8)(dataword2

>>

8));//MSByte

} //**********************************************************************

void funcao_sample()//0xB1

{int16

dataword;

int16

tempos;

dataword

=read_adc();

send((int8)(dataword

&0x00ff));//LSByte

send((int8)(dataword

>>

8));//MSByte

tempos

=get_timer1();

send((int8)(tempos

&0x00ff));//LSByte

send((int8)(tempos

>>

8));//MSByte

} //**********************************************************************

void run_AD()//0xA9

{int16

dataword;

set_adc_channel(

buffer[2] );

delay_us(10);

dataword

=read_adc();

//return as two bytes to host -

LSByte first

send((int8)(dataword

&0x00ff));//LSByte

send((int8)(dataword

>>

8));//MSByte

strobe_SND();//send now

} //**********************************************************************

int8

get_line_in(int8

pin_to_use)

{int8

data;

switch(pin_to_use)

{case PIN_A0

:data

= (int8)input(PIN_A0);

break;

case PIN_A1

:data

= (int8)input(PIN_A1);

break;

case PIN_A2

:data

= (int8)input(PIN_A2);

break;

case PIN_A3

:data

= (int8)input(PIN_A3);

break;

case PIN_A4

:data

= (int8)input(PIN_A4);

break;

case PIN_A5

:data

= (int8)input(PIN_A5);

break;

case PIN_B0

:data

= (int8)input(PIN_B0);

break;

//case PIN_B1

:data

= (int8)input(PIN_B1);

break;

//case PIN_B2

:data

= (int8)input(PIN_B2);

break;

//case PIN_B3

:data

= (int8)input(PIN_B3);

break;

case PIN_B4

:data

= (int8)input(PIN_B4);

break;

case PIN_B5

:data

= (int8)input(PIN_B5);

break;

//case PIN_B6

:data

= (int8)input(PIN_B6);

break;

//case PIN_B7

:data

= (int8)input(PIN_B7);

break;

case PIN_C0

:data

= (int8)input(PIN_C0);

break;

case PIN_C1

:data

= (int8)input(PIN_C1);

break;

case PIN_C2

:data

= (int8)input(PIN_C2);

break;

case PIN_C3

:data

= (int8)input(PIN_C3);

break;

case PIN_C4

:data

= (int8)input(PIN_C4);

break;

case PIN_C5

:data

= (int8)input(PIN_C5);

break;

case PIN_C6

:data

= (int8)input(PIN_C6);

break;

case PIN_C7

:data

= (int8)input(PIN_C7);

break;

case PIN_D0

:data

= (int8)input(PIN_D0);

break;

case PIN_D1

:data

= (int8)input(PIN_D1);

break;

case PIN_D2

:data

= (int8)input(PIN_D2);

break;

case PIN_D3

:data

= (int8)input(PIN_D3);

break;

case PIN_D4

:data

= (int8)input(PIN_D4);

break;

case PIN_D5

:data

= (int8)input(PIN_D5);

break;

case PIN_D6

:data

= (int8)input(PIN_D6);

break;

case PIN_D7

:data

= (int8)input(PIN_D7);

break;

//case PIN_E0

:data

= (int8)input(PIN_E0);

break;

//case PIN_E1

:data

= (int8)input(PIN_E1);

break;

//case PIN_E2

:data

= (int8)input(PIN_E2);

break;

} return data;

} //**********************************************************************

void make_high(int8

pin_to_use)

{switch(pin_to_use)

{case PIN_A0

:output_high(PIN_A0);

break;

case PIN_A1

:output_high(PIN_A1);

break;

case PIN_A2

:output_high(PIN_A2);

break;

case PIN_A3

:output_high(PIN_A3);

break;

case PIN_A4

:output_high(PIN_A4);

break;

case PIN_A5

:output_high(PIN_A5);

break;

case PIN_B0

:output_high(PIN_B0);

break;

//case PIN_B1

:output_high(PIN_B1);

break;

//case PIN_B2

:output_high(PIN_B2);

break;

//case PIN_B3

:output_high(PIN_B3);

break;

//case PIN_B4

:output_high(PIN_B4);

break;

case PIN_B5

:output_high(PIN_B5);

break;

//case PIN_B6

:output_high(PIN_B6);

break;

//case PIN_B7

:output_high(PIN_B7);

break;

case PIN_C0

:output_high(PIN_C0);

break;

case PIN_C1

:output_high(PIN_C1);

break;

case PIN_C2

:output_high(PIN_C2);

break;

case PIN_C3

:output_high(PIN_C3);

break;

case PIN_C4

:output_high(PIN_C4);

break;

case PIN_C5

:output_high(PIN_C5);

break;

case PIN_C6

:output_high(PIN_C6);

break;

case PIN_C7

:output_high(PIN_C7);

break;

case PIN_D0

:output_high(PIN_D0);

break;

case PIN_D1

:output_high(PIN_D1);

break;

case PIN_D2

:output_high(PIN_D2);

break;

case PIN_D3

:output_high(PIN_D3);

break;

case PIN_D4

:output_high(PIN_D4);

break;

case PIN_D5

:output_high(PIN_D5);

break;

case PIN_D6

:output_high(PIN_D6);

break;

case PIN_D7

:output_high(PIN_D7);

break;

case PIN_E0

:output_high(PIN_E0);

break;

//case PIN_E1

:output_high(PIN_E1);

break;

//case PIN_E2

:output_high(PIN_E2);

break;

}} //**********************************************************************

void make_low(int8

pin_to_use)

{switch(pin_to_use)

{case PIN_A0

:output_low(PIN_A0);

break;

case PIN_A1

:output_low(PIN_A1);

break;

case PIN_A2

:output_low(PIN_A2);

break;

case PIN_A3

:output_low(PIN_A3);

break;

case PIN_A4

:output_low(PIN_A4);

break;

case PIN_A5

:output_low(PIN_A5);

break;

case PIN_B0

:output_low(PIN_B0);

break;

//case PIN_B1

:output_low(PIN_B1);

break;

//case PIN_B2

:output_low(PIN_B2);

break;

//case PIN_B3

:output_low(PIN_B3);

break;

//case PIN_B4

:output_low(PIN_B4);

break;

case PIN_B5

:output_low(PIN_B5);

break;

//case PIN_B6

:output_low(PIN_B6);

break;

//case PIN_B7

:output_low(PIN_B7);

break;

case PIN_C0

:output_low(PIN_C0);

break;

case PIN_C1

:output_low(PIN_C1);

break;

case PIN_C2

:output_low(PIN_C2);

break;

case PIN_C3

:output_low(PIN_C3);

break;

case PIN_C4

:output_low(PIN_C4);

break;

case PIN_C5

:output_low(PIN_C5);

break;

case PIN_C6

:output_low(PIN_C6);

break;

case PIN_C7

:output_low(PIN_C7);

break;

case PIN_D0

:output_low(PIN_D0);

break;

case PIN_D1

:output_low(PIN_D1);

break;

case PIN_D2

:output_low(PIN_D2);

break;

case PIN_D3

:output_low(PIN_D3);

break;

case PIN_D4

:output_low(PIN_D4);

break;

case PIN_D5

:output_low(PIN_D5);

break;

case PIN_D6

:output_low(PIN_D6);

break;

case PIN_D7

:output_low(PIN_D7);

break;

case PIN_E0

:output_low(PIN_E0);

break;

//case PIN_E1

:output_low(PIN_E1);

break;

//case PIN_E2

:output_low(PIN_E2);

break;

}} //**********************************************************************

int8

Read_byte()//Read a byte from the DS18S20

{int8

data;

int8

count;

data=0;

for(count=8;

count>0;

count--)

{//Write the bit to the port

make_low(d_pin);

delay_us(2);

//Release port for reading

get_line_in(d_pin);

//delay to center of timeslot

delay_us(10);

D_Data=get_line_in(d_pin);

//Read the data bit in

//Finish the timeslot

delay_us(60);

//Put data into the byte

data

=data

>>

1;

//Shift previous bits across

if(D_Data==1)

//If data was high then add high bit to data

data

+=0x80;

//Delay Between Bits

delay_us(10);

} //rise time plus min space

delay_us(10);

return(data);

} //**********************************************************************

void D_Reset()//Reset the DS18S20

{//int8

count;

D_Error=99;

//--

Reset the status bit to no error

get_line_in(d_pin);

//Start the reset Pulse

make_low(d_pin);

delay_us(480);

//release the line

get_line_in(d_pin);

//delay to about the center of the presence pulse

delay_us(90);

D_Presence

=get_line_in(d_pin);

//get presence status 1=fail

0=present

delay_us(300);

D_SC

=get_line_in(d_pin);

//check for short circuit

if(D_SC

==

0)

//if short circuit then error

D_Error

=8;

if(D_Presence

==

1)

//if no device detected then error

D_Error

=2;

delay_us(10);

} //**********************************************************************

void Write_byte(int8

Data)//write a byte to the DS18S20

{int8

count;

for(count=8;

count>0;

count--)

{D_Data=

Data

&0x01;

//LSB

//write the bit to the port

make_low(d_pin);

delay_us(4);

//time slot start

//write data to the port

if(D_Data)

get_line_in(d_pin);

else

make_low(d_pin);

delay_us(66);

//release port pin

get_line_in(d_pin);

delay_us(10);

Data>>=1;

//shift next bit into place

} delay_us(10);

} //********************************************************************/

void receive_packet()

{int8

pn,

pos2,

checksum,num_bytes,

save_bytes;

num_bytes=read_usb();//get the number of bytes

buffer[0]=num_bytes;

save_bytes

=num_bytes;//save a copy

pos2=1;

while(num_bytes--)

buffer[pos2++]=read_usb();

checksum=0;

for(pn=0;

pn<save_bytes+1;

pn++)

checksum

^= (int8)buffer[pn];

if(read_usb() == checksum)//if checksums match

{delay_us(100);

if(input(RXF)==0)//if more data in FIFO

{//still have data in the FIFO --

ERROR!

delay_ms(5);

while(input(RXF)==0)//clear the FIFO

{delay_ms(5);

read_usb();

} send(0xAb);//error!

packet_ready=0;

}else

{send(0x55);//no error

delay_us(100);

packet_ready=1;

}} else//checksum failed

{send(0xaa);//error!

packet_ready=0;

} strobe_SND();//send now

} //********************************************************************/

void strobe_SND()

{output_low(SND);

output_high(SND);

} //********************************************************************/

void send(int8

thebyte)

{//send the byte back through the USB interface

SET_TRIS_D(

0x0

);//all output

while(input(TXE)==1);//when TXE is high do not write

output_d(thebyte);

//delay_us(50);//50

output_low(WR);//C5=0

//delay_us(20);//20

output_high(WR);//C5=1

SET_TRIS_D(

0xff

);//all input

} //********************************************************************/

int8

read_usb()

{int8

data8;

while(input(RXF)==1);//wait for USB data to arrive

SET_TRIS_D(

0xff

);//all input

output_low(RD);//pull RD low

delay_us(20);

data8

=input_d();//read data

output_high(RD);//take RD back high

return data8;

}

52 Software do microcontrolador

Apendice E

Guias das experiencias

Ekit - Medidor de resistências

Objectivo

Neste trabalho pretende-se realizar a mediçao de resistências utilizando um dispositivo USB contendo um microcontrolador com pinos de conversão de sinal analógico para digital.

Introdução

Para certos circuitos de reduzida complexidade é mais simples utilizar equivalências entre associações de resistências em série e em paralelo. A combinação de resistências serve para substituir um conjunto de resistências arbitrário por uma resistência dita equivalente.

Numa combinação em série a corrente é comum a todas:

Numa combinação em paralelo a tensão é comum em cada nó:

questaoempontoeq I

VR__

IRVN

kk ��

���

��

�1321 RRRReq �

VGIN

kk ��

���

��

�1

321

321 111111

RRRGGGG

Req

eq

��

O medidor de resistências tem como objectivo medir o valor real da resistência teste (Req da figura 1.). O príncipio de funcionamento do Ekit basea-se na associação em série de uma resistência de calibrada (Rref da figura 1.) com a resistência de teste (Req da figura 1.) :

Fig 1.

Com este dividor de tensâo, medindo a tensão no pin 1 e pin 2, é possível calcular o valor da(s) resistência(s) que podem compor a resistência de teste (Req.).Convem referir que é necessário conhecer á priori o valor teórico da resistência calibrada (Rref), para tal tem á disposição no anexo 1. o valor das resistências.

Lista de Material:

PC com matlab.

Dispositivo USB, DLP-2232PB-G, que contém o microcontrolador PIC.

Software disponibilizado na página: https://fenix.ist.utl.pt/homepage/ist148046/ekit.

Breadboard.

Resistências variadas(1k, 10k, 100k).

VCC

GROUND

Experiência 1: Montagem e teste do dispositivo USB Montagem do circuito

Colocar o microcontrolador numa breadboard de acordo com a figura 2:

Figura 2: Dispositivo USB DLP-2232PB-G. a) O curto-circuito dos pinos 23 e 24 alimenta o dispositivo a partir do

USB, e a ligação do pino 4 a Vcc coloca Vcc no canal AD#0. b) Pinos a utilizar do dispositivo USB: alimentação do dispositivo pinos

23 e 24, ground comum pino 50, canal de conversão AD#0 pino 4, canal de conversão AD#1 pino 5.

A montagem do circuito da figura 2 é realizada de acordo com o esquemático da figura 3:

Figura 3.

Para o correcto funcionamento do dispositivo USB e realização desta experiência são necessários os drivers da placa e software de aquisição que se encontram na web em https://fenix.ist.utl.pt/homepage/ist148046/ekit.

Ligação do dispositivo USB ao PC

1. Montar o dispositivo USB na breadboard e efectuar as ligações a vermelho referidas na figura 3.

2. Ligar o dispositivo USB ao PC e verificar que o LED no dispositivo começa a acender periodicamente.

3. Seguir as indicações na pagina web para efectuar a instalação dos drivers do dispositivo.

Medição de uma tensão com o dispositivo USB.

4. Criar uma subdirectoria de trabalho, por exemplo c:\ekit e colocar nessa directoria o programa de interface “ftdi.mex” e o programa de teste do interface “ftdi_tst.m”.

5. Correr o Matlab.exe e realizar os seguintes comandos:

>>cd c:\ekit >>ftdi_tst;

6. Verificar que aparece a mensagem: Conversor lido com sucesso: AD#0 = 5.12 [V]

7. Ligar o pino 4 (AD#0) ao ground comum e repetir o teste:

>>ftdi_tst;

8. Verificar que aparece a mensagem: Conversor lido com sucesso: AD#0 = 0.0 [V]

VCC

GROUND

Rteste

Rcalibrada

Experiência 2: Medição de resistências

Monte o circuito da figura 4. com uma resistência calibrada de 1K e outra resistência de entre o grupo de resistências a medir (ver lista de material). Utilizando o procedimento seguinte no Matlab, obtenha dois valores de tensão que irão permitir o cálculo da resistência.

Figura 4.

A montagem do circuito da figura 4 é realizada de acordo com o esquemático da figura 5:

Figura 5.

Comandos para realizar a medição no Matlab:

>> v1 = ftdi_tst(0); % leitura da tensao no AD#0 pino 4 >> v2 = ftdi_tst(1); % leitura da tensao no AD#1 pino 5 >> R = (v2 – v1) / (v2 / 1e3)

Como alterar o comando matlab no caso de a resistência calibrada ser 10k em vez de 1k?

>> R = (v2 – v1) / (v2 / 1e4)

O resultado foi o esperado para a resistência teste? A que se pode dever uma discrepância de valores?

Experiência 3: Associações de resistências.

Monte o circuito da Fig 6. com três resistências á sua escolha e meça o valor da resistência equivalente (associação em paralelo das duas resistências teste) através dos comandos de Matlab da experiência 2. Determinar previamente (atraves do anexo 1) o valor da resistência calibrada.

Figura 6.

Associe agora em série duas resistências no lugar da resistência equivalente e repita a experiência 2. A resistência equivalente aumenta ou diminui em cada uma das associações (série e paralelo)?

Anexo 1. – Valor das resistências.

Ekit - Carga e Descarga do Condensador em C.C.

Objectivo

Neste trabalho, pretende estudar-se a variação da diferença de potencial (d.d.p.) nos terminais de um condensador em função do tempo, durante os processos de carga e descarga do mesmo, através de uma resistência. Introdução

O condensador serve para armazenar energia na forma de energia potencial de um campo elétrico. Esta sua característica é quantificada por uma grandeza chamada capacidade, C , que indica a quantidade de carga que um condensador armazena quando sujeito a uma diferença de potencial (d.d.p.) de 1V. A unidade de capacidade é o Farad (F). Um condensador instalado num circuito de corrente contínua implica que a corrente que nele circule seja nula. Um condensador pode ser carregado aplicando directamente sobre este uma diferença de potencial constante E. Neste caso o tempo de carga será muito pequeno e não é mensurável. Interessa pois colocar uma resistência R no circuito para que o processo de carga ( ou de descarga ) seja observável ao longo do tempo. No circuito da figura 1 a queda de tensão nos terminais do condensador é igual á d.d.p. da fonte que está a alimentar o circuito: Visto que a corrente no circuito é nula, a queda de tensão na resistência é nula.

Figura 1.

No entanto, estando o condensador inicialmente descarregado, a sua queda de tensão não passa instantaneamente de 0 para E. Ele carregar-se-á não instantaneamente, mas durante um período de tempo, descrito analiticamente por:

Esta situação corresponde ao regime transitório do sistema, isto é, o sistema atinge o regime permanente , V� = E, (teoricamente para t = �) passando pelo regime transitório acima definido. À constante � com as dimensões de tempo dá-se o nome de constante de tempo do circuito e é definida por: Na descarga do condensador o fenómeno é análogo (figura 2). A queda de tensão nos terminais do condensador em regime permanente é nula. No entanto, se no instante inicial a queda de tensão é E (condensador carregado), a queda de tensão não decai instantaneamente a 0, isto é, o sistema passa, do instante inicial (V� = E) ao instante em que V� = 0 (regime permanente) , por um regime transitório.

Figura 2.

Na descarga este regime transitório é descrito analiticamente por:

Lista de Material: PC com matlab Dispositivo USB, DLP-2232PB-G, que contém o microcontrolador PIC. Software disponibilizado na página: https://fenix.ist.utl.pt/homepage/ist148046/ekit. Breadboard. Condensador de 1 μF.

Resistência de 100 K�.

C

R

VCC

GROUND

Experiência 1: Montagem e teste do dispositivo USB

Colocar o dispositivo USB numa breadboard de acordo com a figura 3.

Figura 3.

Os componentes da imagem fazem parte da lista de material, e a sua montagem é realizada de acordo com o esquemático da figura 4:

Figura 4.

� A ligação dos pins 23 e 24 alimenta o dispositivo a partir do USB e disponibiliza VCC (5.12V) ao circuito.

� A ligação do pin 26 disponibiliza ground comum ao circuito.

� A ligação do pin 5, ADC#1, efectua a leitura da tensão aos terminais do condensador.

� A ligação do pin 48 disponibiliza VCC ou ground comum ao circuito consoante o objectivo seja a carga (figura 1) ou descarga (figura 2) do condensador.

Ligação do dispositivo USB ao PC

1. Montar o dispositivo USB na breadboard e efectuar as ligações a vermelho referidas na figura 4.

2. Ligar o dispositivo USB ao PC e verificar que o LED no dispositivo começa a acender periodicamente.

3. Seguir as indicações na pagina web para efectuar a instalação dos drivers do dispositivo.

Confirmação de comunicação com o dispositivo

4. Criar uma subdirectoria de trabalho, por exemplo c:\ekit e colocar nessa directoria o programa de interface do condensador (condensador.mex) ,o programa de teste de comunicação (testeCOM.mex) e os ficheiros de matlab condensador_tst.m e Calculo_condensador.m.

5. Correr o Matlab.exe e realizar os seguintes comandos: >>cd c:\ekit >>testeCOM(porta COM atribuida)

6. Veririficar que aparece a mensagem: Porta COM correcta

7. Voltar ao passo 3 caso receba a mensagem: COM indisponivel

Experiência 2: Carga e descarga do condensador.

Após a realização da experiência 1, e mantendo as ligações anteriores, efectuar agora as ligações a verde da figura 4. Para esta experiência será necessário o condensador e a resistência referidos na lista de material. O circuito depois de todo montado deverá assemelhar-se ao da figura 3. Para determinar o “�” e “C” experimental e visualizar o regime transitório do condensador corra no matlab o seguinte comando: >>condensador_tst(porta COM atribuida(1-9) , 0 – carga ou 1 - descarga) No caso de a porta COM atribuida ser a 1 e querer visualizar a carga do condensador:

>>[Vc,tempos,tau_medio,C,corrente] = condensador_tst(1, 0);

Para visualizar o regime transitório de descarga do condensador corra no matlab o seguinte comando:

>> [Vc,tempos,tau_medio,C,corrente] = condensador_tst(1, 1); Analíse de resultados

1. Calcule a constante de tempo teórica do circuito que montou.

____________________________________________________

2. Determine a constante de tempo de carga e descarga a partir dos gráficos. (deverá ser aproximadamente igual ao � calculado experimentalmente). Compare esse valor com o teórico calculado anteriormente. ____________________________________________________ ____________________________________________________

3. Verifique para o processo de carga do condensador a igualdade

V�(t = �) = 0.63E. _____________________________________________________

4. Verifique para o processo de descarga do condensador a igualdade V�(t = �) = 0.37E. _____________________________________________________

5. No processo de carga, calcule a percentagem de carga que o condensador terá quando t = 5�. Acha que o condensador está praticamente carregado? _____________________________________________________ _____________________________________________________

6. Se alterar a resistência do circuito quais serão as principais diferenças no processo de carga e descarga do condensador? Experimente e interprete os resultados. ______________________________________________________ ______________________________________________________ ______________________________________________________

7. Qual o impacto de mais uma resistência em série com o condensador? Experimente se tiver dúvidas. ______________________________________________________ ______________________________________________________ ______________________________________________________

8. Qual o impacto de uma resistência em paralelo com o condensador? Desenhe o novo circuito, faça a montagem, e interprete os resultados. (Só é valido para carga do condensador,não testar a descarga!)

Ekit - Diagrama de Bode

Objectivo

Neste trabalho, pretende caracterizar-se a resposta em frequência de um sistema de primeira ordem através da sua representação gráfica, o diagrama de Bode. Introdução

Um diagrama de Bode é uma representação gráfica usada para caracterizar a resposta em frequência de um sistema. A ideia de considerar a resposta em frequência de um sistema é em vez de, por exemplo, contabilizar quanto tempo demora a resposta a uma mudança da posição de uma válvula (isto é a resposta no domínio do tempo) considerar antes como o sistema se comporta quando se abre e fecha a válvula imitando uma onda sinusoidal a diferentes frequências. O comportamento do sistema a diferentes frequências é descrito pelo diagrama de Bode. Uma onda sinusoidal:

Fig 1. – Onda sinusoidal

é caracterizada por 3 parâmetros: - Amplitude a - Período P ou frequência f - Fase p A fase de uma onda sinusoidal é uma quantidade relativa, visto que a função pode receber um qualquer argumento e não tem um ponto de partida fixo. Por exemplo um seno em função do tempo t pode ser descrito como: y(t) = a sin (w t + p)

onde a é a amplitude e tem as mesmas unidades que a grandeza y(t). A unidade da fase p é ângulos, em radianos ou graus e w a frequência angular defina como: w = Se considerarmos um sistema cuja entrada é uma onda sinusoidal, por exemplo uma válvula a mover-se consoante um seno, e observarmos a saída e entrada em conjunto:

Fig. 2 – Sinal de entrada e saída.

Concluímos que: - A saída será uma sinusóide com a mesma frequência que a entrada. - A razão entre a amplitude de saída e a amplitude de entrada varia com a frequência do sinal de entrada. - A diferença de fase entre o sinal de saída e de entrada também varia com a frequência. Magnitude A magnitude, ou rácio de amplitude AR(w) é definido como a razão entre a amplitude de saída e a amplitude de entrada, é adimensional, e representa-se numa escala logaritmica de frequências:

AR (dB) = 20 log 10 AR Fase A fase, ou ângulo de fase PA(w) é definido como a diferença entre a fase do sinal de entrada e a fase do sinal de saída. De realçar que o ângulo de fase é sempre negativo uma vez que representa um atraso entre a entrada e saída. Um ângulo de fase positivo implicava que um sistema acelerava (inversão no tempo) a entrada em vez de a atrasar. Um filtro passa-baixo RC tem a seguinte função de transferência:

Onde a frequência limite (cutoff frequency f ( c ) ) toma o valor (em Hertz):

Neste caso, a aproximação para o diagrama de Bode de magnitude consiste em duas linhas: - para frequências abaixo f c é uma linha horizontal a 0 dB. - para frequências acima f c é uma linha com inclinação de -20 dB por década.

Fig. 3 – Diagrama de Bode para um filtro RC passa-baixo.

Lista de Material: PC com matlab Dispositivo USB, DLP-2232PB-G, que contém o microcontrolador PIC. Software disponibilizado na página: https://fenix.ist.utl.pt/homepage/ist148046/ekit. DAC-MCP4822 Breadboard. Condensador de 1 μF. Resistência de 100 K� e de 1 K�.

Experiência 1: Montagem e teste do dispositivo USB

Colocar o dispositivo USB numa breadboard de acordo com a figura 4.

Figura 3.

Os componentes da imagem fazem parte da lista de material, e a sua montagem é realizada de acordo com o esquemático da figura 5:

Fig. - 5.

� A ligação dos pins 23 e 24 alimenta o dispositivo a partir do USB e disponibiliza VCC (5.12V) ao circuito.

� A ligação do pin 26 disponibiliza ground comum ao circuito.

� A ligação do pin 43, 44 e 46 disponibiliza o CS (chip select input), SCK (serial clock input) e SDI (serial data input) para a comunicação entre o modulo e o DAC.

� As ligações 1, 5 e 7 do DAC disponibilizam tensões de referência para o correcto funcionamento do DAC

� A ligação do pin 8 do DAC disponibiliza o sinal gerado usado como entrada do sistema.

� A ligação do pin 4, ADC#0, efectua a leitura da tensão ao terminal de saída do DAC. (sinal gerado usado como entrada do sistema)

� A ligação do pin 5, ADC#1, efectua a leitura da tensão aos terminais do condensador. (saída do sistema)

Ligação do dispositivo USB ao PC

1. Montar o dispositivo USB na breadboard e efectuar as ligações a vermelho referidas na figura 4.

2. Ligar o dispositivo USB ao PC e verificar que o LED no dispositivo começa a acender periodicamente.

3. Seguir as indicações na página web para efectuar a instalação dos drivers do dispositivo.

Confirmação de comunicação com o dispositivo

4. Criar uma subdirectoria de trabalho, por exemplo c:\ekit e colocar nessa directoria o programa de interface do diagrama de bode (bode.mex) ,o programa de teste de comunicação (testeCOM.mex) e os ficheiros de matlab fase.m e plot_bode.m.

5. Correr o Matlab.exe e realizar os seguintes comandos: >>cd c:\ekit >>testeCOM()

6. Veririficar que aparece a mensagem: Porta COM correcta

7. Voltar ao passo 3 caso receba a mensagem: COM indisponivel

Experiência 2: Visualizar o diagrama de Bode.

Após a realização da experiência 1, e mantendo as ligações anteriores, efectuar agora as ligações a verde da figura 5. Para esta experiência será necessário o condensador e a resistência referidos na lista de material. O circuito depois de todo montado deverá assemelhar-se ao da figura 4. Para visualizar o diagrama de bode para o sistema com R = 1 K�: >>plot_bode(freq inicial [rad/s], freq final [rad/s]) Alterar a resistência de 1 K� para 100 K� e repetir a experiência. NOTA: cuidado com a escolha das frequências iniciais e finais pois pode levar a experiência a demorar imenso tempo. (recomendado: freq inicial = 1 rad/s, freq final = 1000rad/s)

Analíse de resultados

1. Através do diagrama de Bode determine a frequência crítica para cada

uma das experiências. ____________________________________________________

2. O que pode concluir da análise do diagrama de Bode. ____________________________________________________ ____________________________________________________

3. Qual a relação entre o período do sinal de entrada e o período do sinal de saída? _____________________________________________________ _____________________________________________________

4. Qual o significado de um ângulo de fase positivo? _____________________________________________________

54 Guias das experiencias

Apendice F

Forum e web page

O forum e a web page funcionam como suporte para os alunos que vao utilizar o Ekit. No forum conseguemesclarecer duvidas, encontrar as respostas para os problemas mais comuns, assim como fazer sugestoes ou inves-tigar como o software foi desenvolvido e como se encontra implementado o interface generico. Na pagina webtem disponıveis os drivers necessarios para a conexao do dispositivo e guias laboratoriais que conduzem os alunosatraves das diversas experiencias sem que necessitem de supervisao de um docente.

Figura F.1: Forum de ajuda

56 Forum e web page

Figura F.2: Site com guias e software