PS2 controller legge valori sbagliati

Buongiorno a tutti, utilizzo questo codice perche vorrei comandare un braccio robot con un controller ps2:

#include <PS2X_lib.h>  //for v1.6
int dir1 = 4;
int dir2 = 5;
int dir3 = 6;
int dir4 = 7;
int value_mapped;
#define PS2_DAT        12
#define PS2_CMD        11
#define PS2_SEL        10
#define PS2_CLK        13

//#define pressures   true
#define pressures   false
//#define rumble      true
#define rumble      false

PS2X ps2x; // create PS2 Controller Class

//right now, the library does NOT support hot pluggable controllers, meaning
//you must always either restart your Arduino after you connect the controller,
//or call config_gamepad(pins) again after connecting the controller.

int error = 0;
byte type = 0;
byte vibrate = 0;

void setup() {

  Serial.begin(9600);
  pinMode(dir1, OUTPUT);
  pinMode(dir2, OUTPUT);
  pinMode(dir3, OUTPUT);
  pinMode(dir4, OUTPUT);

  delay(1000);  //added delay to give wireless ps2 module some time to startup, before configuring it

  //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
if_error_is_found:                                                                                               //      <!---- changed here --->
  //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);

  if (error == 0) {
    Serial.print("Found Controller, configured successful ");
    Serial.print("pressures = ");
    if (pressures)
      Serial.println("true ");
    else
      Serial.println("false");
    Serial.print("rumble = ");
    if (rumble)
      Serial.println("true)");
    else
      Serial.println("false");
    Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
  }
  else if (error == 1)
  {
    Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
    goto if_error_is_found;                                       //      <!---- changed here --->
  }
  else if (error == 2)
    Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");

  else if (error == 3)
    Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
}

