Inertial Sensor Suddenly Stopped Working

For our previous tournament, we had a very accurate and precise turn function using the inertial sensor. However, the function no longer works and we have not changed anything. The issue is that the inertial sensor outputs a value of 0 for “iSensor.getRotation(rotationUnits::deg)”

We have tried multiple things to fix this:

  1. Change the inertial sensor ports
  2. Update to the latest firmware
  3. Change wires
  4. Connect laptop directly to brain

No matter what the inertial sensor outputs a value of 0 for heading, rotation, pitch, yaw, etc. even when we move it manually. When we check the value of heading on the brain however, its correct. Why is the inertial sensor not outputting any value? This is causing the motors to be rotating forever as they never approach the target angle. @jpearman

Here is a picture of our code:

/*
Setup robot facing towards protected zone and back wheels behind white tape
*/
void onecube() {
  while(1) {
    cout << iSensor.rotation() << endl;
    cout << iSensor.yaw() << endl;
    cout << iSensor.pitch() << endl;
    cout << endl;
  }
  // rotateright(45);
  // while(1) {
  //   cout << iSensor.rotation(rotationUnits::deg) << endl;
  // }
}
void rotateright(double angleTurn) {
  /*
  Get initial values and begin rotation
  */
  iSensor.resetRotation();
  rightdt.spin(directionType::fwd, -60, velocityUnits::pct);
  leftdt.spin(directionType::fwd, 60, velocityUnits::pct);

  /*
  This ratio will be used to gradually slow down the robot as it approaches the target angle
  */
  double ratio = iSensor.rotation(rotationUnits::deg) / -(angleTurn);

  /*
  Loops the turn as long as the angle is not met
  Record the ratio adjust speed based on ratio
  */
  while(iSensor.rotation(rotationUnits::deg) < angleTurn) {
    cout << "right: " << -60 + ratio*50 << endl;
    cout << "left: " << 60 - ratio*50 << endl;

    rightdt.spin(directionType::fwd, -60 + ratio*50, velocityUnits::pct);
    leftdt.spin(directionType::fwd, 60 - ratio*50, velocityUnits::pct);
    ratio = iSensor.rotation(rotationUnits::deg) / angleTurn;
    
    cout << "ratio: " << iSensor.rotation(rotationUnits::deg) / angleTurn << endl;
  }

  /*
  Completely stops motors and holds them at angle
  */
  rightdt.stop(hold);
  leftdt.stop(hold);

  vex::task::sleep(100);
}

The ratio variable stays at 0 since the sensor.rotation() stays at 0 and this causes the motors to spin at 60% forever.

All of the code in-case you want to look over it
GreenBayWisconsin.zip (113.4 KB)

https://www.vexforum.com/t/help-us-help-you/74215?u=roboknight

Emphasis mine.

fixed

20 character limit

1 Like

It helps people help you, by letting them copy and paste your code without having to retype it all.

Does it work when you select the dashboard ?

Well, you needed this for the Inertial sensor to work at all, 1.0.9 was the first version we supported it correctly.

2 Likes

Yeah we’re on the latest version of firmware and the heading shows up correctly on the dashboard but not when I print in code

you do need to have a delay in this loop (which I added below), it’s going to overrun all the io buffers otherwise.

/*
Setup robot facing towards protected zone and back wheels behind white tape
*/
void onecube() {
  while(1) {
    cout << iSensor.rotation() << endl;
    cout << iSensor.yaw() << endl;
    cout << iSensor.pitch() << endl;
    cout << endl;
    this_thread::sleep_for(50);
  }
  // rotateright(45);
  // while(1) {
  //   cout << iSensor.rotation(rotationUnits::deg) << endl;
  // }
}
2 Likes

That was just for testing. The rotateright function still fails to run and I don’t know why that’s happening now

same issue, you need to slow down the while loop, you cannot send data to std::cout that fast. Add a 20-50mS delay and you should be able to debug correctly.

2 Likes

Just tested with adding a 100ms delay in the while loop of rotateRight. Same result, cout prints 60 & -60 for the motor speeds and 0 for the ratio. Motors spin forever since ratio doesn’t ever increase due to iSensor.rotation(rotationUnits::deg) not changing.

