Controlar dos motores nema 17 con mando de ps3

Escribo en este foro con la esperanza de que alguien pueda ayudarme ya que he estado varios dias intentando encontrar algun codigo que haga lo que necesito, pero no encuentro nada ni remotamente parecido y la verdad es que estoy ya un poco desesperado y por que no decirlo, un poco frustrado..

Os comento.. Quiero controlar un telescopio con dos motores pap nema 17, los cuales seran movidos con los jostick de un mando de ps3 por bluetooth.. La idea es utilizar un jostick para arriba y abajo y el otro jostick para izquierda y derecha..

Estos son los materiales que tengo:

1 x Arduino uno o Arduino mega (el que mejor se adapte al proyecto)
1 x USB Host Shield V2
2 x Driver A4988 pololu
2 x Motor paso a paso nema 17 de 1.5 amperios
1 x Dongle bluetooth
1 x Mando PS3

He estado probando el ejemplo que viene con la libreria del USB Host Shield para el mando de ps3 y funciona correctamente, recibo por serial las pulsaciones de los botones del mando y los valores al mover los jostick. El problema esta en que no se mucho de programacion en Arduino y no se que modificaciones hay que hacerle al ejemplo para poder controlar los motores con el driver A4988 y no se que pines he de utilizar para que funcionen sin problemas el USB Host Shield y el driver A4988..

Por otra parte, tambien he probado por separado el driver A4988 con arduino uno siguiendo este esquema:

Y utilizando este codigo con la libreria AccelStepper, compruebo que funciona correctamente:

#include <AccelStepper.h>

AccelStepper Xaxis(1, 7, 4); // pin 3 = step, pin 6 = direction

void setup() {
  Xaxis.setMaxSpeed(1000);
  Xaxis.setSpeed(1000);
}

void loop() {  
   Xaxis.runSpeed();
}

El problema es que no se como hay que hacer el codigo para controlar la velocidad y el sentido de giro con los jostick del mando.. Asi que si alguien puede echarme una mano, le estaria muy agradecido..

Un saludo.

Hola Toper, que proyecto mas interesante!!
Bueno ya que has resuelto dos partes del mismo solo falta unirlas asi que a trabajar.
Paso 1: Que salidas entregan los joystick en la posición de reposo NEUTRAL y en los extremos.
Eso definirá un limite esperable que luego convertiremos con una función que se llama map que es como un conversor de escalas.
Mueves el joystick para un lado (digamos positivo) y el motor qira en sentido horario. Mueves para el contrario y el motor hará lo contrario.
Sueltas y se detiene o al menos fijaremos un umbral para que lo haga porque las cosas no son perfectas.
yo consideraría mas que un joystick dos encoders pero es mi visión del tema. También sería interesante un track ball.

Vuelve a conectar el joystick y comentanos las respuestas que obtienes, en las 3 posiciones fundamentales, extremos izq, neutral y derecho.

Gracias surbyte..

Pues a ver.. En reposo sin tocar ningun jostick, estos son los valores que obtengo:

Si muevo el jostick izquierdo hacia la izquierda:

Si muevo el jostick izquierdo hacia la derecha:

Si muevo el jostick derecho hacia la izquierda:

Si muevo el jostick derecho hacia la derecha:

Decir que los jostick tienen potenciometro, los valores van desde 131 en reposo, hasta 255 y hasta 0 segun el recorrido que le des..

Por si te sirve de algo, este es el codigo de ejemplo que viene con la libreria Usb host shield para el mando de ps3 por bluetooh:

/*
 Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus
 For more information visit my blog: http://blog.tkjelectronics.dk/ or
 send me an e-mail:  kristianl@tkjelectronics.com
 */

#include <PS3BT.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif

USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
/* You can create the instance of the class in two ways */
PS3BT PS3(&Btd); // This will just create the instance
//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch

bool printTemperature, printAngle;

