Sunday, February 7, 2010

Coding a HWIL module

It has become a requirement to be able to detect issues with missions by rerunning the logs while the robot is on the bench. This turns out to be bigger than I thought it would be. What I really had to do, was rewrite my logger so that it did a better job simplifying the xml that was being produced.

interface kit 0 not attached
interface kit 1 not attached
< Message time="0" Received="10" Body="" />
< Message time="0" Received="10" Body="" />
< StateMessage:IMessage,ISerializable time="12" Received="12" >< taskManagerState RxQueueLength="0" QueuableCommandsMissed="0" QueuableCommandsMissedTotal="0" time="12" OverrideWaterMark="0" MessagesReceived="12" MessagesSent="12" MessagesNull="0" histo0="0" histo1="3" histo2="0" histo3="0" histo4="0" histo5="0" histo6="1" histo7="0" histo8="1" histo9="7" histo10="1" /> < /StateMessage:IMessage,ISerializable>

What I needed to do was to check the logged item first before it was logged and check to see if it was an entry itself. This was just to keep the number of recursive loops to a minimum. The default XML reader is easy to use if the entry just has values. It is also just easier if nested records were not necessary to wrestle with.

It has become a requirement to be able to detect issues with missions by rerunning the logs while the robot is on the bench. This turns out to be bigger than I thought it would be. What I really had to do, was rewrite my logger so that it did a better job simplifying the xml that was being produced.

interface kit 0 not attached
interface kit 1 not attached
< Message time="0" Received="10" Body="" />
< Message time="0" Received="10" Body="" />
< StateMessage:IMessage,ISerializable time="12" Received="12" >< taskManagerState RxQueueLength="0" QueuableCommandsMissed="0" QueuableCommandsMissedTotal="0" time="12" OverrideWaterMark="0" MessagesReceived="12" MessagesSent="12" MessagesNull="0" histo0="0" histo1="3" histo2="0" histo3="0" histo4="0" histo5="0" histo6="1" histo7="0" histo8="1" histo9="7" histo10="1" /> < /StateMessage:IMessage,ISerializable>

Ok, now that a reasonable data format is available, let's make a factory that can take the XML data and create messages s that they are in the same form as those created by the system. I built a simple Command pattern system that is configured in my normal configuration files. So if it is a normal mission, it will play normally. If the configuration is to rerun an existing log file, it has the path to the log file to read and whether the mission should begin immediately or with some wait period between completing reading the log and beginning the mission.

Most of the time, I find that it is reasonable to ask for a key input before starting the execution of the HWIL test. Nothing like a 30# car scooting across the table when you are not ready. Make sure that the robot is strapped down, sometimes it is more kinetic than was planned.

Now that we have the robot strapped down to a raised dais, we can hit enter and let it run the run. I made this a simple list of Commands following the pattern and a timer. The invoker checks at each timer tick and executes all of the commands that were logged at that time during the normal run.

I had to make simple ICommands that had a hook member and an execute. The invoker is hooked to the timer and I hooked the commands to the TaskManager. That way the Execute() method, just created a proper IMessage and delivered it directly to the TaskManager. It also makes it so that you can rewind the commands. This method has allowed me to find some linkage issues that would have been hard to find other ways. There are some hysteresis issues with any mechanical system, I was not prepared for the number that were found.

"...But knowing is half of the battle..."

Monday, February 1, 2010

The PhidgetsException #9

For the most part, I really like Phidgets. They are good simple equipment that is inexpensive and just works. That is a trick in my experience in the current robotics technology playing field. Their API is the best I have seen and I have to say does a nice job even if you want to write in c# or flash. Yeah, Flash is supported.

So I was happily banging away at my control code to manage these servos. I kept seeing that the code was running. I sent lots and lots of new servo locations to the servos and it just did not move the servos. After some investigation into my logs and trapping lots of PhidgetExceptions. I figured out what the issue was. Like a good little OOP'er I had contained my reading of the Advanced Servo Controller 8 port's properties in an object and then a different handles the executions. Here in lay the problem, the properties of a given servo such as velocity which has no setter (mistake in the documentation) are not exposed until the motor is in engaged.

So I wrote the following code to fix that. These are not threadsafe, you have to make sure that you are not engaged at the wrong time. It will make all kinds of wacky stuff happen.

Viewing code:

public double GetServoPosition(int servoIndex)
{
double position=-1;
try
{
AdvancedServoServo ass=null;
if(advServo.Attached==true)
{
ass=advServo.Servos[servoIndex];
ass.Engaged=true;
position=ass.Position;
ass.Engaged=false;
}
}catch(Exception exc)
{
throw new Exception(className+" public double GetServoPosition( "+ servoIndex+" ) :: "+exc.Message);
}
return position;
}

Motion code:

///
/// move a servo to a new position
///

/// index of the servo to move /// new position, should be 0-100 /// bool if the servo is now in the correct position
public bool MoveServo(int ServoIndex, int newpos)
{
bool movedOk = false;
try
{
AdvancedServoServo curr = null;

double pos = 0.01 * newpos * (basicServoMax - basicServoMin) + basicServoMin;

if (pos > basicServoMax){pos = basicServoMax - 1;}
if (pos < basicServoMin){pos = basicServoMin + 1;} if (aServo0.Attached && ServoIndex<4) { curr = aServo0.servos[ServoIndex]; } if (aServo1.Attached && ServoIndex > 3)
{
curr = aServo0.servos[ServoIndex];
}

if (curr != null)
{
curr.Engaged = true;
if (Math.Abs((curr.Position - pos) / curr.Position) > 0.03)
{

curr.Position = pos;

//disengage the servo when we are not moving it
curr.Engaged = false;
}
}
}
catch (Exception exc)
{
if (LogEvent != null)
{
LogEvent(className + " public bool MoveServo( " + ServoIndex + " , " + newpos + ") :: " +
exc.Message + "\n", false);
}
else
{
throw new Exception(className + " public bool MoveServo( " + ServoIndex + " , " + newpos +
") :: " +
exc.Message + "\n");
}
}
return movedOk;
} //MoveServo
Servo reset code:

///
/// try to reset the servo, when it throws phidgets exceptions, set it to a safe midpoint
///

/// servo to reset void resetServo(AdvancedServoServo srvo)
{
try
{
srvo.Engaged = true;
double midpoint = (basicServoMax - basicServoMin) / 2 + basicServoMin;
srvo.Acceleration = 1000;
srvo.Position =midpoint;
srvo.Engaged = false;

}catch(Exception exc)
{
LogEvent(className + " void resetServo(AdvancedServoServo) :: "+exc.Message, false);
}
}

Another thing, that you have to make sure that you consider is that there are hard to document dead zones in each servo. They are sometimes inherent to the servo design, but each servo can have multiple in different places. I would make sure that if you hear this tell-tale clicking sound when the motor tries to move to the right place and then corrects ad nauseum... that you trap this in your code. My experience is that this burns up your motor pretty quickly. These are toy or better than toy motors. Better motors are available but are more expensive.

Friday, January 1, 2010

Electric Conversion of a King Motors (HPI Baja 5B)

Another interesting project for us is the electric conversion of a King Motors KSRC-002. Ours was bought from Heat Hobby of Miami, FL. Out of the box, the only thing that needed to be assembled was the spoiler. Thankfully, we won't be using it. Inspecting the role cage and the transmission shaft we found some rust. This is not really a nice thing to find on your brand new model. Oh well, it will probably get replaced. Since this is an electric conversion, the first thing that I did was hop onto every HPI forum and King Motors discussion that I could find.

Several guys are using huge current setups, 200A or more. That may be necessary, we will see. I do not think they were using as many cells in serial as we intend to. Our plan is to run 9s2p or 9s3p, we also only want to be able to dash. the conversion we are running will be about getting it set up, and then moving toward the longest running build possible. Out of the box, we can see a bunch of things that do not make sense in a racing vehicle. Ok, probably not a race ready device out of the factory.

Why would you use 0.125" (3mm) steel as your chassis? Cars do not use 3mm of steel in many structural places. It can hold up with a person standing on it. One of our first projects will be to replace the chassis with an Aluminum one. This should take out about 2lbs (1kg) without any stress. Another interesting choice, which is clearly about cost is the roll cage mounts that are plastic. It is my opinion that the plastic knuckles are where the cage breaks not the quarter-inch (6mm) steel tubing. Which was also poorly finished and rusted in one of the welded joints. If King Motors reads this, please do some inspection of the parts before they leave the factory.

The fuel tank was pulled out along with the engine. a few bolts and it removed cleanly. Next time, why bother buying a full setup, go roller chassis. Forum after forum said the FM radio that they ship with it sucks. I have to say that we did have some interference on our little test stand. I could see where this would be an issue. So I yanked it out and replaced it with a composite capable 6ch Spektrum unit which we use in our planes. It is a great 2.4GHz DSM-2 radio. There are two-channel versions if you prefer.

