Encoders not resetting to 0?

Is there a reason that shaft encoders would not reset when you say SensorValue[encoderXX] = 0? (in RobotC)

Our auton skills is running into an odd problem. We’ve got a pattern like this:

  1. drive w/encoder clicks - OK
  2. turn for xxMsec - OK
  3. reset encoders; drive w/encoder clicks - PROBLEM
  4. turn for xxMsec - OK
  5. reset encoders; drive w/encoder clicks - OK
  6. turn for xxMsec - OK
  7. reset encoders; drive w/encoder clicks - OK

We’re using a function to drive w/encoder clicks (therefore it is the same code for steps 1, 3, 5 & 7 with different parameters). The first step in that function is to reset the values to 0 using SensorValue[encoderXX] = 0;.

Clearly it’s working for most cases (steps 1, 5 & 7). What happens with step 3 is that you can hear a tiny pause in the motors after the end of step 2, so I know it’s considering doing step 3, but then skips over the driving and moves on to step 4 (the next turn). The only conclusion I can draw is that it thinks “hey, the encoder count is already over 600 clicks, so I’m going to move on to step 4”. (I can’t think of any other explanation of why it would pause briefly & then go on to step 4.)

In general, is there something special that needs to happen when resetting encoders that we’re not doing? Do we need a teeny wait statement after resetting the encoders? (Sorry, I’m not at a computer now with the precise code, but my question is more general about what needs to happen in order to properly reset encoders to 0 in RobotC.)

Thanks for the advice & knowledge.

As far as I’m aware, encoders don’t need any special rituals to reset. If your other steps are working, I would guess the issues lies somewhere else in your code, perhaps the parameters that you are putting into your driving function.

Just to gather more information, may I ask for your autonomous code to be pasted?
Sometimes, with me, the encoder doesn’t reset when the task isn’t ran instantly. I’d prefer something like a 100-200 msec statement and see if that works.

Have you tried adding a small delay - like 200 msecs - after resetting the encoder? Funny thing about the sensors is that they sometimes don’t operate as expected without a delay - and it is not really predicatable or consistent.

Hi all - thought I’d circle back to tell the end of the story here.

We had another task running during autonomous that was keeping a running average of left & right encoder values (avg = (leftEnc + rtEnc)/2). Our drive-for-clicks function was using that average ## in the while loop. This turned out to be the problem.

Things I tried (one at a time). None of these had any effect:

  • re-download firmware for joystick, cortex, master CPU

  • added a wait statement of varying lengths after resetting the sensor values

  • reduced the wait time in the average-calc task in increments all the way down to 1ms, with no difference (I thought it was possibly a mis-fire timing between the while loop & average calculation)

  • and finally, reverting to our original code, commenting out the average-calc task, and using just one wheel’s encoder value in the while loop to count clicks. That one worked. I’m good with having the real source of the problem still be a mystery. And my cats are glad that I’m done running a robot around the living room.

Thank you to everyone who offered suggestions, and for responding quickly. It is much appreciated.

Post the average Calc task.

How do you read the encoder value?
We have run in inconsistency when mixing getMotorEncoder/resetMotorEncoder with SensorValue[sensorPort], see my analysis at https://vexforum.com/t/sensorvalue-vs-getmotorencoder/44587/1

Either way, we run into the same issue when averaging and it turned out our right encoder was missing ticks (like half or them), apparently because of dust getting into the housing.
As usual, my suggestion is to configure the data logging (this time for the two encoders) and do a logging run. The graphs would easily reveal a mis-counting quad…

resetmotorencoder is a command for internal encoders

If you post your code it will help us all greatly.

[Newbie question: how do people copy & paste their RobotC code here and have it keep the color-coding? When I copy & paste & use the “code” button in the toolbar, it’s all just black. Thanks.]

Encoder-average task:

int encAve;
task encAvgTask(){
   while(true){
      encAve = (SensorValue[rtBack] + SensorValue[ltBack]) / 2;
      wait1Msec(20);
      // tried varying this wait time; no effect
   }
}

Drive function (turns on 4 motors):

void driveFunc(int rightPower, int leftPower){
   SetMotor (FR, rightPower);
   SetMotor (FL, leftPower);
   SetMotor (BR, rightPower);
   SetMotor (BL, leftPower);
}

Drive with encoders function:

void encDriving(int power, int encClicks){
   SensorValue[rtBack] = 0;
   SensorValue[ltBack] = 0;
   // tried adding waits of varying lengths here; no difference

   driveFunc(power, power);
   while(encAve < encClicks){
      wait1Msec(20);
   }
   driveFunc(0,0);
}

Autonomous task (with non-chassis movements removed); if you find small syntax errors here, it’s likely because I had to edit this a bit for presentation here. This does compile & work.