void loop() {

  if (error == 1) //skip loop if no controller found
    return;
  { //DualShock Controller
    ps2x.read_gamepad(); //read controller and set large motor to spin at 'vibrate' speed
    ps2x.reconfig_gamepad();                                                                       //      <!---- changed here --->
    if (ps2x.Button(PSB_START))        //will be TRUE as long as button is pressed
      Serial.println("Start is being held");
    if (ps2x.Button(PSB_SELECT))
      Serial.println("Select is being held");

    if (ps2x.Button(PSB_PAD_UP)) {     //will be TRUE as long as button is pressed
      Serial.print("Up held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
    }
    if (ps2x.Button(PSB_PAD_RIGHT)) {
      Serial.print("Right held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
    }
    if (ps2x.Button(PSB_PAD_LEFT)) {
      Serial.print("LEFT held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
    }
    if (ps2x.Button(PSB_PAD_DOWN)) {
      Serial.print("DOWN held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);
    }

    vibrate = ps2x.Analog(PSAB_CROSS);  //this will set the large motor vibrate speed based on how hard you press the blue (X) button
    if (ps2x.NewButtonState()) {        //will be TRUE if any button changes state (on to off, or off to on)
      if (ps2x.Button(PSB_L3))
        Serial.println("L3 pressed");
      if (ps2x.Button(PSB_R3))
        Serial.println("R3 pressed");
      if (ps2x.Button(PSB_L2))
        Serial.println("L2 pressed");
      if (ps2x.Button(PSB_R2))
        Serial.println("R2 pressed");
      if (ps2x.Button(PSB_TRIANGLE))
        Serial.println("Triangle pressed");
    }

    if (ps2x.ButtonPressed(PSB_CIRCLE))              //will be TRUE if button was JUST pressed
      Serial.println("Circle just pressed");
    if (ps2x.NewButtonState(PSB_CROSS))              //will be TRUE if button was JUST pressed OR released
      Serial.println("X just changed");
    if (ps2x.ButtonReleased(PSB_SQUARE))             //will be TRUE if button was JUST released
      Serial.println("Square just released");

    //  if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) { //print stick values if either is TRUE
    //Serial.println("Stick Values:");
    //Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX
    //Forward Direction And BAckward Diretion

    if (ps2x.Button(PSB_R1)) {
      if (ps2x.Analog(PSS_RY) >= 0)
      {

        //Forward Direction
        if (ps2x.Analog(PSS_RY) < 127)
        {
          Serial.println("All MOtor Running Forward");
          digitalWrite(dir1, LOW);
          digitalWrite(dir2, HIGH);
          digitalWrite(dir3, HIGH);
          digitalWrite(dir4, LOW);
        }
        //BAckward Direction
        if (ps2x.Analog(PSS_RY) >= 127)
        {
          Serial.println("All MOtor Running Backward");
          digitalWrite(dir1, HIGH);
          digitalWrite(dir2, LOW);
          digitalWrite(dir3, LOW);
          digitalWrite(dir4, HIGH);
        }
      }
      // LEft OR Right Direction
      if (ps2x.Analog(PSS_RX) >= 0)
      {

        //Left diretion
        if (ps2x.Analog(PSS_RX) < 128)
        {
          Serial.println("All MOtor Running Left");
          digitalWrite(dir1, HIGH);
          digitalWrite(dir2, HIGH);
          digitalWrite(dir3, LOW);
          digitalWrite(dir4, LOW);
        }
        //Right Direction
        if (ps2x.Analog(PSS_RX) > 128)
        {
          Serial.println("All MOtor Running Right");
          digitalWrite(dir1, LOW);
          digitalWrite(dir2, LOW);
          digitalWrite(dir3, HIGH);
          digitalWrite(dir4, HIGH);
        }
      }

      //All MOtors Clock

      if ( (ps2x.Analog(PSS_LX) < 128)  )
      {
        Serial.println("CLOCKWISE RUNNING ALL MOTORS");
        digitalWrite(dir1, LOW);
        digitalWrite(dir2, LOW);
        digitalWrite(dir3, LOW);
        digitalWrite(dir4, LOW);
      }

      //All MOtors Anti-CLockwise
      if (ps2x.Analog(PSS_LX) > 128)
      {
        Serial.println("CLOCKWISE RUNNING ALL MOTORS");
        digitalWrite(dir1, HIGH);
        digitalWrite(dir2, HIGH);
        digitalWrite(dir3, HIGH);
        digitalWrite(dir4, HIGH);
      }
    }
    if (ps2x.Button(PSB_L1)) {

      //dIAGONAL L


      if (ps2x.Analog(PSS_LX) < 120)
      {
        Serial.println("CLOCKWISE RUNNING ALL MOTORS");
        digitalWrite(dir1, LOW);
        digitalWrite(dir3, HIGH);
      }
      //dIAGONAL R
      if (ps2x.Analog(PSS_LX) >= 128)
      {
        Serial.println("CLOCKWISE RUNNING ALL MOTORS");
        digitalWrite(dir2, HIGH);
        digitalWrite(dir4, LOW);
      }

    }

    //Serial.print(",");
    //Serial.print(ps2x.Analog(PSS_LX), DEC);
    //Serial.print(",");


    //Serial.print(ps2x.Analog(PSS_RY), DEC);
    //Serial.print(",");
    //Serial.println(ps2x.Analog(PSS_RX), DEC);
    //  }
  }
  delay(50);
}

Il codice funziona correttamente e vedo il controller, il problema è che i joypad leggono valori sballati, ad esempio a riposo come posizione degli assi leggono 123, 123, 132, 132 se li sposto su, o tutto a desta o a sinistra leggono 0, dall'altra parte 255.... cosa potrebbe essere?
Interferenze di linea?

Scusa, ma che valori ti aspettavi di leggere? A me sembra funzioni normalmente.

Ciao, Ale.

che a riposo fosse zero! e non 123

NO, il joistick a riposo è come un potenziometro lineare con il pomello regolato a metà strada, menttre quando lo sposti a destra e a sinistra è come se ruotassi il potenziometro tutto da una parte o tutto dall'altra. Dato che gli estermi di detto potenziometro sono uno a GND ed uno a Vcc, quando sei al centro leggi un valore intermedio, tutto da una parte leggi 0 e tutto dall'altra leggi il massimo.

Guglielmo

Ok grazie per la spiegazione chiara. Ma quindi per far muovere degli stepper che valore devo prendere?

Dipende ... ad esempio, il valore centrale potrebbe essere motore fermo, il valori a sinistra, motore indietro, valori a destra, motore avanti.

Guglielmo

Una possibile soluzione:

uint8_t servo_dir = 0 ; // 0=stop;1=orario;2=antiorario
uint8_t servo_speed = 0; // velocità proporzionale (se serve [0/255])

//meglio prevedere una "dead band" per lo zero
if (ps2x.Analog(PSS_RX) < 135 and if (ps2x.Analog(PSS_RX) > 120)) {
  servo_dir=0;
  servo_speed = 0;
}
else{
  if(if (ps2x.Analog(PSS_RX) < 128){
    servo_dir=1;
    servo_speed=(127-ps2x.Analog(PSS_RX))*2;
  }
  else{
    servo_dir=2;
    servo_speed= (ps2x.Analog(PSS_RX) -127)*2;
  }
}

switch(servo_dir){
  case 1:
    //muovi il servo in senso orario
    break;
  case 2:
    //muovi il servo in senso antiorario
    break;
  default:
   //servo stop
    
}

Non so perchè ho chiamato le variabili servo_* visto che si stava parlandi di uno stepper, ma ora non ho voglia di correggere! :grinning:

Ciao, Ale.

Allora ho messo su questo codice con cui piloto 2 stepper ed 1 servo tramite controller wireless della PS2:

#include <PS2X_lib.h>
#include <AccelStepper.h>
#include <Servo.h>

PS2X ps2x;  // create PS2 Controller Class
int error = 0;  // define error variable, initialize as no error
byte type = 0;  // define controller type variable, may test removing
byte vibrate = 0;  // define vibration strength, default to none

Servo myservo;  // create servo object to control a servo
#define servoPin 2 //
int angle = 90;   // initial angle  for servo
int angleStep = 10;
const int minAngle = 90;
const int maxAngle = 170;

// $$$$$ INITIALIZE PROGRAM VARIABLES AND CONSTANTS $$$$$ //
int stickX = 128;  // initialize X-Axis joystick value to the middle of 0-255 range
int stickY = 128;  // initialize Y-Axis joystick value to the middle of 0-255 range

int startSwitchState = 0;  // initialize start switch state as not pressed
int startLastSwitchState = 0;  // initialize start last switch state as not pressed
int R1SwitchState = 0;  // initialize R1 switch state as not pressed
int R1LastSwitchState = 0;  // initialize R1 last switch state as not pressed
int R2SwitchState = 0;  // initialize R2 switch state as not pressed
int R2LastSwitchState = 0;  // initialize R2 last switch state as not pressed
int L1SwitchState = 0;  // initialize L1 switch state as not pressed
int L1LastSwitchState = 0;  // initialize L1 last switch state as not pressed
int L2SwitchState = 0;  // initialize L2 switch state as not pressed
int L2LastSwitchState = 0;  // initialize L2 last switch state as not pressed

const int pinEnable = 8;  //i pin che comandano lo stato ENABLE dei driver A4988 sono in collegati in serie per questo basta un solo pin per gestirli entrambi
const int stepX = 3;  //pin digitale che invia i segnali di STEP al driver delle X
const int dirX = 4; //pin digitale che invia il segnale DIREZIONE al driver delle X
long speedX, valX, mapX;  //variabili di gestione movimenti motore X
const int stepY = 5;  //pin digitale che invia i segnali di STEP al driver delle Y
const int dirY = 6; //pin digitale che invia il segnale DIREZIONE al driver delle Y
long speedY, valY, mapY;  //variabili di gestione movimenti motore Y
//variabili utilizzate dalla libreria AccelStepper
int maxSpeed = 500;  //stando alla documentazione della libreria questo valore può essere impostato fino a 4000 per un Arduino UNO
int minSpeed = 0; //velocità minima del motore
const float accelerazione = 30.0; //numero di step al secondo in accelerazione
boolean muoviX, muoviY;  //variabili di gestione dei movimenti
//istanzia i motori
AccelStepper motoreX(AccelStepper::DRIVER, stepX, dirX);
AccelStepper motoreY(AccelStepper::DRIVER, stepY, dirY);


void setup() {
  Serial.begin(9600);  // begin serial communication, set at 57600 Baud rate, may test changing
  error = ps2x.config_gamepad(13, 10, 11, 12, false, false); // check for errors on PS2 controller

  myservo.attach(servoPin);  // attaches the servo on pin 3 to the servo object
  myservo.write(angle);
  //configura parametri dei motori
  motoreX.setMaxSpeed(maxSpeed);
  motoreX.setSpeed(minSpeed);
  motoreX.setAcceleration(accelerazione);

  motoreY.setMaxSpeed(maxSpeed);
  motoreY.setSpeed(minSpeed);
  motoreY.setAcceleration(accelerazione);

  if (error == 0)
    Serial.print("Found Controller, Configured Successfully.");
  else if (error == 1)
    Serial.println("No Controller Found.");
  else if (error == 2)
    Serial.println("Controller Found but not Accepting Commands.");
  else if (error == 3)
    Serial.println("Controller Refusing to Enter Pressures Mode, May Not Support it.");

  type = ps2x.readType();  // find the type of the

  switch (type) {
    case 0:
      Serial.print("Unknown Controller Type Found ");
      break;
    case 1:
      Serial.print("DualShock Controller Found ");
      break;
  }
}


void loop() {
  if (error == 1) { // skip loop if no controller is found, may test adding config_gamepad(pins)
    ps2x.config_gamepad(13, 10, 11, 12, false, false); // reconfigure PS2 controller to attempt fixing error
    return;
  }
  ps2x.read_gamepad(false, vibrate); //read controller, don't record arrow pressures, and set large motor to spin at 'vibrate' speed

  R2SwitchState = ps2x.ButtonPressed(PSB_R2);  // read R2 switch state

  if (R2SwitchState != R2LastSwitchState) { // see if button state changed
    if (R2SwitchState == HIGH) { // if the button was pressed, not released
      myservo.write(maxAngle); // move the servo to desired angle
      Serial.println("R2 PRESSED");
    }
  }
  R2LastSwitchState = R2SwitchState;  // save switch state for comparison


  if (ps2x.ButtonPressed(PSB_RED)) {
    Serial.println("Circle just pressed");
  }
  if (ps2x.ButtonReleased(PSB_PINK)) {
    Serial.println("Square just pressed");
  }
  if (ps2x.NewButtonState(PSB_BLUE)) {
    Serial.println("X just changed");
  }

  L2SwitchState = ps2x.ButtonPressed(PSB_L2);  // read L2 switch state
  if (L2SwitchState != L2LastSwitchState) { // see if button state changed
    if (L2SwitchState == HIGH) {
      Serial.println("L2 PRESSED");
      myservo.write(minAngle); // move the servo to desired angle
    }
  }
  L2LastSwitchState = L2SwitchState;  // save switch state for comparison

  R1SwitchState = ps2x.ButtonPressed(PSB_R1);  // read R1 switch state
  if (R1SwitchState != R1LastSwitchState) { // see if button state changed
    if (R1SwitchState == HIGH) {
      Serial.println("R1 PRESSED");
    }
  }
  R1LastSwitchState = R1SwitchState;  // save switch state for comparison

  L1SwitchState = ps2x.ButtonPressed(PSB_L1);  // read L1 switch state
  if (L1SwitchState != L1LastSwitchState) { // see if button state changed
    if (L1SwitchState == HIGH) {
      Serial.println("L1 PRESSED");
    }
  }
  L1LastSwitchState = L1SwitchState;  // save switch state for comparison

  startSwitchState = ps2x.ButtonPressed(PSB_START);  // read Start switch state*/
  if (startSwitchState != startLastSwitchState) { // see if button state changed
    if (startSwitchState == HIGH) {
      Serial.println("START PRESSED");
    }
  }
  startLastSwitchState = startSwitchState;  // save switch state for comparison

  stickX = ps2x.Analog(PSS_RX);  // set the analog value of the right stick X-Axis equal (0-255)
  if (stickX != 68 && stickX != 67 && stickX != 66 && stickX != 65) {
    //Serial.print("X-AXIS:");
    //Serial.println(stickX, DEC);
  }

  stickY = ps2x.Analog(PSS_LY);  // set the analog value of the left stick Y-Axis equal (0-255)
  if (stickY != 127) {
    //Serial.print("Y-AXIS:");
    //Serial.println(stickY, DEC);
  }

  // $$$$$ MAP AND MOVE X-AXIS STEPPER MOTOR $$$$$ //
  int mapX = stickX;  // set the desired stepper position equal to the X-Axis value (0-255)
  minSpeed = 0; // reset speed

  if (mapX > 128) { // if the X-Axis stick position is positive
    speedX = map(mapX, 130, minSpeed, minSpeed, maxSpeed);
    muoviX = true;
    //Serial.println("muovo X a destra");
    //Serial.println(speedX);
    //Serial.println(mapX);
  } else if (mapX < 128) { // if the X-Axis stick position is negative
    speedX = -map(mapX, maxSpeed, 126,   maxSpeed, minSpeed);
    muoviX = true;
    //Serial.println("muovo X a sinistra");
    //Serial.println(mapX);
  } else {
    //x sta fermo
    speedX = 0;
    muoviX = false;
  }


  if (muoviX) {
    motoreX.setSpeed(speedX);
    motoreX.run();
  } else {
    motoreX.stop();
  }

  // MUOVO Y-AXIS STEPPER MOTOR //
  mapY = stickY;  // set the desired stepper position equal to the Y-Axis value (0-255)
  minSpeed = 0; // reset speed

  if (mapY > 127) { // if the Y-Axis stick position is positive
    speedY = map(mapY,  maxSpeed, 130,  maxSpeed, minSpeed);
    muoviY = true;
    //Serial.println("muovo Y su");
    //Serial.println(speedY);
    //Serial.println(mapY);
  } else if (mapY < 127) { // if the Y-Axis stick position is negative
    speedY = -map(mapY, 126, minSpeed,   minSpeed, maxSpeed);
    muoviY = true;
    //Serial.println("muovo Y giu");
    //Serial.println(speedY);
    //Serial.println(mapY);
  } else {
    //y sta fermo
    speedY = 0;
    muoviY = false;
  }

  if (muoviY) {
    motoreY.setSpeed(speedY);
    motoreY.run();
  } else {
    motoreY.stop();
  }
  delay(10);
}

L'unico problema è che lo stepper X quando muovo il joystick non si muove bene è come se facesse movimenti avanti e dietro continui!
Ho notato che il valore i uscita ps2x.Analog(PSS_LY) non è stabile, ed a riposo oscilla tra 65 e 68..... potrebbe essere questo il problema?

i cavi DATA (marrone) ed ATTENTION (giallo) sono sotto 1k tramite vcc.
In cosa differenzia dall'altro?