SOLVED: Gyro code malfunction. Value falsely set to zero on SETUP LOOPtransition

Back to the balancing robot.

My project is the MakeBlock balancing robot. The board is an Arduino clone. The gyro always starts with a value of zero. Actually, if you check the MakeBlock MeGyro code you will see that this is correct. Makeblock's code has been corrected here.

Preamble
SerialPlot sometimes drops a frame. When it does this, all values are set to zero. This is a problem of SerialPlot and not an issue of the MeGyro library.

My program is running into an issue with the angle being set to zero. It is not real. I am using the fixed library. So, it is not a result of the library. And, it is not a SerialPlot issue. It occurs when the program switches from SETUP to LOOP. MakeBlock gits around the problem by counting to ten. I would think there would be a better way.

Any one have an idea?

Any one have an idea?

Sure. Fix your code to use some other approach.

Since your code is such a secret, only you can do that.

High again PaulS.

Thank You for your interest.

Remember me and my balancing robot? It’s not a secret. My information and code are all over the Arduino and PlatformIO forums. It’s just that I cannot put it all in one post. I will list what code I can here. The whole program is at Dropbox.

Solved: Variables can be initialized when defined. If not, then they are implicitly initialized as zero. This is the case here.
> Since this variable was not explicitly initialized, it was implicitly initialized to zero.

First This thread started about the Arduino PID Library in the Programming Questions section. It is quickly becoming more consistent with Project Guidance.

Second In my mind, I have already explained everything. However, the information is in several threads at two websites, so it is segmented and not necessarily connected. That always makes communication difficult and confusing. So, I will try to put all the thought together and add details. Some of this will obviously be a reprint. However, I can use that structure to add details.

So here we go . . .
My balancing robot project is to use the MakeBlock build & firmware with a Nintendo Wii nunchuck for control. The firmware has code for some 60-70 devices/sensors and the balancing code. It is 3000 lines long. I only use the code for the accelerator/gyroscope (MPU6050). This amounts to about 100 lines of code. I have reduced the program to about 2000 lines, but I will have to extend the it to accept input from the nunchuck by I2C. This will give me control of left-right turn and forward-backward speed.

The nunchuck has a single gimble. It will give both an X and a Y value as well as 3-axis accelerator and 3-axis-gyro. I will only be using the gimbal’s X & Y value. X for left-right. Y for forward-backward. It returns values as one byte (0 to 255). In order to get equal positive and negative, I will use a bias of 127. That will give me a range of ~(-127 to +127). I do not know what the best maximum speed would be. So, I will try eight ( 8 ). But, since it is a balancing robot, it is expected that commands for a sudden speed change could be detrimental. So, I will perform what I call a running average. Others call it a Low-Pass filter. And for those that can calculate the frequency, that may be a better name. In either event, it is expected that the robot cannot respond to rapid nunchuck control

A two-wheel balancing robot has maximum physical stability left-right, but, minimum physical stability forward-backward. So, consequently, the software code will have to have minimum complexity and accuracy for left-right turns. But it will have to have maximum complexity and accuracy forward-backward. Getting the left-right code to work was quick and easy. The speed code will be more delicate and complicated. It continues to be a problem. Makeblock’s concept is to use a PID (PI) for speed and a separate PID (PID) for balance. The speed PID links the nunchuck to the robot’s instantaneous actual speed. This may initially seem like a good idea, but makes things entirely too complicated. Desired speed is in no way dependent on actual speed. And, an additional, a PID adds three more values to be tuned. Additionally, the speed PID converts a smooth filtered speed to something that almost looks like PWM. (as shown in the graph) I do not see that Makeblock’s concept of using a speed PID is beneficial.

And tuning is hard. So, using a speed PID when it is not required just adds unnecessarily to the complexity. But, as a new user, this puts me in disagreement with the Makeblock experts. I just find the speed PID to be the wrong concept.

The part of the code at play here is

  int x;
  int y;
  x=y;
  double CompAngleXraw = -gyro_ext.getAngleX();
  double alpha = 0.2;
  CompAngleX = (1-alpha)*CompAngleX + alpha*CompAngleXraw;

My_Robot_101.cpp (55.5 KB)

My information and code are all over the Arduino and PlatformIO forums.

You expect me to remember that, and to go look for the code that is causing your current distress? Ain't going to happen.

The whole program is at Dropbox.

