Translate

segunda-feira, 2 de dezembro de 2013

Controle de servo motores com Arduino para FSX

Olá a todos,

como muitos sabem, tenho um desejo muito grande em construir um cockpit de 737. Estou caminhando a passos de formiga, descobrindo alguma coisa aqui, outra ali e juntando muitas destas coisas estou vendo uma luz no fim do túnel. Para os amantes de simulação de voo, a construção de um cockpit acarreta em desembolsar muita "GRANA" e como grana não é uma coisa que não me sobra, tenho que buscar alternativas para o meu projeto. Pois bem, trago uma novidade para quem encontra-se no mesmo pé que eu. A poucos dias esbarrei em um site e encontrei um software desenvolvido pelo próprio mantenedor do site. Este é capaz de captar as informações do FSX e enviar para uma porta "com". O software é fantástico. Muito fácil de configurar e o detalhe; é FREE!!!! No vídeo que eu estou disponibilizando construi um protótipo para movimento utilizando servo motores e uma pequena replica. O link do código para ser gravado no Arduino.  Caso o link não funcione, copie e cole na IDE do Arduino o código a seguir. 

OBS: se você não souber programar e ou conhecimento básico em eletrônica, recomendo que estude antes de aventurar-se nestes testes. 


// Controle de movimento para Cockpit com FSX
// Rodrigo Cainelli - 2013

#include <LiquidCrystal.h>  // Biblioteca para LCD
#include <Servo.h> // Biblioteca para controlar servo motor
String entrada,dados;
char tipo,direcao; 
Servo servo1,servo2,servo3,servo4;
//Servo servo5;
int led_noise_down = 2;
int led_noise_up = 3;
int led_left_down = 4;
int led_left_up = 5;
int led_right_down = 6;
int led_right_up = 7;
int led = 13;
int led_gladeslope = 8;
//int habilita_servo_throler = 9;

int pos,elimina,i;
int valor_flap,flap;
int valor_gearNoise, valor_gearLeft, valor_gearRight;
int valor_apu_speed, airspeed_hold, app_airspeed, valor_throller, var_gladeslope, position_throler;


// Initialize the library with the numbers of the interface pins
//(rs,rw,ena,d4,d5,d6,d7)
LiquidCrystal lcd(10, 11, 12, A2, A0, A1);

