microprocessadores meft 2010/11 trabalho final de · pdf filemicrochip, alguns componentes de...

26
Microprocessadores MEFT 2010/11 Trabalho Final de Laboratório Step-Down Converter monitorizador da carga de um painel fotovoltaico Nome: Tomás Lopes da Cruz Grupo nº: 7 Turno: 5ª Feira Data:17/12/2010 Introdução Este trabalho tem por objectivo criar um step-down converter com vista a monitorizar a carga de um painel fotovoltaico. Um painel fotovoltaico é um conjunto de células fotovoltaicas capazes de converter directamente energia solar em corrente eléctrica por efeito fotoeléctrico. Um painel fotovoltaico é capaz de produzir uma corrente contínua suficiente para ser utilizada por outros dispositivos. Sabe-se que, para um painel genérico, a corrente que ele debita em função da tensão em aberto que ele produz é uma curva não linear com a forma que se pode ver na figura ao lado. Logo a potência que ele produz tem um pico. A esse pico dizemos ser o ponto ideal de funcionamento e é na tensão referente a esse pico que interessa ter o painel a funcionar. O ponto ideal de funcionamento não é uma constante do painel. Este varia com a carga e com a temperatura. Como podemos ver, uma variação na quantidade de radiação que o painel recebe causa uma variação na corrente debitada que por sua vez causa uma variação da tensão produzida e o painel sai logo da zona ideal de funcionamento. Para fazer o controlo disto vamos introduzir um step-down converter, que nos vai permitir decidir sobre qual a tensão que o painel vai fornecer sem que para isso tenhamos que dissipar corrente por ele fornecida. Um step-down converter é um circuito concebido para controlar a potência fornecida a um determinado dispositivo, este faz uso de um transístor (interruptor) um díodo de freewheel, um condensador e uma bobine. A vantagem de utilizar um step- down converter prende-se com a sua elevada eficiência quando comparado a um simples divisor de tensão, já que este não faz uso de elementos resistivos. Tem ainda a

Upload: dotuyen

Post on 07-Mar-2018

217 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Microprocessadores – MEFT 2010/11

Trabalho Final de Laboratório Step-Down Converter monitorizador da carga de um painel

fotovoltaico

Nome: Tomás Lopes da Cruz

Grupo nº: 7 Turno: 5ª Feira Data:17/12/2010

Introdução Este trabalho tem por objectivo criar um step-down converter com vista a monitorizar a carga de um painel fotovoltaico. Um painel fotovoltaico é um conjunto de células fotovoltaicas capazes de converter directamente energia solar em corrente eléctrica por efeito fotoeléctrico. Um painel fotovoltaico é capaz de produzir uma corrente contínua suficiente para ser utilizada por outros dispositivos. Sabe-se que, para um painel genérico, a corrente que ele debita em função da tensão em aberto que ele produz é uma curva não linear com a forma que se pode ver na figura ao lado. Logo a potência que ele produz tem um pico. A esse pico dizemos ser o ponto ideal de funcionamento e é na tensão referente a esse pico que interessa ter o painel a funcionar. O ponto ideal de funcionamento não é uma constante do painel. Este varia com a carga e com a temperatura. Como podemos ver, uma variação na quantidade de radiação que o painel recebe causa uma variação na corrente debitada que por sua vez causa uma variação da tensão produzida e o painel sai logo da zona ideal de funcionamento. Para fazer o controlo disto vamos introduzir um step-down converter, que nos vai permitir decidir sobre qual a tensão que o painel vai fornecer sem que para isso tenhamos que dissipar corrente por ele fornecida.

Um step-down converter é um circuito concebido para controlar a potência fornecida a um determinado dispositivo, este faz uso de um transístor (interruptor) um díodo de freewheel, um condensador e uma bobine. A vantagem de utilizar um step-down converter prende-se com a sua elevada eficiência quando comparado a um simples divisor de tensão, já que este não faz uso de elementos resistivos. Tem ainda a

Page 2: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

vantagem de poder ser regulado e adaptado a diversas condições de tensão continuando a gerar a mesma potência de saída. A figura ao lado ajuda a compreender melhor o funcionamento do step-down converter. O interruptor representado é geralmente um transístor MOSFET que é controlado pela tensão na gate. Como podemos ver, o díodo também funciona como interruptor, fechando o circuito quando se abre o interruptor e abrindo quando se fecha o interruptor. Quando o interruptor está fechado, a tensão aos terminais da bobine é positiva, logo a corrente é crescente. Pelo contrário, quando o interruptor desliga a tensão que aos seus terminais é negativa e a corrente que a atravessa vai ser decrescente. Com uma frequência de switching do interruptor superior à frequência de corte do circuito LC a tensão à saída vai ser mais menos constante, possuindo apenas um ripple que pode ser controlado. A potência à saída vai variar com o tempo em que o interruptor está fechado. A diferença para a potência inicial provém do facto de se ir guardando a potência nos elementos activos enquanto o interruptor está fechado e de essa potência ser libertada para o circuito quando o interruptor abre. Portanto podemos desde já ver que o elemento fundamental de controlo da potência à saída é a frequência de switching do interruptor e o tempo que este se encontra ligado. Usa-se na generalidade das vezes (e também no nosso) um PWM para fazer este controlo.

Como podemos ver este método não promove dissipação de energia pois a corrente que chega à resistência é sensivelmente igual à debitada pelo painel.

Com estas propriedades o nosso objectivo de manter o painel a funcionar no ponto ideal mesmo que haja uma pequena alteração na luminosidade do local torna-se exequível, bastando ligar aos seus terminais um step-down converter cujo tempo em que o interruptor se mantém fechado é controlado por um algoritmo capaz de o relacionar com a tensão ideal e com a variação de corrente sofrida pelo painel. Para este projecto iremos utilizar um microcontrolador dsPIC30F4011 da Microchip, alguns componentes de electrónica disponíveis no laboratório, um osciloscópio digital e um painel fotovoltaico.

