Você está na página 1de 79

CONTROLE DE VELOCIDADE PWM (PONTE H MOSFET

IRF3205) -C/ PIC 12F675 (REF252)


14 de outubro de 2016 Claudio LariosMicrocontroladores, Miscelânea, Programas PIC (Compiler CCS "C")
3

Uma forma simples de gerar sinal PWM para fins de controle de motores de tração DC…

Talvez você já tenha visto o uso de motores de corrente contínua (CC) como de limpadores de para-brisas, para movimentar um carro elétrico
para crianças. Ou ainda uma adaptação para cadeira de rodas usando 2 destes motores.
Esta proposta de montagem gera justamente o sinal PWM necessário para controlar a velocidade de 2 motores de corrente contínua. Poderá ser
útil para suas experiências com este tipo de montagem. Veja o esquema abaixo:
Temos 2 potenciômetros acoplados entre si (joystick) de modo que o operador possa movimentar para frente ou trás e também para os lados.
Estes são tipicamente encontrados em controles de vídeo games, como por exemplo, o Play Station.
Quando ocorre movimentos para os lados e ao mesmo tempo aceleramos para frente ou para trás, teremos valores diferentes de PWM nas
saídas para os motores. Em outras palavras, um motor pode estar mais rápido que o outro dependendo do ângulo que se aciona o joystick
(movimento em diagonal). Isto permite que se faça curvas para um lado ou outro.

Além das entradas dos potenciômetros temos 3 saídas:


PWM1 – fornece o sinal de controle para o motor 1 de 0 a 100 %
PWM2 – fornece o sinal de controle para o motor 2 de 0 a 100 %
DIR – fornece o sinal que indica movimento para frente ou para trás (direção)

Função Soft:
Esta função permite que não ocorra trancos ao se acionar bruscamente o joystick todo para frente ou para trás. A aceleração será de forma
gradativa e de natureza ‘suave’. Se um jumper for colocado no pino 4 com o gnd, esta função será desativada (uso em testes da centralização
do joystick apenas). O grau de suavidade pode ser ajustado no arquivo “C” por meio de um ‘define’ sendo necessário depois recompilar para
obter o novo hex.
A frequência do PWM gerado está por volta dos 60 Hertz, o que poderá gerar algum zumbido nos motores quando em funcionamento.
Para ilustrar de forma didática apenas, como poderia ser usado este gerador de PWM para tração, veja o esquema abaixo:
Suponha que você deseja adaptar motores elétricos a uma cadeira de rodas e criar o necessário para opera-la.
Talvez você decida usar motores de limpadores de para-brisas de caminhão, de 24 Volts de trabalho, facilmente encontrado em autopeças e em
desmanches. Então terá que adaptar uma engrenagem ou polia em seu eixo de saída, para acionar uma corrente ou mesmo uma correia
dentada, que transmitirá o movimento por meio de outra engrenagem ou polia, de diâmetro maior, fixada na roda. Como é apenas um exemplo,
não iremos entrar em detalhes na parte mecânica.
Vamos então analisar um pouco sobre o comando para os motores.
Atualmente é possível obter transistores MOSFET de alta corrente de trabalho entre dreno e supridouro, como o IRF3205, da International
Rectifier. Quando devidamente polarizado, permite operar com correntes de até 110 Amperes!
Por isso são muito empregados nas pontes H usadas juntamente com motores de tração DC.
Também encontramos muitos esquemas destas pontes com este componente na internet. Muitos reclamam de montar alguns destes esquemas
e logo que funcionam, ocorre a queima dos MOSFETs dos lados superior da ponte H. Isto acontece por erro de polarização. Para que a
condução seja plena entre dreno e supridouro, temos que ter uma tensão em torno de 10 Volts entre a gate e o supridouro. Caso isto não
aconteça, o transistor trabalhará na zona resistiva dissipando muito calor, levando a sua destruição.
No caso de uma ponte feita somente com MOSFET tipo N, será necessário garantir esta tensão entre gate e supridouro. Existe diversos métodos
para isto, mas no esquema acima foi usado um elevador de tensão (step-up) construido com base em um circuito integrado 555, oscilando
aproximadamente em 125 khz. Como a tensão de trabalho máxima do 555 é de 18 volts, foi usado a tensão de 12 volts para alimentar esta
fonte chaveada elevadora. Na sua saída obtemos 36 volts, mais do que suficiente para fazer conduzir plenamente os MOSFET da parte superior
da ponte H. Note que no esquema temos um ‘trimpot’ que permite aumentar ou diminuir esta tensão. Mas ela não poderá ser menor que 10
Volts medido entre gate e supridouro com o transistor conduzindo uma carga.Também não pode ser superior a 20 volts, que é o limite máximo
que o transistor suporta com segurança. NOTA: Esta fonte chaveada elevadora de 12 para 36V foi testada em placa de breadboard e funcionou
perfeitamente.
Para levar o sinal PWM do pic para a ponte H foi usado optoacopladores 4N25, por ser facilmente encontrado nas lojas de componentes e em
sucata eletrônicas. Um par complementar de transistores BC546/556 facilitam a carga e descarga da gate de forma rápida, evitando
aquecimentos por chaveamentos. Dependendo da aplicação, podem até ser suprimidos, ficando somente os optoacopladores e os resistores de
10k nas gates. NOTA: Foram feitos testes de condução plena usando os optoacopladores conforme o esquema acima, em placa de breadboard e
foi plenamente funcional.
No esquema foi colocado disjuntores térmicos de proteção em caso de curto, um para cada motor e sua respectiva ponte H. O valor de 60
Amperes foi escolhido a título de exemplo, como um provável valor, tendo-se que adequar melhor conforme a corrente do motor efetivamente
usado (ex. 125% da corrente máxima do motor). A alimentação vem de 2 baterias automotivas de 12 Volts/60 Amp/h em série. Foram usados
alguns reguladores de tensão para obter os 12 Volts e depois os 5 Volts para o PIC.
Os cabos que vão dos MOSFET até os motores tem que ter área de seção compatível com a grande corrente que neles circulará. No caso de
usar circuito impresso, as trilhas que ligam o dreno e supridouro devem ser reforçadas com fios estanhados, para possam suportar a grande
corrente sem serem destruídas. Os MOSFETs devem ser montados em bons dissipadores térmicos, devidamente isolados e com pasta térmica de
boa qualidade.
Obs. Como esta montagem é de carater experimental e didática está sujeita a “bugs” ainda não detectados.
Estão sendo fornecidos os arquivos para que cada hobista possa alterar o programa segundo suas necessidades.
Segue pasta com os arquivos desta montagem:

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