void setup(){
  //lcd.begin(16, 2);
  //pinMode(12,OUTPUT);
  pinMode(led_noise_down, OUTPUT);
  pinMode(led_noise_up, OUTPUT);
  pinMode(led_left_down, OUTPUT);
  pinMode(led_left_up, OUTPUT);
  pinMode(led_right_down, OUTPUT);
  pinMode(led_right_up, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(led_gladeslope,OUTPUT);
  //pinMode(habilita_servo_throler, OUTPUT);
  servo1.attach(9); //Vertical
  servo2.attach(A4); //Horizontal
  servo3.attach(A3); //Flaps 
  servo4.attach(A5); //APU Speed
  //servo5.attach(A6); //Throller
  
  
  //Iniciando a comunicação serial
  //Serial.begin(115200);
  lcd.begin(16, 2);
  Serial.begin(115200);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("FSX - Boeing 737");
  lcd.setCursor(0,1);
  lcd.print("Rodrigo Cainelli");
  delay(4000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("APU Volts:");
  lcd.setCursor(0,1);
  lcd.print("Eng Volts:");
}

void loop(){
  
  //digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  
  
  if (Serial.available()) {
    delay(10);
    while (Serial.available() > 0) {

      elimina = char(Serial.read()); //Para versão nova do Link2fs
      tipo=char(Serial.read());
      switch (tipo){
        case 'A':
              // Trem de pouso
              //digitalWrite(led, LOW);
              //delay(10);
              entrada= "";
              valor_gearNoise = 0;
              for( i = 0; i < 3; i++){
                entrada += char(Serial.read());
              }
              valor_gearNoise = entrada.toInt();
              
              if(valor_gearNoise > 0 && valor_gearNoise <= 50){
                  digitalWrite(led_noise_up, LOW);
                  digitalWrite(led_noise_down, HIGH);
                  delay(2000);
              }else{
                    if(valor_gearNoise > 50 && valor_gearNoise <= 100){
                      digitalWrite(led_noise_up, HIGH);
                      digitalWrite(led_noise_down, LOW);
                    }else{
                      digitalWrite(led_noise_up, HIGH);
                      digitalWrite(led_noise_down, HIGH);
                    }
              }
              break;
        case 'B':
              // Trem de pouso
              //delay(10);
              entrada= "";
              valor_gearLeft = 0;
              for( i = 0; i < 3; i++){
                entrada += char(Serial.read());
              }
              valor_gearLeft = entrada.toInt();
              if(valor_gearLeft > 0 && valor_gearLeft <= 50){
                  digitalWrite(led_left_up, LOW);
                  digitalWrite(led_left_down, HIGH);
              }else{
                    if(valor_gearLeft > 50 && valor_gearLeft <= 100){
                      digitalWrite(led_left_up, HIGH);
                      digitalWrite(led_left_down, LOW);
                    }else{
                      digitalWrite(led_left_up, HIGH);
                      digitalWrite(led_left_down, HIGH);
                    }
              }
              break;
        case 'C':
              // Trem de pouso
              //delay(10);
              entrada= "";
              valor_gearRight = 0;
              for( i = 0; i < 3; i++){
                entrada += char(Serial.read());
              }
              valor_gearRight = entrada.toInt();
              if(valor_gearRight > 0 && valor_gearRight <= 50){
                  digitalWrite(led_right_up, LOW);
                  digitalWrite(led_right_down, HIGH);
              }else{
                    if(valor_gearRight > 50 && valor_gearRight <= 100){
                      digitalWrite(led_right_up, HIGH);
                      digitalWrite(led_right_down, LOW);
                    }else{
                      digitalWrite(led_right_up, HIGH);
                      digitalWrite(led_right_down, HIGH);
                    }
              }
              break;
              
        case 'g':
               //APU Speed
              //digitalWrite(led, LOW);
              //delay(10);
              entrada= "";
              for( i = 0; i < 3; i++){
                entrada += char(Serial.read());
              }
              valor_apu_speed = entrada.toInt();
              
              valor_apu_speed=map(valor_apu_speed,0,100,180,20);
              servo4.write(valor_apu_speed); 
              break;
            
        case 'G':
               //Flaps    
              //digitalWrite(led, LOW);
              //delay(10);
              entrada= "";
              for( i = 0; i < 3; i++){
                entrada += char(Serial.read());
              }
              valor_flap = entrada.toInt();
              switch (valor_flap){
    case 0: flap = 179;
     break;
    case 1: flap = 159;
     break;
    case 3: flap = 139;
     break;
    case 7: flap = 119;
     break;
                        case 14: flap = 99;
     break;
                        case 21: flap = 79;
     break;
                        case 36: flap = 62;
     break;
                        case 43: flap = 44;
     break;
                        case 57: flap = 19;
     break;
    default:
                            break;
    }
              valor_flap=map(flap,0,57,20,180);
              servo3.write(flap);
              break;
          
        case 'i':
             //APU volts
             entrada = "";
             //entrada += char(Serial.read());
             for( i = 0; i < 2; i++){
                entrada += char(Serial.read());
              }
             airspeed_hold = entrada.toInt();
             //app_airspeed = airspeed_hold;
             lcd.setCursor(11,0);
             lcd.print("  ");
             lcd.setCursor(11,0);
             lcd.print(airspeed_hold);
             delay(20);
             break;  
              
        case 'W':
              // Throller
              entrada= "";
              elimina = char(Serial.read());
              for( i = 0; i < 3; i++){
                  entrada += char(Serial.read());
              }
              valor_throller = entrada.toInt();
              
              break;
              
        case 'r':
             //Gladeslope
             entrada = "";
             entrada += char(Serial.read());
             var_gladeslope = entrada.toInt();
             //app_airspeed = airspeed_hold;
             if ( var_gladeslope > 0 ){
                Serial.println("GLS Localizado.");
                digitalWrite(led_gladeslope, LOW);
              }else{
                digitalWrite(led_gladeslope, HIGH);
                Serial.println("GLS perdido.");
              }
             break;
              
        case 'y':
             //Engine 1 Volts
             entrada = "";
             //entrada += char(Serial.read());
             for( i = 0; i < 2; i++){
                entrada += char(Serial.read());
              }
             var_gladeslope = entrada.toInt();
             //app_airspeed = airspeed_hold;
             lcd.setCursor(11,1);
             lcd.print("  ");
             lcd.setCursor(11,1);
             lcd.print(var_gladeslope);
             delay(20);
             break;
             
       case 'z':
             //Engine 1 Volts
             entrada = "";
             entrada += char(Serial.read());
             var_gladeslope = entrada.toInt();
             //app_airspeed = airspeed_hold;
             //lcd.setCursor(0,1);
             //lcd.print("ENG 2 Volts: "+var_gladeslope);
             break;
       
             
        default: break;
      }
      
      if ((tipo=='Q')||(tipo=='R')){
        digitalWrite(led, LOW);
        
        entrada= "";
        direcao=char(Serial.read());
        for( i = 0; i < 5; i++){
            entrada += char(Serial.read());
          }
        int valor_servo = entrada.toInt();
        valor_servo = valor_servo*10;        
          if (tipo=='Q'){
            if(direcao=='-'){
                valor_servo=map(valor_servo,0,50,90,30);
                servo1.write(valor_servo);
                
            }else{
              if(direcao=='+'){
                valor_servo=map(valor_servo,0,50,90,160);
                servo1.write(valor_servo);
              }
            }
          }
          if (tipo == 'R'){
              if(direcao=='+'){
                valor_servo=map(valor_servo,0,500,90,20);
                servo2.write(valor_servo);
            }else{
              if(direcao=='-'){
                valor_servo=map(valor_servo,0,500,90,160);
                servo2.write(valor_servo);
              }
            }
          }                
       }       
      }
    }

  }





Maiores informações, poste no blog. 

Obrigado pela atenção.





Será um prazer tê-lo como seguidor.

14 comentários:

  1. Boa noite amigo, esse codigo funciona no arduino uno r3 e com a versao mais atual do jims pra fsx e win 64bits?

    ResponderExcluir
    Respostas
    1. Olá Ricardo,
      acredito que funcione sim no Arduino R3 e com relação ao Jims, é preciso verificar as string enviadas. Assim que possível darei uma olhada e lhe reporto.

      Em alguns dias estarei disponibilizando um novo tutorial com um código para chaves e outro para indicadores e servos.

      Excluir
  2. boa tarde ... tenho visto seu projeto no youtube e achei muito entesante estou começando agora com o Arduíno mais venho a muito tempo desenvolvendo cockpit uso placa controladoras do tpw Mjoy16 e estou querendo desenvolver estes movimentos dentro de uma estrutura .. e parabéns pelo seu projeto.

    ResponderExcluir
    Respostas
    1. Obrigado Victor,

      olha só o material que eu utilizo:

      - 2 controles USB (http://vieiraeletronicos.com.br/loja/product_images/w/572/controle_usb_PC_1___02638_zoom.jpg) onde desmontei e espalhei os botões pelo cockpit e retirei os potenciômetros dos controle e montei o quadrante, manche e pedais.

      - 2 computadores, um deles com o simulador e o outro com para as telas.
      - Software das telas eu encontrei em: e é free.
      - Estou montando 3 placas para os avisos, chaves e servos. Uma delas com PIC 18f4550 e as demais com o Arduino mini.
      - Comunicação entre o simulador e as placas estou fazendo com o software do Jims cujo link e citei na descrição do vídeo.
      - Central com uma placa de declado para o controle da tela do NAV e PFD do PC secundário.
      - MCP e Rádios, estou utilizando as placas do USB Interface, excelente custo benefício.


      Estou desmontando meu Cockpit hoje para a construção do novo. Pretendo documentar todas as etapas.

      Abraços e bons voos para você.

      Acompanhe as atualizações.

      Excluir
  3. amigo me fala onde vc conseguiu esta "Link2FS InOut v4j seu projeto ficou 10 e queria fazer um desse?








    ResponderExcluir
    Respostas
    1. Os links estão na descrição do vídeo.

      Abraço.

      Excluir
    2. Você já têm o Arduino?
      Que FS você está utilizando, o 2004 ou o X?
      Você já tem os servos?

      Aguardo o seu retorno.

      Excluir
  4. vc conseguiria fazer um igual a este mas com um emulador de corrida ?

    ResponderExcluir
    Respostas
    1. Ai você me pegou. Tenho vontade de fazer um cockpit para corrida, porém, não tenho ideia de como funcionam os games de corrida ainda. Pretendo me aventurar nas corridas só quando terminar o meu cockpit do 737. O problema que vejo está na obtenção dos dados do game para que seja possível jogar para servos, luzes e etc. No mais, acredito que comprando um bom conjunto de volante e pedais é possível desmonta-los e jogar os botões para um painel e demais recursos.

      Por enquanto não terei como lhe ajudar neste assunto amigo.

      Excluir
  5. Este comentário foi removido pelo autor.

    ResponderExcluir
  6. Olá Rodrigo chara kk,seu home esta muito massa eu tbm fi um e estou querendo colocar motores na cabine para movimento do mesmo,andei vendo seu projeto e focou mt massa, o q eu queria entender era em vez de micro servo usar motores maiores o código será o mesmo? ou como funciona tem ideia grato pela atenção.

    ResponderExcluir
    Respostas
    1. Olá chara. Bem existem válvulas pneumáticas de duplo estágio que podem ser utilizadas com este código efetuando algumas modificações. O braço pneumático terá que ter um potenciômetro para informar a placa com relação a sua posição e desta forma, esta, poderá liberar mais o pistão o recolhe-lo.
      Outra opção seria utilizando motores de passo. Os motores terão que ser "bagualudos" uma vez que, a força exercida sobre eles para vencer a inércia será muito grande mesmo se movimentarem cockpit pequeno.

      Este sistema é muito parecido com o que eu montei em miniatura.
      https://www.youtube.com/watch?v=JQAZB3EnI_w

      Se não ficou claro, posta aí que vamos falando.
      Seria um prazer telo como seguidor.

      Obrigado pela atenção.

      Excluir
  7. Boa noite.
    Ainda tem o projeto do circuito utilizado?

    ResponderExcluir
  8. Infelizmente não, apenas o que está registrado no vídeo. O código está no próprio corpo do post. Já têm um tempo que meu cockpit está parado sem evolução alguma.

    ResponderExcluir

Sua postagem será avaliada pelos administradores do Blog com o intuito de assegurar que conteúdos ou palavras impróprias sejam utilizadas.

Obrigado pela compreensão.