Funcionamento Como já foi referido, a potência fornecida ao circuito vai ser controlada pelo tempo em que o interruptor vai estar lidado/desligado e pela frequência das transições. Se colocarmos um transístor no lugar do interruptor podemos controlar a tensão que lhe chega à gate, e com base nisto controlar o fecho e a abertura do interruptor. Para controlar esta tensão utilizaremos um PWM gerado pelo dsPIC. Um PWM é um sinal digital cujo período e tempo a high é ditado pelo utilizador. Assim, faremos

Page 3: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

uso de um PWM gerado pelo módulo Output Compare com o sinal proveniente de um Timer. Temos a nosso dispor o controlo do período do sinal e do tempo em que o sinal está a high. No entanto isto não nos serve de muito caso não saibamos quais os valores para estas grandezas. Para saber qual a frequência podemos assumir várias abordagens. A escolhida foi: visto que esta vai ser importante tendo em conta a característica do circuito LC, dimensionou-se o circuito e definiu-se com base em bom senso uma frequência para o PWM que não cause um grande ripple na potência à saída.

Como o ponto ideal de funcionamento depende da carga e da temperatura, o próximo passo é tabelar os pontos ideais de funcionamento para algumas situações possíveis. Sabemos que a potência fornecida vai depender do duty cycle do PWM, portanto a melhor maneira de saber qual a tensão que fornece maior potência será ir variando o duty cycle e, para cada um, medir a tensão aos terminais da resistência de carga (para saber a corrente) e a tensão fornecida pelo painel. Estas medições serão feitas com o ADC do dsPIC. A partir dos resultados obtidos e traça-se o gráfico da potência em função da tensão e verifica-se qual a que dá maior potência. A tabela obtida é então guardada na EEPROM para poder ser utilizada cada vez que seja necessário alterar as condições de carga ou temperatura do painel. Quando ocorre uma variação na tensão de entrada temos de voltar a acertar o duty cycle para manter o painel no ponto óptimo. Para o efeito usamos um algoritmo PID, que recebe o valor óptimo de trabalho e o valor de tensão fornecida pelo painel, e que nos dá qual o melhor ajuste seguinte a fazer ao duty cycle. O nosso algoritmo é optimizado pelo método de Ziegler-Nichols. Para melhor compreender o funcionamento do dispositivo ver o esquema: 1 – O sinal saído do painel entra no step-down converter 2 – O ADC lê a tensão do sinal proveniente do painel 3 – O ADC mandão sinal lido para o PID 4 – No início vai-se buscar à EEPROM qual a tensão que para as condições actuais seria a de melhor funcionamento do painel 5 – O PID diz-nos qual o valor seguinte a colocar no duty cycle do PWM 7 – O PWM com o novo duty cycle vai para o step-down converter

Page 4: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Nota: Esta era a ideia original do trabalho, no entanto, devido a alguns problemas que ocorreram, não se conseguiu tabelar os pontos de funcionamento ideal desejados, pelo que teremos de colocar à mão qual o ponto de trabalho do painel. Além disso, não se conseguiu fazer a implementação do método de Ziegler-Nichols, pelo que apenas se tem um controlador P. Este funciona na mesma, no entanto não converge tão rapidamente nem tão seguramente como um PID optimizado.

Page 5: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Calibração

Antes de começar a medir pontos de funcionamento temos de dimensionar o circuito. Utiliza-se um transístor MOSFET e um díodo normais existentes no laboratório. Foram fornecidos um condensador de 47µF e uma bobine de 0,1mH. Para escolher a resistência de carga tivemos em consideração que por um lado o led não pode receber correntes excessivamente altas, que a dissipação de energia tem de ser baixa e que o ADC deve receber tensões inferiores a 5V. Fez-se então um divisor de tensão com uma resistência de 1.2kΩ e outra de 27kΩ, pois, como a tensão máxima que ali chega ronda os 17V o ADC ligado em modo diferencial ao terminais da menor resistência vai trabalhar numa região de tensão inferior aos 5V.

O circuito obtido é:

Após o dimensionamento temos de saber quais os tempos a utilizar no circuito. Começemos pelo cálculo da frequência de corte do circuito (passa baixo): Frequência de corte de um filtro LC:

Logo

e portanto

Page 6: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Para que a variação de tensão induzida pelo switching do interruptor seja atenuada, normalizando a tensão à saída temos de utilizar um período na PWM inferior a .

A frequência de oscilador que estamos a utilizar é , logo, com 4x PLL, dá um . No cálculo da configuração PWM temos ainda de ter em atenção o tempo de reacção do circuito à transição, pelo que não será favorável trabalhar a frequências demasiado elevadas. A melhor forma será portanto definir com base no bom senso um período razoável para o sinal do PWM, esse valor será .

Para se conseguir este valor temos de colocar o prescaler de 1:1 no timer e definir o período para 740.

Definição os tempos de aquisição do ADC: como não vale a pena fazer aquisições muito frequentemente vamos decidir fazer uma aquisição a cada . Logo, vamos fazer uma aquisição a cada períodos do timer. Vamos escolher um o que nos dá um Escolhendo agora um tempo de sampling de ( ) dá um tempo total do ADC de (muito menor que o período do PWM, como pretendido). Começando cada aquisição no final de um período, vamos ainda esperar cerca de até começar a aquisição para que esta não ocorra na transição.

Temos ainda que descobrir qual a tensão que fornece o ponto ideal de funcionamento para cada situação em que se encontra o painel. Para tal colocou-se o painel em diferentes condições: Painel a ser fortemente iluminado com muita intensidade; Painel a ser iluminado com pouca intensidade; Painel a ser pouco iluminado por luz interior; Painel a ser muito pouco iluminado/semicoberto. Para cada uma destas condições faz-se um varrimento de todos os duty cycle possíveis e adquirem-se a corrente e tensão fornecida pelo painel. Os gráficos obtidos são os seguintes:

Page 7: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Nota: Como podemos observar, para potências e tensões baixas os pontos tiveram exactamente o comportamento esperado (ver 1ª imagem do relatório). No entanto para tensões o potências mais elevadas não se conseguiu resultados tão bons e não se conseguiu tirar pontos ideais. O que nos permite construir a seguinte tabela: Condições do painel Ponto de funcionamento ideal

Painel a ser fortemente iluminado com muita intensidade ------

Painel a ser iluminado com pouca intensidade -----

Painel a ser pouco iluminado por luz interior 240

Painel a ser muito pouco iluminado/semi coberto 170

Temos ainda de calibrar o algoritmo PID achando os valores de Ku e Pu. Estes obtêm-se com um controlador P, o Ku obtém-se fazendo crescer o K até o sistema se tornar instável. O valor de K limite é o Ku e o período de oscilação do sinal instável para K=Ku é o Pu.

Apesar de se ter tentado procurar este valores não se conseguiu encontrar um ponto de funcionamento em que o sistema fosse perfeitamente oscilante, pelo que não se conseguiu aplicar o PID, fincando implementado apenas o P. Este apesar de não ser tão bom também funciona bem.

Page 8: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Código O código conseguido para fazer funcionar este mecanismo é então: Header file: /********************************************************************/

/* Header para as funções do trab. final de Microprocessadores */

/* de: Tomás Cruz data: Dezembro de 2010 */

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

/* ---------------------------------------------------- */

/* Bibliotecas necessárias ao funcionamento do programa */

/* ---------------------------------------------------- */

#include <p30F4011.h> /* biblioteca com os registos do dspic */

#include <stdio.h> /* biblioteca standard de C para IO */

#include <libpic30.h> /* biblioteca com as configurações do compilador C30 */

#include <uart.h> /* biblioteca com as funções e utilitários da UART */

#include <timer.h> /* biblioteca com as funções e utilitários dos Timers */

#include <string.h> /* biblioteca standard de C para strings */

#include <outcompare.h> /* biblioteca com as funções e utilitários do Output

Compare */

#include <adc10.h> /* biblioteca com as funções e utilitários do ADC 10bit */

/* ----------------------------------------------- */

/* Defines úteis para sintetizar algumas variáveis */

/* ----------------------------------------------- */

/* define dos leds para facilitar a sua utilização */

#define LED2 LATDbits.LATD3

#define LED1 LATDbits.LATD2

/* define da frequência de oscilação do oscilador */

#define FCY ((long) 7372)

/* defines de variáveis de configuração da UART */

#define UART_ALTRX_ALTTX 0xFFE7

#define UART_RX_TX 0xFBE7

/* defines de variáveis de configuração do ADC de 10bit*/

#define ADCON1 ADC_MODULE_ON & ADC_IDLE_STOP & ADC_FORMAT_INTG & ADC_CLK_AUTO

& ADC_AUTO_SAMPLING_OFF & ADC_SAMPLE_SIMULTANEOUS & ADC_SAMP_OFF

#define ADCON2 ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_CONVERT_CH_0A &

ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF

#define ADCON3 ADC_SAMPLE_TIME_3 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_12Tcy

#define ADPCF ENABLE_ALL_ANA

#define ADCSSL SCAN_NONE

/* defines de variáveis de configuração do Timer 2 */

#define T2config T2_ON & T2_IDLE_STOP & T2_GATE_OFF & T2_PS_1_1 &

T2_SOURCE_INT

/* defines de variáveis de configuração do Output Compare */

#define OC1config OC_IDLE_STOP & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_DISABLE

/* -------------------------------------------- */

/* Variáveis globais que utilizadas no programa */

/* -------------------------------------------- */

/* variáveis da memória */

extern int _EEDATA(32) fooArrayInDataEE[16]; /* EEPROM inicial */

Page 9: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

extern int RAM1[16]; /* vector a ser depositado ne memória */

extern int RAM2[16]; /* vector onde são colocados os valores quando a memória

é lida */

extern _prog_addressT EE_addr; /* endereço de memória a utilizar*/

/* variáveis de comunicação pela UART */

extern char RXbuffer[80]; /* buffer usado para guardar os caracteres

provenientes da UART */

extern int str_pos; /* posição no RXbuffer */

/* --------------------------------------------- */

/* Protótipos das funções utilizadas no programa */

/* --------------------------------------------- */

#ifndef funcoes

#define funcoes

void iniciar(); /* inicia algumas variáveis e prepara a memória */

void uartconfig(); /* configura a UART */

void pwmconfig(int); /* configura o Timer e o Output Compare para gerar a PWM

*/

void adcconfig(); /* configura o ADC */

int PID (int); /* algoritmo PID */

void memwrite(); /* guardar novos valores em memória */

int memread(int); /* ler valores em memória */

void memclear(); /* apagar valores em memória */

void Rxbfclear(); /* apagar Rxbuffer */

void desligar(); /* desligar e limpar tudo */

void help(); /* ecra descritivo do programa */

void ecraerro1(); /* ecra de ajuda 1 */

void ecraerro2(); /* ecra de ajuda 2 */

void pausa(); /* ecra de ajuda quando ocorre uma pausa */

#endif

Ficheiro com as funções: /********************************************************************/

/* Ficheiro com as funções do trab. final de Microprocessadores */

/* de: Tomás Cruz data: Dezembro de 2010 */

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

#include"jtheader.h" /* incui o header */

/* --------------------------------- */

/* Variáveis globais para as funções */

/* --------------------------------- */

Page 10: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

/* variáveis globais para memória e comuticação pela UART */

int _EEDATA(32) fooArrayInDataEE[16];

int RAM1[16];

int RAM2[16];

_prog_addressT EE_addr;

char RXbuffer[80];