/*
Rotates robot right using Inertial Sensor
*/
void rotateright(double angleTurn) {
  /*
  Get initial values and begin rotation
  */
  iSensor.resetRotation();
  rightdt.spin(directionType::fwd, -60, velocityUnits::pct);
  leftdt.spin(directionType::fwd, 60, velocityUnits::pct);

  /*
  This ratio will be used to gradually slow down the robot as it approaches the target angle
  */
  double ratio = iSensor.rotation(rotationUnits::deg) / -(angleTurn);

  /*
  Loops the turn as long as the angle is not met
  Record the ratio adjust speed based on ratio
  */
  while(iSensor.rotation(rotationUnits::deg) < angleTurn) {
    cout << "right: " << -60 + ratio*50 << endl;
    cout << "left: " << 60 - ratio*50 << endl;

    rightdt.spin(directionType::fwd, -60 + ratio*50, velocityUnits::pct);
    leftdt.spin(directionType::fwd, 60 - ratio*50, velocityUnits::pct);
    ratio = iSensor.rotation(rotationUnits::deg) / angleTurn;
    
    cout << "ratio: " << iSensor.rotation(rotationUnits::deg) / angleTurn << endl;
    vex::task::sleep(100);
  }

  /*
  Completely stops motors and holds them at angle
  */
  rightdt.stop(hold);
  leftdt.stop(hold);

  vex::task::sleep(100);
}

I pulled some of your code into a test program. Seems to work ok.
Make sure IMU is plugged into the correct port.
Make sure you wait for IMU to finish calibration.
Try this test code, it works here.

/*----------------------------------------------------------------------------*/
/*                                                                            */
/*    Module:       main.cpp                                                  */
/*    Author:       james                                                     */
/*    Created:      Sun Feb 02 2020                                           */
/*    Description:  V5 project                                                */
/*                                                                            */
/*----------------------------------------------------------------------------*/
#include "vex.h"
#include <iostream>

using namespace vex;

// A global instance of vex::brain used for printing to the V5 brain screen
vex::brain       Brain;

// define your global instances of motors and other devices here

vex::motor rightdtFront(vex::PORT20, vex::gearSetting::ratio18_1, true);
vex::motor rightdtBack(vex::PORT11, vex::gearSetting::ratio18_1, true);

vex::motor leftdtFront(vex::PORT10, vex::gearSetting::ratio18_1, false);
vex::motor leftdtBack(vex::PORT1, vex::gearSetting::ratio18_1, false);

vex::inertial iSensor(vex::PORT3);

motor_group rightdt(rightdtFront, rightdtBack); 
motor_group leftdt(leftdtFront, leftdtBack); 

/*
Rotates robot right using Inertial Sensor
*/
void rotateright(double angleTurn) {
  /*
  Get initial values and begin rotation
  */
  iSensor.resetRotation();
  rightdt.spin(directionType::fwd, -60, velocityUnits::pct);
  leftdt.spin(directionType::fwd, 60, velocityUnits::pct);

  /*
  This ratio will be used to gradually slow down the robot as it approaches the target angle
  */
  double ratio = iSensor.rotation(rotationUnits::deg) / -(angleTurn);

  /*
  Loops the turn as long as the angle is not met
  Record the ratio adjust speed based on ratio
  */
  while(iSensor.rotation(rotationUnits::deg) < angleTurn) {
    std::cout << "right: " << -60 + ratio*50 << std::endl; // sign changed
    std::cout << "left: " << 60 - ratio*50 << std::endl; // sign changed

    rightdt.spin(directionType::fwd, -60 + ratio*50, velocityUnits::pct);
    leftdt.spin(directionType::fwd, 60 - ratio*50, velocityUnits::pct);
    ratio = iSensor.rotation(rotationUnits::deg) / angleTurn;
    
    std::cout << "ratio: " << iSensor.rotation(rotationUnits::deg) / angleTurn << std::endl;

    // delay so we don't saturate cout
    this_thread::sleep_for(50);
  }

  /*
  Completely stops motors and holds them at angle
  */
  rightdt.stop(hold);
  leftdt.stop(hold);

  vex::task::sleep(100);
}

int main() {
    while( iSensor.isCalibrating() )
        this_thread::sleep_for(10);

    rotateright( 90 );

    while(1) {
        // Allow other tasks to run
        this_thread::sleep_for(10);
    }
}
2 Likes