Go Down

Topic: USB Host Shield&Joysticks,How to get data from joystick to use on Motor Shield ? (Read 1 time) previous topic - next topic

MEKACI

I want to make a project to control my robot car with a Logitech joystick ( this is the picture of it : ).

Thus, I bought a USB Host Shield Arduino and I bought a Logitech Extreme 3D Pro Joystick. I have DC Motor Driver 2x 15A to make motors to move.

I downloaded the latest version of library from here: http://www.arduinolibraries.info/libraries/usb-host-shield-library-2-0.

From the library, there is an example to see the values we are getting from the joystick sticks and buttons on our arduino serial monitor. You can see the example file and its cpp and h files from here yourself too: https://github.com/felis/USB_Host_Shield_2.0/tree/master/examples/HID/USBHIDJoystick. I am going to post the same example from the given link too and then ask my question to you.

USBHIDJoystick.ino sketch:
Code: [Select]
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>

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

#include "hidjoystickrptparser.h"

USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid(&Usb);
JoystickEvents JoyEvents;
JoystickReportParser Joy(&JoyEvents);

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
        Serial.println("Start");

        if (Usb.Init() == -1)
                Serial.println("OSC did not start.");

        delay(200);

        if (!Hid.SetReportParser(0, &Joy))
                ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
}

void loop() {
        Usb.Task();
}



Sketch's cpp file:
Code: [Select]
#include "hidjoystickrptparser.h"

JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
joyEvents(evt),
oldHat(0xDE),
oldButtons(0) {
        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
                oldPad[i] = 0xD;
}

void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
        bool match = true;

        // Checking if there are changes in report since the method was last called
        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
                if (buf[i] != oldPad[i]) {
                        match = false;
                        break;
                }

        // Calling Game Pad event handler
        if (!match && joyEvents) {
                joyEvents->OnGamePadChanged((const GamePadEventData*)buf);

                for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];
        }

        uint8_t hat = (buf[5] & 0xF);

        // Calling Hat Switch event handler
        if (hat != oldHat && joyEvents) {
                joyEvents->OnHatSwitch(hat);
                oldHat = hat;
        }

        uint16_t buttons = (0x0000 | buf[6]);
        buttons <<= 4;
        buttons |= (buf[5] >> 4);
        uint16_t changes = (buttons ^ oldButtons);

        // Calling Button Event Handler for every button changed
        if (changes) {
                for (uint8_t i = 0; i < 0x0C; i++) {
                        uint16_t mask = (0x0001 << i);

                        if (((mask & changes) > 0) && joyEvents) {
                                if ((buttons & mask) > 0)
                                        joyEvents->OnButtonDn(i + 1);
                                else
                                        joyEvents->OnButtonUp(i + 1);
                        }
                }
                oldButtons = buttons;
        }
}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
        Serial.print("X1: ");
        PrintHex<uint8_t > (evt->X, 0x80);
        Serial.print("\tY1: ");
        PrintHex<uint8_t > (evt->Y, 0x80);
        Serial.print("\tX2: ");
        PrintHex<uint8_t > (evt->Z1, 0x80);
        Serial.print("\tY2: ");
        PrintHex<uint8_t > (evt->Z2, 0x80);
        Serial.print("\tRz: ");
        PrintHex<uint8_t > (evt->Rz, 0x80);
        Serial.println("");
}

void JoystickEvents::OnHatSwitch(uint8_t hat) {
        Serial.print("Hat Switch: ");
        PrintHex<uint8_t > (hat, 0x80);
        Serial.println("");
}

void JoystickEvents::OnButtonUp(uint8_t but_id) {
        Serial.print("Up: ");
        Serial.println(but_id, DEC);
}

void JoystickEvents::OnButtonDn(uint8_t but_id) {
        Serial.print("Dn: ");
        Serial.println(but_id, DEC);
}



Sketch's h file:
Code: [Select]
#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__

#include <usbhid.h>

struct GamePadEventData {
        uint8_t X, Y, Z1, Z2, Rz;
};

class JoystickEvents {
public:
        virtual void OnGamePadChanged(const GamePadEventData *evt);
        virtual void OnHatSwitch(uint8_t hat);
        virtual void OnButtonUp(uint8_t but_id);
        virtual void OnButtonDn(uint8_t but_id);
};

#define RPT_GEMEPAD_LEN 5

class JoystickReportParser : public HIDReportParser {
        JoystickEvents *joyEvents;

        uint8_t oldPad[RPT_GEMEPAD_LEN];
        uint8_t oldHat;
        uint16_t oldButtons;

public:
        JoystickReportParser(JoystickEvents *evt);

        virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};

#endif // __HIDJOYSTICKRPTPARSER_H__



This is the code from cpp file we print the data values we get from joystick to serial monitor at arduino:
Code: [Select]
void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
        Serial.print("X1: ");
        PrintHex<uint8_t > (evt->X, 0x80);
        Serial.print("\tY1: ");
        PrintHex<uint8_t > (evt->Y, 0x80);
        Serial.print("\tX2: ");
        PrintHex<uint8_t > (evt->Z1, 0x80);
        Serial.print("\tY2: ");
        PrintHex<uint8_t > (evt->Z2, 0x80);
        Serial.print("\tRz: ");
        PrintHex<uint8_t > (evt->Rz, 0x80);
        Serial.println("");
}



How to apply these codes in cpp file or access these codes from cpp file to use on arduino's main code block side ( arduino sketch .ino ) ?

What do I need to write in void setup() and void loop() section to make my dc motors to move according to the values I get from the joystick ?


I thought so much and check internet to find any single clue to solve the main problem I encountered. This is my first time using HID device to work on arduino ( with the help of an arduino library ).

Shortly, I came here to seek your guidance and help. I really want to learn this topic and how to apply it too. I hope that some of you friends help me out. I look forward your replies to me in this thread. Thank you very much from now on.




vinceherman

Break your work down into smaller parts.

First, get the joystick demo working.  You have the library.  You have the example in USBHIDJoystick.ino

Have you tried uploading that and seeing if it works with your joystick?

After you get the joystick reading working, then tackle the next step - your motor driver.  Does the manufacturer provide any tutorial or examples with it? Try to get it working without your joystick being involved.  After you get the motor driver working, THEN work on combining the 2.

MEKACI

My motor driver is working fine alone and my dc motors work too. This is my motor shield : https://www.dfrobot.com/wiki/index.php/DC_Motor_Driver_2x15A_Lite_(SKU:_DRI0018).

This is the code of motor driver:
Code: [Select]
int E1 = 5;     //M1 Speed Control
int E2 = 6;     //M2 Speed Control
int M1 = 4;     //M1 Direction Control
int M2 = 7;     //M1 Direction Control
int counter=0;

void stop(void)                    //Stop
{
  digitalWrite(E1,0);
  digitalWrite(M1,LOW);   
  digitalWrite(E2,0);   
  digitalWrite(M2,LOW);   
}   
void advance(char a,char b)          //Move forward
{
  analogWrite (E1,a);      //PWM Speed Control
  digitalWrite(M1,HIGH);   
  analogWrite (E2,b);   
  digitalWrite(M2,HIGH);

void back_off (char a,char b)          //Move backward
{
  analogWrite (E1,a);
  digitalWrite(M1,LOW);   
  analogWrite (E2,b);   
  digitalWrite(M2,LOW);
}
void turn_L (char a,char b)             //Turn Left
{
  analogWrite (E1,a);
  digitalWrite(M1,LOW);   
  analogWrite (E2,b);   
  digitalWrite(M2,HIGH);
}
void turn_R (char a,char b)             //Turn Right
{
  analogWrite (E1,a);
  digitalWrite(M1,HIGH);   
  analogWrite (E2,b);   
  digitalWrite(M2,LOW);
}
void current_sense()                  // current sense and diagnosis
{
  int val1=digitalRead(2);           
  int val2=digitalRead(3);
  if(val1==HIGH || val2==HIGH){
    counter++;
    if(counter==3){
      counter=0;
      Serial.println("Warning");
    } 
  }
}

void setup(void)
{
  int i;
  for(i=4;i<=7;i++)
    pinMode(i, OUTPUT); 
  Serial.begin(19200);      //Set Baud Rate
  Serial.println("Run keyboard control");
  digitalWrite(E1,LOW);   
  digitalWrite(E2,LOW);
  pinMode(2,INPUT);
  pinMode(3,INPUT);
}

void loop(void)
{
  /*
  static unsigned long timePoint = 0;    // current sense and diagnosis,if you want to use this
   if(millis() - timePoint > 1000){       //function,please show it & don't forget to connect the IS pins to Arduino                                             
   current_sense();
   timePoint = millis();
   }
   */
  if(Serial.available()){
    char val = Serial.read();
    if(val != -1)
    {
      switch(val)
      {
      case 'w'://Move Forward
        advance (255,255);   //move forward in max speed
        break;
      case 's'://Move Backward
        back_off (255,255);   //move back in max speed
        break;
      case 'a'://Turn Left
        turn_L (100,100);       
        break;       
      case 'd'://Turn Right
        turn_R (100,100);
        break;
      case 'z':
        Serial.println("Hello");
        break;
      case 'x':
        stop();
        break;
      }
    }
    else stop(); 
  }

}


For example, I want to put the data I get from joystick itself on this code here: advance (255,255); Replace the 255,255 ones.

PrintHex<uint8_t > (evt->X, 0x80); This code gives you hex values. So, for my motor shield I probably need to convert hex to int too.

My logitech joystick is working with that sample example from the usb host library, I get values on serial monitor when I move the joystick in x and y axis successfully.


This code block is in cpp file of the example:
Code: [Select]
void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
        Serial.print("X1: ");
        PrintHex<uint8_t > (evt->X, 0x80);
        Serial.print("\tY1: ");
        PrintHex<uint8_t > (evt->Y, 0x80);
        Serial.print("\tX2: ");
        PrintHex<uint8_t > (evt->Z1, 0x80);
        Serial.print("\tY2: ");
        PrintHex<uint8_t > (evt->Z2, 0x80);
        Serial.print("\tRz: ");
        PrintHex<uint8_t > (evt->Rz, 0x80);
        Serial.println("");
}