int str_pos = 0;

/* ------- */

/* Funções */

/* ------- */

/* função que inicia algumas variáveis e prepara a memória */

void iniciar()

{

TRISDbits.TRISD0=0; /* define o pin do OC1 como output */

TRISDbits.TRISD2 = 0; /* define o pin que liga ao LED1 como output */

TRISDbits.TRISD3 = 0; /* define o pin que liga ao LED1 como output */

LED1=1; /* apaga o LED1 */

LED2=0; /* acende o LED2 */

_init_prog_address(EE_addr, fooArrayInDataEE); /* inicia a memória */

/* preparar os valores a ser guardados em memória */

/* devem ser previamente colocados aqui e pela ordem correcta os valores

óptimos para cada situação (ver porquê na função ecraerro1()) */

RAM1[1]=0;

RAM1[2]=0;

RAM1[3]=0;

RAM1[4]=0;

memwrite(); /* escrever os valores na memória */

}

/* função que configura a UART */

void uartconfig()

{

/* variáveis auxiliares de configuração da UART */

unsigned int UMODEvalue, U2STAvalue;

UMODEvalue = UART_EN & UART_IDLE_CON & UART_NO_PAR_8BIT;

U2STAvalue = UART_INT_TX & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_RX_TX;

OpenUART2 (UMODEvalue, U2STAvalue, 3); /* configura e activa a UART a

115000 bps*/

U2STAbits.URXISEL = 1;

_U2RXIE = 1; /* activa a interrupção da UART */

U2MODEbits.LPBACK = 0;

__C30_UART = 2; /*define UART2 as predefined for use with stdio library,

printf etc*/

printf("\n\r Serial port ONLINE \n");

}

/* função que configura o Timer2 e o Output Compare para gerar a PWM */

void pwmconfig(int dutyc)

{

OpenTimer2(T2config, 740); /* configura e activa o Timer2 com um período

de 74 */

ConfigIntTimer2(T2_INT_PRIOR_3 & T2_INT_ON); /* activa interrupt do Timer

2 */

Page 11: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

OpenOC1(OC1config, dutyc, dutyc); /* configura o OC1 no modo PWM com duty

cycle a definir */

}

/* função que configura o ADC */

void adcconfig()

{

OpenADC10(ADCON1, ADCON2, ADCON3, ADPCF, ADCSSL); /* configura e inicia o

ADC */

SetChanADC10(ADC_CH0_POS_SAMPLEA_AN0 & ADC_CH0_NEG_SAMPLEA_AN1 &

ADC_CHX_POS_SAMPLEA_AN3AN4AN5 & ADC_CHX_NEG_SAMPLEA_NVREF); /* estabelece a

relação entre os canais e as entradas */

ConfigIntADC10(ADC_INT_PRI_4 & ADC_INT_ENABLE); /* activa interrupt do

ADC*/

}

/* função que aplica o algoritmo PID */

int PID(int e)

{

/* variáveis auxiliares para implementar o PID */

/* o PID já se encontra calibrado para o nosso trabalho */

/* por razões já explicadas não se colocou em funcionamento o algoritmo

PID. Apesar disso apresenta-se contudo o algoritmo que o faria funcionar. O

controlo é então feito apenas com um algoritmo P */

/*int K, Ti, Td, Ts;

static int uk[1];

static int ek[2];

ek[0]=e;

K=0.6*; constante da parte proporcional

Ti=0.5*; constante da parte integral

Td=0.125*; constante da parte diferencial

Ts=; tempo de amostragem

uk[0]=uk[1]+K*((1+Ts/Ti+Td/Ts)*ek[0]-(1+2*Td/Ts)*ek[1]+(Td/Ts)*ek[2]);

uk[1]=uk[0];

ek[2]=ek[1];

ek[1]=ek[0];

return uk[0];*/

/* algoritmo P */

int u;

u = (int)(2*e);

return u;

}

/* função que lê valores da memória */

int memread(int i)

{

_memcpy_p2d16(RAM2, EE_addr, _EE_ROW); /* copia a memória para o vector

RAM2 */

return RAM2[i]; /* devolve o valor de RAM[2] requerido */

}

/* função que guarda novos valores em memória */

void memwrite()

{

_erase_eedata(EE_addr, _EE_ROW); /* apaga primeiro a memória para depois

escrever */

_wait_eedata();

_write_eedata_row(EE_addr,(int)RAM1); /* escreve os valores de RAM1 para a

memória */

_wait_eedata();

Page 12: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

}

/* função que apaga valores da memória */

void memclear()

{

_erase_eedata(EE_addr, _EE_ROW); /* apaga os valores existentes na memória

*/

_wait_eedata();

}

/* função que apaga o Rxbuffer */

void Rxbfclear()

{

int j=0;

str_pos = 0; /* volta à posição 0 do Rxbuffer */

for(j=0; j<80; j++)

RXbuffer[j] = '\0'; /* apaga o Rxbuffer */

}

/* função que desliga e limpa tudo */

void desligar()

{

memclear(); /* apaga memória */

Rxbfclear(); /* apaga o Rxbuffer */

CloseTimer2(); /* desliga o Timer 2 */

CloseOC1(); /* desliga o módulo OC1 */

CloseADC10(); /* desliga o ADC */

}

/* ecra descritivo do programa */

void help()

