Finally, here's the link to the fresh upload:
https://drive.google.com/open?id=1ysOoYG8mwlvJy0023XwJUgclYXbO1ulSThere were several causes for the delay - some bugs needing squashing and some improvements to be made, but Rachi's chair needed attention and that had priority over working on programming.
I had planned to take a day to replace all of the caster stem and wheel bearings and re-work the stem mounting to ensure that the bearings stay tightly aligned, but the day before that Rachi's aid had a cup of dirty water and blended food for Rachi's PEG knocked out of her hand and straight onto the electronics. Needless to say, 300 ml of dirty water + all the accumulated salt from many days at the sea, didn't do the chair any good at all - it stopped working & there was some magic smoke. So pull it all, rinse thoroughly with deionized water, dry and inspect. The magic smoke was a burnt PA45 connector on one of the brake lines, cleaning and drying everything external let it start up and all seemed well except that there was no Roboteq motor output. Expecting the worst, opened the HDC2450 and turned out to be very lucky. There was some water inside and a nice green deposit on the header connecting the MCU and power boards. The rest of th board had no corrosion as I'd given them a urethane conformal coating. Dried it, cleaned the header and sprayed with deox/lube and it was back in business.
But, before getting back to programming, I did spend another day taking care of those bearings. Made a huge difference! The chair originally had truly awful shopping-cart type casters and I'd long ago replaced them with stem casters with top and bottom bearings, drilling out the cross bar to 14mm (not enough room for a spacer, but the most I could do) and adding a stainless outer tube to hold the bearings. (I later added thrust bearings because it was eating the no-spacer deep-groove bearings.) However, the ID of the stainless tube is ca. 4mm larger than the OD of the bearings and I'd held them centered by filling with quick-set epoxy and micro balloons, which after several years had really degraded on one side. So, this time I trued up the seating surfaces, chamfered the inner bore to make sure there would be no interference with the inner races, filled around them with high strength epoxy and cotton flox, used 12 mm bolts without casters to clamp them centered and cured at 60o overnight. Put the casters (with new wheel bearings) back on and re-mounted the rear canted swing-arm axle to the chair. Not even a hint of hesitation now in turn-in-place.
After that long blather (and lots of work), back to the programming. FIRST, the usual warning. The CANbus version has been tested on the bench and on the chair. The analog version has had only minimal testing, so do be cautious.
At startup, the script now automatically checks for whether there are external motor current sensors and that they are working properly (the STARTUP_SENSOR_CHECK subroutine). Then, the AUTO_CURRENTSENSORS subroutine checks that the polarity of external sensors (if there are any) is right and corrects that if necessary, and checks for whether there are internal motor current sensors and chooses to use either those or my "enhanced" estimated motor current if there are not. The default user setting is CurrentSensors = external as all is handled automatically, and the only time you might want to set this to CurrentSensors = internal is if you have working external sensors but don't want to use them.
During the sensor checking, the motors are commanded to 10 (1% of max output) for about 50 milliseconds (shorter if accel is set higher than on Rachi's). On Rachi's chair, the script also disconnects the brakes during this, so it certainly can't move, but at motor power = 10 it probably won't move even without brakes in 50 milliseconds. Took me a while to figure out how to do it, but the script avoids any brake clicking during all this. I also cleaned up how the script removes any drift or offset of sensor zero point. I'd been doing it by reading the sensors once every ca. 5 seconds when the chair is not moving, calculating offsets, and subtracting them every time sensor current was read. The CheckSensorZero: subroutine now uses the Roboteq SetConfig (_ACTR ...) command to re-configure the zero point to actual reading, so no subtracting offsets is needed elsewhere. Uncertainty of the zero point between calls to CheckSensorZero is (2/1000)*100 = 0.2 Amps, but usually actually zero or sometimes 1 (0.1 Motor amps).
Now some special notes particularly for Will and Vitolds.
Will, rather than trying to modify your analog program to match the CANbus script, which I'd screwed up more than once, this analog script parallels the CANbus one. It does not have any of the things, such as AccelPot, that you'd added, so if you want them you will have to do some programming.
Will & Vitolds (and others using brushless motors). I want to emphasize once again that Accel means different things in Roboteqese for brushed and brushless controllers. For brushed motor controllers it is change of PWM per second rather than actual change of RPM per second. The chair's actual physical acceleration is greatly dependent on inertia. Hence a heavy bloke in a heavy chair who likes sharp accel and decel will need much higher Accel and Decel values than a pipsqueek like my daughter.
For brushless controllers, accel is change of RPM per second (commutation frequency) and the only time you won't get that much physical acceleration is if the current limit of the controller has been reached. Hence, inertia has much less effect. An acceleration value that John likes on a brushed-motor controller could well be a rubber-burning experience with brushless. Please be cautious.
I have to go make us some lunch now, so I'll post this without re-reading it till later. If I see something needing an edit, I'll post a separate message with that.