void setup() {
  Serial.begin(115200);
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
  Serial.print(F("\r\nPS3 Bluetooth Library Started"));
}
void loop() {
  Usb.Task();

  if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
    if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {
      Serial.print(F("\r\nLeftHatX: "));
      Serial.print(PS3.getAnalogHat(LeftHatX));
      Serial.print(F("\tLeftHatY: "));
      Serial.print(PS3.getAnalogHat(LeftHatY));
      if (PS3.PS3Connected) { // The Navigation controller only have one joystick
        Serial.print(F("\tRightHatX: "));
        Serial.print(PS3.getAnalogHat(RightHatX));
        Serial.print(F("\tRightHatY: "));
        Serial.print(PS3.getAnalogHat(RightHatY));
      }
    }

    // Analog button values can be read from almost all buttons
    if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {
      Serial.print(F("\r\nL2: "));
      Serial.print(PS3.getAnalogButton(L2));
      if (PS3.PS3Connected) {
        Serial.print(F("\tR2: "));
        Serial.print(PS3.getAnalogButton(R2));
      }
    }

    if (PS3.getButtonClick(PS)) {
      Serial.print(F("\r\nPS"));
      PS3.disconnect();
    }
    else {
      if (PS3.getButtonClick(TRIANGLE)) {
        Serial.print(F("\r\nTraingle"));
        PS3.setRumbleOn(RumbleLow);
      }
      if (PS3.getButtonClick(CIRCLE)) {
        Serial.print(F("\r\nCircle"));
        PS3.setRumbleOn(RumbleHigh);
      }
      if (PS3.getButtonClick(CROSS))
        Serial.print(F("\r\nCross"));
      if (PS3.getButtonClick(SQUARE))
        Serial.print(F("\r\nSquare"));

      if (PS3.getButtonClick(UP)) {
        Serial.print(F("\r\nUp"));
        if (PS3.PS3Connected) {
          PS3.setLedOff();
          PS3.setLedOn(LED4);
        }
      }
      if (PS3.getButtonClick(RIGHT)) {
        Serial.print(F("\r\nRight"));
        if (PS3.PS3Connected) {
          PS3.setLedOff();
          PS3.setLedOn(LED1);
        }
      }
      if (PS3.getButtonClick(DOWN)) {
        Serial.print(F("\r\nDown"));
        if (PS3.PS3Connected) {
          PS3.setLedOff();
          PS3.setLedOn(LED2);
        }
      }
      if (PS3.getButtonClick(LEFT)) {
        Serial.print(F("\r\nLeft"));
        if (PS3.PS3Connected) {
          PS3.setLedOff();
          PS3.setLedOn(LED3);
        }
      }

      if (PS3.getButtonClick(L1))
        Serial.print(F("\r\nL1"));
      if (PS3.getButtonClick(L3))
        Serial.print(F("\r\nL3"));
      if (PS3.getButtonClick(R1))
        Serial.print(F("\r\nR1"));
      if (PS3.getButtonClick(R3))
        Serial.print(F("\r\nR3"));

      if (PS3.getButtonClick(SELECT)) {
        Serial.print(F("\r\nSelect - "));
        PS3.printStatusString();
      }
      if (PS3.getButtonClick(START)) {
        Serial.print(F("\r\nStart"));
        printAngle = !printAngle;
      }
    }
#if 0 // Set this to 1 in order to see the angle of the controller
    if (printAngle) {
      Serial.print(F("\r\nPitch: "));
      Serial.print(PS3.getAngle(Pitch));
      Serial.print(F("\tRoll: "));
      Serial.print(PS3.getAngle(Roll));
    }
#endif
  }
#if 0 // Set this to 1 in order to enable support for the Playstation Move controller
  else if (PS3.PS3MoveConnected) {
    if (PS3.getAnalogButton(T)) {
      Serial.print(F("\r\nT: "));
      Serial.print(PS3.getAnalogButton(T));
    }
    if (PS3.getButtonClick(PS)) {
      Serial.print(F("\r\nPS"));
      PS3.disconnect();
    }
    else {
      if (PS3.getButtonClick(SELECT)) {
        Serial.print(F("\r\nSelect"));
        printTemperature = !printTemperature;
      }
      if (PS3.getButtonClick(START)) {
        Serial.print(F("\r\nStart"));
        printAngle = !printAngle;
      }
      if (PS3.getButtonClick(TRIANGLE)) {
        Serial.print(F("\r\nTriangle"));
        PS3.moveSetBulb(Red);
      }
      if (PS3.getButtonClick(CIRCLE)) {
        Serial.print(F("\r\nCircle"));
        PS3.moveSetBulb(Green);
      }
      if (PS3.getButtonClick(SQUARE)) {
        Serial.print(F("\r\nSquare"));
        PS3.moveSetBulb(Blue);
      }
      if (PS3.getButtonClick(CROSS)) {
        Serial.print(F("\r\nCross"));
        PS3.moveSetBulb(Yellow);
      }
      if (PS3.getButtonClick(MOVE)) {
        PS3.moveSetBulb(Off);
        Serial.print(F("\r\nMove"));
        Serial.print(F(" - "));
        PS3.printStatusString();
      }
    }
    if (printAngle) {
      Serial.print(F("\r\nPitch: "));
      Serial.print(PS3.getAngle(Pitch));
      Serial.print(F("\tRoll: "));
      Serial.print(PS3.getAngle(Roll));
    }
    else if (printTemperature) {
      Serial.print(F("\r\nTemperature: "));
      Serial.print(PS3.getTemperature());
    }
  }