//

// PWM_TRAÇÃO.C

//

// c/ PIC 12F675

//

//

// OBJETIVO: GERADOR DE PWM DE 0 A 100% PARA CONTROLE DE VELOCIDADE E DIREÇÃO

// APLICAÇÃO:TRAÇÃO DE VEICULOS ELÉTRICOS (EX.CADEIRA DE RODAS MOTORIZADA)

// COM 2 MOTORES INDEPENDENTES - VIA PONTE H MOSFET (IR3205)

//

//

// AUTOR: CLÁUDIO LÁRIOS

//

// INÍCIO: 11/11/2016 TÉRMINO: 14/10/2016


//

// USO PARA FINS DIDÁTICOS APENAS.

// ESTE ARQUIVO É PARTE INTEGRANTE DO BLOG LARIOS.TECNOLOGIA.WS

//==============================================================================

//

//==============================================================================

// NOTA IMPORTANTE PARA OBTER O FUNCIONAMENTO DESTE SOFTWARE

//==============================================================================

// ATENÇÃO: CERTIFIQUE DE EXISTIR O BYTE DE CALIBRAÇÃO NO ENDEREÇO 3FFH DA FLASH

// Caso tenha sido apagado acidentalmente, ao ligar, após a programação do pic,

// NÃO funcionará. O programa irá fazer um 'call'para buscar o byte de calibra-

// ção, mas não encontrará a instrução de retorno 'retlw xx'. Isto fará o progra-

// se perder, resetando continuamente.

// COMO SABER SE TENHO O BYTE DE CALIBRAÇÃO NO PIC?

// LENDO A FLASH COM UM PROGRAMADOR, DEVERÁ SER ENCONTRADO NO ENDEREÇO 0X3FF, UM

// VALOR COMEÇANDO COM 34 SEGUIDO DE 2 DIGITOS. EX. 3480. (34=RETLW 80= LITERAL
// QUE SERÁ RETORNADO EM 'W' PARA CARGA DO REGISTRADOR '0SCCAL'.

// #define PERDI_BYTE_CALIBRACAO

//Descomente o acima se você tem um pic que foi apagado o byte de calibração.

//Será substituido por valor padrão que permita a operação do circuito.

//

//==============================================================================

//

// DEFINIÇÕES GERAIS DO PROGRAMA

//

//==============================================================================
#include <12F675.h> // includes

#device adc=8

#ignore_warnings 203 //desconsidera mensagem de 'condition always true'

#fuses INTRC_IO,NOWDT,NOPROTECT, NOMCLR ,BROWNOUT, PUT // palavra configuração

#use delay(clock=4000000) // clock para 4 mhz

#use fast_io(A) // sentido das portas feita pelo programador

#ifdef PERDI_BYTE_CALIBRACAO // calibração do oscilador interno do pic

#ROM 0X3FF = {0X3480}//máxima freq= 0x34fc ;média=0x3480; minima=0x3400

#endif

//BYTES

#byte GPIO = 0X05

#byte TRISIO = 0X85

#byte timer0 = 0x01 // declara timer 0


//BITS

#bit m2t = 0X05.2 // PINO 5

#bit dir = 0X05.5 // PINO 2 //saída indicadora de direção frente ou tras

#bit m1t = 0X05.4 // PINO 3

#bit soft = 0x05.3 // PINO 4

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

// TRIS-STATE GPIO 543210 PINOS 2,3,4,5,6,7 -> '0' SAÍDA E '1' ENTRADA

int8 const TRIS_GPIO = 0b001011; //SENTIDO DAS PORTAS

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

int8 const jan__central_desl = 0x07 ; // janela onde saída= 0 (cursor centrado)

//==============================================================================
//variáveis globais

int8 vpwm1,vpwm2,xvpwm1,xvpwm2,pwm,kpwm2,pot1,pot2,spot1,spot2;// reg. globais

int1 flag_sup127FT,flag_sup127ED ;

// valores para direção

#define r_1 0x15// velocidade iguais dos motores

#define r_2 0x2a//75% em um motor

#define r_3 0x3f//50% em um motor

#define r_4 0x54//25% em um motor

#define r_5 0x80//um motor desligado


//==============================================================================

// DECLARAÇÃO DE PROTÓTIPOS DE SUBROTINAS E FUNÇÕES

//==============================================================================

void init_ram();

void acionar ();

void reset_rx ();

void get_rx();

//==============================================================================

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

//

// SUBROTINAS E FUNÇÕES DO PROGRAMA

//

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

//==============================================================================

//==============================================================================
// LE A TENSÃO DOS POTENCIÔMETROS DE FRENTE/RÉ E ESQ/DIR

//==============================================================================

