- Diagrama de circuito
- Gerando sinais PWM no pino GPIO para controle do servo motor
- Programação PIC16F8771A para braço robótico
- Simulação de código de braço robótico PIC
- Projeto de PCB usando EasyEDA
- Cálculo e pedido de amostras online
- Trabalho do braço robótico PIC
Da linha de montagem das indústrias de fabricação de automóveis aos robôs de telecirurgia no espaço, os braços robóticos podem ser encontrados em todos os lugares. Os mecanismos desses robôs são semelhantes aos de um ser humano, que podem ser programados para funções semelhantes e capacidades aumentadas. Eles podem ser usados para executar ações repetidas mais rápidas e precisas do que os humanos ou podem ser usados em ambientes hostis sem arriscar a vida humana. Já construímos um braço robótico Record and Play usando o Arduino, que pode ser treinado para realizar uma tarefa específica e repetido para sempre.
Neste tutorial, usaremos o microcontrolador de 8 bits PIC16F877A padrão da indústria para controlar o mesmo braço robótico com potenciômetros. O desafio com este projeto é que o PIC16F877A tem apenas dois pinos com capacidade para PWN, mas precisamos controlar cerca de 5 servo motores para nosso robô, que requer 5 pinos PWM individuais. Portanto, temos que utilizar os pinos GPIO e gerar sinais PWM nos pinos PIC GPIO usando as interrupções do temporizador. Agora, é claro que podemos atualizar para um microcontrolador melhor ou usar um IC desmultiplexador para tornar as coisas muito mais fáceis aqui. Mesmo assim, vale a pena dar uma chance a este projeto pela experiência de aprendizagem.
A estrutura mecânica do braço robótico que estou usando neste projeto foi totalmente impressa em 3D para meu projeto anterior; você pode encontrar os arquivos de projeto completos e procedimento de montagem aqui. Como alternativa, se você não tiver uma impressora 3D, também pode construir um braço robótico simples usando papelão, conforme mostrado no link. Supondo que você tenha conseguido de alguma forma seu braço robótico, vamos prosseguir com o projeto.
Diagrama de circuito
O diagrama de circuito completo para este braço robótico baseado em microcontrolador PIC é mostrado abaixo. O esquema foi desenhado usando EasyEDA.
O diagrama do circuito é bastante simples; o projeto completo é alimentado pelo adaptador 12V. Esses 12 V são então convertidos para + 5 V usando dois reguladores de tensão 7805. Um é rotulado como + 5V e o outro é rotulado como + 5V (2). A razão para ter dois reguladores é que quando o servo gira, ele puxa uma grande quantidade de corrente que cria uma queda de tensão. Esta queda de tensão força o PIC a reiniciar-se, portanto, não podemos operar o PIC e os servo motores no mesmo trilho de + 5V. Portanto, aquele rotulado como + 5V é usado para alimentar o microcontrolador PIC, LCD e potenciômetros e uma saída reguladora separada rotulada como + 5V (2) é usada para alimentar os servo motores.
Os cinco pinos de saída dos potenciômetros que fornecem uma voltagem variável de 0 V a 5 V são conectados aos pinos analógicos An0 a AN4 do PIC. Já que estamos planejando usar temporizadores para gerar PWM, os servo motores podem ser conectados a qualquer pino GPIO. Selecionei os pinos de RD2 a RD6 para os servo motores, mas pode ser qualquer GPIO de sua escolha.
Como o programa envolve muita depuração, um display LCD 16x2 também faz interface com a porta B do PIC. Isso exibirá o ciclo de trabalho dos servo motores que estão sendo controlados. Além disso, também estendi as conexões para todos os pinos GPIO e analógicos, apenas no caso de algum sensor precisar ser conectado no futuro. Finalmente, também conectei o pino do programador H1 para programar diretamente o PIC com pickit3 usando a opção de programação ICSP.
Gerando sinais PWM no pino GPIO para controle do servo motor
Uma vez que o circuito está pronto, temos que descobrir como gerar sinais PWN no pino GPIO do PIC para controlar o servo motor. Já cansamos algo semelhante usando o método de interrupção do temporizador e tivemos sucesso. Aqui, vamos apenas construir em cima dele, então se você é novo aqui, eu recomendo fortemente que você leia este tutorial anterior antes de prosseguir.
Todos os servo motores de hobby trabalham com uma frequência de 50Hz. Significando que um ciclo de pulso completo para um servo motor será 1/50 (F = 1 / T), que é 20 ms. Destes 20ms completos, o sinal de controle é apenas de 0 a 2ms, enquanto o resto do sinal está sempre desligado. A figura abaixo mostra como o tempo ON varia apenas de 0 a 2ms para girar o motor de 0 graus a 180 graus da duração total de 20ms.
Com isso em mente, devemos escrever o programa de tal forma que o PIC leia 0 a 1204 do potenciômetro e mapeie de 0 a 100 que será o ciclo de trabalho do servo motor. Usando este ciclo de trabalho, podemos calcular o tempo de ativação do servo motor. Então, podemos inicializar a interrupção do cronômetro para estourar em um intervalo regular, de forma que ela atue de maneira semelhante à função millis () no Arduino. Com isso, podemos alternar o pino GPIO de status para alto por uma duração desejada e desligá-lo após 20 ms (um ciclo completo) e, em seguida, repetir o mesmo processo. Agora que entendemos a lógica, vamos entrar no programa.
Programação PIC16F8771A para braço robótico
Como sempre, o programa completo com um Vídeo pode ser encontrado no final desta página, o código também pode ser baixado aqui com todos os arquivos necessários. Nesta seção, discutiremos a lógica por trás do programa. O programa emprega o módulo ADC, o Módulo Timer e o Módulo LCD para controlar o braço robótico. Se você não está ciente de como usar os recursos ADC ou recursos de temporizador ou para fazer a interface de um LCD com PIC, você pode recorrer aos respectivos links para aprendê-los. A explicação abaixo é fornecida assumindo que o leitor esteja familiarizado com esses conceitos.
Configuração da porta do temporizador 0
A seção mais importante do código é definir o Timer 0 para transbordar para cada atraso específico. As fórmulas para calcular este atraso podem ser fornecidas como
Atraso = ((256-REG_val) * (Prescal * 4)) / Fosc
Usando os registradores OPTION_REG e TMR0, configuramos o Timer 0 para operar com um valor pré-escalar de 32 e o REG val está configurado para 248. A frequência do cristal (Fosc) usada em nosso hardware é 20Mhz. Com esses valores, o atraso pode ser calculado como
Atraso = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 segundos (ou) = 0,05 mseg
Portanto, agora definimos o temporizador para transbordar a cada 0,05 ms. O código para fazer o mesmo é fornecido abaixo
/ ***** Configuração da porta para temporizador ****** / OPTION_REG = 0b00000100; // Timer0 com freq externa e 32 como prescalar // Também habilita PULL UPs TMR0 = 248; // Carrega o valor do tempo para 0,0001s; delayValue pode estar entre 0-256 somente TMR0IE = 1; // Habilita o bit de interrupção do temporizador no registro PIE1 GIE = 1; // Habilita a interrupção global PEIE = 1; // Habilite a interrupção periférica / *********** ______ *********** /
Do total da janela de controle de 0ms a 2ms do servo motor podemos controlá-la com uma resolução de 0,05mseg, o que nos permite ter (2 / 0,05) 40 posições diferentes para o motor entre 0 graus a 180 graus. Você pode diminuir este valor ainda mais se seu MCU puder suportá-lo para obter mais posições e controle preciso.
Rotina de serviço de interrupção (ISR)
Agora que temos o Timer 0 definido para transbordar a cada 0,05 ms, teremos o sinalizador de interrupção TMR0IF definido para 0,05 ms. Portanto, dentro da função ISR, podemos redefinir esse sinalizador e incrementar uma variável chamada contagem em um. Portanto, agora esta variável será incrementada em 1 para cada 0,05 ms.
void interrupt timer_isr () { if (TMR0IF == 1) // O sinalizador do temporizador foi acionado devido ao estouro do temporizador -> definido para estouro a cada 0,05 ms { TMR0 = 248; // Carrega o valor do temporizador TMR0IF = 0; // Limpa a contagem do sinalizador de interrupção do temporizador ++; // Contar incrementos de 1 para cada 0,05 ms }
Cálculo do ciclo de trabalho e no prazo
Em seguida, temos que calcular o ciclo de trabalho e o tempo para todos os cinco servo motores. Temos cinco servo motores, cada um dos quais é usado para controlar seções individuais do braço. Portanto, temos que ler o valor ADC de todos os cinco e calcular o ciclo de trabalho e a hora de cada um.
O valor ADC estará na faixa de 0 a 1024, que pode ser convertido em 0% a 100% do ciclo de trabalho simplesmente multiplicando 0,0976 (100/1024 = 0,0976) pelo valor obtido. Este ciclo de trabalho de 0 a 100% deve ser convertido para o tempo ON. Sabemos que em 100% do ciclo de trabalho o tempo de LIGADO deve ser 2 ms (para 180 graus), portanto, multiplicar 0,02 (2/100 = 0,02) converterá o ciclo de trabalho de 0 a 100 em 0 a 2 ms. Mas então nossa contagem de variável do temporizador é configurada para aumentar uma vez a cada 0,05 ms. Isso significa que o valor da contagem será 20 (1 / 0,05 = 20) para cada 1 ms. Portanto, temos que multiplicar 20 por 0,02 para calcular o tempo exato para o nosso programa, que nos dará o valor 0,4 (0,02 * 20 = 0,4). O código para o mesmo é mostrado abaixo, você pode vê-lo repetido 5 vezes para todos os 5 potes usando um loop for. Os valores resultantes são armazenados na matriz T_ON.
para (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // Lê o valor de POT usando ADC Duty_cycle = (POT_val * 0,0976); // Mapeie 0 a 1024 a 0 a 100 T_ON = Duty_cycle * 0.4; // 20 * 0.02
Selecionando qual motor girar
Não podemos controlar todos os cinco motores juntos, pois isso tornará o código ISR pesado, desacelerando todo o microcontrolador. Portanto, temos que girar apenas um servo motor por vez. Para selecionar qual servo girar, o microcontrolador monitora o tempo ON de todos os cinco servo motores e o compara com o tempo anterior. Se houver uma mudança no tempo ON, podemos concluir que o servo em particular deve ser movido. O código para o mesmo é mostrado abaixo.
if (T_ON! = Pev_val) { Lcd_Clear (); servo = pot_num; Lcd_Set_Cursor (2,11); Lcd_Print_String ("S:"); Lcd_Print_Char (servo + '0'); if (pot_num == 0) {Lcd_Set_Cursor (1,1); Lcd_Print_String ("A:");} else if (pot_num == 1) {Lcd_Set_Cursor (1,6); Lcd_Print_String ("B:");} else if (pot_num == 2) {Lcd_Set_Cursor (1,11); Lcd_Print_String ("C:");} else if (pot_num == 3) {Lcd_Set_Cursor (2,1); Lcd_Print_String ("D:");} else if (pot_num == 4) {Lcd_Set_Cursor (2,6); Lcd_Print_String ("E:");} char d2 = (Duty_cycle)% 10; char d1 = (Ciclo_de_dutividade / 10)% 10; Lcd_Print_Char (d1 + '0'); Lcd_Print_Char (d2 + '0');
Também imprimimos o ciclo de trabalho do servo na tela LCD para que o usuário possa estar ciente de sua posição atual. Com base na mudança no tempo ON, o servo variável é atualizado com números de 0 a 4, cada um representando motores individuais.
Controlando o servo motor dentro do ISR
Dentro do ISR, temos a contagem de variáveis sendo incrementada a cada 0,05 ms, isso significa que a cada 1 ms a variável será incrementada em 20. Usando isso, temos que controlar os pinos para produzir o sinal PWM. Se o valor da contagem for menor que o tempo de ativação, o GPIO desse motor é ligado usando a linha abaixo
PORTD = PORTD - servo_code;
Aqui, a matriz servo_code tem o detalhe do pino de todos os cinco servo motores e com base no valor da variável servo, o código para aquele servo motor específico será usado. É então logicamente OR (-) com bits PORTD existentes para que não perturbemos os valores de outro motor e atualizemos apenas este motor específico. Da mesma forma para desligar o pino
PORTD = PORTD & ~ (servo_code);
Invertemos o valor do bit usando o operador lógico inverso (~) e, em seguida, executamos uma operação AND (&) no PORTD para desligar apenas o pino desejado, deixando os outros pinos em seu estado anterior. O trecho de código completo é mostrado abaixo.
void interrupt timer_isr () { if (TMR0IF == 1) // O sinalizador do temporizador foi acionado devido ao estouro do temporizador -> definido para estouro a cada 0,05 ms { TMR0 = 248; // Carrega o valor do temporizador TMR0IF = 0; // Limpa a contagem do sinalizador de interrupção do temporizador ++; // Contar incrementos de 1 para cada 0,05ms -> a contagem será 20 para cada 1ms (0,05 / 1 = 20)) } int servo_code = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100}; if (contagem> = 20 * 20) contagem = 0; if (contagem <= (T_ON)) PORTD = PORTD - servo_code; else PORTD = PORTD & ~ (servo_code); }
Sabemos que o ciclo total deve durar 20 ms antes que o pino GPIO seja ligado novamente. Portanto, verificamos se a contagem ultrapassou 20ms comparando o valor da contagem com 400 (mesmo cálculo discutido acima) e se sim, temos que inicializar a contagem para zero novamente.
Simulação de código de braço robótico PIC
É sempre melhor simular o código antes de levá-lo para o hardware real. Usei o Proteus para simular meu código e verifiquei se ele funcionava corretamente. O circuito usado para simulação é mostrado abaixo. Usamos um osciloscópio para verificar se os sinais PWM estão sendo gerados conforme necessário. Também podemos verificar se o LCD e os servo motores estão girando conforme o esperado.
Como você pode ver, o LCD exibe o ciclo de trabalho do motor D como sendo 07 com base no valor do potenciômetro que é o terceiro motor. Semelhante, se outro potenciômetro for movido, o ciclo de trabalho desse potenciômetro e seu número de motor serão exibidos no LCD. O sinal PWM mostrado no osciloscópio é mostrado abaixo.
O período total do ciclo é medido em 22,2ms usando a opção do cursor no osciloscópio, que está muito próximo dos 20ms desejados. Finalmente, temos certeza de que o código funciona, então, para continuar com o circuito, podemos soldá-lo em uma placa perf ou usar um PCB. Não funcionará facilmente no breadboard porque o POT sempre tende a apresentar alguns problemas devido a conexões ruins.
Projeto de PCB usando EasyEDA
Para projetar este braço robótico PIC, escolhemos a ferramenta EDA online chamada EasyEDA. Eu tenho usado há muito tempo e acho muito conveniente devido à sua vasta disponibilidade de pegadas e fácil de usar a natureza. Depois de projetar o PCB, podemos solicitar as amostras de PCB por seus serviços de fabricação de PCB de baixo custo. Eles também oferecem serviço de fornecimento de componentes, onde têm um grande estoque de componentes eletrônicos e os usuários podem solicitar seus componentes necessários junto com o pedido de PCB.
Ao projetar seus circuitos e PCBs, você também pode tornar seus circuitos e projetos de PCB públicos para que outros usuários possam copiá-los ou editá-los e possam tirar proveito de seu trabalho. Também tornamos públicos todos os nossos circuitos e layouts de PCB para este circuito, verifique o link abaixo:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Usando este link, você pode solicitar diretamente o mesmo PCB que estamos usando neste projeto e usá-lo. Assim que o design estiver concluído, a placa pode ser vista como um modelo 3D, o que será muito útil para visualizar como a placa ficaria após a fabricação. O modelo 3D da placa que estamos usando é mostrado abaixo. Além disso, você também pode visualizar as camadas superior e inferior da placa para verificar se a tela lisa é a esperada.
Cálculo e pedido de amostras online
Depois de concluir o design deste PIC Robot PCB, você pode solicitar o PCB em JLCPCB.com. Para solicitar o PCB do JLCPCB, você precisa do Arquivo Gerber. Para baixar os arquivos Gerber de seu PCB, basta clicar no botão Gerar Arquivo de Fabricação na página do editor EasyEDA, depois baixar o arquivo Gerber de lá ou clicar em Pedido no JLCPCB, conforme mostrado na imagem abaixo. Isso o redirecionará para JLCPCB.com, onde você pode selecionar o número de PCBs que deseja solicitar, quantas camadas de cobre você precisa, a espessura do PCB, o peso do cobre e até mesmo a cor do PCB, como o instantâneo mostrado abaixo:
Depois de selecionar todas as opções, clique em “Salvar no carrinho” e então você será levado à página onde poderá fazer o upload do seu arquivo Gerber, que baixamos do EasyEDA. Carregue seu arquivo Gerber e clique em “Salvar no carrinho”. E, finalmente, clique em Check-out com segurança para concluir seu pedido e, alguns dias depois, você receberá seus PCBs. Eles estão fabricando o PCB a uma taxa muito baixa, que é de US $ 2. Seu tempo de construção também é muito menor, que é de 48 horas com entrega DHL de 3-5 dias, basicamente você receberá seus PCBs dentro de uma semana após o pedido.
Após fazer o pedido do PCB, você pode verificar o andamento da produção de seu PCB com data e hora. Você verifica indo na página da conta e clica em "Progresso da produção".
Depois de alguns dias pedindo PCBs, recebi as amostras de PCB em uma bela embalagem, conforme mostrado nas fotos abaixo.
E depois de obter essas peças, soldei todos os componentes necessários no PCB. Eu também soldei diretamente o POT em vez de usar fios de conexão porque os fios fêmea para fêmea que usei inicialmente forneciam tensões de saída analógica estranhas, provavelmente por causa de contatos soltos. Depois que todos os componentes foram montados, meu PCB parecia algo assim.
Você deve ter notado que há apenas um 7805 nesta placa. Isso porque inicialmente eu pensei que poderia me safar apenas com o regulador para alimentar o PIC e o servo motor e depois percebi que preciso de dois. Usei um circuito externo para alimentar os servo motores por meio dos fios verdes que você vê aqui.
No entanto, você não precisa se preocupar muito com isso porque; Eu fiz as alterações no PCB agora. Você pode fazer uso do PCB modificado e soldar ambos os reguladores a bordo.
Trabalho do braço robótico PIC
Depois de todo o trabalho cansativo, é hora de pagar. Solde todos os componentes da placa e carregue o programa para o controlador PIC. O código completo é fornecido abaixo ou pode ser baixado aqui. O conector de programação fornecido na placa deve ajudá-lo a carregar o programa diretamente usando o Pickit 3 sem muitos problemas. Assim que o programa for carregado, você deverá ver o LCD exibindo o servo que está sendo controlado no momento. Para saber mais sobre a programação do Microcontrolador PIC, basta seguir o tutorial anterior.
A partir daí, você pode simplesmente girar o potenciômetro e verificar como os servo motores respondem a cada potenciômetro. Depois de entender o formato, você pode controlar o braço robótico para executar qualquer ação necessária e se divertir. Você pode encontrar o funcionamento completo do projeto no vídeo no link abaixo.
É isso, pessoal, espero que tenham entendido o projeto e aprendido algo novo com ele. Se você tiver alguma dúvida, deixe-a na seção de comentários ou use os fóruns para outras discussões técnicas.