Controle de servo-motor com PIC

servo

O que a princípio parecia algo simples, transformou-se em um pesadelo; controlar um simples servo-motor RC em PIC.

Quem já o fez em Arduino, sabe o quão simples é, bastando utilizar uma biblioteca própria que inclui exemplos, ou seja, trabalho nulo. Mas você sabe como funciona a comunicação entre um servo-motor e a MCU?

O servo-motor possui um motor DC em seu interior, um conjunto de engrenagens e um pequeno circuito utilizado para intercomunicação. Se você ainda não fez esse controle com nenhuma MCU, repare nesse post e também nesse outro a simplicidade de fazê-lo em Arduino.

Basicamente ele possui 3 fios, sendo o central normalmente vermelho para +5v, o marrom para Ground e no outro canto um fio para comunicação, normalmente laranja. Os modelos mais comuns trabalham a 50Htz com intervalo de pulso de 20ms e um ângulo de abertura de 180°. Também há servos com abertura de apenas 90° e servos que atingem 360° sem (ou com) giro continuo. Pulsos PWM dentro do intervalo de 20ms fazem com que o servo interprete um comando de movimento, variando de 1ms (para – 45°) a 2ms (para +45°). É aí que começa um problema.

Se você nunca teve curiosidade de olhar, edite a biblioteca do Arduino referente ao controle de servos. Repare que até o prescaler necessita ser configurado. Como em PIC (mesmo com IDE) a camada entre o usuário é mais baixa, há um trabalho não tão grande, porém cheio de conceitos.

Para funcionar o servo, a primeira coisa que tive que fazer (depois de dias de pesquisa) foi ajustar o clock da MCU para 8MHz (porque não consegui fazer o servo funcionar com frequência superior, confesso). Nesse post anterior eu cito como configurar o clock utilizando o registrador OSCCON e dou uma breve explicação a respeito dos conjuntos de bits.

Colocarei alguns comentários mais conforme dispuser o código de exemplo, mas não poderei ir muito a fundo porque ainda não tenho o completo entendimento sobre o funcionamento. Portanto, se não funcionar para você, dificilmente eu poderei lhe ajudar a resolver o problema. A MCU utilizada em questão é o PIC16F1827, mas deve funcionar para a maioria dos PICs.




Special Function Register
Trata-se de um controlador de funcionalidades da MCU, tratando I/O, eventos, etc. Há uma variável da MCU que necessita ser monitorada e modificada tanto pelo usuário como pelo sistema. Se você declarar algo no código (lib PWM) e tentar por exemplo, utilizá-la em interrupts() e em main(), obterá um erro. Para permitir que a variável seja manipulada sem controle, então utiliza-se além do monitoramento da MCU, a declaração do tipo volatile.
Sobre o SFR, deixo esse link da wikipedia a respeito.

Abertamente, não foi uma implementação totalmente minha. Tive que entrar em contato pelo fórum da MikroEletronica (tenho uma licença e o suporte é atencioso), então recebi uma explicação muito boa sobre o funcionamento, que está (em inglês) nesse link

Se não quiser queimar neurônios, pegue esse meu código de exemplo e manipule apenas OSCCON e o pino que gerará PWM. E falando em PWM, repare que o pino para essa função foi configurado como ANALóGICO. Se você colocar como digital, o pino estará sempre up e você só ouvirá um ruido do motor, nada de movimento.

Vou traduzir a explicação que recebi, mas já antecipei o link porque não quero tomar o mérito desse cara (que na minha opinião, é um grande hacker). A palavra ‘ticks’ eu mantive, mas traduza como ‘um momento’ ou ‘fração de tempo’.

CCP1CON = 0x0B configura o módulo CCP em modo comparador (trigger special event). Sempre que TMR1 (TMR1H:TMR1L) casar com o CCPR1 (CCPR1H:CCPR1L), o bit CCP1IF bit é ajustado e TMR1 limpo. Os tempos de “ON” e “OFF” são manipulados através do CCPR1.
Se a frequencia PWM é de 50Hz (T = 20 ms) e pretende-se um ciclo de 25%, então os tempos de ON e OFF são: Ton = 5 ms, Toff = T – Ton = 15 ms.
Agora converte-se os valores de tempo para os valores do registor (ticks or counts). Considerando a frequência da MCU configurada à 8 MHz, o timer é incrementado a cada 4 clocks (ciclo de instrução): T = 4 * 1 / 8 = 0.5 us.

A fórumla mais genérica seria: T = 4 / f[MHz] ou em kHz: T = 4000 / __FOSC__ ( __FOSC__ é uma constante definida na IDE MikroC, procure em Help).

Questão: Se T é o tempo de 1 tick então quantos ticks representam a variável de tempo t?
Resposta: 1 : T = N : t => N = t * 1 / T = t * __FOSC__ / 4000

The final formula: N = t * __FOSC__ / 4000 é usada para traduzir o valor do tempo para o valor do registrador (sendo t dado em microseconds).

Neste exemplo em particular, 50Hz PWM é realizada dessa meneira:
1. TMR1 inicia a contagem; SOUT = 1; CCPR1 configurado para casar um tempo de 5ms para ON
2. TMR1 alcança CCPR1 e ocorre a interrupção; TMR1 reinicia automaticamente; SOUT = 0; CCPR1 é ajustado para casar com um tempo de 15 ms OFF
3. TMR1 alcança CCPR1 após 15 ms e o processo de repete outra vez do primeiro passo

“I hope the explanation was clear enough”.

É claríssima, mas envolve alguns conceitos importantes, então acaba parecendo abstrato, porque TMR1 é o Timer1, e a MCU tem também o timer0. CCPR0 também existem, CCP é o módulo que configura PWM, e assim diversos outros detalhes vão incrementando esse post, por isso prefiro ser superficial para não dar informação errada e também para não desanimá-lo com muita informação de uma vez.

Não colocarei video nesse post porque esse código será totalmente aplicado ao cofrinho eletrônico (agora sim, no próximo post) e no video devo explicar algo mais.

Se gostou, não deixe de compartilhar; dê seu like no video e inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Prefere seguir-nos pelo facebook? Basta curtir aqui.

Prefere twitter? @DobitAoByte.

Próximo post a caminho!

Comments

comments

Djames Suhanko

Djames Suhanko é Perito Forense Digital. Já atuou com deployer em sistemas de missão critica em diversos países pelo mundão. Programador Shell, Python, C, C++ e Qt, tendo contato com embarcados ( ora profissionalmente, ora por lazer ) desde 2009.

Um comentário em “Controle de servo-motor com PIC

Deixe uma resposta