{

printf("\n\tControlador de carga do painel fotovoltaico\n\n\r");

printf("Este programa serve para manter o painel sempre no seu ponto ideal

de funcionamento\n\r");

printf("Para iniciar pressione ENTER\n\r");

printf("Para interromper pressione 's'\n\n\r");

}

/* ecra de ajuda 1 */

/* o número escolhido corresponderá à posição em memória, pelo que se deve ter

muito cuidado ao inserir os valores na memória */

void ecraerro1()

{

printf("\n\tQuais as condicoes em que esta a funcionar o painel?\n\n\r");

printf("\n\t(pressione o numero para a sua opcao seguido de

ENTER)\n\n\n\r");

printf("\t 1 - Painel a ser fortemente iluminado com muita

intensidade\n\n\r");

printf("\t 2 - Painel a ser iluminado com pouca intensidade\n\n\r");

printf("\t 3 - Painel a ser pouco iluminado por luz interior\n\n\r");

printf("\t 4 - Painel a ser muito pouco iluminado/semicoberto\n\n\n\r");

}

/* ecra de ajuda 2 */

void ecraerro2()

{

printf("\n\t ATENCAO!! O painel nao consegue atingir o ponto ideal de

funcionamento.\n\n\r");

printf("\n\t De certeza que o painel ainda se encontra nas mesmas

condicoes?\n\n\n\r");

printf("\n\t(pressione o numero para a sua opcao seguido de

ENTER)\n\n\n\r");

printf("\t 1 - Mudar as condicoes em que se encontra o painel\n\n\r");

printf("\t 2 - Parar\n\n\r");

printf("\t 3 - Continuar a tentar\n\n\n\r");

}

Page 13: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

/* ecra de ajuda quando ocorre uma pausa */

void pausa()

{

printf("\n\t Decidiu pausar o programa.\n\n\r");

printf("\n\t(pressione o numero para a sua opcao seguido de

ENTER)\n\n\n\r");

printf("\t 1 - Mudar as condicoes em que se encontra o painel\n\n\r");

printf("\t 2 - Parar\n\n\r");

printf("\t 3 - Continuar\n\n\n\r");

}

Main code: /********************************************************************/

/* Main Code para o trab. final de Microprocessadores */

/* de: Tomás Cruz data: Dezembro de 2010 */

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

#include"jtheader.h"

_FOSC(CSW_FSCM_OFF & XT_PLL4); /* define oscilador com PLL 4x */

_FWDT(WDT_OFF); /* desliga watchdog timer */

/* variáveis auxiliares para trabalhar com interrupções*/

int f=0;

int d=0;

int main(void)

{

/* variáveis auxiliares para o funcionamento dos menus */

int aux1, aux2, aux3, stop=0;

/* variáveis auxiliares que vão definir o funcionamento */

int dutyc=50;

int ide;

/* configura a uart */

uartconfig();

/* inicia algumas variáveis e prepara a memória */

iniciar();

/* descreve o programa*/

help();

/* pede ao utilizador quais as condições de funcionamento */

ecraerro1();

Rxbfclear();

/* ciclo onde se recebem as condições de funcionamento dadas pelo

utilizador */

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%d", &aux1);

/* conforme as condições, vai buscar o setpoint à memória */

ide=memread(aux1);

break;

}

}

/* configura e inicia ADC */

Page 14: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

adcconfig();

/* configura e inicia PWM */

pwmconfig(dutyc);

printf("\n\t Programa iniciado \n\r");

Rxbfclear();

/* ciclo principal (o código corre até ser dada pelo utilizador a

instrução de parar) */

while(stop!=1)

{

/* como a tensão máxima é dada pelo dutyc = 0 e a tensão mínima é dada

pelo dutyc = 740, cado estes valores sejam excedidos é porque o painel não

consegue a tensão pretendida */

if(dutyc<0 || dutyc>740)

{

Rxbfclear();

/* pergunta o que fazer */

ecraerro2();

while(1)

{

/* ciclo onde se recebem o que o utilizador pretende fazer */

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%d", &aux2);

/* caso deseje mudar as condições em que o painel está a

trabalhar */

if(aux2==1)

{

Rxbfclear();

/* volta a mostrar as opções */

ecraerro1();

/* ciclo onde se recebem as condições de funcionamento

dadas pelo utilizador */

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%d", &aux1);

/* conforme as condições, vai buscar o

setpoint à memória */

ide=memread(aux1);

break;

}

}

/* volta a partir do ponto inicial*/

dutyc=50;

break;

}

/* caso deseje terminar o programa */

else if (aux2==2)

{

stop=1;

break;

}

/* caso deseje continuar */

else if (aux2==3)

{

/* volta a partir do ponto inicial */

dutyc=50;

Page 15: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

break;

}

}

}

}

/* quando o timer dá sinal que é momento do ADC fazer uma aquisição */

if(d==1)

{

/* espera 40 us para que a aquisição seja feita no meio do período

da PWM, fugindo assim ao pulo de tensão inicial */

__delay32(295);

/* manda o ADC fazer a aquisição */

ADCON1bits.SAMP=1;

d=0;

}

/* quando o ADC dá sinal que já tem o valor da conversão */

if(f==1)

{

/* aplica-se o algoritmo e incrementa-se o valor obtido ao valor

do duty cycle antigo */

dutyc+=PID((ADCBUF1-ide));

/* faz-se o set do novo valor para o duty cycle */

SetDCOC1PWM(dutyc);

/* inprimem-se no hipertermminal os valores obtidos */

printf("%d\t%d\t%d\n\r", dutyc, ADCBUF0, ADCBUF1);

f=0;

}

/* caso de dê ordem de pausa do programa */

if(RXbuffer[str_pos-1] =='s')

{

Rxbfclear();

/* mostra-se o menu de pausa */

pausa();

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%d", &aux3);

/* caso o utilizador tenha pausado para alterar as

condições de trabalho do painel */

if(aux3==1)

{

Rxbfclear();

ecraerro1();

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%d", &aux1);

ide=memread(aux1);

break;

}

}

/* volta a partir do ponto inicial */

dutyc=50;

break;

}

Page 16: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

/* caso o utilizador tenha pausado para terminar o

programa */

else if (aux3==2)

{

stop=1;

break;

}

/* caso o utilizador tenha pausado mas que o pretenda

retomar */

else if (aux3==3)

{

break;

}

}

}

}

}

/* se for dito para terminar o programa desliga todos os periféricos */