#endif
}

Perfecto!!
Entonces tenemos por lo visto valores muy estables. Excelente igualmente tomaremos recaudos.
Fase 1 concluida.
Tenemos dos códigos que funcionan bien, hemos identificado nuestro control

Fase 2: Definamos velocidades de trabajo.
Tendras una velocidad constante o quieres cierta acelaración y luego una aproximación a tu objetivo?

Me gustaria si es posible poder regular la velocidad en funcion del recorrido que le de al jostick. Como se ve en este video:

Video Youtube

O sea.. que en los extremos tienes MAXima velocidad en el sentido de giro que sea.
Okay.

Si sirve de algo, encontre este codigo que tambien utiliza un mando de ps3, pero en este caso utiliza un wifi shield y un motor shield:

// Robot controlled by a PS3 controller using Arduino Uno and Wifi Shield

//Include the necessary libraries.
#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>

//Wifi Variables
int status = WL_IDLE_STATUS;
char ssid[] = "YOURSSID"; //  your network SSID (name) 
char pass[] = "YOURPASSWORD";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

unsigned int localPort = 2390;      // local port to listen on

char packetBuffer[255]; //buffer to hold incoming packet

WiFiUDP Udp;

// Motor Control Variables
int PWM1 = 9;
int ENABLE1 = 8;
int PWM2 = 5;                         
int ENABLE2 = 1;                           
int PWM3 = 3;
int ENABLE3 = 0;
int PWM4 = 6;
int ENABLE4 = 2;

int lX, lY, rX, rY;

void setup(){
  
  //IF YOU WANT TO TEST YOUR SHIELD AND SEE INFORMATION ON THE SERIAL MONTIOR,
  //UNCOMMENT THE FOLLOWING FUNCTION.
  //IF YOU WANT TO RUN THE MOTORS, COMMENT IT OUT AGAIN.
  //Serial.begin(9600); 

  //Set pinMode for the enable pins 
  pinMode (ENABLE1, OUTPUT);
  pinMode (ENABLE2, OUTPUT);
  pinMode (ENABLE3, OUTPUT);
  pinMode (ENABLE4, OUTPUT);
  
  //UDP Configuration
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    // don't continue:
    while(true);
  } 
  
  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:    
    status = WiFi.begin(ssid,pass);
  
    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  //printWifiStatus();
  
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  Udp.begin(localPort);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remoteIp = Udp.remoteIP();
    Serial.print(remoteIp);
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    int len = Udp.read(packetBuffer,255);
    if (len >0) packetBuffer[len]=0;
     Serial.println("Contents:");
     Serial.println(packetBuffer);
    
    char* pch;
    pch = strtok (packetBuffer," ");
 
    for(int i = 0; i < 4; i++)
    {
    if(i == 0) lX = atoi(pch);
    if(i == 1) lY = atoi(pch);
    if(i == 2) rX = atoi(pch);
    if(i == 3) rY = atoi(pch); 
    pch = strtok (NULL," ");
    }
    CommandMotors(lY,rY);
  }
}