So, I cannot access to this code in main arduino sketch. When I add it, it says " this argument is no exist or not defined errors ".

In USBHIDJoystick.ino sketch's void loop() only consists of with this line "  Usb.Task(); ". This is part I am struggling now. I don't know how to bring the main codes that makes the print in the serial monitor from cpp file to " USBHIDJoystick.ino sketch ".

I hope that I was more clear with my question this time. I will be very happy if someone would teach me how to solve this problem.






MEKACI

Anyone would show me please what kind of modifications do I need to make in cpp , h and arduino sketch files to get these values on the serial monitor to use on my motor shield in the void loop() section of arduino ? I really need help of some knowledgeable people about this issue. This is my first time doing such a thing, thank you.

asheeshcric

Even I am searching for the same thing. The problem is I am not getting the way to deal with the input values that I am getting from the Joystick. I need my motors to be controlled using the values obtained from the joystick, but I am not being able to use the inputs in the main program.

MEKACI

Even I am searching for the same thing. The problem is I am not getting the way to deal with the input values that I am getting from the Joystick. I need my motors to be controlled using the values obtained from the joystick, but I am not being able to use the inputs in the main program.
nrf24 and usb shield block each other so when you connect them at the same time, non of them are working at all. I tried all kind of experimental tries on internet and myself too and I was not able to solve the problem to use nrf24 and usb shield at the same time at all. Noone offence please but when they design these shields that thy know this will happen so why thy give a solution for that already for years ?

I still hope that some very knowledgeable guy in arduino forum will help us for this problem really. I study AI and Robotics in the university as an international student and I learned java,python, c# and pic programming. I only didn't see c++ ( some people say thy are similar, yes thy are similar but their way of implementation is very different than each other too ) so I try to learn c++ deeply too now and use it on arduino in detailed way in my robot too, for example, the current issue which requires a deep knowledge on c++, arduino, and board designs to apply a solution.

Shortly, who would help us to learn and solve this problem please ? There is no solid solution to fix this problem on the internet or anywhere really and I cannot find anyone in real life to ask or who might help me too. I asked in uni but I couldn't get any help in this very specific problem too.

gdsports

I think the idea is to call the motor control functions from the OnGamePadChanged function.

You should be able to determine the JoyXMin* and JoyXMax* values by looking at the joystick console output when moving the joystick to its extreme positions. The sketch must map the values in this range to the range of values for the motor controller.

Adjust if the Y-axis is the forward and reverse axis. Also I have no way to test this code be sure you understand the code before plugging it in.

Code: [Select]

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
        uint8_t motorspeed;

        Serial.print("X1: ");
        PrintHex<uint8_t > (evt->X, 0x80);
        //https://www.arduino.cc/reference/en/language/functions/math/map/
        if (evt->X >= JoyXMinForward && evt->X <= JoyXMaxForward) {
            motorspeed = map(evt->X, JoyXMinForward, JoyXMaxForward, 0, 255);
            advance(motorspeed);
        }
        else if (evt->X >= JoyXMinReverse && evt->X <= JoyXMaxReverse) {
            motorspeed = map(evt->X, JoyXMinReverse, JoyXMaxReverse, 0, 255);
            back_off(motorspeed);
        }
        else {
            Serial.println("Check the joystick X min and max values again.");
        }

Go Up