sexta-feira, 29 de abril de 2016

F5im Alpha 0.1

Estamos evoluindo no desenvolvimento dos códigos para o display e para a plataforma do full motion. Essa semana, tive como meta, (re)produzir e aprimorar os códigos para o Arduino.

Comecemos pela parte boa!

Usei, como ponto de partida para o display do F5im, o projeto do FergoTech. O Fernando, utilizou nesse projeto apenas 1 display com controlador TM1638. No F5im, utilizaremos 2 displays com o mesmo controlador TM1638. Assim, podemos acessar o dobro de informações de maneira simultânea e também nos deixa com um button box integrado de 16 botões, o que não é nada mal!!!

Primeiros testes com 2 displays TM1638 integrados:




Agora, vou precisar de mais estudo para poder integrar os display e separar as informações para cada um!!!

Agora vamos para a parte dolorosa!

Na plataforma full motion, os testes preliminares foram um sucesso!!!! Até ligarmos as 2 fontes de 24V nos controladores. Algum curto, ainda não identificado, acabou queimando a fonte e talvez o controlador. Ainda não consegui testa-lo...

A fonte queimada é a da direita, porém, não consegui identificar qual componente foi afetado.


Próxima semana estarei afastado das atividades, tanto do blog, quanto do F5im.

Até breve pessoal!

quarta-feira, 20 de abril de 2016

O Código F-5im

Essa semana começamos com os testes no arduino and, so far, so good!!! No final do post deixo o código para aqueles que queiram se aventurar!!!


Na próxima semana, farei os testes com os moteres bosch acoplados ao sistema e ainda começaremos a pensar no layout para prender todas as fontes e placas dentro da caixa de Pandora. Acrílico? Suporte Metálico? Ideias e sugestões são bem vindos! Mais detalhes em Caixa de Pandora.

Abraços e até lá...

Code: Select all
/* 
 Arduino code for dynamic playseat 2DOF
 Created 24 May 2011 by Jim Lindblom   SparkFun Electronics https://www.sparkfun.com/products/10182 "Example Code"
 Created 24 Apr 2012 by Jean David SEDRUE Version betatest26 - 24042012 http://www.gamoover.net/Forums/index.php?topic=25907
 Updated 20 May 2013 by RacingMat in english http://www.x-sim.de/forum/posting.php?mode=edit&f=37&t=943&p=8481  in french : http://www.gamoover.net/Forums/index.php?topic=27617
 Updated 30 April 2014 by RacingMat (bug for value below 16 corrected)
 Updated 20 April 2016 by Guto Antunes for F-5im Motorsport Simulations http://f5im.blogspot.com.br 
*/

#define BRAKEVCC 0
#define RV  2 //beware it's depending on your hardware wiring
#define FW  1 //beware it's depending on your hardware wiring
#define STOP 0
#define BRAKEGND 3

////////////////////////////////////////////////////////////////////////////////
#define pwmMax 255 // or less, if you want to lower the maximum motor's speed

// defining the range of potentiometer's rotation
const int potMini=208;
const int potMaxi=815;

////////////////////////////////////////////////////////////////////////////////
#define motLeft 0
#define motRight 1
#define potL A0
#define potR A1

////////////////////////////////////////////////////////////////////////////////
//  DECLARATIONS
////////////////////////////////////////////////////////////////////////////////
/*  VNH3SP30 pin definitions*/
int inApin[2] = {
  7, 4};  // INA: Clockwise input
int inBpin[2] = {
  8, 9}; // INB: Counter-clockwise input
int pwmpin[2] = {
  5, 6}; // PWM input
int cspin[2] = {
  2, 3}; // CS: Current sense ANALOG input
int enpin[2] = {
  0, 1}; // EN: Status of switches output (Analog pin)
int statpin = 13;  //not explained by Sparkfun
/* init position value*/
int DataValueL=512; //middle position 0-1024
int DataValueR=512; //middle position 0-1024

