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!