![]() |
Bizarre Driving Issue
So we're using four wheels, four motors.
We set them up to run through some deadzone code, then perform some calculations, and assign the power to the PWMs in pairs. The idea is to have the simpliest of holonomic drive code possible. Here's the jist of it: Code:
The other problem we're having is that when we try and go foward the left two wheels (pwm01,pwm02) get up to about 20 or 30 before the right wheels begin responding. When we go backwards the right two wheels (pwm3,pwm4) get up to 20 or 30 before the left two wheels respond. When pressing left the back two wheels (pwm2, pwm4) get up to speed first. When pressing right the front two wheels act similarly. We know that we could fix this by using four geartooth sensors, but the code behind that would be monstrous and confusing, and require four sensors! Any help would be appreciated. |
Re: Bizarre Driving Issue
p2_x and p2_y are unsigned integers. When your subtract from them to end up with a negative value, the computer will start to have problems. Store them in signed integers before you try to subtract 122.
basically change this: Code:
if(p2_x<122) //more than 5 below 127Code:
if(p2_x<122) //more than 5 below 127 |
Re: Bizarre Driving Issue
Can that be fixed through recalibration? Or have you found another method? But this is probably it! Thanks!
And the part where you said that they're usigned integers wouldn't make sense mainly because the negative works for the p2_x but not for p2_y and that doesn't explain why p2_x doesn't work when positive. We'll try both typecasting and storing it in a smaller variable, but I don't think that's the solution for why the deadzone code isn't working. |
Re: Bizarre Driving Issue
Quote:
You are not actually changing the values of p2_y and p2_x, are you? If you are just using the for calculations, it shouldn't matter what type they are. Sorry if I'm wrong, I can't test it right now. Otherwise I would just cast p2_y as an int instead of declaring a separate variable. |
Re: Bizarre Driving Issue
Recalibration didn't help. We made a graph of PWM output vs wheel speed and then made a lookup table of the PWM values required to achieve the desired wheel speeds. I'll post more details about it when I have time tomorrow if you want.
When we were initially messing around with holonomic driving, my team did run into a few problems with subtracting from unsigned variables, so it's definitely worth a try. Have you tried following the values of your variables with the MPLab debugger? That can be an easier way to test different situations without using the robot. |
Re: Bizarre Driving Issue
Also, here's a general thing that will cut down code, therefore space used, will "upload" faster and run faster :D
Turn this: Code:
if(p2_x<122) //more than 5 below 127Code:
if(p2_x>=122 && p2_x<=132) //within deadzone |
Re: Bizarre Driving Issue
tdlrali: It would be nice if things worked that way, but the point of the code is to find the difference between the input and the end of the deadzone then scaling it to cover 127 values. Finding that difference requires a separate case for above and below, with below subtracting 122 rather than 132. With the code you suggest, holding the controller at full reverse would result in deadx equaling -10.
Kelly: Considering our build team, I'm sort of doubtful we'd ever find enough time with the robot to make an accurate lookup table, but all suggestions are definitely appreciated. Also, no, we have not tried the debugger. I, at least, was not even aware of its existence, though kitscuzz is generally much better informed than I am. |
Re: Bizarre Driving Issue
you are overflowing, i can guarantee it. The type of the variable is an unsigned char, and none of the numbers are larger than that range within the calculation. Therefore, your values overflow when you multiply by that huge number.
Typecast "p2_x" and whatnot into signed ints, and this should rectify that issue. (note that you could also use encoders which are much more accurate and friendly) |
Re: Bizarre Driving Issue
It still seems strange that an overflow would create such specific fail points and be different for p2_x and p2_y, but it's not like typecasting is very difficult. We'll give it a shot, whether it's an issue for your reason, Kelly's, or something none of us has thought of.
|
Re: Bizarre Driving Issue
well it will create fail points because that is where your numbers will overflow. believe me, i have seen it all too many times.
|
Re: Bizarre Driving Issue
I don't doubt you, but doesn't overflow involve the numbers becoming too large? Given the code, the largest numbers should occur at full forward and full reverse, but the failure occurs for all inputs below 122 and none above with p2_y and for all inputs above 132 and none below with p2_x. I mean, the largest number that occurs at any point is 15494 (from p2_y=254) and that works just fine. Of course, I sort of get the feeling I'm displaying some horrible ignorance here. Too bad it's sort of difficult to get into the school and test these things out at 12:44 AM.
|
Re: Bizarre Driving Issue
p2_x and deadx are (unsigned char), a single byte, and can only hold the values 0 to 255.
unsigned char p2_x; unsigned char deadx; We all use them to hold PWM values where 127 is neutral, 255 full forward, 0 full reverse. For an example set p2_x to be 50, a value less than the 122 that you are having problems with. The code looks like: deadx = ((p2_x - 122) * 127)/122 + 127; Now subtract the 122: p2_x = p2_x - 122; /* or p2_x -= 122; or (p2_x-122) */ What's the value of p2_x, it's not -72 like we wanted it's instead now 184. The math overflowed the range of values, the result became 256-72 instead. Think of it as wrapping around, instead of going from 2, 1, 0, -1, it goes 2, 1, 0, 255, 254, 253 ... That's the first problem, now imagine we do the multiplication, it's going to wrap around many times and come to rest somewhere unexpected, (n*127 mod 256). Then division will only return 0, 1, 2 and that's all folks. So how do you fix it? Take care of the typecasting to a (signed int) that is 2 bytes wide and can be both positive and negative, once you have finished the scaling calculation, cast the result back to an (unsigned char) deadx = (unsigned char) (( ((int)p2_x - 122) * 127 )/122 + 127 ); C always does math using the widest type (most number of bytes) of the two values. Aside: The last cast to (unsigned char) is actually unnecessary as we are assigning it to an unsigned char variable and C will do the typecast for us. However by including the typecast we are making clear our intent and it'll help remind us what is going on. Short answer: the problem with negative values occurs because all numbers must have a positive result with (unsigned char) or it overflows. The problem with some +ve numbers happens because the result of the *127 won't fit in a single byte. Casting to (int) will fix those problems. However, the other comments about how to handle a deadzone are correct too., there may still be other problems. Note: The code that reverses the motors (127-pwm) could be simplifed if you just reverse the motor connection to the victors, of one of the motor pairs. It'll also help getting matched speeds as the speeds 127+n and 127-n are not necessarily the same. Don't forget that the victors also have a deadband around 127 too. Happy coding :cool: |
Re: Bizarre Driving Issue
1 Attachment(s)
I'm pretty sure your current problems are caused by overflowing unsigned variables, however, if you're like us, the next problem you'll have is with your robot listing to one side or another as it drives. We fixed it by collecting data about the pwms and making a lookup table that relates desired wheel speeds and actual pwms.
We collected this data by hooking the robot to the computer and cycling through all the possible pwms. The units on wheel speeds are not actually RPMs, but encoder counts per 115 program loops, because there was no need to convert units. Note the fact that the maximum speeds in each direction are not the same and also the fact that the dead zone is centered about 132. This was causing our robot to drift, because wheels that were supposed to be going in the same speeds with opposite directions weren't. Also, notice that the slope gets really steep in the middle and flatten out at the end. We wanted our robot to accelerate linearly. To fix this, we made a list of what the motor speeds would be if they were increasing linearly from 0 - the maximum and put it in a new column lining up with the old columns. We made our lookup table by looking at our list of "desired speeds" and finding a pwm setting that would create that speed. Unfortunately, that work is on the computer at school, but I'll post it soon. I'm actually considering putting together a whitepaper on the topic of holonomic driving, assuming ours works out. |
Re: Bizarre Driving Issue
AndrewN:
We'll definitely try this, but I repeat that it's strange because in the example you've provided we actually get the correct values. when ps_x is less than 122, the code behaves as we originally expected. Where it doesn't behave properly is when p2_x exceeds 132, a case where there shouldn't even be a plausible overflow. When it does exceed 132, the deadzone code returns 127. I guess that does seem to fit into the idea that it would only return 0, 1, or 2 after the division. But I guess I'm just looking for a reason why they would both work in completely opposite positions. But then again, all things considered, you're all probably smarter than me anyway and this definitely fits the problem, because checking back in the notes, we got 128 occasionally. Thanks. |
Re: Bizarre Driving Issue
Check and make sure your drives are going the right way, i dont think its your program, i hate to admit it but we could only go forward and backwards for about 6 hours because we didnt have the PWM;s in the right spots, and then we couldnt go right because the trim on our controller was wrong. So before you think its the program ( its usually that ) but u should check your robot and the controls aswell. Just my two cents.
|
Re: Bizarre Driving Issue
1 Attachment(s)
Really the math almost succeeds by accident ... try out the following code:
Attachment 5029 Code:
#include <stdio.h>I left the rest alone just so you could see how it almost works... I'm very suprised and delighted at how close it comes to being correct :yikes: But you still have a further overflow problem with the lines like: Code:
pair1 = deady+127-deadx; |
Re: Bizarre Driving Issue
Quote:
|
Re: Bizarre Driving Issue
Actually, I'm hoping that we can avoid the use of a gyro (and the overhead from running four PID loops), but could someone please explain what exactly a PID loop is? We're all essentially self-taught here, with no mentor, so we're lost on some of the finer points.
Perhaps as a simple example, just one motor, one joystick, and one encoder? We know how to set up and run all the separate parts, and we know essentially what a PID loop should do (compare input to output), but how exactly it does it do the calculation? |
Re: Bizarre Driving Issue
A PID loop controls by looking at error.
The proportional portion says: "Where should I be" - "Where I am". Then it multiples that by a gain factor. So - in pseudocode Gyro_Proportional_Amount = (Current_Gyro_Heading - Gyro_Heading_We_Want) * Gain Modify the drive values going to the motors with the Gyro_Proportional_Amount. The I and D are basically the same, but one works on the accumulated error (the I or integrative) and one works on the error rate of change (D or derivative). There is a bit of sample code in the PID whitepaper you can search for here - it does a great job of explaining. MOST times, you can get away with just the "P" portion of the code I showed above. |
Re: Bizarre Driving Issue
Quote:
|
Re: Bizarre Driving Issue
Oh, and we just uploaded the code. Sure enough:
Overflow. It works fine now. We flipped around the motors that were reversed so now the deadzones for going forward and backward are matched, but going left and right still suffers from the weird "two get going faster before the others." They seem even enough after they make it past a certain point, but it's still upleasant. kaszeta: Although PID loops may not contain much overhead, that would still need four geartooth sensors, which WOULD generate a lot of overhead. Though, I guess technically we... might be able to put only two on and just force all the pairs to match. It's still unfortunate to need any gearteeth, just because it's difficult to mount them as close as they need to be on the robot, and when we crash, they tend to crash into the gears (well... okay that only happened once on a testbed, but still stinks to buy new parts). |
Re: Bizarre Driving Issue
Quote:
|
Re: Bizarre Driving Issue
We didn't recieve our gyro panel in the mail, and realized too late :- (
But anyway: Whoa! I think I may have figured out something awesome. Everyone has been talking about these "asymmetrical" deadzones, but no one has ever found a good solution outside of lookup tables (at least not in this thread). But weirdly enough has anyone ever tried recalibration of the Victors? We set up this simple code like so: Code:
void Process_Data_From_Master_uP(void) |
Re: Bizarre Driving Issue
We had a problem with uneven deadzones on the four wheels in our holonomic drive; calibrating the Victors completely solved this problem. I highly recommend calibration.
|
| All times are GMT -5. The time now is 00:23. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi