Работа с китаёзным джойстиком

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Сразу оговорюсь: ни на что не претендую, просто разместил объяву. Итак: возникла как-то необходимость управлять с джойстика - да чем угодно управлять, теми же сервами. Посмотрел, что к чему, пощупал свои экземпляры вот таких китаёз:

и понял - не алё они, требуют индивидуальной калибровки как по осям, так и между экземплярами. Плюс - либо я плохо искал, либо никому не нужно было, но - в "библиотеках" работы с джойстиком не увидел полярных координат, от слова "вообще" - а ведь это вещь полезная, когда надо, например, удобно соотнести наклон джойстика с поворотом платформы вокруг своей оси. Короче:

1. Заголовочник:

#pragma once
//--------------------------------------------------------------------------------------------------------------------------------------
#include <Arduino.h>
//--------------------------------------------------------------------------------------------------------------------------------------
class Joystick
{
  public:

    Joystick();

   void begin(uint8_t xPin, uint8_t yPin, int16_t midPointX, int16_t midPointY, uint8_t histeresis = 20);
   void update();

   // возвращает сырые значения с потенциометров
   int16_t getXRaw();
   int16_t getYRaw();

   // возвращает нормализованные значения с потенциометров, приведённые к диапазону [-1.0, 1.0]
   float getX();
   float getY();

   // возвращает угол по каждой из осей. degreesFreedom - степень свободы по оси, градусов
   float getXAngle(uint8_t degreesFreedom=180);
   float getYAngle(uint8_t degreesFreedom=180);

   // возвращает угол в полярных координатах
   float getPolarAngle();

 private:

  uint8_t pinX, pinY;
  int16_t curX, curY;

  int16_t midX, midY;

  uint8_t histeresis;

  float reflect(int16_t current, int16_t midpoint, uint8_t histeresis);
  float computeAngle(float val, uint8_t degreesFreedom);
  
};
//--------------------------------------------------------------------------------------------------------------------------------------

2. Сырец:

#include "CoreJoystick.h"
//--------------------------------------------------------------------------------------------------------------------------------------
Joystick::Joystick()
{
  pinX = pinY = 0;
  curX = curY = 0;
  midX = midY = 512;
  histeresis = 20;
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::reflect(int16_t current, int16_t midpoint, uint8_t histeresis)
{
  if(current >= (midpoint - histeresis) && current <= (midpoint + histeresis))
    return 0.0;

 float reflectedPos = current - midpoint;

  float result = (reflectedPos/midpoint);

  if(result < -1.0)
    result = -1.0;
  
  if(result > 1.0)
    result = 1.0;

  return result;
}
//--------------------------------------------------------------------------------------------------------------------------------------
void Joystick::begin(uint8_t xPin, uint8_t yPin, int16_t midPointX, int16_t midPointY, uint8_t _histeresis)
{
  pinX = xPin;
  pinY = yPin;

  midX = midPointX;
  midY = midPointY;

  histeresis = _histeresis;
  
}
//--------------------------------------------------------------------------------------------------------------------------------------
void Joystick::update()
{
  curX = analogRead(pinX);
  curY = analogRead(pinY);
}
//--------------------------------------------------------------------------------------------------------------------------------------
int16_t Joystick::getXRaw()
{
  return curX;
}
//--------------------------------------------------------------------------------------------------------------------------------------
int16_t Joystick::getYRaw()
{
  return curY;
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::getX()
{
  return reflect(curX,midX,histeresis);  
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::getY()
{
  return reflect(curY,midY,histeresis);  
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::getPolarAngle()
{
  float x = getX();
  float y = getY();

  float atanResult = atan2(y, x);
  
  float ang = degrees(atanResult);
  if (ang < 0)  
    ang += 360;
  
  if(ang > 0)
    ang = 360 - ang;

  return ang;
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::computeAngle(float val, uint8_t degreesFreedom)
{
  val += 1.0;
  float stepSize = float(degreesFreedom)/2.0;
  return val*stepSize;
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::getXAngle(uint8_t degreesFreedom)
{
   return computeAngle(getX(),degreesFreedom);
}
//--------------------------------------------------------------------------------------------------------------------------------------
float Joystick::getYAngle(uint8_t degreesFreedom)
{
  return computeAngle(getY(),degreesFreedom);
}
//--------------------------------------------------------------------------------------------------------------------------------------

midPointX, midPointY - это как раз калибровка, значения с потенциометров, когда джойстик находится в состоянии покоя, т.е. - не тронут шаловливыми ручками. histeresis - надеюсь, понятно, для чего: чуть загрубляем, чтобы не было мелких дрожаний. degreesFreedom - степень свободы по оси, как показала практика - оси данного дешёвого поделия не двигаются на 180 градусов, тащемта.

Код, ессно, можно и упростить, убрав хранение переменных в классе, но мне - и так норм. От использования float - сам не в восторге, но, ещё раз - это просто пример.

По итогу - все имеющиеся в наличии джойстики удалось откалибровать и уверенно снимать с них показания, самым актуальным было - именно полярные координаты.

Такой вот мопед, квон должен оценить :)

strarbit
Offline
Зарегистрирован: 12.06.2016

+55555)