Interface PPM  - Usando rádio controle de modelismo
Autor: Jean Carlos | Publicado: 2013-09-29T07:54:00-07:00

&nbsp; E ai pessoal, tudo certo?&nbsp; estou voltando aos post’s e gostaria de apresentar a vocês um projeto bacana para quem pretende conciliar duas áreas distintas porém que trazem muitas alegrias a quem lhes concede tempo e empenho, são elas a eletrônica embarcada e o modelismo! &nbsp;  &nbsp; Que tal desenvolvermos um software para agregarmos funções aos nossos modelos? ou quem sabe incrementarmos aquele robô em desenvolvimento para que possamos obter distâncias maiores além de podermos utilizar vários rádios disponíveis no mercado a preço atraentes… bora lá!!! Bom para tanto precisamos entender como funciona o sistema de rádio controle destes utilizados no modelismo, não importando qual área de modelismo se aplica, tanto auto, aero ou helimodelismo utilizam a mesma técnica de controle que se dá através de controle PPM. Controle PPM PPM (Pulse Position Modulation) é a técnica de controle de servos e outros dispositivos utilizados em modelismo que consiste da modulação por posicionamento de pulso, esta técnica já foi vista anteriormente no blog quando abordamos o&nbsp; controle de servomotores e mostramos como gerar os pulsos para controlarmos os dispositivos atuadores (servos). &nbsp;  &nbsp; A abordagem desta vez será inversa, ou seja, iremos aprender a ler um pulso proveniente de um receptor de aeromodelismo a fim de criarmos nossos próprios atuadores, que podem ser chaves digitais On-Off, saídas de tensão proporcionais aos valores dos Sticks do rádio, sistemas de iluminação, automáticos para trens de pouso, sequenciadores de portas, enfim, o que sua imaginação lhe proporcionar! &nbsp; Rádios e Receptores Atualmente os sistemas de radio controle para modelismo sofreram uma merecida atualização no que diz respeito ao meio de comunicação entre rádio e receptor, várias técnicas já foram utilizadas, sendo elas AM(Amplitude Modulada), FM (Frequência Modulada) muito comum até então e por fim a mais utilizada atualmente, a 2.4GHz que utiliza um protocolo baseado em salto de frequência, mais isso no momento não é o foco do nosso projeto, iremos nos concentrar apenas no sinal PPM já processado pelo receptor. &nbsp;  &nbsp; Neste exemplo vamos utilizar um receptor DSMX2 da marca Orange, que possui uma taxa de repetição de frames a cada 22ms, cada frame varia então de 1ms a 2ms correspondentes a posição do Stick do rádio, a alimentação do receptor é de 5V sendo alimentado pela própria placa PK2Lab. &nbsp;  &nbsp; &nbsp; Processamento do sinal PPM Para efetuarmos a análise do sinal PPM pelo microcontrolador podemos efetuar a medição do tempo em que o sinal permanece em nível alto, para isto vamos utilizar o recurso CAPTURE do modulo CCP1 do PIC 16F887. &nbsp;  &nbsp; Bom, temos agora que começar configurando o TMR1 do PIC16F887 para incremento a cada 1us,&nbsp; e a borda de interrupção do módulo CCP1 para captura na borda de subida, assim que este evento for detectado, zeramos os contadores de 16 bits do TMR1 e alteramos a borda de captura para detectar o momento exato em que esse sinal volta a nível baixo, quando isso ocorrer os registradores do TMR1 irão conter o valor exato correspondente diretamente ao tempo em que o sinal permaneceu alto, esse tempo é um espelho do posicionamento do stick do controle. Vale observar que a mudança de sensibilidade de borda do módulo CCP1 gera o disparo errôneo desta interrupção, portanto, temos que tomar a precaução de manter desabilitada essa interrupção durante esta mudança de borda. &nbsp; Programa &nbsp; /****************************************************************************** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JL Audio Manutenção Eletrônica Data: 09/2013Autor: Jean CarlosProjeto: Decodificador de sinais PPMMicroprocessador: PIC16F887Clock do processador: 8MHzEstação de desenvolvimento: PK2LabCompilador: MikroC PRO V4.60.0.0Versão atual:&nbsp; 1.0Descrição: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Este projeto consiste em decodificar os sinais PPM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provenientes da saída de um receptor de rádio controle *******************************************************************************/// Configuração do LCD da placa PK2Lab V.1.1 sbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit; sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit; //Variáveis Globais char txt[7];unsigned int Tempo_L, Tempo_H, Pulso; //Interrupções void interrupt(){if(CCP1IF_bit &amp;&amp; CCP1CON.B0)&nbsp; // Captura por CCP1 e borda como subida... {&nbsp; CCP1IF_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Limpa a flag para nova captura&nbsp; CCP1IE_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Desabilita interrupção por periféricos(CCP1)&nbsp; CCP1CON&nbsp;&nbsp;&nbsp;&nbsp; = 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Configura a borda de captura para DESCIDA.&nbsp; CCP1IE_bit&nbsp; = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Habilita interrupção por periféricos(CCP1)&nbsp; TMR1H&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Zera registradores do TMR1 para contagem de tempo&nbsp; TMR1L&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp; TMR1ON_bit&nbsp; = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Habilita contagem de tempo. } else if(CCP1IF_bit)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CCP1IF_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Limpa a flag para nova captura&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TMR1ON_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp; // Desabilita contagem de tempo.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CCP1IE_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Desabilita interrupção por periféricos(CCP1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CCP1CON&nbsp;&nbsp;&nbsp;&nbsp; = 5;&nbsp;&nbsp;&nbsp;&nbsp; // Configura a borda de captura para SUBIDA. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CCP1IE_bit&nbsp; = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Habilita interrupção por periféricos(CCP1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tempo_H&nbsp;&nbsp;&nbsp;&nbsp; = CCPR1H;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tempo_L&nbsp;&nbsp;&nbsp;&nbsp; = CCPR1L;&nbsp; // Carrega valores de tempo&nbsp;&nbsp; capturado&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } } //Rotina Principal void main(){TRISD&nbsp; = 0b00000000;TRISE&nbsp; = 0b00000000;TRISC&nbsp; = 0b00000100;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Entrada CCP1PORTC&nbsp; = 0b00000000;ANSEL&nbsp; = 0b00000000;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Entradas digitais.ANSELH = 0b00000000;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Entradas digitais.INTCON = 0b11000000;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Liga interruptores GIE e PEIETMR1IE_bit = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Desabilita interrpções de TMR1CCP1IE_Bit = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Habilita interrupções por CAPTURA(CCP1)CCP1CON&nbsp;&nbsp;&nbsp; = 5;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // CCP1 para CAPTURA borda de SUBIDA. T1CKPS1_bit = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Prescaller TMR1 2:1T1CKPS0_bit = 1;TMR1CS_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Clock selecionado -&gt; OSC/4TMR1ON_bit&nbsp; = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Timer -&gt; 1 = Habilita contagem Lcd_Init();Lcd_Cmd(_Lcd_Cursor_Off);Lcd_Cmd(_LCD_CLEAR);Lcd_Out(1,1,"***&nbsp; PK2Lab&nbsp; ***");Lcd_Out(2,1,"Pulso us:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ");Delay_ms(100); while(1){ Delay_ms(100);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Intervalo entre leituras. Pulso = (Tempo_H&lt;&lt;8)+ Tempo_L;&nbsp;&nbsp; // Obtenção do pulso PPM IntToStr(Pulso, txt);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Converte texto para impressão Lcd_Out(2,11,txt);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Mostra Pulso em us no display  if(Pulso &gt; 1600) PORTE.B1 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTE.B1 = 0;  if(Pulso &gt; 1100) PORTD.B0 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B0 = 0;  if(Pulso &gt; 1200) PORTD.B1 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B1 = 0;  if(Pulso &gt; 1300) PORTD.B2 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B2 = 0;&nbsp;&nbsp;&nbsp;  if(Pulso &gt; 1400) PORTD.B3 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B3 = 0;  if(Pulso &gt; 1500) PORTD.B4 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B4 = 0;  if(Pulso &gt; 1600) PORTD.B5 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B5 = 0;  if(Pulso &gt; 1700) PORTD.B6 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B6 = 0;  if(Pulso &gt; 1800) PORTD.B7 = 1;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTD.B7 = 0;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }//while(1)}//main /****************************************************************************** &nbsp; Vídeo do projeto