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 |
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.
Este comentário foi removido por um administrador do blog.
ResponderExcluirEste comentário foi removido por um administrador do blog.
ResponderExcluir