Controlando um ESC com FPGA

Usando Kit da Avnet Xilinx Spartan 3A Evaluation Kit

 

 

1 - Funcionamento do ESC

     O funcionamento do ESC é relativamente simples. Ele usa o sistema de controle por PPM ( Pulse Position Modulation  ou Modulação por Posição de Pulso), é um sistema semelhante ao PWM ( Pulse Width Modulation ou Modulação por Largura de Pulso) porém não necessita de uma precisão grande.

      O funcionamento é basicamente o seguinte, você tem um ciclo de 18 a 20 ms, onde 1 a 2 ms é tOn (Tempo Ligado, ou sinal Lógico 1) e 18 a 19 ms de tOff (Tempo Desligado, ou sinal lógico 0), como representa o gráfico abaixo:

Forma de onda do PPM

     Sendo o mínimo do sinal tOn 1ms e o máximo 2ms, a velocidade do motor no ESC é feita através da duração do tOn acima de 1ms e abaixo de 2ms. Pode-se fazer uma associação assim:

1ms => 0%

2ms => 100%

logo

1.5ms => 50%

     Entenderam? É bem simples. O período da onda pode ser qualquer coisa entre 18 e 20ms, o importante para o ESC é o tOn.

 

2 - Idealizando a programação

 

     Vamos agora idealizar um programa que faça essa variação. No FPGA teremos uma fonte de clock (No exemplo aqui 16MHz), dois botões para o controle (Um para aumentar a velocidade, e um para diminuir) e dois leds para referências (Um será usado para detectar que o programa está rodando e outro será a visualização do PPM).

     Primeiro iremos dividir esse clock de 16MHz por 1000 para formar um de 16kHz que tem como período 62.5us. Faremos agora outra divisão para fazer um contador de milesegundos, para isso basta dividirmos o clock que conseguimos por 16. (16 * 62.5us = 1000us = 1ms)

     Como o contador de milesegundos tem 16 posições, podemos usar essas 16 posições para controlar a velocidade, gerando assim 16 velocidades em teoria (na pratica não é bem 16). Armazenaremos o valor da velocidade no registrador de velocidade.

     Temos também de fazer um relógio que conte até 20, para contar o tempo do pulso.

     Feito isso, faremos comparações:

1  - Se a posição do relógio for 0, a saída PPM será nível lógico 1.

2 - Se a posição do relógio for 1 e o contador de posições for igual ou menor que o valor do registrador de velocidade, a saída PPM será nível lógico 1.

3  - Caso não seja nenhuma das duas acima, a saída PPM será nível lógico 0.


     Com estas comparações, já fizemos a saída PPM funcionar de acordo com a velocidade. Porém ainda falta o sistema para incrementar e decrementar o registrador de velocidade. Para isso iremos usar o botão 1 para incrementar, e botão 2 para decrementar. Porém só pode se incrementar/decrementar uma vez com o botão apertado, e para incrementar/decrementar novamente, é necessário soltar o botão novamente. Então teremos que criar dois registradores para gravar o ultimo estado do botão. Adicionalmente, vamos fazer a verificação se o registrador de velocidade já está nos seus valores máximo (16) e mínimo (0). Faremos as seguintes comparações:

1 - Se o botão 1 estiver apertado, e o registrador de estado do botão 1 for nível lógico 0,  verificar se o registrador de velocidade não está no máximo e incrementar o registrador de velocidade.

2 - Se o botão 2 estiver apertado, e o registrador de estado do botão 2 for nível lógico 0,  verificar se o registrador de velocidade não está no mínimo e decrementar o registador de velocidade.

3 - Se o botão 1 não estiver apertado, e o registrador de estado do botão 1 for nível lógico 1, zerar o registrador de estado.

4 - Se o botão 2 não estiver aperto, e o registrador de estado do botão 2 for nível lógico 1, zerar o registrador de estado.

 

    Com tudo isso, estamos prontos para iniciar a programação!

 

3 - Programando

 

      Abra o Xilinx ISE e vá em File -> New Project,

Primeira Tela de Criação de Projeto no ISE

     Preencha o Nome do projeto e o local de trabalho como desejar. Clique em Next

Configurações do projeto

     Acerte as configurações para o seu FPGA, se o teu kit for o mesmo do que o meu (Avnet Xilinx Spartan 3A EVL Kit) as configurações estão listadas na imagem. Clique em Next.

Resumo do Projeto

     Aqui estará as configurações para a criação do projeto, apenas clique em Finish.

     Após isso você estará no workspace do seu projeto recém criado. Precisamos criar um arquivo com o código a ser compilado para o FPGA. Para isso vá em Hierarchy e clique com botão direito e vá em New Source.

