Page 1 of 1

firmware to emulate controller

Posted: Tue Jan 27, 2015 4:20 am
by almaz_1c
Hello! I have crazyflie quadcopter but don't have any controller like Xbox 360 or Playstation 3.
But i want to switch on balancing of PID controllers.
My i idea - i place the motors M1 and M3 sholders on any handhold and make to balancing M2 and M4 shoulders in air.
So is someone can point me how to modify firmware to switch on PID controlled balancing? Emulate RX commands or any other way to do it.

Re: firmware to emulate controller

Posted: Tue Jan 27, 2015 10:16 am
by arnaud
Hi,
You can see and modify the PID parameters from the PC client in the parameter tabs. To modify the firmware in itself you will need to download the source-code from github, modify it and flash your modified version (this can be done with the radio bootloader).

The easiest to get started is to use the virtualmachine: http://wiki.bitcraze.se/projects:virtualmachine:index

The code you are looking for is in/around stabilizer.c: https://github.com/bitcraze/crazyflie-f ... zer.c#L240
This task is responsible for running the PIDs and controlling the motors.

Re: firmware to emulate controller

Posted: Tue Jan 27, 2015 10:43 am
by almaz_1c
Thank you arnaud! You right!
It is very easy - i modify stabilizerTask as you said and now my quadcopter balancing after power on!

Code: Select all

static void stabilizerTask(void* param)
{
  uint32_t attitudeCounter = 0;
  uint32_t altHoldCounter = 0;
  uint32_t lastWakeTime;

  vTaskSetApplicationTaskTag(0, (void*)TASK_STABILIZER_ID_NBR);

  motorsSetRatio(0, 10000);
  motorsSetRatio(1, 10000);
  motorsSetRatio(2, 10000);
  motorsSetRatio(3, 10000);
  //Wait for the system to be fully started to start stabilization loop
  systemWaitStart();

  lastWakeTime = xTaskGetTickCount ();

  int al_counter = 0;
  float al_x, al_y, al_z;
  while(1)
  {
    vTaskDelayUntil(&lastWakeTime, F2T(IMU_UPDATE_FREQ)); // 500Hz
	al_counter++;

    // Magnetometer not yet used more then for logging.
    imu9Read(&gyro, &acc, &mag);

    if (imu6IsCalibrated())
    {
//       commanderGetRPY(&eulerRollDesired, &eulerPitchDesired, &eulerYawDesired);
      eulerRollDesired = 0.0;
	  eulerPitchDesired = 0,0;
	  eulerYawDesired = 0.0;
      commanderGetRPYType(&rollType, &pitchType, &yawType);

      // 250HZ
      if (++attitudeCounter >= ATTITUDE_UPDATE_RATE_DIVIDER)
      {
        sensfusion6UpdateQ(gyro.x, gyro.y, gyro.z, acc.x, acc.y, acc.z, FUSION_UPDATE_DT);
        sensfusion6GetEulerRPY(&eulerRollActual, &eulerPitchActual, &eulerYawActual);

// 		gyro_angle_count( gyro.x, gyro.y, gyro.z, FUSION_UPDATE_DT);
// 		al_x = gyro_angle_X_get();
// 		al_y = gyro_angle_Y_get();
// 		al_z = gyro_angle_Z_get();
// 		DEBUG_PRINT("%d, %f, %f\n", al_counter,
// 										eulerRollActual,
// 										al_x
// 				);
        accWZ = sensfusion6GetAccZWithoutGravity(acc.x, acc.y, acc.z);
        accMAG = (acc.x*acc.x) + (acc.y*acc.y) + (acc.z*acc.z);
        // Estimate speed from acc (drifts)
        vSpeed += deadband(accWZ, vAccDeadband) * FUSION_UPDATE_DT;

        controllerCorrectAttitudePID(eulerRollActual, eulerPitchActual, eulerYawActual,
                                     eulerRollDesired, eulerPitchDesired, -eulerYawDesired,
                                     &rollRateDesired, &pitchRateDesired, &yawRateDesired);
        attitudeCounter = 0;
      }

      // 100HZ
      if (imuHasBarometer() && (++altHoldCounter >= ALTHOLD_UPDATE_RATE_DIVIDER))
      {
        stabilizerAltHoldUpdate();
        altHoldCounter = 0;
      }

      if (rollType == RATE)
      {
        rollRateDesired = eulerRollDesired;
      }
      if (pitchType == RATE)
      {
        pitchRateDesired = eulerPitchDesired;
      }
      if (yawType == RATE)
      {
        yawRateDesired = -eulerYawDesired;
      }

      // TODO: Investigate possibility to subtract gyro drift.
      controllerCorrectRatePID(gyro.x, -gyro.y, gyro.z,
                               rollRateDesired, pitchRateDesired, yawRateDesired);

      controllerGetActuatorOutput(&actuatorRoll, &actuatorPitch, &actuatorYaw);

      if (!altHold || !imuHasBarometer())
      {
        // Use thrust from controller if not in altitude hold mode
//         commanderGetThrust(&actuatorThrust);
			actuatorThrust = 10000;
      }
      else
      {
        // Added so thrust can be set to 0 while in altitude hold mode after disconnect
        commanderWatchdog();
      }

      if (actuatorThrust > 0)
      {
#if defined(TUNE_ROLL)
        distributePower(actuatorThrust, actuatorRoll, 0, 0);
#elif defined(TUNE_PITCH)
        distributePower(actuatorThrust, 0, actuatorPitch, 0);
#elif defined(TUNE_YAW)
        distributePower(actuatorThrust, 0, 0, -actuatorYaw);
#else
        distributePower(actuatorThrust, actuatorRoll, actuatorPitch, -actuatorYaw);
#endif
      }
      else
      {
        distributePower(0, 0, 0, 0);
        controllerResetAllPID();
      }
    }
  }
}