Then your question should be there, too. You could attach a zip file, here, if you read the stickies.

Me4Button buttonSensor;

What kind of sensor senses buttons?

I only use the code for the accelerator/gyroscope (MPU6050).

So, how does that explain:

MeTemperature ts;
MeRGBLed led;
MeUltrasonicSensor *us = NULL;     //PORT_7
Me7SegmentDisplay seg;
MePort generalDevice;
MeLEDMatrix ledMx;
MeInfraredReceiver *ir = NULL;     //PORT_6
MeGyro gyro_ext(0,0x68);           //external gryo sensor
MeCompass Compass;
MeJoystick joystick;
MeStepperOnBoard steppers[4];
MeBuzzer buzzer;
MeHumiture humiture;
MeFlameSensor FlameSensor;
MeGasSensor GasSensor;
MeTouchSensor touchSensor;
Me4Button buttonSensor;
MeEncoderOnBoard Encoder_1(SLOT1);    
MeEncoderOnBoard Encoder_2(SLOT2); 
MeEncoderOnBoard Encoder_3(SLOT3);
MeEncoderOnBoard Encoder_4(SLOT4);
MeLineFollower line(PORT_8);

//MeGyro gyro_ext(0,0x68);           //external gryo sensor
MeGyro gyro;                                                      // 'MeGyro' does not name a type      MAM

If you don't have any/all of these things, don't create these objects.

You mentioned that some code accomplishes something by counting to 10. Where does that happen?

You expect me to remember that, and to go look for the code that is causing your current distress? Ain’t going to happen.

The program file is also included here with the post as a .cpp file

What kind of sensor senses buttons?

MakeBlock also makes an IR remote with buttons. This call is for that remote.

So, how does that explain:

The MakeBlock firmware is 3000 line. I have removed 1000 lines, so I am down to 2000 lines. I am removing to routine calls before removing the routines themselves. I am making sure that the program compiles after each routine is removed. I have just removed another 500 lines. So, I am down to 1500 lines.

If you don’t have any/all of these things, don’t create these objects.

I have simply deleted the ones that are not implemented. Some of the rest are implemented but not used. I have to delete the code before I can delete the object.

You mentioned that some code accomplishes something by counting to 10. Where does that happen?

In the original code, the routine reset handles this. “agx_start_count” counts the times through Loop. If the count ever reaches 20, there is an error.

void reset(void)
{
  if((start_flag == false) && (abs(gyro_ext.getAngleX()) < 5))  //  Count
  {
    agx_start_count++;
  }
  if((start_flag == true) && (abs(gyro_ext.getAngleX()) > 32))  //  I have fallen
  {
    agx_start_count = 0;
    Encoder_1.setMotorPwm(0);
    Encoder_2.setMotorPwm(0);
    PID_speed.Integral = 0;
    PID_angle.Setpoint = RELAX_ANGLE;
    PID_speed.Setpoint = 0;
    PID_turn.Setpoint = 0;
    Encoder_1.setPulsePos(0);
    Encoder_2.setPulsePos(0);
    PID_speed.Integral = 0;
    start_flag = false;
    last_speed_setpoint_filter = 0.0;
    last_turn_setpoint_filter = 0.0;
#ifdef DEBUG_INFO
    Serial.println("> 32");
#endif
  }
  else if(agx_start_count > 20)  //  Error
  {
    agx_start_count = 0;
    PID_speed.Integral = 0;
    Encoder_1.setMotorPwm(0);
    Encoder_2.setMotorPwm(0);
    PID_angle.Setpoint = RELAX_ANGLE;
    Encoder_1.setPulsePos(0);
    Encoder_2.setPulsePos(0);
    lasttime_speed = lasttime_angle = millis();
    start_flag = true;
#ifdef DEBUG_INFO
    Serial.println("< 5");
#endif
  }
}

My_Robot_101.cpp (47.1 KB)

This call is for that remote.

That was NOT a function call, and the remote is NOT sensing buttons.

I have to delete the code before I can delete the object.

I would do it the other way around. Delete the object, then delete all the code that tries to use that object.

I’m beginning to suspect that your problem is all about starting from the wrong point (MakeBlock).

I don't use either of them, but best i can figure, the associations are

MeInfraredReceiver *ir = NULL;     //PORT_6
if(ir != NULL){
 IrProcess();}

Me4Button buttonSensor;

4Button2.png

4Button2.png