void CommandMotors(int LY, int RY)
{
  
  if(LY < 120) {
   digitalWrite (ENABLE1, HIGH);
   digitalWrite (ENABLE4, HIGH);
   analogWrite(PWM1, (LY-120)*-2.125);
   analogWrite(PWM4, (LY-120)*-2.125);
  }
  if(LY > 135) {
   digitalWrite (ENABLE1, LOW);
   digitalWrite (ENABLE4, LOW);   
   analogWrite(PWM1, (LY-135)*2.125);
   analogWrite(PWM4, (LY-135)*2.125);
  }
  if(RY < 120) {
   digitalWrite (ENABLE2, HIGH);
   digitalWrite (ENABLE3, HIGH);
   analogWrite(PWM2, (RY-120)*-2.125);
   analogWrite(PWM3, (RY-120)*-2.125);
  }
  if(RY > 135) {
   digitalWrite (ENABLE2, LOW);
   digitalWrite (ENABLE3, LOW);   
   analogWrite(PWM2, (RY-135)*2.125);
   analogWrite(PWM3, (RY-135)*2.125);
  }

  //STOP
  if(LY > 120 && LY < 135) {
   analogWrite(PWM1, 0);
   analogWrite(PWM4, 0);
  }
  if(RY > 120 && RY < 135) {
   analogWrite(PWM2, 0);
   analogWrite(PWM3, 0);
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Versión 1.0

/*
 Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus
 For more information visit my blog: http://blog.tkjelectronics.dk/ or
 send me an e-mail:  kristianl@tkjelectronics.com
 */

#include <PS3BT.h>
#include <usbhub.h>
#include <AccelStepper.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
  #include <spi4teensy3.h>
  #include <SPI.h>
#endif

USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
/* You can create the instance of the class in two ways */
PS3BT PS3(&Btd); // This will just create the instance
//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch

bool printTemperature, printAngle;
unsigned int izqX, izqY;
unsigned int derX, derY;
unsigned int izqXAnt, izqYAnt;
unsigned int derXAnt, derYAnt;

// The Left o Stepper Izq pins
#define STEPPER1_DIR_PIN  3
#define STEPPER1_STEP_PIN 2
// The Right o Derecha stepper pins
#define STEPPER2_DIR_PIN  7
#define STEPPER2_STEP_PIN 6
// Define some steppers and the pins the will use
AccelStepper StepperIZQ(AccelStepper::DRIVER, STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
AccelStepper StepperDER(AccelStepper::DRIVER, STEPPER2_STEP_PIN, STEPPER2_DIR_PIN);

#define  MAX_SPEED 1000.0
#define  MIN_SPEED 0.1

void setup() {
  Serial.begin(115200);
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
  Serial.print(F("\r\nPS3 Bluetooth Library Started"));

  StepperIZQ.setMaxSpeed(1000.0);
  StepperIZQ.setAcceleration(200.0);
  StepperIZQ.setSpeed(0); // lo pongo a 0
  StepperDER.setMaxSpeed(1000);
  StepperDER.setAcceleration(200.0);
  StepperDER.setSpeed(0); // lo pongo a 0
}
void loop() {
  Usb.Task();

  if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
    if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {
        izqX = PS3.getAnalogHat(LeftHatX);
        //izqY = PS3.getAnalogHat(LeftHatY);
        derX = PS3.getAnalogHat(RightHatX);
        //derY = PS3.getAnalogHat(RightHatY);
        if (izqX =! izqXAnt) {
            izqVel = mapf(izqX, 0, 255, -MAX_SPEED, MAX_SPEED);
            StepperIZQ.setSpeed(izqVel);
        }
           
        if (derX =! derXAnt) {
            derVel = mapf(derX, 0, 255, -MAX_SPEED, MAX_SPEED);
            StepperDER.setSpeed(derVel);
        }
    }
  }
  izqXAnt = izqX;
  derXAnt = derX;

  StepperIZQ.runSpeed();
  StepperDER.runSpeed();
}

float mapf(int x, int in_min, int in_max, float out_min, float out_max)  {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

No tengo idea de como funcionará si rápido lento si compila o no.
Pruebalo y me dices.

Muchas gracias por el codigo amigo.. Obtengo este error:

Parece que no estan declarados "izqVel" ni "derVel"

¿los declaro ambos como "unsigned int"?

Defínelos o no sabes hacerlo? Hay que trabajar un poco por cuenta propia no?

float izqVel, derVel;

Por eso te preguntaba si los declaraba como unsigned int.. porque no sabia si era el metodo correcto..

En cualquier caso gracias de nuevo. Lo pruebo y te comento.

Edito:

Ya he compilado y subido el codigo, pero se queda a una velocidad fija el motor desde que enciendo el Arduino y no responde al movimiento del jostick..

Según lo que vi en la librería AccelStepper van como floats.
Cuando no sepas algo, ve a la librería y lee la documentación. Te ahorra dolores de cabeza.

Ya.. pero por mucho que lea si no entiendo lo que estoy leyendo ni se la forma de aplicarlo, no sirve de nada..

Por eso recurri a este foro.. del tema de programacion solo se lo justito..