`The Setup: our Arm Link Firmware supports 3 different arms. A one line
//#define PINCHER //#define REACTOR //#define WIDOWX
Just uncomment the line for your arm and you're good to go, the firmware takes care of all the work for picking the arm.
The Problem: If you try to compile the code you get a slew of unhelpful errors, starting with ...
In file included from InputControl.h:4, from InterbotixArmLinkSerial.ino:72: Kinematics.h: In function 'uint8_t doArmIK(boolean, int, int, int, int)': Kinematics.h:101: error: 'WristLength' was not declared in this scope Kinematics.h:102: error: 'BaseHeight' was not declared in this scope Kinematics.h:106: error: 'ShoulderLength' was not declared in this scope Kinematics.h:106: error: 'ElbowLength' was not declared in this scope Kinematics.h:143: error: 'BASE_N' was not declared in this scope Kinematics.h:143: error: 'BASE_MIN' was not declared in this scope Kinematics.h:143: error: 'BASE_MAX' was not declared in this scope
and going on for several dozen lines. Now if you've read the Setup guide then you should know that you have to uncomment a line for your arm. But what if you didn't? Or what if you forgot? How can we make this a better user experience?
A while back I did some searching for 'Custom Arduino Errors' and the like, but I never found much. But last month while looking at the Razor AHRS Firmware I found exactly what I needed
// Check if hardware version code is defined #ifndef HW__VERSION_CODE // Generate compile error #error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.ino! #endif
You see, the Razor AHRS Firmware supports a bunch of different hardware, so at the very top of the file you need to define which hardware you're using (sounds familiar, eh?). So the little block above throws an error and stops the user if the hardware wan't defined. And it's a totally custom message, so you can explicitly tell the user what the problem is. Since this code lets you throw custom errors based on pre-processor defines. So now the Arm Link code looks like
#define PINCHER 1 #define REACTOR 2 #define WIDOWX 3 //uncomment one of the following lines depending on which arm you want to use //#define ARMTYPE PINCHER //#define ARMTYPE REACTOR //#define ARMTYPE WIDOWX #if !defined(ARMTYPE) #error YOU HAVE TO SELECT THE ARM YOU ARE USING! Uncomment the correct line above for your arm #endif
Later in the code we can check the type of the arm (see GlobalArm.h)
#if ARMTYPE == PINCHER #define ARMID 1 #define CNT_SERVOS 5 //(sizeof(pgm_axdIDs)/sizeof(pgm_axdIDs)) //...etc #endif
It is worth noting that the firmware should probably be doing a check against the servos that it sees and not engaging unless it sees all the servos. Though this would cause a whole different issue - code running on the robot but no good way to tell the user that servo discovery has found a problem. But that's a quest for next time I guess.