Painel Hierarchy

     Na janela que irá abrir, em Select source type, selecione Verilog Module, e em File name coloque main. Clique em next.

Criação de um código

     Agora iremos definir as entradas e saídas do código. Iremos criar 3 entradas e 3 saídas, sendo elas:

Entradas:
clk => Entrada do Clock de 16MHz
button1 => Botão para aumentar a velocidade
button2 => Botão para diminuir a velocidade
Saidas:

 

led1 => Led para amostragem visual do PPM led2 => Led para mostrar o programa rodando ppm => Saída PPM para o ESC

Clique em Next

 

 

Definição de Entradas e Saídas

     Será agora exibido o sumário do código criado. Apenas clique em Finish

Sumário do código criado

     Após isso você estará em uma tela semelhante a essa:

Tela Após criação do código

     Agora vamos a programação do controlador. Iniciaremos definindo parâmetros e registradores. Abaixo tudo que precisamos definir, com seus devidos comentários:

 

parameter clkdividermax = 1000; 	// 16MHz / 1000 = 16kHz = 62.5us
					//Para 1ms  = 16 clocks. 62.5 * 16 = 1000 us = 1ms
parameter clockpositionmax = 20;	//20ms maximos para o relógio
reg [9:0] clkdivider = 0; 		// Contador para dividir o clock, 2^10 = 1024
reg [3:0] position= 0; 			// Overflow com 1ms 4 bits 2^4 = 16  clocks para 1 ms;
reg [4:0] clkpositioncounter= 0; 	// Posição do clock 2^5 = 32, porém só usamos até 20.
reg [3:0] speed = 0; 			// Registrador para a velocidade, 2^4 = 16 velocidades em teoria
wire dividermax = (clkdivider == clkdividermax); // Detecção da posição maxima do contador
wire positionmax = (position == 15); // Detector de overflow
wire clkpositionmaxed = (clkpositioncounter == clockpositionmax); //Detecção da posição maxima do relógio 
reg ppmtmp; // Registrador para a saida PPM

      Com isso, definimos tudo que vamos usar na rotina de contagem/divisão de clock e também na geração do PPM. Vamos então a programação da rotina para gerar o PPM.

//Rotina de contagem e geração do PPM
always @(posedge clk)
begin
    if(dividermax)         clkdivider <= 0;// Se o contador de divisão chegar o limite, ele será resetado     else         clkdivider <= clkdivider +1; // Se não, incrementar.
             if(dividermax) //Incrementar um no contador de milesegundos quando o contador de divisão chegar ao limite.         position <= position+1;              if(position == 15) // Quando o contador de milesegundos marcar um milesegundo, começar o processo do relógio     begin         if(clkpositionmaxed)
            clkpositioncounter <= 0; //Se o contador do relógio chegar a 20ms ele será resetado.         else             clkpositioncounter <= clkpositioncounter + 1; // Caso não, será incrementado         position <= 0; // Resetar o contador de milesegundos
    end     //Se o contador de milesegundos for igual ao registrador de velocidade E estiver no primeiro milesegundo do relógio     //Ou a posição do relógio for 0, a saida do PPM será 1, caso não, será 0     if(((position <= speed) & clkpositioncounter == 1) | clkpositioncounter == 0)         ppmtmp <= 1;     else         ppmtmp <= 0; end

 

     Com isso temos o PPM gerado corretamente, mas ainda precisamos fazer a rotina que incremente e decremente o registrador de velocidade quando pressionado os botões.

//Rotina de incrementação e decrementação do registrador de velocidade.
reg button1pressed, button2pressed; // Registradores para armazenar o estado do botão.
wire speedmax = (speed == 15); // Detecção do valor máximo do registrador de velocidade
wire speedmin = (speed == 0); // Detecção do valor mínimo do registrador de velocidade
always @(posedge clk)
begin

    if(button1 & ~button1pressed) //Se o botão 1 está pressionado, e ele não estava no ciclo passado
    begin
        if(~speedmax) //Se o registrador de velocidade não estiver no maximo, incremente
            speed <= speed + 1;
        button1pressed <= 1; //Marca que o botão 1 foi pressionado     end          if(button2 & ~button2pressed) //Se o botão 2 está pressionado, e ele não estava no ciclo passado     begin         if(~speedmin) //Se o registrador de velocidade não estiver no mínimo, decremente             speed <= speed - 1;         button2pressed <= 1; //Marca que o botão 2 foi pressionado     end          if(~button1 & button1pressed) //Se o botão 1 não estiver pressionado, e no ciclo anterior ele estava, resetar o estado do botão         button1pressed <= 0;         
    if(~button2 & button2pressed) //Se o botão 2 não estiver pressionado, e no ciclo anterior ele estava, resetar o estado do botão         button2pressed <= 0; end

     Agora temos um programa funcional, onde o PPM será gerado baseado no registrador de velocidade speed e a cada toque no botão button1 o registrador será incrementado até o seu valor máximo, e a cada toque no botão button2 o registrador será decrementado até seu valor mínimo. Após isso só resta fazer as associações entre registradores e saidas.

