Páginas

Mostrando postagens com marcador #bancada. Mostrar todas as postagens
Mostrando postagens com marcador #bancada. Mostrar todas as postagens

sexta-feira, 9 de setembro de 2016

Projetos - Gerando Senoides com o PIC - Parte 1

Finalmente resolvi tirar essa postagem da gaveta de rascunhos e compartilhar um projeto de bancada que me foi útil na ocasião e pode também ser para outros. O Gerador de Onda Senoidal faz o que o nome diz, fornece um sinal tipo senoide modificada com resolução e frequência ajustáveis a nível de projeto. É possível também gerar outras formas de onda utilizando o mesmo conceito descrito e o Módulo de Tensão de Referência. Já falei sobre esse periférico do PIC aqui no blog quando utilizei ele em conjunto com o Comparador Analógico no projeto do Termômetro Bargraph. Agora vou mostrar como é possível gerar uma senoide ou outra forma de onda qualquer utilizando o VREF.

Conceitos Básico e recursos do PIC:
Muitos PICs, e outros microcontroladores em geral, possuem um módulo VREF que é um periférico bem versátil. É basicamente um conversor digital-analógico (CDA) e como tal, converte um valor binário em um nível tensão DC no pino de I/O do PIC. No caso do PIC, é possível escolher entre 26 valores distintos entre 0 e 5 Volts.

A arquitetura do módulo VREF é baseada em uma associação com 16 resistores multiplexados. Um divisor de tensão controlado pelo bit <VRR>  permite o módulo trabalhar com duas escalas (ranges) de tensões. Cada divisão (high e low) pode assumir 16 valores diferentes.

figura 01 - Diagrama do Módulo de Tensão de Referência. 
- retirado do datasheet do pic -

Como se pode ver na figura, escrevendo um valor binário entre 0000 e 1111 nos bits VR0 a VR3 do registrador VCON, você faz a multiplexação dos resistores que ficarão ativos e com isso, altera o valor da tensão de saída.
Quando programando em C no MPLAB e com o compilador CCS, o controle é feito utilizando a função SETUP_VREF(arg1| arg2 | arg3)que recebe 3 argumentos.
Argumento1: VREF_HIGH / VREF_LOW / FALSE- indica qual escala (range) deve ser usado. Alto  ou baixo ou ainda se o módulo ficará desligado (false).
Argumento2: VREF_A2 - determina onde a tensão de saída do módulo será disponível interna ou externamente. Nesse exemplo, VREF estará disponível no pino A2.
Argumento3: Neste argumento deve ser passado um valor numérico de entre 0 e 15, que corresponde ao valor nos bits de controle <VR3:0>. O Efetivo valor da tensão DC é dado pelas equações mostradas abaixo.
Quando na escala alta (VREF_HIGH) o valor da tensão de saída é dado pela equação:


Quando na escala baixa (VREF_LOW), o valor da tensão é dado agora pela equação:


Note que o módulo também utiliza VDD e VSS como alimentação e portanto, variações ou flutuações em VDD/VSS  irão refletir em VREF. Com base nas equações mostradas criei uma tabela onde calculei todos os valores que VREF pode assumir para um valor de VDD igual a 5 volts. Uma outra limitação é o fato que alguns pontos dos dois ranges são coincidentes, e portanto, não é possível ter 32 pontos de resolução mas apenas 26.

A tabela abaixo mostra todos as 32 tensões possíveis que podemos obter utilizando VDD = 5 Volts.

figura 02 - Valores possíveis de VREF para ambos os ranges


Lógica do Projeto: Uma vez que não estamos realmente gerando uma senoide pura, mas sim uma senoide modificada ou digitalizada. Configuramos VREF para fornecer a mínima tensão desejada na saída, fazemos um delay para que a tensão se estabilize, em seguida mudamos os argumentos da função SETUP_VREF() para aumentar a tensão de saída para o próximo valor, repetimos o processo até atingimos o valor máximo desejado e então fazemos o caminho inverso, diminuindo a tensão à cada delay. A figura abaixo ilustra um caso particular, onde foram usados 5 patamares distintos.
figura 03 - Senoide modificada, n=5
Aumentando o número de pontos, aumentamos a resolução e mais próximo vamos chegando da forma de uma senoide pura. Quanto a frequência da senoide, basta perceber que é preciso passar por todos os pontos, tanto de subida quanto de descida, no intervalo de tempo definido pelo período T=1/f.  Nesse projeto eu queria obter a máxima resolução bem como e a máxima excursão da amplitude do sinal de saída e portanto os intervalos foram calculados para se obter uma senoide com frequência de 1 kHz (que era o que eu precisava na hora pra testar um outro projeto). Formas de onda diferentes e frequências maiores podem ser alcançadas, porém é preciso ficar atento às limitações do componente e principalmente com o tempo de estabilização necessário do módulo VREF.

