project: Segbot; using a MPU-6050 IMU, Atmega328P-AU, and a SAbertooth 2x25 controller
It's working great! However, when no one is on it, it will self balance okay in a perfect environment, but just a little bump will start it oscillating. The motor speed maxes out at 100% at about 30 degrees tilt, which is just about perfect for riding. With no load (person), and I set the motor speed to be 50% at 30 degrees, it sets by itself very nicely, and can not be made to oscillate.
So I need to detect when it is not being ridden, and change the motor mapping to standbyMapping, rather than RidingMapping.
What sounds like a workable solution is this: If the motorVal goes Negative (reverse) more than once a second, put it in StandbyMode. Longer than 1 second since the last Negative value, go back to ridingMode. It sounds easy, but I'm struggling with it. It's more than just reading a negative value, but reading a "change to negative from positive". Any help would be greatly appreciated.
See lines 11 & 12 of my motor code here. I need to do one or the other, depending on standby mode or riding mode:
void update_motor(){ // Update the motors
static unsigned long prevTime;
int motor1, motor2;
if (millis() - prevTime < 30) return; //only do this every 30 ms
prevTime = millis(); //update the time stamp
maxPitch = 1500; //value from the MPU-6050, this makes 30 degrees the max tilt for 100% speed
maxSpeed = 64;
standbySpeed = 32;
if (pitch < -3000) crash(); //we probably crashed
if (pitch > 3000) crash(); //we probably crashed
motor_speed = map(pitch, -maxPitch, maxPitch, -standbySpeed, standbySpeed); //standby mode
motor_speed = map(pitch, -maxPitch, maxPitch, -maxSpeed, maxSpeed); // map the angle to the sabertooth controller range 1-64
if (motor_speed > 64) motor_speed = 64; //that's the maximum speed
if (motor_speed > 0) motor_speed = fscale( 1, 64, 1, 64, motor_speed, -1.4); //scale it to change slightly at low numbers
if (motor_speed < 0) motor_speed = fscale( -64,-1, -64,-1,motor_speed, 2); //scale it to change slightly at low numbers
motor1 = motor_speed + get_Steering(); //add steering bias to motor 1
motor2 = motor_speed - get_Steering(); //add steering bias to motor 2
// assign final motor output values
motor1 = 65 + motor1; //64 is neutral for motor 1
motor2 = 192 + motor2; //192 is neutral for motor 2
motor1 = constrain(motor1, 1, 127); //constrain the value to it's min/max
motor2 = constrain(motor2, 128, 255);//constrain the value to it's min/max
if (!debugMode) Segway.write(motor1); //Send motor 1 speed over serial
delay(1); //sabertooth can only receive commands at 2000/second
if (!debugMode) Segway.write(motor2); //Send motor 2 speed over serial
if (!debugMode) {
Serial.print("Pitch: ");
Serial.print(pitch);
Serial.print("\tMotorSpeed1: ");
Serial.print(motor1);
Serial.print("\tMotorSpeed2: ");
Serial.println(motor2);
}
}