////////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
////////////////////////////////////////////////////////////////////////////////
void setup()
{
  // serial initialization
  Serial.begin(115200);

  // initialization of Arduino's pins
  pinMode(statpin, OUTPUT); //not explained by Sparkfun
  digitalWrite(statpin, LOW);

  for (int i=0; i<2; i++)
  {
    pinMode(inApin[i], OUTPUT);
    pinMode(inBpin[i], OUTPUT);
    pinMode(pwmpin[i], OUTPUT);
  }
  // Initialize braked for motor
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
}
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Main Loop ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void loop()
{
  int sensorL,sensorR;

  readSerialData();   // DataValueR & L contain the last order received (if there is no newer received, the last is kept)
  // the previous order will still be used by the PID regulation MotorMotion Function

  sensorR = analogRead(potR);  // range 0-1024
  sensorL = analogRead(potL);  // range 0-1024

  motorMotion(motRight,sensorR,DataValueR);
  motorMotion(motLeft,sensorL,DataValueL);
}
////////////////////////////////////////////////////////////////////////////////
// Procedure: wait for complete trame
////////////////////////////////////////////////////////////////////////////////
void readSerialData()
{
  byte Data[3]={
    '0','0','0'          };
  // keep this function short, because the loop has to be short to keep the control over the motors

  if (Serial.available()>2){
    //parse the buffer : test if the byte is the first of the order "R"
    Data[0]=Serial.read();
    if (Data[0]=='L'){
      Data[1]=Serial.read();
      Data[2]=Serial.read();
      //  call the function that converts the hexa in decimal and that maps the range
      DataValueR=NormalizeData(Data);
    }
    if (Data[0]=='R'){
      Data[1]=Serial.read();
      Data[2]=Serial.read();
      //  call the function that converts the hexa in decimal and maps the range
      DataValueL=NormalizeData(Data);

    }
  }
  if (Serial.available()>16) Serial.flush();
}
////////////////////////////////////////////////////////
void motorMotion(int numMot,int actualPos,int targetPos)
////////////////////////////////////////////////////////
{
  int Tol=20; // no order to move will be sent to the motor if the target is close to the actual position
  // this prevents short jittering moves
  //could be a parameter read from a pot on an analogic pin
  // the highest value, the calmest the simulator would be (less moves)

  int gap;
  int pwm;
  int brakingDistance=30;

  // security concern : targetPos has to be within the mechanically authorized range
  targetPos=constrain(targetPos,potMini+brakingDistance,potMaxi-brakingDistance);

  gap=abs(targetPos-actualPos);

  if (gap<= Tol) {
    motorOff(numMot); //too near to move   
  }
  else {
    // PID : calculates speed according to distance
    pwm=195;
    if (gap>50)   pwm=215;
    if (gap>75)   pwm=235; 
    if (gap>100)  pwm=255;
    pwm=map(pwm, 0, 255, 0, pwmMax);  //adjust the value according to pwmMax for mechanical debugging purpose !

    // if motor is outside from the range, send motor back to the limit !
    // go forward (up)
    if ((actualPos<potMini) || (actualPos<targetPos)) motorGo(numMot, FW, pwm);
    // go reverse (down) 
    if ((actualPos>potMaxi) || (actualPos>targetPos)) motorGo(numMot, RV, pwm);

  }
}



////////////////////////////////////////////////////////////////////////////////
void motorOff(int motor){ //Brake Ground : free wheel actually
  ////////////////////////////////////////////////////////////////////////////////
  digitalWrite(inApin[motor], LOW);
  digitalWrite(inBpin[motor], LOW);
  analogWrite(pwmpin[motor], 0);
}
////////////////////////////////////////////////////////////////////////////////
void motorOffBraked(int motor){ // "brake VCC" : short-circuit inducing electromagnetic brake
  ////////////////////////////////////////////////////////////////////////////////
  digitalWrite(inApin[motor], HIGH);
  digitalWrite(inBpin[motor], HIGH);
  analogWrite(pwmpin[motor], 0);
}

////////////////////////////////////////////////////////////////////////////////
void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
////////////////////////////////////////////////////////////////////////////////
{
  if (motor <= 1)
  {
    if (direct <=4)
    {
      // Set inA[motor]
      if (direct <=1)
        digitalWrite(inApin[motor], HIGH);
      else
        digitalWrite(inApin[motor], LOW);

      // Set inB[motor]
      if ((direct==0)||(direct==2))
        digitalWrite(inBpin[motor], HIGH);
      else
        digitalWrite(inBpin[motor], LOW);

      analogWrite(pwmpin[motor], pwm);

    }
  }
}