Software: Primeiro é feito a configuração dos registradores de controle do periférico em seguida, um laço garante a geração da senoide ad infinitum. O código abaixo foi escrito por meu colega Eng. Heitor M. Couto em 2014 na época, estudante de graduação e meu estagiário.

NOTA: Conforme o datasheet, quando configurado no modo de tensão de referência, o pino RA2 trabalha como uma saída de alta impedância. Antes de usa-lo é preciso configurá-lo como ENTRADA e conectar ao pino apenas cargas de alta impedância ligada ao pino. 

void main() 
{ 
   SET_TRIS_A(0b00000100);  //pino RA2 como ENTRADA!!!
   setup_comparator(NC_NC_NC_NC);//desabilita o módulo comparador

   for(;;)
   {
      senoide();
   }
}

void senoide(void)
{ 
   setup_vref(VREF_LOW | VREF_A2 | 9);//1,87
   delay_us(245);
   setup_vref(VREF_HIGH | VREF_A2 | 5);//2,03
   delay_us(82);
   setup_vref(VREF_LOW | VREF_A2 | 10);//2,08
   delay_us(165);
   setup_vref(VREF_HIGH | VREF_A2 | 6);//2,18
   delay_us(167);
   setup_vref(VREF_LOW | VREF_A2 | 11);//2,29
   delay_us(84);
   setup_vref(VREF_HIGH | VREF_A2 | 7);//2,34
   delay_us(257);
   setup_vref(VREF_LOW | VREF_A2 | 12);//2,5
   delay_us(267);
   setup_vref(VREF_HIGH | VREF_A2 | 9);//2,656
   delay_us(92);
   setup_vref(VREF_LOW | VREF_A2 | 13);//2,708
   delay_us(190);
   setup_vref(VREF_HIGH | VREF_A2 | 10);//2,81
   delay_us(199);
   setup_vref(VREF_LOW | VREF_A2 | 14);//2,916
   delay_us(104);
   setup_vref(VREF_HIGH | VREF_A2 | 11);//2,96
   delay_us(333);
   setup_vref(VREF_LOW | VREF_A2 | 15);//3,125
   delay_us(385);
   setup_vref(VREF_HIGH | VREF_A2 | 13);//3,28
   delay_us(489);
   setup_vref(VREF_HIGH | VREF_A2 | 14);//3,437
   delay_us(1149);
   setup_vref(VREF_HIGH | VREF_A2 | 15);//3,59
   delay_us(1149);
   //até aqui é 90°
   setup_vref(VREF_HIGH | VREF_A2 | 14);//3,437
   delay_us(489);
   setup_vref(VREF_HIGH | VREF_A2 | 13);//3,28
   delay_us(385);
   setup_vref(VREF_low | VREF_A2 | 15);//3,125
   delay_us(333);
   setup_vref(VREF_HIGH | VREF_A2 | 11);//2,96
   delay_us(104);
   setup_vref(VREF_LOW | VREF_A2 | 14);//2,916
   delay_us(199);
   setup_vref(VREF_HIGH | VREF_A2 | 10);//2,81
   delay_us(190);
   setup_vref(VREF_LOW | VREF_A2 | 13);//2,708
   delay_us(92);
   setup_vref(VREF_HIGH | VREF_A2 | 9);//2,656
   delay_us(267);
   setup_vref(VREF_LOW | VREF_A2 | 12);//2,5
   delay_us(257);
   setup_vref(VREF_HIGH | VREF_A2 | 7);//2,34
   delay_us(84);
   setup_vref(VREF_LOW | VREF_A2 | 11);//2,29
   delay_us(167);
   setup_vref(VREF_HIGH | VREF_A2 |6);//2,18
   delay_us(165);
   setup_vref(VREF_LOW | VREF_A2 | 10);//2,08
   delay_us(82);
   setup_vref(VREF_HIGH | VREF_A2 |5);//2,03
   delay_us(245);
   //ATÉ AQUI 180°
   
   setup_vref(VREF_LOW | VREF_A2 | 9);//1,87
   delay_us(245);
   setup_vref(VREF_HIGH | VREF_A2 | 3);//1,718
   delay_us(82);
   setup_vref(VREF_LOW | VREF_A2 | 8);//1,667
   delay_us(166);
   setup_vref(VREF_HIGH | VREF_A2 |2);//1,5625
   delay_us(168);
   setup_vref(VREF_LOW | VREF_A2 | 7);//1,4583
   delay_us(85);
   setup_vref(VREF_HIGH | VREF_A2 | 1);//1,4063
   delay_us(260);
   setup_vref(VREF_LOW | VREF_A2 | 6);//1,25
   delay_us(365);
   setup_vref(VREF_LOW | VREF_A2 | 5);//1,0417
   delay_us(398);
   setup_vref(VREF_LOW | VREF_A2 | 4);//0,8333
   delay_us(455);
   setup_vref(VREF_LOW | VREF_A2 | 3);//0,625
   delay_us(572);
   setup_vref(VREF_LOW | VREF_A2 | 2);//,04167
   delay_us(1330);
   setup_vref(VREF_LOW | VREF_A2 | 1);//0,2083
   delay_us(1330);
   //Até aqui 270°
   
   setup_vref(VREF_LOW | VREF_A2 | 2);//,04167
   delay_us(572);
   setup_vref(VREF_LOW | VREF_A2 | 3);//0,625
   delay_us(455);
   setup_vref(VREF_LOW | VREF_A2 | 4);//0,8333
   delay_us(398);
   setup_vref(VREF_LOW | VREF_A2 | 5);//1,0417
   delay_us(365);
   setup_vref(VREF_LOW | VREF_A2 | 6);//1,25
   delay_us(260);
   setup_vref(VREF_HIGH | VREF_A2 | 1);//1,4063
   delay_us(85);
   setup_vref(VREF_LOW | VREF_A2 | 7);//1,4583
   delay_us(168);
   setup_vref(VREF_HIGH | VREF_A2 |2);//1,5625
   delay_us(166);
   setup_vref(VREF_LOW | VREF_A2 | 8);//1,667
   delay_us(82);
   setup_vref(VREF_HIGH | VREF_A2 | 3);//1,718
   delay_us(245);
   //Até aqui 360°
}

