Escolar Documentos
Profissional Documentos
Cultura Documentos
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.
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
//
//
//
//
//
//==============================================================================
//
//==============================================================================
//==============================================================================
// ção, mas não encontrará a instrução de retorno 'retlw xx'. Isto fará o progra-
// 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.
//
//==============================================================================
//
//
//==============================================================================
#include <12F675.h> // includes
#device adc=8
#endif
//BYTES
//------------------------------------------------------------------------------
// TRIS-STATE GPIO 543210 PINOS 2,3,4,5,6,7 -> '0' SAÍDA E '1' ENTRADA
//------------------------------------------------------------------------------
//==============================================================================
//variáveis globais
int1 flag_sup127FT,flag_sup127ED ;
//==============================================================================
void init_ram();
void get_rx();
//==============================================================================
////////////////////////////////////////////////////////////////////////////////
//
//
////////////////////////////////////////////////////////////////////////////////
//==============================================================================
//==============================================================================
// 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
else{//<=127
if(pot2>spot2)pot2--;//acelaração gradativa
else{
pot2=read_adc();
}
}
/*
//==============================================================================
//==============================================================================
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();
*/
//==============================================================================
//==============================================================================
void adj_pwm(){
if((pwm<=vpwm2)&&(jan__central_desl<vpwm2)) { m2t=1;}
else { m2t=0;}
else { m1t=0;}
}
//==============================================================================
//==============================================================================
void pwm_porcent_A(){
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%
//==============================================================================
//==============================================================================
void pwm_porcent_B(){
//==============================================================================
//==============================================================================
//==============================================================================
//==============================================================================
void init_ram(){
m1t=0;
m2t=0;
pot1=127;//valores iniciais
pot2=127;//valores iniciais
vpwm1=129;
vpwm2=129;
//==============================================================================
//==============================================================================
//==============================================================================
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//==============================================================================
#int_timer1
void isr_tmr1(){
++pwm;
//==============================================================================
//==============================================================================
if (pwm>=128){
pwm=0;
kpwm2=vpwm2;
if(xvpwm1>127) { flag_sup127ED=1; vpwm1= (xvpwm1-128) ; pwm_porcent_A();}
adj_pwm();
}//void isr_tmr1()
//==============================================================================
//==============================================================================
//==============================================================================
///////////////////////////////////////////////////////////////////////////////
//
// ROTINA PRINCIPAL
//
////////////////////////////////////////////////////////////////////////////////
//==============================================================================
//==============================================================================
//==============================================================================
void main(){
setup_adc(ADC_CLOCK_DIV_8);//frequencia de amostragem
init_ram();
//==============================================================================
//==============================================================================
for(;;) {
//==============================================================================
//==============================================================================
}// for(;;)
}//void main()
//==============================================================================
//==============================================================================
//==============================================================================
// 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
0000: MOVLW 00
0001: MOVWF 0A
0006: MOVWF 22
0008: MOVWF 23
000B: MOVWF 22
000D: MOVWF 23
0010: MOVWF 27
0011: CLRF 0A
0015: MOVWF 24
0017: MOVWF 25
0019: MOVWF 26
001B: MOVLW 8C
001C: MOVWF 04
0022: MOVWF 04
0023: MOVF 25,W
0024: MOVWF 20
0026: MOVWF 21
0028: MOVWF 0A
002A: MOVWF 03
002F: RETFIE
0032: MOVWF 10
0033: MOVLW 00
0034: MOVWF 0A
.................... ////////////////////////////////////////////////////////////////////////////////
.................... //
.................... // PWM_TRAÇÃO.C
.................... //
.................... //
.................... //
.................... //
.................... //
.................... //
.................... //==============================================================================
.................... //
.................... //==============================================================================
.................... //==============================================================================
.................... // 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-
.................... // VALOR COMEÇANDO COM 34 SEGUIDO DE 2 DIGITOS. EX. 3480. (34=RETLW 80= LITERAL
....................
....................
....................
....................
....................
....................
.................... //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.
.................... //
.................... //==============================================================================
.................... //
.................... //==============================================================================
....................
.................... //////// Standard Header file for the PIC12F675 device ////////////////
.................... #list
....................
....................
0131: MOVLW 33
0132: MOVWF 04
0133: MOVF 00,W
0136: MOVLW 01
0137: MOVWF 21
0138: CLRF 20
013D: MOVLW 4A
013E: MOVWF 20
0141: NOP
0142: NOP
0143: DECFSZ 00,F
....................
.................... #endif
.................... //BYTES
....................
.................... //BITS
....................
....................
....................
.................... //------------------------------------------------------------------------------
.................... // TRIS-STATE GPIO 543210 PINOS 2,3,4,5,6,7 -> '0' SAÍDA E '1' ENTRADA
.................... //------------------------------------------------------------------------------
.................... int8 const jan__central_desl = 0x07 ; // janela onde saída= 0 (cursor centrado)
.................... //==============================================================================
....................
....................
....................
....................
....................
....................
....................
....................
....................
.................... //==============================================================================
.................... //==============================================================================
.................... void init_ram();
.................... //==============================================================================
.................... ////////////////////////////////////////////////////////////////////////////////
.................... //
.................... //
.................... ////////////////////////////////////////////////////////////////////////////////
.................... //==============================================================================
.................... //==============================================================================
.................... //==============================================================================
....................
.................... set_adc_channel(0);//esq/dir
00E5: MOVLW 00
00E6: MOVWF 21
00E8: ANDLW C3
00EA: MOVWF 1F
.................... delay_us(50);
00EB: MOVLW 10
00EC: MOVWF 20
00EF: NOP
.................... spot1=read_adc();
00F0: BSF 1F.1
00F4: MOVWF 30
.................... pot1=read_adc();
00F9: MOVWF 2E
....................
....................
....................
.................... set_adc_channel(1);//frente/tras
00FA: MOVLW 04
00FB: MOVWF 21
00FD: ANDLW C3
00FF: MOVWF 1F
.................... delay_us(50);
0100: MOVLW 10
0101: MOVWF 20
0104: NOP
....................
....................
.................... if(soft){
010B: MOVWF 31
.................... if(spot2>127){
010D: SUBLW 7F
0119: MOVWF 2F
.................... }
.................... else{//<=127
0124: MOVWF 2F
.................... }
.................... }
.................... else{
.................... pot2=read_adc();
012A: MOVWF 2F
.................... }
....................
....................
....................
....................
.................... }
.................... /*
.................... //==============================================================================
.................... //==============================================================================
....................
....................
.................... set_adc_channel(0);//esq/dir
.................... delay_us(50);
.................... pot1=read_adc();
....................
.................... set_adc_channel(1);//frente/tras
.................... delay_us(50);
.................... pot2=read_adc();
.................... }
.................... */
....................
.................... //==============================================================================
.................... //==============================================================================
....................
00C3: SUBLW 07
....................
00CE: SUBLW 07
.................... }
....................
....................
....................
.................... //==============================================================================
.................... //==============================================================================
.................... void pwm_porcent_A(){
005A: SUBLW 14
005E: MOVWF 28
0061: SUBLW 29
0067: MOVLW 3F
006C: MOVWF 28
006F: SUBLW 3E
0077: SUBLW 53
007B: MOVWF 28
007D: MOVLW 3F
0081: SUBLW 7F
0082: BTFSS 03.0
0084: CLRF 28
....................
.................... }
.................... //==============================================================================
.................... //==============================================================================
....................
008C: SUBLW 14
0090: MOVWF 28
0093: SUBLW 29
0097: MOVWF 34
0099: MOVLW 3F
009E: MOVWF 29
00A0: MOVWF 28
00A3: SUBLW 3E
00A9: MOVWF 28
00AC: SUBLW 53
00B1: MOVLW 3F
00B4: MOVWF 28
00B7: SUBLW 7F
00BC: MOVWF 28
....................
.................... }
.................... //==============================================================================
.................... //==============================================================================
....................
.................... xvpwm1=pot1; //carrega valor do pwm para canal 1 (0-5v) pot. centro=0 v
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
.................... }
....................
....................
.................... //==============================================================================
.................... //==============================================================================
....................
00D7: MOVLW 0B
00D9: MOVWF 05
.................... //desliga saidas dos motores 1 e 2
.................... m1t=0;
.................... m2t=0;
00DE: MOVLW 7F
00DF: MOVWF 2E
00E0: MOVWF 2F
.................... vpwm1=129;
00E1: MOVLW 81
00E2: MOVWF 28
.................... vpwm2=129;
00E3: MOVWF 29
.................... }
....................
.................... //==============================================================================
.................... //==============================================================================
....................
....................
....................
.................... //==============================================================================
.................... ////////////////////////////////////////////////////////////////////////////////
.................... ////////////////////////////////////////////////////////////////////////////////
.................... //==============================================================================
....................
.................... #int_timer1
....................
....................
0036: MOVLW FF
0037: MOVWF 0F
0038: MOVLW 5F
0039: MOVWF 0E
.................... ++pwm;
....................
.................... //==============================================================================
.................... if (pwm>=128){
003C: SUBLW 7F
.................... pwm=0;
003F: CLRF 2C
....................
0041: SUBLW 7F
0048: MOVWF 29
004D: SUBLW 7F
004E: MOVWF 29
.................... kpwm2=vpwm2;
0050: MOVWF 2D
....................
0056: MOVLW 80
0058: MOVWF 28
0089: SUBLW 7F
008A: MOVWF 28
....................
.................... }
....................
.................... adj_pwm();
....................
.................... //==============================================================================
.................... //==============================================================================
....................
.................... //==============================================================================
.................... ///////////////////////////////////////////////////////////////////////////////
.................... //
.................... //
.................... ////////////////////////////////////////////////////////////////////////////////
.................... //==============================================================================
....................
.................... //==============================================================================
.................... //==============================================================================
....................
0146: CLRF 04
0147: MOVLW 1F
014A: ANDLW BF
014B: MOVWF 1F
014E: ANDLW F0
014F: IORLW 0F
0150: MOVWF 1F
0151: MOVLW 07
0153: MOVWF 1F
....................
0155: ANDLW BF
0156: MOVWF 1F
015A: IORLW 03
015B: MOVWF 1F
015D: ANDLW 8F
015E: IORLW 10
015F: MOVWF 1F
0163: MOVLW 07
0164: MOVWF 19
0169: MOVWF 20
016E: MOVLW 08
016F: MOVWF 20
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
017E: ANDLW C0
0180: MOVWF 00
0181: MOVLW 85
0182: MOVWF 10
.................... init_ram();
0187: MOVLW 0B
0189: MOVWF 05
018A: MOVLW C0
....................
.................... //==============================================================================
.................... //==============================================================================
....................
.................... for(;;) {
.................... //==============================================================================
.................... //==============================================================================
....................
018F: MOVLW 0A
0190: MOVWF 33
....................
....................
.................... //==============================================================================
.................... //==============================================================================
....................
....................
....................
....................
....................
.................... //==============================================================================
.................... //==============================================================================
....................
0193: SLEEP
Configuration Fuses:
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]
[Opened Files]
1=C:\claudio_backup\internet projetos\Z_cadeira_roda\pwm_tracao.c
2=
3=
4=
Pwm_tracao
Manuais:
PIC 12F675
4n25 datasheet
IRF3205 datasheet
LM555 datasheet