void get_pots(){

set_adc_channel(0);//esq/dir

delay_us(50);

spot1=read_adc();

pot1=read_adc();

set_adc_channel(1);//frente/tras

delay_us(50);
if(soft){

spot2=read_adc();

if(spot2>127){

if(pot2<spot2)pot2++;//acelaração gradativa

if(pot2>spot2)pot2=spot2; //desaceleração imediata

else{//<=127

if(pot2>spot2)pot2--;//acelaração gradativa

if(pot2<spot2)pot2=spot2; //desaceleração imediata

else{

pot2=read_adc();

}
}

/*

//==============================================================================

// LE A TENSÃO DOS POTENCIÔMETROS DE FRENTE/RÉ E ESQ/DIR

//==============================================================================

void get_pots(){

set_adc_channel(0);//esq/dir

delay_us(50);

pot1=read_adc();

set_adc_channel(1);//frente/tras

delay_us(50);
pot2=read_adc();

*/

//==============================================================================

// AJUSTA NOVOS VALORE DE PWM PARA OS MOTORES

//==============================================================================

void adj_pwm(){

if((pwm<=vpwm2)&&(jan__central_desl<vpwm2)) { m2t=1;}

else { m2t=0;}

if((pwm<=vpwm1) &&(jan__central_desl<vpwm1)) { m1t=1;}

else { m1t=0;}

}
//==============================================================================

// DETERMINA VALORES DE PWM DO MOTOR ESQUERDO

//==============================================================================

void pwm_porcent_A(){

if(vpwm1<r_1){vpwm1=vpwm2; return;}//mesma rotação

if(vpwm1<r_2){vpwm1=(vpwm2>>2)+ (vpwm2>>1); return;}//75%

if(vpwm1<r_3){vpwm1=vpwm2>>1; return;}//50%

if(vpwm1<r_4){vpwm1=vpwm2>>2; return;}//25%

if(vpwm1<r_5){vpwm1=0; return;}//0%

//==============================================================================

// DETERMINA VALORES DE PWM DO MOTOR DIREITO

//==============================================================================
void pwm_porcent_B(){

if(vpwm1<r_1){vpwm1=vpwm2; return;}//mesma rotação

if(vpwm1<r_2){vpwm2=(vpwm2>>2)+ (vpwm2>>1); vpwm1=kpwm2; return;}//75%

if(vpwm1<r_3){vpwm2=vpwm2>>1; vpwm1=kpwm2; return;}//50%

if(vpwm1<r_4){vpwm2=vpwm2>>2; vpwm1=kpwm2; return;}//25%

if(vpwm1<r_5){vpwm2=0; vpwm1=kpwm2; return;}//0%

//==============================================================================

// ACIONAMENTOS DE SAÍDAS DOS BOTÕES E CARGA DOS VALORES DE PWM

//==============================================================================

void acionar (){

xvpwm1=pot1; //carrega valor do pwm para canal 1 (0-5v) pot. centro=0 v

xvpwm2=pot2; //carrega valor do pwm para canal 2 (0-5v) pot. centro=0 v


}

//==============================================================================

// INICIALIZAÇÃO DE REGISTRADORES NA RAM

//==============================================================================

void init_ram(){

TRISIO= TRIS_GPIO;// ajusta trisio

//desliga saidas dos motores 1 e 2

m1t=0;

m2t=0;

dir=1; //para frente

pot1=127;//valores iniciais

pot2=127;//valores iniciais

vpwm1=129;
vpwm2=129;

//==============================================================================

// FIM DAS SUBROTINAS GERAIS

//==============================================================================

//==============================================================================

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

// ROTINA DE INTERRUPÇÃO DO TIMER 1

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

//==============================================================================

#int_timer1
void isr_tmr1(){

set_timer1(0xffff - 160); // carga: timer 1 irá interromper a cada 140 us //

++pwm;

//==============================================================================

// LÓGICA P/ CENTRALIZAR O MINIMO DO PWM (0-5V,m1t/m1f) P/ MEIO DO POTENCIOMETRO

//==============================================================================

if (pwm>=128){

pwm=0;

if(xvpwm2>127) { flag_sup127FT=1; dir=0; vpwm2= (xvpwm2-128) ; }

else { flag_sup127FT=0; dir=1; vpwm2= (127-xvpwm2) ; }

kpwm2=vpwm2;
if(xvpwm1>127) { flag_sup127ED=1; vpwm1= (xvpwm1-128) ; pwm_porcent_A();}

else { flag_sup127ED=0; vpwm1= (127-xvpwm1); pwm_porcent_B(); }

adj_pwm();

}//void isr_tmr1()

//==============================================================================

// FIM DA ROTINA DE INTERRUPÇÃO DO TIMER 1

//==============================================================================

//==============================================================================

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

//

// ROTINA PRINCIPAL
//

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

//==============================================================================

//==============================================================================

// INICIALIZAÇÃO DE PORTAS E REGISTRADORES

//==============================================================================

void main(){

#define ACEL_SOFT 10 //aceleração soft normal (5=rápido / 20=lento)

setup_adc_ports(sAN0|sAN1|VSS_VDD );//ajusta canal 0 e 1

setup_adc(ADC_CLOCK_DIV_8);//frequencia de amostragem

setup_comparator(nc_nc_nc_nc); // desliga comparadores

setup_counters (RTCC_INTERNAL,RTCC_DIV_1); //timer 0 interno /1

setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //timer1 /1


ENABLE_INTERRUPTS(int_timer1); // liga interrupção por overflow do timer1

init_ram();

TRISIO= TRIS_GPIO;// ajusta sentido das portas de entrada e saídas

enable_interrupts(GLOBAL); // liga interrupção geral

//==============================================================================

// LOOP PRINCIPAL DE REPETIÇÃO

//==============================================================================

for(;;) {

//==============================================================================

// TESTA POR UMA RECEPÇÃO

//==============================================================================

get_pots(); //lê os potenciômetros que fornecerão novos valores de pwm

acionar(); //temos uma recepção correta, acionar saídas


delay_ms(ACEL_SOFT);//delay (ajusta velocidade da aceleração 'soft')

}// for(;;)

}//void main()

//==============================================================================

// FIM DA ROTINA PRINCIPAL

//==============================================================================

//==============================================================================

// FIM DO PROGRAMA

//==============================================================================
Código EX.

:1000000000308A0030280000831A0A28A200030E5C

:10001000A3000F288312A200030EA300A3140A0852

:10002000A7008A018313A20E0408A4002008A500DB

:100030002108A60083128C308400001C21280C1893

:100040003628240884002508A0002608A1002708D7

:100050008A00230E83008312220EA3188316090040

:10006000FF238316900000308A004629FF308F005E

:100070005F308E00AC0A2C087F3C0318BE28AC0110

:100080002B087F3C03184A283214851280302B023B

:10009000A9004F28321085162B087F3CA90029089B

:1000A000AD002A087F3C03188728B21480302A024A

:1000B000A8002808143C031C60282908A8008628EA
:1000C0002808293C031C6E28290CB400B40C3F30CE

:1000D000B4050310290C3407A800862828083E3CE4

:1000E000031C76280310290CA80086282808533CF6

:1000F000031C8028290CA800A80C3F30A8058628DE

:1001000028087F3C031C8628A8018628BE28B21038

:100110002A087F3CA8002808143C031C92282908C0

:10012000A800BE282808293C031CA228290CB400DA

:10013000B40C3F30B4050310290C3407A9002D0876

:10014000A800BE2828083E3C031CAB280310A90CBD

:100150002D08A800BE282808533C031CB628A90C6B

:10016000A90C3F30A9052D08A800BE2828087F3C0F

:10017000031CBE28A9012D08A800BE282C082902AE

:10018000031CC8282908073C0318C8280515C928D6

:1001900005112C082802031CD3282808073C031843

:1001A000D3280516D42805120C108A1121280B30EB

:1001B0008316850083120512051185167F30AE0067
:1001C000AF008130A800A90087290030A1001F08D6

:1001D000C33921049F001030A000A00BED280000BF

:1001E0009F149F18F1281E08B0009F149F18F6282E

:1001F0001E08AE000430A1001F08C33921049F006F

:100200001030A000A00B02290000851D26299F1494

:100210009F1808291E08B10031087F3C03181B29CC

:1002200031082F02031CAF0A2F08310203181A29C4

:100230003108AF0025292F083102031CAF03310814

:100240002F02031825293108AF002B299F149F186E

:1002500027291E08AF008E292E08AA002F08AB0000

:100260008F29333084000008031945290130A1008B

:10027000A001A00B3929A10B38294A30A000A00BFE

:100280003F2900000000800B3629922984011F308D

:1002900083051F08BF399F0083161F08F0390F38E8

:1002A0009F00073083129F001F08BF399F008316ED

:1002B0001F08F03903389F001F088F3910389F003E
:1002C00083129F131F14073099008316050803300B

:1002D0008312A000A00B6A2919088C110830A00015

:1002E000A01D7A2907308101813084000008C039BF

:1002F0000F3880006400813084000008C039200479

:1003000080008530900083160C148312D7280B30A0

:1003100083168500C03083128B04E5282C290A300F

:08032000B30031298D296300AF

:02400E00C439B3

:00000001FF

;PIC12F675

CCS PCM C Compiler, Version 3.200

0000: MOVLW 00

0001: MOVWF 0A

0002: GOTO 030


0003: NOP

0004: BTFSC 03.5

0005: GOTO 00A

0006: MOVWF 22

0007: SWAPF 03,W

0008: MOVWF 23

0009: GOTO 00F

000A: BCF 03.5

000B: MOVWF 22

000C: SWAPF 03,W

000D: MOVWF 23

000E: BSF 23.1

000F: MOVF 0A,W

0010: MOVWF 27

0011: CLRF 0A

0012: BCF 03.7


0013: SWAPF 22,F

0014: MOVF 04,W

0015: MOVWF 24

0016: MOVF 20,W

0017: MOVWF 25

0018: MOVF 21,W

0019: MOVWF 26

001A: BCF 03.5

001B: MOVLW 8C

001C: MOVWF 04

001D: BTFSS 00.0

001E: GOTO 021

001F: BTFSC 0C.0

0020: GOTO 036

0021: MOVF 24,W

0022: MOVWF 04
0023: MOVF 25,W

0024: MOVWF 20

0025: MOVF 26,W

0026: MOVWF 21

0027: MOVF 27,W

0028: MOVWF 0A

0029: SWAPF 23,W

002A: MOVWF 03

002B: BCF 03.5

002C: SWAPF 22,W

002D: BTFSC 23.1

002E: BSF 03.5

002F: RETFIE

0030: CALL 3FF

0031: BSF 03.5

0032: MOVWF 10
0033: MOVLW 00

0034: MOVWF 0A

0035: GOTO 146

.................... ////////////////////////////////////////////////////////////////////////////////

.................... //

.................... // PWM_TRAÇÃO.C

.................... //

.................... // c/ PIC 12F675

.................... //

.................... //

.................... // OBJETIVO: GERADOR DE PWM DE 0 A 100% PARA CONTROLE DE VELOCIDADE E DIREÇÃO

.................... // APLICAÇÃO:TRAÇÃO DE VEICULOS ELÉTRICOS (EX.CADEIRA DE RODAS MOTORIZADA)

.................... // COM 2 MOTORES INDEPENDENTES - VIA PONTE H MOSFET (IR3205)

.................... //

.................... //

.................... // AUTOR: CLÁUDIO LÁRIOS


.................... //

.................... // INÍCIO: 11/11/2016 TÉRMINO: 14/10/2016

.................... //

.................... // USO PARA FINS DIDÁTICOS APENAS.

.................... // ESTE ARQUIVO É PARTE INTEGRANTE DO BLOG LARIOS.TECNOLOGIA.WS

.................... //==============================================================================

.................... //

.................... //==============================================================================

.................... // NOTA IMPORTANTE PARA OBTER O FUNCIONAMENTO DESTE SOFTWARE

.................... //==============================================================================

.................... // ATENÇÃO: CERTIFIQUE DE EXISTIR O BYTE DE CALIBRAÇÃO NO ENDEREÇO 3FFH DA FLASH

.................... // Caso tenha sido apagado acidentalmente, ao ligar, após a programação do pic,

.................... // NÃO funcionará. O programa irá fazer um 'call'para buscar o byte de calibra-

.................... // ção, mas não encontrará a instrução de retorno 'retlw xx'. Isto fará o progra-

.................... // se perder, resetando continuamente.

.................... // COMO SABER SE TENHO O BYTE DE CALIBRAÇÃO NO PIC?


.................... // LENDO A FLASH COM UM PROGRAMADOR, DEVERÁ SER ENCONTRADO NO ENDEREÇO 0X3FF, UM

.................... // VALOR COMEÇANDO COM 34 SEGUIDO DE 2 DIGITOS. EX. 3480. (34=RETLW 80= LITERAL

.................... // QUE SERÁ RETORNADO EM 'W' PARA CARGA DO REGISTRADOR '0SCCAL'.

....................

....................

....................

.................... // #define PERDI_BYTE_CALIBRACAO

....................

....................

....................

.................... //Descomente o acima se você tem um pic que foi apagado o byte de calibração.

.................... //Será substituido por valor padrão que permita a operação do circuito.

.................... //

.................... //==============================================================================

.................... //

.................... // DEFINIÇÕES GERAIS DO PROGRAMA


.................... //

.................... //==============================================================================

....................

.................... #include <12F675.h> // includes

.................... //////// Standard Header file for the PIC12F675 device ////////////////

.................... #device PIC12F675

.................... #list

....................

.................... #device adc=8

.................... #ignore_warnings 203 //desconsidera mensagem de 'condition always true'

....................

.................... #fuses INTRC_IO,NOWDT,NOPROTECT, NOMCLR ,BROWNOUT, PUT // palavra configuração

.................... #use delay(clock=4000000) // clock para 4 mhz

0131: MOVLW 33

0132: MOVWF 04
0133: MOVF 00,W

0134: BTFSC 03.2

0135: GOTO 145

0136: MOVLW 01

0137: MOVWF 21

0138: CLRF 20

0139: DECFSZ 20,F

013A: GOTO 139

013B: DECFSZ 21,F

013C: GOTO 138

013D: MOVLW 4A

013E: MOVWF 20

013F: DECFSZ 20,F

0140: GOTO 13F

0141: NOP

0142: NOP
0143: DECFSZ 00,F

0144: GOTO 136

0145: GOTO 192 (RETURN)

.................... #use fast_io(A) // sentido das portas feita pelo programador

....................

.................... #ifdef PERDI_BYTE_CALIBRACAO // calibração do oscilador interno do pic

.................... #ROM 0X3FF = {0X3480}//máxima freq= 0x34fc ;média=0x3480; minima=0x3400

.................... #endif

.................... //BYTES

.................... #byte GPIO = 0X05

.................... #byte TRISIO = 0X85

.................... #byte timer0 = 0x01 // declara timer 0

....................

.................... //BITS

....................

.................... #bit m2t = 0X05.2 // PINO 5


.................... #bit dir = 0X05.5 // PINO 2 //saída indicadora de direção frente ou tras

.................... #bit m1t = 0X05.4 // PINO 3

.................... #bit soft = 0x05.3 // PINO 4

....................

....................

.................... //------------------------------------------------------------------------------

.................... // TRIS-STATE GPIO 543210 PINOS 2,3,4,5,6,7 -> '0' SAÍDA E '1' ENTRADA

.................... int8 const TRIS_GPIO = 0b001011; //SENTIDO DAS PORTAS

.................... //------------------------------------------------------------------------------

.................... int8 const jan__central_desl = 0x07 ; // janela onde saída= 0 (cursor centrado)

.................... //==============================================================================

....................

....................

....................

....................

.................... //variáveis globais


.................... int8 vpwm1,vpwm2,xvpwm1,xvpwm2,pwm,kpwm2,pot1,pot2,spot1,spot2;// reg. globais

.................... int1 flag_sup127FT,flag_sup127ED ;

....................

....................

.................... // valores para direção

.................... #define r_1 0x15// velocidade iguais dos motores

.................... #define r_2 0x2a//75% em um motor

.................... #define r_3 0x3f//50% em um motor

.................... #define r_4 0x54//25% em um motor

.................... #define r_5 0x80//um motor desligado

....................

....................

....................

.................... //==============================================================================

.................... // DECLARAÇÃO DE PROTÓTIPOS DE SUBROTINAS E FUNÇÕES

.................... //==============================================================================
.................... void init_ram();

.................... void acionar ();

.................... void reset_rx ();

.................... void get_rx();

.................... //==============================================================================

.................... ////////////////////////////////////////////////////////////////////////////////

.................... //

.................... // SUBROTINAS E FUNÇÕES DO PROGRAMA

.................... //

.................... ////////////////////////////////////////////////////////////////////////////////

.................... //==============================================================================

.................... //==============================================================================

.................... // LE A TENSÃO DOS POTENCIÔMETROS DE FRENTE/RÉ E ESQ/DIR

.................... //==============================================================================

....................

.................... void get_pots(){


....................

.................... set_adc_channel(0);//esq/dir

00E5: MOVLW 00

00E6: MOVWF 21

00E7: MOVF 1F,W

00E8: ANDLW C3

00E9: IORWF 21,W

00EA: MOVWF 1F

.................... delay_us(50);

00EB: MOVLW 10

00EC: MOVWF 20

00ED: DECFSZ 20,F

00EE: GOTO 0ED

00EF: NOP

.................... spot1=read_adc();
00F0: BSF 1F.1

00F1: BTFSC 1F.1

00F2: GOTO 0F1

00F3: MOVF 1E,W

00F4: MOVWF 30

.................... pot1=read_adc();

00F5: BSF 1F.1

00F6: BTFSC 1F.1

00F7: GOTO 0F6

00F8: MOVF 1E,W

00F9: MOVWF 2E

....................

....................

....................

.................... set_adc_channel(1);//frente/tras

00FA: MOVLW 04
00FB: MOVWF 21

00FC: MOVF 1F,W

00FD: ANDLW C3

00FE: IORWF 21,W

00FF: MOVWF 1F

.................... delay_us(50);

0100: MOVLW 10

0101: MOVWF 20

0102: DECFSZ 20,F

0103: GOTO 102

0104: NOP

....................

....................

.................... if(soft){

0105: BTFSS 05.3

0106: GOTO 126


.................... spot2=read_adc();

0107: BSF 1F.1

0108: BTFSC 1F.1

0109: GOTO 108

010A: MOVF 1E,W

010B: MOVWF 31

.................... if(spot2>127){

010C: MOVF 31,W

010D: SUBLW 7F

010E: BTFSC 03.0

010F: GOTO 11B

.................... if(pot2<spot2)pot2++;//acelaração gradativa

0110: MOVF 31,W

0111: SUBWF 2F,W

0112: BTFSS 03.0

0113: INCF 2F,F


.................... if(pot2>spot2)pot2=spot2; //desaceleração imediata

0114: MOVF 2F,W

0115: SUBWF 31,W

0116: BTFSC 03.0

0117: GOTO 11A

0118: MOVF 31,W

0119: MOVWF 2F

.................... }

.................... else{//<=127

011A: GOTO 125

.................... if(pot2>spot2)pot2--;//acelaração gradativa

011B: MOVF 2F,W

011C: SUBWF 31,W

011D: BTFSS 03.0

011E: DECF 2F,F

.................... if(pot2<spot2)pot2=spot2; //desaceleração imediata


011F: MOVF 31,W

0120: SUBWF 2F,W

0121: BTFSC 03.0

0122: GOTO 125

0123: MOVF 31,W

0124: MOVWF 2F

.................... }

.................... }

.................... else{

0125: GOTO 12B

.................... pot2=read_adc();

0126: BSF 1F.1

0127: BTFSC 1F.1

0128: GOTO 127

0129: MOVF 1E,W

012A: MOVWF 2F
.................... }

....................

....................

....................

....................

.................... }

012B: GOTO 18E (RETURN)

.................... /*

.................... //==============================================================================

.................... // LE A TENSÃO DOS POTENCIÔMETROS DE FRENTE/RÉ E ESQ/DIR

.................... //==============================================================================

....................

.................... void get_pots(){

....................

.................... set_adc_channel(0);//esq/dir

.................... delay_us(50);
.................... pot1=read_adc();

....................

.................... set_adc_channel(1);//frente/tras

.................... delay_us(50);

.................... pot2=read_adc();

.................... }

.................... */

....................

.................... //==============================================================================

.................... // AJUSTA NOVOS VALORE DE PWM PARA OS MOTORES

.................... //==============================================================================

.................... void adj_pwm(){

....................

.................... if((pwm<=vpwm2)&&(jan__central_desl<vpwm2)) { m2t=1;}

00BE: MOVF 2C,W


00BF: SUBWF 29,W

00C0: BTFSS 03.0

00C1: GOTO 0C8

00C2: MOVF 29,W

00C3: SUBLW 07

00C4: BTFSC 03.0

00C5: GOTO 0C8

00C6: BSF 05.2

.................... else { m2t=0;}

00C7: GOTO 0C9

00C8: BCF 05.2

....................

.................... if((pwm<=vpwm1) &&(jan__central_desl<vpwm1)) { m1t=1;}

00C9: MOVF 2C,W

00CA: SUBWF 28,W

00CB: BTFSS 03.0


00CC: GOTO 0D3

00CD: MOVF 28,W

00CE: SUBLW 07

00CF: BTFSC 03.0

00D0: GOTO 0D3

00D1: BSF 05.4

.................... else { m1t=0;}

00D2: GOTO 0D4

00D3: BCF 05.4

.................... }

....................

....................

....................

.................... //==============================================================================

.................... // DETERMINA VALORES DE PWM DO MOTOR ESQUERDO

.................... //==============================================================================
.................... void pwm_porcent_A(){

.................... if(vpwm1<r_1){vpwm1=vpwm2; return;}//mesma rotação

0059: MOVF 28,W

005A: SUBLW 14

005B: BTFSS 03.0

005C: GOTO 060

005D: MOVF 29,W

005E: MOVWF 28

005F: GOTO 086

.................... if(vpwm1<r_2){vpwm1=(vpwm2>>2)+ (vpwm2>>1); return;}//75%

0060: MOVF 28,W

0061: SUBLW 29

0062: BTFSS 03.0

0063: GOTO 06E

0064: RRF 29,W


0065: MOVWF 34

0066: RRF 34,F

0067: MOVLW 3F

0068: ANDWF 34,F

0069: BCF 03.0

006A: RRF 29,W

006B: ADDWF 34,W

006C: MOVWF 28

006D: GOTO 086

.................... if(vpwm1<r_3){vpwm1=vpwm2>>1; return;}//50%

006E: MOVF 28,W

006F: SUBLW 3E

0070: BTFSS 03.0

0071: GOTO 076

0072: BCF 03.0

0073: RRF 29,W


0074: MOVWF 28

0075: GOTO 086

.................... if(vpwm1<r_4){vpwm1=vpwm2>>2; return;}//25%

0076: MOVF 28,W

0077: SUBLW 53

0078: BTFSS 03.0

0079: GOTO 080

007A: RRF 29,W

007B: MOVWF 28

007C: RRF 28,F

007D: MOVLW 3F

007E: ANDWF 28,F

007F: GOTO 086

.................... if(vpwm1<r_5){vpwm1=0; return;}//0%

0080: MOVF 28,W

0081: SUBLW 7F
0082: BTFSS 03.0

0083: GOTO 086

0084: CLRF 28

0085: GOTO 086

....................

.................... }

.................... //==============================================================================

.................... // DETERMINA VALORES DE PWM DO MOTOR DIREITO

.................... //==============================================================================

.................... void pwm_porcent_B(){

....................

.................... if(vpwm1<r_1){vpwm1=vpwm2; return;}//mesma rotação

008B: MOVF 28,W

008C: SUBLW 14

008D: BTFSS 03.0


008E: GOTO 092

008F: MOVF 29,W

0090: MOVWF 28

0091: GOTO 0BE

.................... if(vpwm1<r_2){vpwm2=(vpwm2>>2)+ (vpwm2>>1); vpwm1=kpwm2; return;}//75%

0092: MOVF 28,W

0093: SUBLW 29

0094: BTFSS 03.0

0095: GOTO 0A2

0096: RRF 29,W

0097: MOVWF 34

0098: RRF 34,F

0099: MOVLW 3F

009A: ANDWF 34,F

009B: BCF 03.0

009C: RRF 29,W


009D: ADDWF 34,W

009E: MOVWF 29

009F: MOVF 2D,W

00A0: MOVWF 28

00A1: GOTO 0BE

.................... if(vpwm1<r_3){vpwm2=vpwm2>>1; vpwm1=kpwm2; return;}//50%

00A2: MOVF 28,W

00A3: SUBLW 3E

00A4: BTFSS 03.0

00A5: GOTO 0AB

00A6: BCF 03.0

00A7: RRF 29,F

00A8: MOVF 2D,W

00A9: MOVWF 28

00AA: GOTO 0BE

.................... if(vpwm1<r_4){vpwm2=vpwm2>>2; vpwm1=kpwm2; return;}//25%


00AB: MOVF 28,W

00AC: SUBLW 53

00AD: BTFSS 03.0

00AE: GOTO 0B6

00AF: RRF 29,F

00B0: RRF 29,F

00B1: MOVLW 3F

00B2: ANDWF 29,F

00B3: MOVF 2D,W

00B4: MOVWF 28

00B5: GOTO 0BE

.................... if(vpwm1<r_5){vpwm2=0; vpwm1=kpwm2; return;}//0%

00B6: MOVF 28,W

00B7: SUBLW 7F

00B8: BTFSS 03.0

00B9: GOTO 0BE


00BA: CLRF 29

00BB: MOVF 2D,W

00BC: MOVWF 28

00BD: GOTO 0BE

....................

.................... }

.................... //==============================================================================

.................... // ACIONAMENTOS DE SAÍDAS DOS BOTÕES E CARGA DOS VALORES DE PWM

.................... //==============================================================================

....................

.................... void acionar (){

.................... xvpwm1=pot1; //carrega valor do pwm para canal 1 (0-5v) pot. centro=0 v

012C: MOVF 2E,W

012D: MOVWF 2A

.................... xvpwm2=pot2; //carrega valor do pwm para canal 2 (0-5v) pot. centro=0 v
012E: MOVF 2F,W

012F: MOVWF 2B

.................... }

0130: GOTO 18F (RETURN)

....................

....................

.................... //==============================================================================

.................... // INICIALIZAÇÃO DE REGISTRADORES NA RAM

.................... //==============================================================================

.................... void init_ram(){

....................

.................... TRISIO= TRIS_GPIO;// ajusta trisio

00D7: MOVLW 0B

00D8: BSF 03.5

00D9: MOVWF 05
.................... //desliga saidas dos motores 1 e 2

.................... m1t=0;

00DA: BCF 03.5

00DB: BCF 05.4

.................... m2t=0;

00DC: BCF 05.2

.................... dir=1; //para frente

00DD: BSF 05.5

.................... pot1=127;//valores iniciais

00DE: MOVLW 7F

00DF: MOVWF 2E

.................... pot2=127;//valores iniciais

00E0: MOVWF 2F

.................... vpwm1=129;

00E1: MOVLW 81

00E2: MOVWF 28
.................... vpwm2=129;

00E3: MOVWF 29

.................... }

00E4: GOTO 187 (RETURN)

....................

.................... //==============================================================================

.................... // FIM DAS SUBROTINAS GERAIS

.................... //==============================================================================

....................

....................

....................

.................... //==============================================================================

.................... ////////////////////////////////////////////////////////////////////////////////

.................... // ROTINA DE INTERRUPÇÃO DO TIMER 1

.................... ////////////////////////////////////////////////////////////////////////////////

.................... //==============================================================================
....................

.................... #int_timer1

....................

.................... void isr_tmr1(){

....................

.................... set_timer1(0xffff - 160); // carga: timer 1 irá interromper a cada 140 us //

0036: MOVLW FF

0037: MOVWF 0F

0038: MOVLW 5F

0039: MOVWF 0E

.................... ++pwm;

003A: INCF 2C,F

....................

.................... //==============================================================================

.................... // LÓGICA P/ CENTRALIZAR O MINIMO DO PWM (0-5V,m1t/m1f) P/ MEIO DO POTENCIOMETRO


.................... //==============================================================================

.................... if (pwm>=128){

003B: MOVF 2C,W

003C: SUBLW 7F

003D: BTFSC 03.0

003E: GOTO 0BE

.................... pwm=0;

003F: CLRF 2C

....................

.................... if(xvpwm2>127) { flag_sup127FT=1; dir=0; vpwm2= (xvpwm2-128) ; }

0040: MOVF 2B,W

0041: SUBLW 7F

0042: BTFSC 03.0

0043: GOTO 04A

0044: BSF 32.0

0045: BCF 05.5


0046: MOVLW 80

0047: SUBWF 2B,W

0048: MOVWF 29

.................... else { flag_sup127FT=0; dir=1; vpwm2= (127-xvpwm2) ; }

0049: GOTO 04F

004A: BCF 32.0

004B: BSF 05.5

004C: MOVF 2B,W

004D: SUBLW 7F

004E: MOVWF 29

.................... kpwm2=vpwm2;

004F: MOVF 29,W

0050: MOVWF 2D

....................

.................... if(xvpwm1>127) { flag_sup127ED=1; vpwm1= (xvpwm1-128) ; pwm_porcent_A();}

0051: MOVF 2A,W


0052: SUBLW 7F

0053: BTFSC 03.0

0054: GOTO 087

0055: BSF 32.1

0056: MOVLW 80

0057: SUBWF 2A,W

0058: MOVWF 28

.................... else { flag_sup127ED=0; vpwm1= (127-xvpwm1); pwm_porcent_B(); }

0086: GOTO 0BE

0087: BCF 32.1

0088: MOVF 2A,W

0089: SUBLW 7F

008A: MOVWF 28

....................

.................... }
....................

.................... adj_pwm();

....................

.................... }//void isr_tmr1()

.................... //==============================================================================

.................... // FIM DA ROTINA DE INTERRUPÇÃO DO TIMER 1

.................... //==============================================================================

....................

.................... //==============================================================================

.................... ///////////////////////////////////////////////////////////////////////////////

.................... //

.................... // ROTINA PRINCIPAL

.................... //

.................... ////////////////////////////////////////////////////////////////////////////////

.................... //==============================================================================

....................
.................... //==============================================================================

.................... // INICIALIZAÇÃO DE PORTAS E REGISTRADORES

.................... //==============================================================================

....................

00D4: BCF 0C.0

00D5: BCF 0A.3

00D6: GOTO 021

.................... void main(){

.................... #define ACEL_SOFT 10 //aceleração soft normal (5=rápido / 20=lento)

0146: CLRF 04

0147: MOVLW 1F

0148: ANDWF 03,F

0149: MOVF 1F,W

014A: ANDLW BF
014B: MOVWF 1F

014C: BSF 03.5

014D: MOVF 1F,W

014E: ANDLW F0

014F: IORLW 0F

0150: MOVWF 1F

0151: MOVLW 07

0152: BCF 03.5

0153: MOVWF 1F

....................

.................... setup_adc_ports(sAN0|sAN1|VSS_VDD );//ajusta canal 0 e 1

0154: MOVF 1F,W

0155: ANDLW BF

0156: MOVWF 1F

0157: BSF 03.5

0158: MOVF 1F,W


0159: ANDLW F0

015A: IORLW 03

015B: MOVWF 1F

.................... setup_adc(ADC_CLOCK_DIV_8);//frequencia de amostragem

015C: MOVF 1F,W

015D: ANDLW 8F

015E: IORLW 10

015F: MOVWF 1F

0160: BCF 03.5

0161: BCF 1F.7

0162: BSF 1F.0

.................... setup_comparator(nc_nc_nc_nc); // desliga comparadores

0163: MOVLW 07

0164: MOVWF 19

0165: BSF 03.5

0166: MOVF 05,W


0167: MOVLW 03

0168: BCF 03.5

0169: MOVWF 20

016A: DECFSZ 20,F

016B: GOTO 16A

016C: MOVF 19,W

016D: BCF 0C.3

.................... setup_counters (RTCC_INTERNAL,RTCC_DIV_1); //timer 0 interno /1

016E: MOVLW 08

016F: MOVWF 20

0170: BTFSS 20.3

0171: GOTO 17A

0172: MOVLW 07

0173: CLRF 01

0174: MOVLW 81

0175: MOVWF 04
0176: MOVF 00,W

0177: ANDLW C0

0178: IORLW 0F

0179: MOVWF 00

017A: CLRWDT

017B: MOVLW 81

017C: MOVWF 04

017D: MOVF 00,W

017E: ANDLW C0

017F: IORWF 20,W

0180: MOVWF 00

.................... setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //timer1 /1

0181: MOVLW 85

0182: MOVWF 10

.................... ENABLE_INTERRUPTS(int_timer1); // liga interrupção por overflow do timer1

0183: BSF 03.5


0184: BSF 0C.0

.................... init_ram();

0185: BCF 03.5

0186: GOTO 0D7

.................... TRISIO= TRIS_GPIO;// ajusta sentido das portas de entrada e saídas

0187: MOVLW 0B

0188: BSF 03.5

0189: MOVWF 05

.................... enable_interrupts(GLOBAL); // liga interrupção geral

018A: MOVLW C0

018B: BCF 03.5

018C: IORWF 0B,F

....................

.................... //==============================================================================

.................... // LOOP PRINCIPAL DE REPETIÇÃO

.................... //==============================================================================
....................

.................... for(;;) {

.................... //==============================================================================

.................... // TESTA POR UMA RECEPÇÃO

.................... //==============================================================================

....................

.................... get_pots(); //lê os potenciômetros que fornecerão novos valores de pwm

018D: GOTO 0E5

.................... acionar(); //temos uma recepção correta, acionar saídas

018E: GOTO 12C

.................... delay_ms(ACEL_SOFT);//delay (ajusta velocidade da aceleração 'soft')

018F: MOVLW 0A

0190: MOVWF 33

0191: GOTO 131

....................

.................... }// for(;;)


0192: GOTO 18D

.................... }//void main()

....................

.................... //==============================================================================

.................... // FIM DA ROTINA PRINCIPAL

.................... //==============================================================================

....................

....................

....................

....................

....................

.................... //==============================================================================

.................... // FIM DO PROGRAMA

.................... //==============================================================================

....................

.................... // Then, be happy! Enjoy with this assembly!


....................

0193: SLEEP

Configuration Fuses:

Word 1: 39C4 NOWDT NOCPD NOPROTECT NOMCLR PUT INTRC_IO BROWNOUT

Target=cr_pwm2c_3b.HEX

Development_Mode=2

Processor=0x2675

ToolSuite=CCS

[Directories]

Include=

Library=

LinkerScript=
[Target Data]

FileList=cr_pwm2c_3b.c;

BuildTool=C-COMPILER

OptionString=+FM

AdditionalOptionString=

BuildRequired=1

[cr_pwm2c_3b.c]

Type=4

Path=

FileList=

BuildTool=

OptionString=

AdditionalOptionString=

[mru-list]
1=C:\proj\PIC_C\proj_c_g\CR_PWM~1\CR_PWM~1.C

[Windows]

0=0000 C:\proj\PIC_C\proj_c_g\CR_PWM~1\CR_PWM~1.C 0 0 796 451 3 0

[Opened Files]

1=C:\claudio_backup\internet projetos\Z_cadeira_roda\pwm_tracao.c

2=

3=

4=

// Then, be happy! Enjoy with this assembly!

Pwm_tracao

Manuais:
PIC 12F675
4n25 datasheet
IRF3205 datasheet
LM555 datasheet

Você também pode gostar