Hardware: A saída do módulo é feita no pino RA2/AN2, no caso do 16F628A corresponde ao pino 1 do CI. É preciso lembrar que o PIC não tem capacidade de corrente suficiente para a maioria das aplicações e portanto é preciso utilizar um driver ou buffer na saída para alimentar a sua carga. Se você não precisa de muita corrente, um simples transistor tipo BC ou BD com a base ligada através de um resistor de alto valor ao pino RA2 deve ser suficiente. Se o seu projeto necessita de mais corrente é mandatório o uso de mais estágios de amplificação filtros que podem melhorar a forma de onda, reduzindo as componentes harmônicas de alta frequência que sempre estão presentes quando se faz chaveamentos desse tipo.

A senoide gerada possui um nível DC incorporado, já que só podemos excursionar o sinal gerado pelo PIC entre 0V e 5V. Isso pode ser contornado utilizando fontes simétricas no circuito de amplificação.

Utilização: Para utilizar o circuito basta compilar o código, gravar no chip, uma vez alimentado, o circuito já começa a funcionar e fica gerando o sinal eternamente. Para melhorar esse projeto O primeiro refinamento é incluir uma interface com LCD e pelo menos dois botões para visualizar e fazer a seleção da frequência de forma mais simples e não ter que ficar recompilando toda vez que precisar fazer alguma mudança. Isso vai exigir uma abordagem diferente também no código. As constantes usadas na rotina delay_us()são transformadas em variáveis calculadas em uma rotina à parte que irá receber os argumentos via interface.

Quando chegar nesse ponto, já fica ridiculamente fácil incluir também outras formas de onda e construir um pequeno gerador de funções.

Na parte 2, vou mostrar as imagens obtidas com o código acima no osciloscópio e a análise no domínio da frequência da senoide gerada. Gostou, não gostou, achou um erro no projeto? deixe um comentário.

quarta-feira, 14 de agosto de 2013

Back to live... parte II

É isso ai, mais de um ano sem nenhuma postagem. Ideias e projetos não faltam... falta é tempo de colocar tudo no papel na tela. Vou tirar a noite pra consertar os links onde estavam hospedados os arquivos (minha conta no 4shared foi cancelada por inatividade, eles tentaram me alertar em Fevereiro mas só agora vi o e-mail) e tentar voltar as postagens regulares, se é que elas um dia existiram.

Pra começar, vou publicar a maior parte dos rascunhos que estavam no servidor, são vários projetos com PIC que já estavam praticamente prontos pra publicar, mas a minha preocupação excessiva com os detalhes não deixavam os posts irem para o ar.

Vou também começar uma nova série de publicações sobre a minha experiência com uma impressora 3D. Resolvi que já tinha passado da hora de montar uma dessas pra facilitar na prototipagem de peças na minha empresa. Nos próximos meses irei, aos poucos, adquirindo as peças e pretendo compartilhar essa experiência.

Boa noite.


quarta-feira, 14 de março de 2012

A bancada

A bancada do Dnail está uma bagunça, em breve mais conteúdo e mais organização