desligar();

}

/* função de interrupção da UART */

void __attribute__((__interrupt__,auto_psv)) _U2RXInterrupt(void)

{

/* apaga a flag da interrupção */

IFS1bits.U2RXIF = 0;

while(U2STAbits.URXDA)

{

/*guarda o valor que chega à UART no buffer */

RXbuffer[str_pos] = U2RXREG;

str_pos++;

if(str_pos >= 80)

str_pos = 0;

}

}

/* função de interrupção do ADC */

void __attribute__((interrupt, no_auto_psv)) _ADCInterrupt(void)

{

/* "activa" a variável que no código vai dizer que chegou o valor de uma

nova leitura */

f=1;

/* apaga a flag da interrupção */

IFS0bits.ADIF = 0;

}

/* função de interrupção do Timer2 */

void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void)

{

static int x=0;

/* passados 7000 períodos do timer */

if(x++>6999)

{

/* "activa" a variável que no código vai dizer ao ADC para fazer uma

nova aquisição */

x=0;

d=1;

}

/* apaga a flag da interrupção */

IFS0bits.T2IF = 0;

}

Page 17: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Considerações sobre o código É de referir que numa parte inicial de testes foram utilizados outros códigos para testar as várias componentes do dsPIC com que se está a trabalhar. Estes códigos estiveram na base do código apresentado e encontram-se em anexo. Tentou formalizar-se o código usando um header e um código com funções gerais, que podem ser reaproveitados para outras ocasiões. O main code faz a interface com o utilizador e aplica as funções criadas com vista à concretização do nosso objectivo. Apesar de não se ter conseguido aplicar o PID mostra-se o seu algoritmo caso conseguisse encontrar o valor de Pu e Ku. Além disso, apesar de não se ter conseguido encontrar os pontos de funcionamento ideal para o painel mais iluminado, no código guardou-se o lugar para os colocar. Apesar de não se ter guardado os pontos resultantes do correr do código, mostra-se de seguida um esquema genérico de qual o seu comportamento observado no hiperterminal.

Imprime-se ainda no hiperterminal a corrente debitada pelo painel. Esta serve

para ver a potência que se está a fornecer, o que nos permite verificar se estamos a obter o comportamento pretendido ou não.

Conclusão No final deste trabalho pode-se então verificar o bom funcionamento do código e a boa calibração efectuada. Viu-se então que esta utilização dos microcontroladores para regular a potência à saída de um painel fotovoltaico é mais uma excelente aplicação dos mesmos. Tem-se ainda a referir que, apesar de ainda não estar da forma mais desejada (com o PID em vez do P a fazer controlo da potência em vez da tensão para muitas mais situações que as conseguidas), este funciona já bastante bem e com um pouco mais de tempo e trabalho conseguiria sem dúvida aperfeiçoa-lo e colocá-lo da forma pretendida. O trabalho em si foi muito enriquecedor e permitiu aumentar em muito a destreza em utilizar um microprocessador, familiarizando com os seus periféricos e com as suas capacidades.

Page 18: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Referências [1] Bernardo B. Carvalho e Daniel Valcárcel, Introduction to PID controllers [2] Horácio Fernandes, Aula sobre trabalho final de laboratório [3] http://www.en.wikipedia.org/wiki/Buck_converter

Page 19: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Em anexo por questão de curiosidade irei mostrar as main codes dos programas utilizados para os testes, estes tiveram como base os programas desenvolvidos ao longo do ano no laboratório e são eles que estão na base do código final apresentado no relatório.

Estes códigos teste têm por trás o código genérico de funções e o header que não será aqui repetido, apresentando-se apenas o main code (apenas algumas diferenças nas funções help, irrelevantes para o caso).

Anexo A – Main Code do programa de teste da UART

#include"jtheader.h"

_FOSC(CSW_FSCM_OFF & XT_PLL4); /* define oscilador com PLL 4x */

_FWDT(WDT_OFF); /* desliga watchdog timer */

int main(void)

{

/* configura a uart */

uartconfig();

/* inicia algumas variáveis */

iniciar();

/* descreve o programa, aqui é pedido para pressionar a tecla 1, 2 ou T

seguida de ENTER, este procedimento pode ser repetido */

help();

char c;

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%c", &c);

/* caso se tenha pressionado 1 */

if(c=='1')

{

/* faz-se toggle do LED1 */

LED1++;

/* e apaga-se o buffer */

Rxbfclear();

}

/* caso se tenha pressionado 2 */

else if(c=='2')

{

/* faz-se toggle do LED2 */

LED2++;

/* e apaga-se o buffer */

Rxbfclear();

}

/* caso se tenha pressionado T */

else if(c=='T')

{

/* reinicia-se o valor dos leds para que fiquem em alternado */

LED1=0;

LED2=1;

Page 20: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

while(1)

{

/* faz-se repetidamente o toggle aos leds com um delay de

100ms para que fiquem a piscar em alternado */

LED1++;

LED2++;

delay_ms(100);

/* caso se pressione a tecla s pára-se este processo e

volta a ficar à espera de instruções */

if(RXbuffer[str_pos-1] =='S')

break;

}

/* apaga o buffer */

Rxbfclear();

}

}

}

}

/* função de interrupção da UART */

void __attribute__((__interrupt__,auto_psv)) _U2RXInterrupt(void)

{

/* apaga a flag da interrupção */

IFS1bits.U2RXIF = 0;

while(U2STAbits.URXDA)

{

/*guarda o valor que chega à UART no buffer */

RXbuffer[str_pos] = U2RXREG;

str_pos++;

if(str_pos >= 80)

str_pos = 0;

}

}

Anexo B – Main Code do programa de teste da EEPROM #include"jtheader.h"

_FOSC(CSW_FSCM_OFF & XT_PLL4); /* define oscilador com PLL 4x */