assign ppm = ppmtmp; // Associar saida PPM ao registrador ppmtmp
assign led1 = ppmtmp; // Associar o primeiro led ao registrador ppmtmp
assign led2 = 1; //Associar o segundo led ao nível logico 1

     Terminamos aqui o programa para gerar o PPM. Iremos agora compila-lo e gravar no FPGA.

 

4 - Gerando associações de pinos e compilando programa

 

    Vamos agora associar os pinos virtuais aos pinos reais e compilar o programa. Em Processes: main , abrir a aba User Constrains e clicar em I/O Pin Planning (PlanAhead) Pre-Synthesis. Clique Sim no aviso que aparecer.

Janela de Processos

    Após isso, será aberto o PlanAhead que dentre outras funções, faz a associação dos pinos virtuais com os reais.

PlanAhead aberto

     Clique em Scalar Ports (6) e após estar selecionada todas as portas clique com o botão direito e vá em Configure I/O Ports.

Portas Selecionadas

     Após ir em Configure I/O Ports mude o I/O Standard para LVCMOS33 e clique em OK.

Trocando I/O Standard para LVCMOS33

    Feito isso, as portas estão configuradas para trabalhar a 3.3V e não 2.5V como pré-definidas pelo programa. Apesar do ESC funcionar com 5V, 3.3V ainda é considerado nível lógico 1 para um circuito TTL 5V. E como não há comunicação de volta do ESC, não há problemas em se usar 3.3V.

Portas configuradas para LVCMOS33

    Agora é necessário fazer as associações dos pinos. Este mapa colorido chego de bolas, quadrados e hexagonos é o FPGA visto por baixo. Ai estão todos os pinos com coordenadas horizontais de 1 a 16 e verticais de A a T. Para associar o pino, basta seleciona-lo em Scalar Ports e arrasta-lo até o pino determinado. Caso esteja usando o mesmo kit que eu, faça as seguintes ligações:

button1 => K3
button2 => H5
clk => C10
led1 => D14
led2 => C16
ppm => B4

Feito isso, os pinos estarão mapeados correntamente.

Portas mapeadas (Site)

Mapa de Pinos

Após isso, basta clicar em Salvar no canto esquerdo superior da tela.

Botão Salvar

Vamos agora descrever o clock principal para o compilador. Para isso vá em Processes: main e clique em Create Timing Constrains

Dados do clock

Altere os campos em branco a direita para:

TIMESPEC Name* => TS_CLK_16MHZ
Clock Net* => clk
Period => 62.5 ns
Duty Cycle => 50%
Edge => High

Configuração do Clock

     Pronto! O clock está configurado. Clique em main.v na aba inferior da direita e Design na aba inferior da esquerda. Vamos agora compilar o programa! Em Processes: main clique em Generate Programming File. Aguarde até que o programa esteja compilado.

Programa Compilado

Feito isso, terminamos a produção do programa! Agora é só gravar no FPGA!

 

5 - Gravando programa no FPGA

    Conecte o kit ao computador e abra o software de gravação (caso seja o kit da Avnet, abra o Avnet Board Programming Utility).

Programa de Gravação do FPGA

Clique em Connect to COMX. Após a conexão, clique em browse e selecione o arquivo main.bit que está na pasta do seu projeto.

Selecionando arquivo main.bit


Após isso clique em Configure FPGA e se iniciará o processo de gravação. Após gravado conecte o GND (Fio preto) do ESC no GND da placa e o Fio branco (Controle) no pino B4. Ligue a energia ao ESC e você notará um apito no motor. Isso é normal, demonstra que está tudo funcionando correntamente. Clique no Botão PUSH_A para aumentar a velocidade e PUSH_B para reduzir a velocidade.

Pronto! Tudo funcionando corretamente, agora use a sua criatividade e coloque mais recursos neste programa!

Video:

 

Programa Completo:

ESC.rar

Por: Lucas Teske


Licença Creative Commons
Esta obra de EnergyLabs Brasil, foi licenciada com uma Licença Creative Commons - Atribuição - Partilha nos Mesmos Termos 3.0 Não Adaptada.
Permissões adicionais ao âmbito desta licença podem estar disponíveis em http://www.energylabs.com.br.


Comente este conteúdo!





Você está em: Documento => - Translate this page to English