MAL4X Научно-технический форум разработчиков симуляторов и автоматики


Симуляторы перегрузок. DIY электроника. ЭВМ. Компьютерные сети.
Up

Новейшая прошивка для Arduino.

Строим реалистичный симулятор перегрузок своими руками. Рекомендации. Советы.

Модераторы: Death_Morozz, null, Ale

Сообщение SimAl » 07 окт 2017, 14:01

Simctrl это тулза для настройки? Ну, видимо, разные. Скорее всего эта утилита отправляет всегда значения двумя цифрами - добавляет ноль впереди при необходимости, т.е. 01, 02 ... 0F, 10... FF. А симтулз первый, ничего не значащий ноль опускает: 0, 1 ... F,10...FF. По смыслу это одно и то же, но отсутствие нуля вводит ардуино в ступор.
Аватара пользователя
SimAl
SIMER
 
Сообщения: 347
Зарегистрирован: 22 ноя 2013, 20:03
Откуда: Кропивницкий
Благодарил (а): 56 раз.
Поблагодарили: 235 раз.
Баллы репутации: 108
ТехнарьТехнарь

Re: Новейшая прошивка для Arduino.

Сообщение lm890405 » 12 окт 2017, 19:51

DmRaF писал(а):А против писка моторов использую наушники

вот прошивка которая не пищит

Код: Выделить всё
/*   
 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 Mathieu RIVIER in english http://www.xsimulator.net/2dof-wiper-motor-playseat/ in french : http://www.gamoover.net/Forums/index.php?topic=27617
 Updated 30 April 2014 by RacingMat (bug for value below 16 corrected)
 Updated 1 June 2014 by RacingMat: implementation of Ultrasonic PWM (don't stack the motomonster! follow the new pinout!)
 results in video here : https://www.youtube.com/watch?v=FzhUga64fJs
 */

#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 than 255, if you want to lower the maximum motor's speed
#define pwmMini 150

// defining the range of potentiometer's rotation 0 <-> 1024
const int potMini=200;
const int potMaxi=800;

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

////////////////////////////////////////////////////////////////////////////////
//  DECLARATIONS
////////////////////////////////////////////////////////////////////////////////
/*  VNH2SP30 pin definitions
 // with 20kHz PWM pinout is changed, you CANNOT stack the motomonster anymore!
 Arduino /..Motomonster1
 ......GND <-> GND pin
 ........5V <-> 5V
 .....pin 4 <-> pin 4 inA motor1
 .....pin 5 <-> pin 9 inB motor2
 .....pin 6 <-> xxxx
 .....pin 7 <-> pin 7 inA motor2
 .....pin 8 <-> pin 8 inB motor1
 .....pin 9 <-> pin 5 pwm motor1
 .....pin 10 <-> pin 6 pwm motor2 */

int inApin[2] = {
  7, 4};  // INA: Clockwise input
int inBpin[2] = {
  8, 5}; // INB: Counter-clockwise input
int pwmpin[2] = {
  9, 10}; // PWM input
/* init position value at startup */
int DataValueL=512; //middle position 0-1024
int DataValueR=512; //middle position 0-1024