_FWDT(WDT_OFF); /* desliga watchdog timer */

int main(void)

{

/* configura a uart */

uartconfig();

/* inicia algumas variáveis */

iniciar();

/* descreve o programa, aqui é pedido para pressionar a tecla C, N ou A

seguida de ENTER, este procedimento pode ser repetido */

help();

/* variáveis auxiliares para funcionamento do programa */

int val;

char c;

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

Page 21: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

sscanf(RXbuffer,"%c", &c);

/* caso tenha sido pressionado C */

if(c=='C')

{

/* limpa a memória */

memclear();

printf("Done\n\n\r");

/* apaga o buffer */

Rxbfclear();

}

/* caso tenha sido pressionado N */

else if(c=='N')

{

/* pede valores para guardar em memória */

printf("Insira na ordem desejada os valores a guardar na

EEPROM separarados por um espaço (máximo 16 valores)\n\r");

/* apaga o buffer e espera que os valores sejam

colocados */

Rxbfclear();

delay_ms(5000);

/* recebe os valores */

sscanf(RXbuffer,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d

%d", &RAM1[0], &RAM1[1], &RAM1[2], &RAM1[3], &RAM1[4], &RAM1[5], &RAM1[6],

&RAM1[7], &RAM1[8], &RAM1[9], &RAM1[10], &RAM1[11], &RAM1[12], &RAM1[13],

&RAM1[14], &RAM1[15]);

/* grava em memória os valores colocados no hiperterminal */

memwrite();

printf("Done\n\n\r");

/* apaga o buffer */

Rxbfclear();

}

/* caso tenha sido pressionado A */

else if(c=='A')

{

while(1)

{

/* pede qual o valor em memória a ler */

printf("Insira qual o local da memória que quer ler (de 0

a 16)\n\r");

/* apaga o buffer e espera que os valores sejam colocados */

Rxbfclear();

delay_ms(500);

/* recebe os valores */

sscanf(RXbuffer,"%d", &val);

/* lê o valor em memória */

val = memread(val);

/* imprime no hiperterminal o valor lido */

printf("O valor lido na memória é %d\n\r", val);

/* dá a opção de ler outro valor */

printf("Se pretender ler um novo valor pressione 'O', caso

contrário pressione qualquer outra tecla\n\r");

/* apaga o buffer e espera que a opção seja colocada */

Page 22: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

Rxbfclear();

delay_ms(500);

sscanf(RXbuffer,"%s", &c);

/* caso se tenha escolhido ler um novo */

if(c=='O')

/* repete o procedimento */

continue;

else

/* sai desta opção */

break;

printf("Done\n\n\r");

/* apaga o buffer */

Rxbfclear();

}

}

}

/* apaga o buffer */

Rxbfclear();

}

}

/* função de interrupção da UART */

void __attribute__((__interrupt__,auto_psv)) _U2RXInterrupt(void)

{

/* apaga a flag da interrupção */

IFS1bits.U2RXIF = 0;

while(U2STAbits.URXDA)

{

/*guarda o valor que chega à UART no buffer */

RXbuffer[str_pos] = U2RXREG;

str_pos++;

if(str_pos >= 80)

str_pos = 0;

}

}

Anexo C – Main Code do programa de teste do PWM #include"jtheader.h"

_FOSC(CSW_FSCM_OFF & XT_PLL4); /* define oscilador com PLL 4x */

_FWDT(WDT_OFF); /* desliga watchdog timer */

int main(void)

