4

I am working on a project of a robot arm. The joints are made of servo motor. The basic function can be describe as:

  • The robot arm (the servos) were moved manually by the Logitech joystick.
  • The user could press a certain button to remember a position. I made 6 buttons for 6 positions, in detail.
  • After the remembering, if an activating button was pressed, the robot arm would move repeatedly around those 6 positions until a stopping button was pressed.

The problem was the bold words.

In order to make the robot arm could move repeatedly with one pressing, I used a while loop.

However, when the program was in while loop, the joystick events stopped updating no matter how I pressed or pulled the joystick. Therefore, I couldn't program a stopping button.

I guessed that was because the joystick events were called outside the loop, but I don't know how to get it inside. My code was based on the example of the USB Host Shield library.

Here is the code. It contained 3 files. My robot also has some more function so I only quote the part that I had problem here.

.ino file:

#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
#include "le3dp_rptparser.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                                          Hub(&Usb);
HIDUniversal                                    Hid(&Usb);
JoystickEvents                                  JoyEvents;
JoystickReportParser                            Joy(&JoyEvents);

//int waist_back, shoulder_back, wrist_back, gripper_back;

void setup()
{
  Serial.begin( 115200 );
#if !defined(__MIPSEL__)
  while (!Serial);
#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();
}

.cpp file: This was where I worked. Please look at the JoystickEvents::OnGamePadChanged

#include "le3dp_rptparser.h"

//Many parameters for robot here

JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
    joyEvents(evt)
{}

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_GAMEPAD_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_GAMEPAD_LEN; i++) oldPad[i] = buf[i];
    }
}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt)
{
  Serial.print("X: ");
  Serial.print(evt->x);
  Serial.print(" Y: ");
  Serial.print(evt->y);
  Serial.print(" Hat Switch: ");
  Serial.print(evt->hat);
  Serial.print(" Twist: ");
  Serial.print(evt->twist);
  Serial.print(" Slider: ");
  Serial.print(evt->slider);
  Serial.print(" Buttons A: ");
  Serial.print(evt->buttons_a);
  Serial.print(" Buttons B: ");
  Serial.print(evt->buttons_b);
  Serial.println("");

  // Manual control program here. I didn't post because it was so long.


  //Activation

  if (evt->buttons_a == 32){
    while (evt->slider == 0){

    //Robot working here, also a long code that was out of limit for a block here.

    Serial.print(evt->slider);
    }
  }
}

.h file:

#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__

#include <usbhid.h>

struct GamePadEventData
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t hat : 4;
      uint32_t twist : 8;      
    };
  };
  uint8_t buttons_a;
  uint8_t slider;
  uint8_t buttons_b;
};

class JoystickEvents
{
public:
    virtual void OnGamePadChanged(const GamePadEventData *evt);
  static GamePadEventData mostRecentEvent;
};

#define RPT_GAMEPAD_LEN sizeof(GamePadEventData)/sizeof(uint8_t)

class JoystickReportParser : public HIDReportParser
{
    JoystickEvents      *joyEvents;

  uint8_t oldPad[RPT_GAMEPAD_LEN];

public:
    JoystickReportParser(JoystickEvents *evt);

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

#endif // __HIDJOYSTICKRPTPARSER_H__

After the //Activation under JoystickEvents::OnGamePadChanged, no matter how I pulled the slider of the joystick, the event was not updated, the evt->slider always returned zero and the robot arm couldn't be stopped.

Is there any method to update the joystick event inside the while loop?

Or another method other than while loop to make something move repeatedly after pressing one button, and can be stopped with another button?

Thank you so much for reading, and please help me!

2 Answers 2

1

As full code is not posted I cant suggest you correctly but you should add the two buttons, START & STOP.

When STOP button is pressed all events (your code is performing on) should stop working.

Just make sure when you program for a joystick control, the code for START & STOP buttons should fall under the joystick control loop.

if (STOP PRESSED){

}else if(START PRESSED){

    //INVOKE THE FUNCTIONS FOR ACTIONS TO BE PERFORMED
}
2
  • Thank you. I planed to post the full code at the beginning, but the site told me that I was out of limit so I had no choice but to post the part I needed.
    – John Keane
    Jul 20, 2017 at 13:09
  • @JohnKeane. In that case, reduce you sketch to the minimum size that still show the problem. That will make easy for the rest of us to work on your question.
    – user31481
    Oct 23, 2017 at 13:50
0

The trick is to never use a while loop to wait for something physical to happen. Instead write code that doesn't block execution of the rest of the code. Write your code so that instead of sitting in a while loop, the function relies on being called over and over from the loop function. Let the loop function do the looping.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.