int sensorL,sensorR;   
////////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
////////////////////////////////////////////////////////////////////////////////
void analogWriteSAH_Init( void )
{
  // Stop the timer while we muck with it

  TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10);

  // Set the timer to mode 14...
  //
  // Mode  WGM13  WGM12  WGM11  WGM10  Timer/Counter Mode of Operation  TOP   Update of OCR1x at TOV1  Flag Set on
  //              CTC1   PWM11  PWM10
  // ----  -----  -----  -----  -----  -------------------------------  ----  -----------------------  -----------
  // 14    1      1      1      0      Fast PWM                         ICR1  BOTTOM                   TOP

  // Set output on Channel A and B to...
  //
  // COM1z1  COM1z0  Description
  // ------  ------  -----------------------------------------------------------
  // 1       0       Clear OC1A/OC1B on Compare Match (Set output to low level).

  TCCR1A =
    (1 << COM1A1) | (0 << COM1A0) |   // COM1A1, COM1A0 = 1, 0
  (1 << COM1B1) | (0 << COM1B0) |
    (1 << WGM11) | (0 << WGM10);      // WGM11, WGM10 = 1, 0

    // Set TOP to...
  //
  // fclk_I/O = 16000000
  // N        = 1
  // TOP      = 799
  //
  // fOCnxPWM = fclk_I/O / (N * (1 + TOP))
  // fOCnxPWM = 16000000 / (1 * (1 + 799))
  // fOCnxPWM = 16000000 / 800
  // fOCnxPWM = 20000

    ICR1 = 799;

  // Ensure the first slope is complete

  TCNT1 = 0;

  // Ensure Channel A and B start at zero / off

  OCR1A = 0;
  OCR1B = 0;

  // We don't need no stinkin interrupts

  TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (0 << TOIE1);

  // Ensure the Channel A and B pins are configured for output
  DDRB |= (1 << DDB1);
  DDRB |= (1 << DDB2);

  // Start the timer...
  //
  // CS12  CS11  CS10  Description
  // ----  ----  ----  ------------------------
  // 0     0     1     clkI/O/1 (No prescaling)

  TCCR1B =
    (0 << ICNC1) | (0 << ICES1) |
    (1 << WGM13) | (1 << WGM12) |              // WGM13, WGM12 = 1, 1
  (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void analogWriteUltrasonic255( uint8_t motor, uint16_t value )

  //  My variable value varies from 0 to 255
  //  but awaited range in OCR1A is from 0 to 799 and nothing else!
  switch (motor) {
  case 0:
    OCR1A=constrain(map(value, 0, 255, 0, 799), 0, 799); //D9
    break;
  case 1:
    OCR1B=constrain(map(value, 0, 255, 0, 799), 0, 799); //D10
    break;
  }
}


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

  // initialization of Arduino's pins

  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()
{
  while (1==1) // to get the fastest loop possible
{

  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); // 0 <-> 1024

  if (gap<= Tol) {
        analogWriteUltrasonic255(numMot,0); //too near to move : stop -> pwm=0   
  }
  else {
    // PID : P only as it calculates speed according to distance
    // smooth growing of speed
    //pwm=pwmMini+((255-pwmMini)/(100-Tol))*(gap-Tol);
        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 global sensitivity !

    // if motor is outside from the range, send motor back to the limit !
    // go forward (up)
    if ((actualPos<potMini) || (actualPos<targetPos))
    {   
      digitalWrite(inApin[numMot], HIGH);
      digitalWrite(inBpin[numMot], LOW);
    }
    // go reverse (down)   
    if ((actualPos>potMaxi) || (actualPos>targetPos))
    {   
      digitalWrite(inApin[numMot], LOW);
      digitalWrite(inBpin[numMot], HIGH);
    }
    analogWriteUltrasonic255(numMot,pwm);
  }
}

////////////////////////////////////////////////////////////////////////////////
// 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 xA to xF
      x[i]=x[i]-48;
    }                       
    if (  x[i]>64 && x[i]<71 ){//for x0 to x9
      x[i]=x[i]-55;               
    }
  }
  // map the range from game telemetry which is sent between (0 <-> 255) to the mechanically authorized range (potMini <-> potMaxi) (0<->1024)
  result=map((x[1]*16+x[2]),0,255,potMini,potMaxi);
  return result;
}



lm890405
Новичок
 
Сообщения: 12
Зарегистрирован: 03 сен 2017, 23:20
Благодарил (а): 3 раз.
Поблагодарили: 0 раз.
Баллы репутации: 0

Re: Новейшая прошивка для Arduino.

Сообщение SimAl » 12 окт 2017, 20:26

lm890405 писал(а):вот прошивка которая не пищит
Да, тут не нулевой таймер используется, а первый. Он позволяет задать произвольную частоту, соответственно можно избавиться от писка. Но на Ардуино с такой прошивкой монстр не станет бутербродом - потребуются либо хардварные модификации, либо соединять соплями.
Аватара пользователя
SimAl
SIMER
 
Сообщения: 347
Зарегистрирован: 22 ноя 2013, 20:03
Откуда: Кропивницкий
Благодарил (а): 56 раз.
Поблагодарили: 235 раз.
Баллы репутации: 108
ТехнарьТехнарь

Re: Новейшая прошивка для Arduino.

Сообщение Spirit » 14 окт 2017, 00:59

Возможно этот глюк поправили в Simtools 2, если проверишь - отпишись пожалуйста.
Чтобы избавиться от писка надо установить частоты повыше, SMC3 может помочь.
Аватара пользователя
Spirit
SIMER
 
Сообщения: 277
Зарегистрирован: 18 ноя 2014, 14:40
Откуда: Киев
Благодарил (а): 76 раз.
Поблагодарили: 91 раз.
Баллы репутации: 46
Пользователь

Пред.

Вернуться в X-SIMULATOR и RU-SIMULATOR & SimTools

Кто сейчас на конференции

Сейчас этот форум просматривают: Andrey.Lukyanov, Bing [Bot] и гости: 9

x

#{title}

#{text}