{

/* configura a uart */

uartconfig();

/* inicia algumas variáveis */

iniciar();

TRISDbits.TRISD0=0;

/* descreve o programa, aqui é pedido para pressionar a tecla F ou I

seguida de ENTER, este procedimento pode ser repetido */

help();

/* variáveis auxiliares para funcionamento do programa */

unsigned int per=0;

int d=0;

char c;

int dutyc=0;

Page 23: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

while(1)

{

if(RXbuffer[str_pos-1] =='\r')

{

sscanf(RXbuffer,"%c", &c);

/* caso tenha sido pressionado F gera um PWM com duty cycle fixo */

if(c=='F')

{

/* pede valores para o período e para o duty cycle */

printf("Insira o valor desejado para o periodo seguido do

valor desejado para o duty cycle\n\r");

/* apaga o buffer e espera que os valores sejam colocados */

Rxbfclear();

delay_ms(7000);

/* recebe os valores */

sscanf(RXbuffer,"%d %d", &per, &dutyc);

/* configura o timer e o oc para gerar a pwm com as definições

requeridas */

OpenTimer2(T2_ON & T2_IDLE_STOP & T2_GATE_OFF & T2_PS_1_1 &

T2_SOURCE_INT, per);

OpenOC1(OC_IDLE_STOP & OC_TIMER2_SRC &

OC_PWM_FAULT_PIN_DISABLE, dutyc, dutyc);

printf("Para terminar a producao da PWM perssione 'S'\n\r");

while(1)

{

/* gera a PWM até se pressionar S */

if(RXbuffer[str_pos-1] =='S')

break;

}

/* quando se pretende parar desliga os módulos timer e oc e

limpa o buffer */

desligar();

}

/* caso tenha sido pressionado I gera um PWM com duty cycle a

incrementar */

else if (c=='I')

{

/* pede o valor para o período */

printf("Insira o valor desejado para o periodo\n\r");

/* apaga o buffer e espera que o valor seja colocado */

Rxbfclear();

delay_ms(7000);

/* recebe os valores */

sscanf(RXbuffer,"%d", &per);

/* configura o timer e o oc para gerar a pwm com as definições

requeridas */

OpenTimer2(T2_ON & T2_IDLE_STOP & T2_GATE_OFF & T2_PS_1_1 &

T2_SOURCE_INT, per);

OpenOC1(OC_IDLE_STOP & OC_TIMER2_SRC &

OC_PWM_FAULT_PIN_DISABLE, 0, 0);

printf("Para terminar a producao da PWM perssione 'S'\n\r");

while(1)

{

/* incrementa o duty cycle do 0 até ao valor do período */

for(dutyc=0; dutyc<per; dutyc++)

Page 24: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

{

/* faz o set do novo duty cycle */

SetDCOC1PWM(dutyc);

delay_ms(30);

/* caso se pressione S pára o procedimento */

if(RXbuffer[str_pos-1] =='S')

{

d=1;

break;

}

}

if(d==1)

break

}

/* quando se pretende parar desliga os módulos timer e oc e

limpa o buffer */

desligar();

}

}

}

}

/* função de interrupção da UART */

void __attribute__((__interrupt__,auto_psv)) _U2RXInterrupt(void)

{

/* apaga a flag da interrupção */

IFS1bits.U2RXIF = 0;

while(U2STAbits.URXDA)

{

/*guarda o valor que chega à UART no buffer */

RXbuffer[str_pos] = U2RXREG;

str_pos++;

if(str_pos >= 80)

str_pos = 0;

}

}

Anexo D – Main Code do programa de teste do ADC (programa usado para ver a característica do painel para várias condições, com objectivo de encontrar o ponto ideal de funcionamento) #include"jtheader.h"

_FOSC(CSW_FSCM_OFF & XT_PLL4); /* define oscilador com PLL 4x */

_FWDT(WDT_OFF); /* desliga watchdog timer */

/* defines de variáveis de configuração do ADC de 10bit*/

#define ADCON1 ADC_MODULE_ON & ADC_IDLE_STOP & ADC_FORMAT_INTG & ADC_CLK_AUTO

& ADC_AUTO_SAMPLING_OFF & ADC_SAMPLE_SIMULTANEOUS & ADC_SAMP_OFF

#define ADCON2 ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_CONVERT_CH_0A &

ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF

#define ADCON3 ADC_SAMPLE_TIME_3 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_12Tcy

#define ADPCF ENABLE_ALL_ANA

#define ADCSSL SCAN_NONE

/* defines de variáveis de configuração do Timer 2 */

#define T2config T2_ON & T2_IDLE_STOP & T2_GATE_OFF & T2_PS_1_1 &

T2_SOURCE_INT

/* defines de variáveis de configuração do Output Compare */

#define OC1config OC_IDLE_STOP & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_DISABLE

Page 25: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

/* variáveis auxiliares para trabalhar com interrupções*/

int d=0;

int i=0;

int main(void)

{

/* configura a uart */

uartconfig();

/* inicia algumas variáveis */

iniciar();

TRISDbits.TRISD0=0;

/* descreve o programa, aqui é pedido para pressionar ENTER, este

procedimento pode ser repetido */

help();

/* variáveis auxiliares para funcionamento do programa, altera-se aqui o

valor do período */

char c;

int dutyc=0;

unsigned int per=740;

while(1)

{

/* começa-se com o duty cycle a 0 */

dutyc=0;

if(RXbuffer[str_pos-1] =='\r')

{

/* limpa o buffer */

Rxbfclear();

/* configura o timer e o oc para gerar a pwm com as definições

requeridas */

OpenTimer2(T2config, per);

OpenOC1(OC1config, 0, 0);

/* configura o ADC requeridas */

OpenADC10(ADCON1, ADCON2, ADCON3, ADPCF, ADCSSL);

SetChanADC10(ADC_CH0_POS_SAMPLEA_AN0 &

ADC_CH0_NEG_SAMPLEA_AN1 & ADC_CHX_POS_SAMPLEA_AN3AN4AN5 &

ADC_CHX_NEG_SAMPLEA_NVREF);

ConfigIntADC10(ADC_INT_PRI_3 & ADC_INT_ENABLE);

while(dutyc<per)

{

/* quando o timer dá sinal que é momento do ADC fazer uma

aquisição */

if(d==1)

{

/* espera 40 us para que a aquisição seja feita

no meio do período da PWM, fugindo assim ao pulo de tensão inicial */

__delay32(295);

/* manda o ADC fazer a aquisição */

ADCON1bits.SAMP=1;

d=0;

}

/* quando o ADC dá sinal que já tem o valor da

conversão */

if(i==1)

{

/* imprime-se no hiperterminal os valores lidos no ADC e o de

duty cycle */

printf("%d\t%d\t%d\n\r", dutyc, ADCBUF0, ADCBUF1);

Page 26: Microprocessadores MEFT 2010/11 Trabalho Final de · PDF fileMicrochip, alguns componentes de electrónica disponíveis no laboratório, um ... A tabela obtida é então guardada na

/* incrementa e faz set do novo duty cycle*/

dutyc++;

SetDCOC1PWM(dutyc);

i=0;

}

}

/* no final o programa desliga todos os periféricos */

desligar();

}

}

}

/* função de interrupção da UART */

void __attribute__((__interrupt__,auto_psv)) _U2RXInterrupt(void)

{

/* apaga a flag da interrupção */

IFS1bits.U2RXIF = 0;

while(U2STAbits.URXDA)

{

/*guarda o valor que chega à UART no buffer */

RXbuffer[str_pos] = U2RXREG;

str_pos++;

if(str_pos >= 80)

str_pos = 0;

}

}

/* função de interrupção do ADC */

void __attribute__((interrupt, no_auto_psv)) _ADCInterrupt(void)

{

/* "activa" a variável que no código vai dizer que chegou o valor de uma

nova leitura */

f=1;

/* apaga a flag da interrupção */

IFS0bits.ADIF = 0;

}

/* função de interrupção do Timer */

void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void)

{

static int x=0;

/* passados 7000 períodos do timer */

if(x++>6999)

{

/* "activa" a variável que no código vai dizer ao ADC para fazer uma

nova aquisição */

x=0;

d=1;

}

/* apaga a flag da interrupção */

IFS0bits.T2IF = 0;

}