////////////////////////////////////////////////////////////////////////////////
void motorDrive(uint8_t motor, uint8_t direct, uint8_t pwm)
////////////////////////////////////////////////////////////////////////////////
{
  // more readable function than Jim's (for educational purpose)
  // but 50 octets heavier ->  unused
  if (motor <= 1 && direct <=4)
  {
    switch (direct) {
    case 0: //electromagnetic brake : brake VCC
      digitalWrite(inApin[motor], HIGH);
      digitalWrite(inBpin[motor], HIGH);
      break;
    case 3: //Brake Ground (free wheel)
      digitalWrite(inApin[motor], LOW);
      digitalWrite(inBpin[motor], LOW);
      break;
    case 1: // forward : beware it's depending on your hardware wiring
      digitalWrite(inApin[motor], HIGH);
      digitalWrite(inBpin[motor], LOW);
      break;
    case 2: // Reverse : beware it's depending on your hardware wiring
      digitalWrite(inApin[motor], LOW);
      digitalWrite(inBpin[motor], HIGH);
      break;
    }
    analogWrite(pwmpin[motor], pwm);
  }
}
////////////////////////////////////////////////////////////////////////////////
// testPot
////////////////////////////////////////////////////////////////////////////////
void testPot(){

  Serial.print(analogRead(potL));
  Serial.print(";");
  Serial.println(analogRead(potR));
  delay(250);

}
////////////////////////////////////////////////////////////////////////////////
void testpulse(){
  int pw=120;
  while (true){

    motorGo(motLeft, FW, pw);
    delay(250);     
    motorOff(motLeft);
    delay(250);     
    motorGo(motLeft, RV, pw);
    delay(250);     
    motorOff(motLeft);   

    delay(500);     

    motorGo(motRight, FW, pw);
    delay(250);     
    motorOff(motRight);
    delay(250);     
    motorGo(motRight, RV, pw);
    delay(250);     
    motorOff(motRight);   
    Serial.println("testpulse pwm:80");   
    delay(500);

  }
}
////////////////////////////////////////////////////////////////////////////////
// Function: convert Hex to Dec
////////////////////////////////////////////////////////////////////////////////
int NormalizeData(byte x[3])
////////////////////////////////////////////////////////////////////////////////
{
  int result;

  if ((x[2]==13) || (x[2]=='R') || (x[2]=='L'))  //only a LSB and Carrier Return or 'L' or 'R' in case of value below 16 (ie one CHAR and not 2)
  {
    x[2]=x[1];  //move MSB to LSB
    x[1]='0';     //clear MSB
  }
  for (int i=1; i<3; i++)
   {
    if (x[i]>47 && x[i]<58 ){//for x0 to x9
      x[i]=x[i]-48;
    }                     
      if (x[i]>64 && x[i]<71 ){//for xA to xF
      x[i]=(x[i]-65)+10;     
    }
  }
  // map the range from Xsim (0 <-> 255) to the mechanically authorized range (potMini <-> potMaxi)
  result=map((x[1]*16+x[2]),0,255,potMini,potMaxi);
  return result;
}
 

quinta-feira, 14 de abril de 2016

Over the limits!!!

Semana bem agitada na garagem F-5im! Novidades na eletrônica, na montagem, na estrutura do banco, no SimVIBE e nos  400W de potência aplicada nos shakers... uma semana muito produtiva!!!


Na foto acima temos um resumo geral de todas as atualizações!

Amplificador dos shakers e fonte 24V instaladas de maneira provisória


Toda a eletrônica, para a parte full motion do projeto já montada em plataforma experimental.



Evolução do banco










É isso aí pessoal!!! Semana que vem tem mais!!!!

quarta-feira, 13 de abril de 2016

ÚLTIMOS HARDWARES (VNH3SP30 + POT. 100K CERMET)

Após a primeira compra frustrada pelo nosso correio/receita, fiz um novo pedido do motor driver VNH3SP30, fundamental para fazer o sistema funcionar em 24 Volts. Dessa vez selecionei uma courier para o frete, e em 4 dias, as peças chegaram!


Os potenciômetros 100K CERMET, de alta precisão, também chegaram.


Vitória!!! Temos todas as peças/equipamentos necessários para montar o quebra cabeça.

Agora, a brincadeira ficou séria!!

quinta-feira, 7 de abril de 2016

SimuCUBE + F5im

Acabou, a pouco, mais um crowd founding da Granite Devices, fornecedora dos melhores controladores de motores servo drive do mundo. Com o sucesso da marca alcançada após o lançamento, em 2015, do IONI, a GD apresenta um novo produto voltado específico para o mercado do AV, o SimuCUBE. 


O SimuCUBE promete ser uma plataforma para integrar o controle do volante FFB, pedaleira, câmbio e button voz. 



O kit é composto pelo SimuCUBE + uma placa IONI PRO HC.



O kit padrão vem com uma fonte de 320W. Conseguimos um upgrade e o F5im contará com uma fonte de 480W, que é mais do que suficiente para "empurrar" o motor Mige.


Mais informações em: www.granitedevices.com



quarta-feira, 6 de abril de 2016

Chassis vs Banco

Dando andamento nos procedimentos necessários para transformar o chassis no corpo do simulador, a primeira etapa será a adaptação de um banco concha no chassis do F5im. Estou aproveitando a oportunidade que tem um excelente profissional que esta prestando serviço em fibra de vidro, pedi para ele adequar um banco concha a estrutura!



O assento já apresenta as primeiras cicatrizes para a adaptação.



A próxima etapa será adequar as costas e o apoio da cabeça a forma do chassis.


Fiquem ligados!!!

segunda-feira, 4 de abril de 2016

Caixa de Pandora!!!

Chegamos ao centro nervoso do sistema!!!


Essa semana daremos continuidade na parte nervosa do sistema, com as ligações elétricas, e primeiros testes com o Arduino controlando os motores Bosch, ainda na bancada...

Na foto abaixo, podemos identificar os 2 arduinos que serão utilizados no sistema, um MEGA com LCD e outro UNO, exclusivamente para controlar os 2 motores Bosch. Na parte inferior da foto está localizada o amplificador 4x100 W RMS que controla os shakers.


Detalhe dos 2 Arduinos, o MEGA com LCD e o UNO com o Motor Monster (controladora).


Disposição final


Comprei a fonte dos shakers nos EUA e as 2 necessárias para os motores BOSCH aqui no Brasil.



Vamos em frente...