task autonomous() {
   startTask(encAvgTask);

   // drive: -60 power, 1550 clicks
   // works fine
   encDriving(-60, 1550);

   //Turn - uses time
   driveFunc(-80, 80);
   wait1Msec(1200);
   driveFunc(0, 0);
   wait1Msec(50);

   //drive: -127 power, 400 clicks
   // *** does not work using encAve; section is skipped over ****
   // *does* work using SensorValue[rtBack] instead of
   // encAve 
   encDriving(-127, 400); 

   //turn using time
   driveFunc(-80, 80);
   wait1Msec(750);
   driveFunc(0, 0);
   wait1Msec(50);

   //dirve: -127 power, 800 clicks
   //works fine
   encDriving(-127,800);

   //turn using time
   driveFunc(80, -80);
   wait1Msec(750);
   driveFunc(0, 0);
   wait1Msec(50);

   //drive: -127 power, 1000 clicks
   // works fine
   encDriving(-127, 1000);

   stopTask(encAvgTask);
}

Just like you did. It doesn’t color up in preview, but is fine afterwards as long as you use code tags.

Well, I suggest you first change your “task” into a function:


int encAvg() {
    return (SensorValue[rtBack] + SensorValue[ltBack]) / 2;
}

It might work as written but only in RobotC. In real programming languages with real multitasking, your auton task might never “see” the update of the variable.

But then, I suspect your other encoder doesn’t see all the ticks properly and suggest again to get the datalog :wink:

No, it works with anything that is associated with the motor in the Motor and Sensor setup. But still, see this.

So there will be a timing issue.
encoders are reset in encDriving function.
then encAve is tested, however, it almost certainly will not have been updated because it’s unlikely a task switch would have happened after the encoder reset code. So either force the encAvgTask to run by sleeping the current task for a few mS or, as nenik suggested, make encAvgTask a function and just call it in the while loop you have in encDriving, making sure you call it before testing encAve so perhaps reorganize as a do {} while(encAve < encClicks); loop.

@jpearman - the curiosity here is that the setup as written (using avgEnc) works for every instance of driving with encoders except the one marked (step #3 in my original post up top). And it’s always the one marked that it skips over/doesn’t reset; the rest all function as desired.

I thought that varying the wait times in the avg task and in the drive-with-encoders function would make at least some difference, but with all permutations of time changes, it’s still the 2nd drive-with-encoders instance that fails. I just would just have expected the other instances to at least sometimes get caught up in the mix too. Apparently not.

As I said, we’re new to RobotC this year. We figured that having the average calculation be a task running in parallel with the other activities would be a good thing, instead of calculating that average in the drive-with-encoders function (or, alternately, as its own function).

So the first time it will work as everything will start of at zero anyway.
Then you turn, no encoder used here.
Then it fails, that’s because encAve probably has the last value calculated and it’s above 400. but the encoder are still reset, if you had allowed a task switch it would have ben set back to 0 after a few mS.
next you turn, that works ok.
then another drive, I don’t know what encAve will be set to but you turned the other way so it may be negative on the first test, a few mS later it will have been set back to the correct value as you did reset the encoders.

The problem will only occur on the very first test of the while loop, as soon as you sleep for 20mS everything will work as expected. The test would fail only if encAve is positive and above the threshold.

I was facing this exact problem when trying to reset my encoders and no amount of timing would help. I even wrote a new very simple program (with no tasks or functions) everything was in “task main”. The program should go forward for 1800 encoder ticks and then go forward for 2000 more encoder ticks. The problem is even after resisting the encoders between the two commands they continue to hold on to their current values. This means instead of going forward for 2000 ticks the second time it only moves forward 200 encoder ticks (2000-1800). I have even added 1sec delays between resetting the encoders (as suggested) but to no avail.


task main()
{
  wait1Msec(50);  // 2 Second Delay

  //Clear Encoders
  delay(1000);
  SensorValue[rightEncoder] = 0;
  delay(1000);
  SensorValue[leftEncoder] = 0;
  delay(1000);

  while(SensorValue[leftEncoder] < 1800)  // While less than 5 rotations on the leftEncoder...
  {
    //...Move Forward
    motor[rightMotor] = 63;
    motor[leftMotor] = 63;
  }
  stopAllMotors();
  
  //Clear Encoders
  delay(1000);
  SensorValue[rightEncoder] = 0;
  delay(1000);
  SensorValue[leftEncoder] = 0;
  delay(1000);

  while(SensorValue[leftEncoder] < 2000)  
  {
    //...Move Forward
    motor[rightMotor] = 63;
    motor[leftMotor] = 63;
  }
  stopAllMotors();
}

The problem was I was using Vex Integrated Motor Encoders and the way to control those is not the same, I was using


SensorValue[what ever I named the I2C encoder]

. The method to interact with Vex Integrated Motor Encoders is this


nMotorEncoder[what ever motor they are internally connected to]

. This actually resets them but not the I2C sensor which I learned are treated differently. So under the “Sensors” tab of the debugging windows, it will seem as nothing has happened, however, if you check under the “MotorsWithPID” tab you will see they are being reset. Another way to check is to assign them to a variable and check the Variable under the “Global Variables” tab. Example:


test_right=nMotorEncoder[rightDrive]
test_left=nMotorEncoder[leftDrive]

Using this method for Vex Integrated Motor Encoders works and actually resets them. It should also be noted I think that my results are from Vex Virtual Worlds using; the Vex Turing Point Map, and the Fantastilaunch robot. I assume however that the simulation simulates the real world accurately for something like this anyway. (I do not know why my code is showing up like this (I selected it and then clicked the code button, as well as verified that it has the code tags in front and aroun it)