View unanswered posts | View active topics It is currently Tue Sep 30, 2014 6:18 pm






Reply to topic  [ 9 posts ] 
while loop monitoring motor encoders stops short 
Author Message
Rookie

Joined: Fri Mar 11, 2011 9:30 pm
Posts: 12
Post while loop monitoring motor encoders stops short
We are having sporadic problems doing a move based on encoder values.

Basically we zero the encoders, move while encoder values less than target (steering via gyro as we go), then immediately after exit from the while loop stop the motors.

It USUALLY moves the right distance. But some percentage of the time it stops short, significantly short, like it reached the threshold early. We are planning to do some debugging by displaying the encoder values at various points in this routine but wondered if anybody else had experienced a similar problem. We had the same thing happen sporadically when we were using labview.

We have tried waiting as much as 250ms after zeroing the encoder values per another thread.

_________________
Jamie Diamond
Cougar Robotics Team (Ring It Up!, Bowled Over!, Get Over It! #4251)
(Smart Moves #127, Climate Connections #437, Power Puzzle #1470)
coach@cougarrobot.com
http://www.cougarrobot.com
https://www.facebook.com/CougarRoboticsTeam


Tue Mar 29, 2011 1:18 pm
Profile
Rookie

Joined: Fri Mar 11, 2011 9:30 pm
Posts: 12
Post Re: while loop monitoring motor encoders stops short
Well, we sort of got to the bottom of this.

1. We added debug lines to our program and found that the program would very occasionally end up with a "bad" value returned from nMotorEncoder[motor...] for example we might get the following values returned from nMotorlEncoder[motor...] in our debugStream:

100
100
100
100
200
200
200
200
300
300
300
300
12750
12750
12750
12750
500
500
500
500
600
600
600
600

So if our code was set to stop after 600 motorEncoder ticks then it would stop at what was really 400. This was true whether we used our own logic in a while loop, i.e. while(nMotorEncoder[motor...] < 600) or whether we used the nMotorEncoderTarget=600 to stop our motors. Either way it would intermittently stop short.

We swapped out the motor controller and the problem persisted.

A limited amount of testing seems to indicate that the problem becomes more frequent as the program becomes more multi-threaded/as other threads require more of the processing power.

In the end we wrote our own code to only stop if we got two different (unique) threshold values in a row.

At this point our guess is that there is something in the motor controller firmware, or the rom on the brick, or in the lower level routines that is at the source of the problem.

_________________
Jamie Diamond
Cougar Robotics Team (Ring It Up!, Bowled Over!, Get Over It! #4251)
(Smart Moves #127, Climate Connections #437, Power Puzzle #1470)
coach@cougarrobot.com
http://www.cougarrobot.com
https://www.facebook.com/CougarRoboticsTeam


Mon Apr 04, 2011 6:22 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: while loop monitoring motor encoders stops short
Was your while loop a tight loop or do you have a wait statement in the loop? Since you mentioned multi-threaded, how many task does your code have?


Mon Apr 04, 2011 8:43 pm
Profile
Rookie

Joined: Fri Mar 11, 2011 9:30 pm
Posts: 12
Post Re: while loop monitoring motor encoders stops short
This is our autonomous program.

The Main calls all the mission subroutines and is a thread by itself. It launches 3 more tasks as outlined below.

The 2nd task monitors 5 sensors in a loop. It has a 50 millisecond wait in it so I would not call it "tight".
- gyroscope to constantly calculate heading and post it to a global variable for other threads to use.
- monitor IR Seeker and post a calculated dc and ac heading and post them both to global variables.
- monitor an ultrasonic sensor and post to global variable
- monitor an accelerometer and post apparent pitch and roll to global variables
- monitor an angle sensor to know angle of robot's manipulator arm and post to global variable.

A 3rd task displays the 5 sensor values to the screen on the brick. Its loop has a 200 millisecond wait in it.

A 4th task uses a DC motor to constantly control the angle of our manipulator arm based on a global variable. That is, it reads a global variable and moves the arm to that angle and then holds it there.

When the main thread says move a distance with our drive motors it tends to be a tight loop, no waits in it. If we are waiting for runStateIdle we have a while with only a comment in it. When we are steering to a gyro heading we adjust the two motor speeds continuously without waits until the distance threshold for the while loop is satisfied. So the actual moves are very tight loops.

_________________
Jamie Diamond
Cougar Robotics Team (Ring It Up!, Bowled Over!, Get Over It! #4251)
(Smart Moves #127, Climate Connections #437, Power Puzzle #1470)
coach@cougarrobot.com
http://www.cougarrobot.com
https://www.facebook.com/CougarRoboticsTeam


Mon Apr 04, 2011 11:26 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: while loop monitoring motor encoders stops short
Since you have multiple tasks, is there a chance this is a problem of global variables accessed by multiple tasks at the same time (i.e. contention). Did you protect your access to these shared variable through hogCPU and releaseCPU? Since I don't see your code, I can't tell if this is the problem. But something worth to check. Of course, there is always the possibility of a bug in the encoder support in the firmware, but I have no way to tell that either unless you can reproduce this in a simpler test program and then you can send it to the RobotC developers (support@robotc.net).

BTW, tight loop is not a good thing, you may want to add an EndTimeSlice() statement in the empty while loop. Tight loop will tie up the CPU and may starve some of the system tasks. This may affect the built-in encoder support. Also, runStateIdle is not reliable especially if you enabled built-in PID. There is a chance that you will be stuck in a while loop waiting for runStateIdle and never come out of it because PID control may generate an output too weak to allow the motor to complete the PID target. But of course that's not the problem you are investigating, just a note.


Mon Apr 04, 2011 11:49 pm
Profile
Rookie

Joined: Wed Feb 24, 2010 11:43 pm
Posts: 34
Post Re: while loop monitoring motor encoders stops short
We noted this issue last year when we had too many controllers on the same port... since you didn't list your #pragmas, I can't tell if it might be the same problem.

We believe that the problem was partly from the power draw on the i2c link, and partly due to a bug in the firmware. (see the thread at viewtopic.php?f=52&t=2220)


Tue Apr 05, 2011 8:05 pm
Profile
Rookie

Joined: Fri Mar 11, 2011 9:30 pm
Posts: 12
Post Re: while loop monitoring motor encoders stops short
MHTS wrote:
is there a chance this is a problem of global variables accessed by multiple tasks at the same time (i.e. contention)

I don't think this is it but I suppose it could be. We did not wrap all our writes and reads of the global variables being passed between threads with hogCPU() and releaseCPU(). However the nMotorEncoder[motor...] is not being written to or read from any of the global variables. It is pretty simple in-line stuff with local variables.

MHTS wrote:
BTW, tight loop is not a good thing, you may want to add an EndTimeSlice() statement in the empty while loop. Tight loop will tie up the CPU and may starve some of the system tasks. This may affect the built-in encoder support.

This strikes me as more plausible. I will modify our latest code to add waits and/or EndTimeSlice() statements. We have already implemented the logic that deals with single sets of bad values by waiting until it reads two threshold values in a row to end a routine. But we still have the debug lines in our code that let us monitor when we are getting bad reads from the nMotorEncode[motor...]. I would be very interested in learning more about when it is most appropriate to add waits and when it is more appropriate to use EndTimeSlice() to let the processor move on to another thread. This is our first experience with ROBOTC or even C. Previous coding has been in LabVIEW and NXT-G.

MHTS wrote:
Also, runStateIdle is not reliable especially if you enabled built-in PID. There is a chance that you will be stuck in a while loop waiting for runStateIdle and never come out of it because PID control may generate an output too weak to allow the motor to complete the PID target. But of course that's not the problem you are investigating, just a note.

We have had no problems at all with runStateIdle and are/were regularly using the built-in PID. The only problem we had with that logic was the early abort due to what I am confident was a situation of the built-in PID also receiving bad motor encoder values. We never had the PID stall short of target.

_________________
Jamie Diamond
Cougar Robotics Team (Ring It Up!, Bowled Over!, Get Over It! #4251)
(Smart Moves #127, Climate Connections #437, Power Puzzle #1470)
coach@cougarrobot.com
http://www.cougarrobot.com
https://www.facebook.com/CougarRoboticsTeam


Tue Apr 05, 2011 8:46 pm
Profile
Rookie

Joined: Fri Mar 11, 2011 9:30 pm
Posts: 12
Post Re: while loop monitoring motor encoders stops short
alanlevezu wrote:
We noted this issue last year when we had too many controllers on the same port... since you didn't list your #pragmas, I can't tell if it might be the same problem.

We believe that the problem was partly from the power draw on the i2c link, and partly due to a bug in the firmware. (see the thread at viewtopic.php?f=52&t=2220)

Here's our #pragmas:

#pragma config(Hubs, S1, HTMotor, HTMotor, HTServo, none)
#pragma config(Sensor, S2, HTSMUX, sensorI2CCustom)
#pragma config(Sensor, S3, HTSMUX2, sensorI2CCustom)
#pragma config(Motor, motorC, motorBatonSpinner, tmotorNormal, PIDControl, encoder)
#pragma config(Motor, mtr_S1_C1_1, motorLeft, tmotorNormal, PIDControl, reversed, encoder)
#pragma config(Motor, mtr_S1_C1_2, motorRight, tmotorNormal, PIDControl, encoder)
#pragma config(Motor, mtr_S1_C2_1, motorArm, tmotorNormal, PIDControl, encoder)
#pragma config(Motor, mtr_S1_C2_2, motorG, tmotorNormal, openLoop)
#pragma config(Servo, srvo_S1_C3_1, servoBatonHolder, tServoStandard)
#pragma config(Servo, srvo_S1_C3_2, servoSideGate, tServoStandard)
#pragma config(Servo, srvo_S1_C3_3, servoFrontGate, tServoStandard)
#pragma config(Servo, srvo_S1_C3_4, servoAimV, tServoStandard)

on HTSMUX we have:
- a HiTechnic Angle sensor
- a HiTechnic Accelerometer
- a HiTechnic IR Seeker 2
- a LEGO Ultrasonic sensor

On HTSMUX2 we have:
- a HiTechnic Gyro sensor

I looked through the thread you referenced. It sounds similar but I wouldn't have described our motor encoder values as jumping around all over the place. Given the update rate of the sensor, and how many times we are seeing the bad values I'm guessing that we're seeing the bad value, on average, on about 1 out of 2000 or so reads. Could be 1 out of 1000. Could be 1 out of 5000. By now needing two back-to-back bad readings in a row to go south we take our bad reads that can affect us up to somewhere between 1 out of 1,000,000 to 1 out of 25,000,000. Instead of tripping us up every other run now it will trip us up every couple of thousand runs.

_________________
Jamie Diamond
Cougar Robotics Team (Ring It Up!, Bowled Over!, Get Over It! #4251)
(Smart Moves #127, Climate Connections #437, Power Puzzle #1470)
coach@cougarrobot.com
http://www.cougarrobot.com
https://www.facebook.com/CougarRoboticsTeam


Tue Apr 05, 2011 9:05 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: while loop monitoring motor encoders stops short
JamieD wrote:
I would be very interested in learning more about when it is most appropriate to add waits and when it is more appropriate to use EndTimeSlice() to let the processor move on to another thread. This is our first experience with ROBOTC or even C. Previous coding has been in LabVIEW and NXT-G.

EndTimeSlice() allows you to release the timeslice of your task so another task can run. On the next timeslice, you will be run again. However, any wait statements such as wait1Msec() will put your task to sleep for the specified amount of time. So if you want to monitor something in a relatively tight loop but want to yield to other tasks since your task is not ready yet, you can call EndTimeSlice() to give up just one timeslice. If your task will not be ready for a while and you don't care if you need to act fast once it's ready, then you can call wait1Msec().


Tue Apr 05, 2011 9:16 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 9 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.