The throttle servo and steering servos are crap, but useable. One part that is a bit challenging was the clutch. Not the clutch bell, but the clutch on the drive flywheel. Several places lauded designs that keep it in, noting that the clutch helps reduce the biting nature of the electric motors' torque curve. Anything to keep the wheels hooked up is better. Just make sure that you put the pin in first, othwerise you cannot get it through the hole with the shoe. You will need a piece of wire to go through the eye on the pin and above the retaining plate to keep the pin from falling through the hole. It is not hard to fix, but it is annoying.

The steering servo was replaced with a nice metal-bearing quarter scale unit. Our HB unit is faster, digital and stronger than the factory version. There is no reason not to use digital anymore, I hear that there were some issues in the beginning.

The catch with this that we found. The drive pinion that you need is a 1.5 mod. Yes, 1.5mod, the stock that came with our bell housing is a 17t. I contacted my normal strange parts connection at Impakt/Tekno RC. They are always awesome. They said that they did not have the parts in the scale, and directed me over to Monster RC. This is a reason, that I always go to them first. Customer service is not only helping them on your site, but helping them get what they need. Following their suggestion, I went over to RC Monster. They had the a selection of 1.5 mod gears. I emailed Mike at RC Monster, he responded quickly and said which parts that I needed. Again, great customer service, you can get 1.5 mod gears in a bunch of sizes from 12t-22t. They are cut for 8mm shafts, so pick up the reducers as well. RC Monster shipped my order the same day.

Adventures in Composites

The big thing that we learned in this episode is how to manage holes or penetrations. We made a male mold and were trying to decide how to mark and spot where we wanted to make penetrations called for in the fuselage.Marking the fabric was not particularly accurate, but it did work. The real answer that we saw was to make a potrusion where the penetration was.

It is easier to cut off a piece that sticks out past the piece that you want than it is to dig out material where you do not want it. Our design has four or so penetrations into the fuselage. Additional wedges of blue insulation were hacked to fit into the holes. They were not made to perfectly match, but were close. So you could easily see what you wanted to keep and cut.

Another interesting thing that we learned was the relative softness of home-owner classes of epoxy. Be aware of this. Y, is that any feature that looks liou can make a mess of your piece if you heat it too much to melt the wax. You have to pull the piece free form the molds and set them back down once the part is free. Putting it back down to the mold really helped the part retain its shape. As we pulled our parts off, we were concerned that they would not be square when we put the parts back together.

Due to some communications issues, there were some delaminations in areas that would have been better had they not occured. These anomalies were healed by forcing a needle into the void and using a syringe to fill it with epoxy. Epoxy is viscous, be aware that it is tough to dispense through a narrow needle. Voids were filled until it appeared to be full visually, pockets were no longer hollow appearing.

Molds seem to be effected strongly by Murphy's Law. Everything that could have gone wrong with our parts did. Our shape has several bays. Bays are hollows where square sides would be best. The bay that we took the time to box in with plywood came out well. The bays that had no boxing in had delaminations and other issues such as corner delaminations, non-square lay ups and twists where pieces hung on something and were not carefully managed back into place. In a bay, is the only area that we had any mold damage. It was due to pieces of cloth almost wrapping a narrow piece of mold. Had it been boxed in, the pieces would not have been able to wrap the way they did and pin the mold into place. This damage was minimal and was fixed with filling the cracks with glue and for the most part was a non-issue.

Monday, December 14, 2009

UGV work

Another kind of cool development is that we were asked to see if we could make a unmanned ground vehicle,UGV, with the same brains as we use in the UAVs. That combined with our ripe fruit turret idea gave me a bunch of new ideas about how to separate the hardware from the software stacks. The turret will use some interesting ideas on color detection and correction to detect whether fruit is ripe enough to be picked.

Now there is a UGV in the mix. What better a system to tow the turret around, than a 1/5th scale 4WD buggy. It is also leading us onto a bunch of other applications with the same device. Our new ideas, we hope are very investment worthy. If President O actually does something for small business, then we may be able to attract some investment. I think that there are several interesting campus or property management applications that will make the software easy enough to develop and/or repurpose.

Hopefully, I will get some more pictures of our electric conversion of the buggy and some assembly stuff. So that everyone can get an idea of how to do the electric conversion and the other steps that we took setting things up. We have some math that we have already worked out to hopefully help reduce some of the initial setup mistakes. Many scientific papers all say that small alignment errors in setup can ruin the mathematical assumptions that are made in software. That is why we keep trying to set up our software and then back out the math. Not always a working approach, but it is better than thinking everything is perfect.

Neah, engineers are never perfect... we are within 20%, 80% of the time.