I apologize if these questions are answered, but I promise I've looked on this site and others. Perhaps I'm just dumb....
First some context.... I am building an autonomous robot with the Rover 5, 2 motor/2 encoder version. The motors are driven and encoder pulses are captured by a DFRobot Romeo v2 board (Arduino Leonardo based). There are crash switches, a servo with an IR proximity detector also all driven at a low level by the Romeo. All the real intelligence is provided by an on board Raspberry Pi model B that sends commands to the Romeo. So far I've been able to get autonomous behavior where the robot successfully avoids moderately complex obstacles while trying to travel from an origin point to a target point. This has made me quite happy. That said, the area traversed by the robot is about 3 meters by 3 meters. I want to extend its "playground", and also have another behavior where it wanders around and maps the floor plan of my condo. These additional goals made me start getting deeper into the accuracy of the Rover 5. Now onto my questions.
The specifications for the Rover say, at least in one place, "1000 state changes for 3 wheel revolutions". What I've discovered in my testing is that I see 250 interrupts in the Romeo for about 3 wheel revolutions. This makes me think that "state changes" takes into account that there are 2 phases for each encoder and that going up is one change and going down is a second change. Since I generate an interrupt on rising edges for one phase, that makes me think I am getting exactly what the specs imply. Can anyone verify?
The next question regards accuracy or maybe precision of the mechanics and electronics. A couple of days of testing indicate that the same PWM applied to the motors results in approximately 1.3% greater distance on the right motor vs the left motor, at least at some level of PWM. I am not completely sure that figure is constant as the speed (PWM) changes. Has anyone else seen that?
Another question. There seems to be some "play" or "slop" in the wheels. What I mean is that I can turn a wheel by hand easily for maybe 0.5 cm, and then it appears that I begin turning the motor. Is this expected?
Last question. I have tested motion on a reasonably flat wood floor with decent friction (no plastic finish) and on an oriental rug that is also reasonably flat. While the robot travels a little to the left (a 1-4 cm) while commanded to go straight a distance of about 2.5 m, on the rug, it travels way to the left, maybe 15-20 cm. I cannot come up with an explanation that I fully believe. Can anyone offer a hypothesis?
Thanks to both bdk6 and
Thanks to both bdk6 and OddBot.
I am gratified to know that my hypothesis regarding 250 vs 1000 was right. It appears that I can double the number of pulses counted simply by changing the interrupt mode in the Arduino code from RISING to CHANGE.
To bdk6:
You have confirmed my hypothesis about the differences I see in travel distances based on what I’ve seen in some articles called “systematic errors” (see http://www-personal.umich.edu/~johannb/Papers/umbmark.pdf). I am hoping that paper will help me determine some way of dealing with such errors and the possibly more daunting “non-systematic” errors. For example, if the 1.3% difference I’ve found could be considered systematic, my thinking is the the wood surface vs rug surface will be a non-systematic error.
To OddBot:
I’ve actually read your tutorial at least 6 times since I acquired the Rover early this year. That said, I’ve not appreciated it as much as I should have.
I also really appreciate your sample code. I think I understand it for the most part (I have not used I2C, so I’m speculating a bit there). I do have a couple of questions. It seems to me that you get a command via I2C that contains a left and right speed. In loop() a speed is turned into a period between pulses; how did you derive the formula for that? You then compare the period desired to that period between pulses, and adjust the PWM signal to the motor accordingly by 1. It appears that if the period is longer than 25 microsec, you conclude the motor is stalling and bump the PWM signal by 2. I may not understand this correctly, but it seems to me that when the motor is just starting motion, it will almost certainly appear to be stalling, so the PWM will get bumped up quickly, potentially well above where it needs to be to achieve the desired period, tho, maybe 2 is really just enough of a “low pass filter”. I also wonder about what happens when the speed is set to zero; it looks like the actual PWM siganl is ramped down slowly; is that true? Does that provide better control than simply turning off the PWM (making it zero)?
Great hints
To OddBot,
Thanks for the feedback. I believe I understand now what you’ve done and why.
You have convinced me that I can get much better behavior if I implement some sort of dynamic speed control. Everything I’ve read suggests PID can be a bit tricky to tune, and while I may play with it, I’ll likely end up with something akin to what you’ve done.
Now, I am much more interested in as much precision in position than I am in speed. This applies to traveling straight, as well as 90 and 180 degree turns. I am hoping that I can apply your advice and code to account for systematic and non-systematic errors and make the robot do what I want with enough accuracy and precision to suit my goals.
P.S. I did test yesterday setting Arduino interrupts to CHANGE, and I now get 500 interrupts per 3 rotations. Cheers!