Advertisement
Guest User

Untitled

a guest
Jul 3rd, 2024
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.93 KB | None | 0 0
  1. constexpr int motor_pin{12};
  2. constexpr int dir_pin{16};
  3. constexpr int limit_switch{22};
  4. constexpr int us_trig = 17;
  5. constexpr int us_echo = 27;
  6.  
  7.  
  8. class EnergyController{
  9. public:
  10.  
  11.     EnergyController(double k_energy, double upright_threshold=0.2, double length=0.2): k_energy(k_energy), upright_threshold(upright_threshold), length(length){
  12.       bar_mass = calculate_bar_mass(0.005, length);
  13.       inertia = calculate_polar_inertia(bar_mass, length);
  14.       std::cout << "k_energy " << k_energy << std::endl;
  15.       previous_output = k_energy*gravity;
  16.     }
  17.     double control_input = 0;
  18.     double upright_threshold;
  19.     double length;
  20.     double bar_mass;
  21.     double inertia;
  22.     double gravity = 9.806;
  23.     double k_energy;
  24.  
  25.  
  26.     double previous_output;
  27.  
  28.  
  29.     double calculate_bar_mass(double radius, double height){
  30.       double density = 7850;
  31.       double mass = density * 3.14159 * radius*radius * height;
  32.        
  33.       return mass;
  34.     }
  35.  
  36.  
  37.     double calculate_polar_inertia(double mass,double length){
  38.       double inertia_pivot = (1 / 12) * mass * length*length;
  39.       return inertia_pivot;
  40.     }
  41.    
  42.     double total_energy(double angle, double angular_velocity){
  43.       double potential_energy = -bar_mass * gravity * (length) * (std::cos(angle));
  44.       double kinetic_energy = 0.5 * inertia * angular_velocity*angular_velocity;
  45.       double total_energy = potential_energy;
  46.       return total_energy;
  47.     }
  48.    
  49.     double control(double angle, double angular_velocity){
  50.       double reference_energy = total_energy(0, 0);
  51.      
  52.       double energy_error = total_energy(angle, angular_velocity) - reference_energy;
  53.       double abs_ang_vel =std::abs(angular_velocity);
  54.       if (abs_ang_vel == 0) {
  55.         return previous_output;
  56.       }
  57.       if ((energy_error*angular_velocity*std::cos(angle))>0 ) {
  58.         previous_output = -k_energy*gravity;
  59.         return -k_energy*gravity;
  60.       } else {
  61.         previous_output = k_energy*gravity;
  62.         return k_energy*gravity;
  63.       }
  64.     }
  65.   };
  66.  
  67.  
  68. void output_to_motor(double output) {
  69.   gpioWrite(dir_pin, output > 0);
  70.   output = abs(output)+ 25;
  71.   if (output > 255)
  72.     output = 255;
  73.   gpioPWM(motor_pin, output);
  74. }
  75.  
  76. bool loop_should_stop{false};
  77.  
  78. void limitSwitchISR(int gpio, int level, uint32_t tick) {
  79.   std::cout << "ISR ENTERED" << std::endl;
  80.   loop_should_stop = true;
  81.   gpioPWM(motor_pin, 0);
  82. }
  83.  
  84.  
  85. // Convert AS5600 output to radians where 0 is vertically upright position. PI is the hang down position.
  86. double uart_to_radians(int uart_value, int reference_angle) {
  87.   const auto diff = 4096 - reference_angle;
  88.   return static_cast<double>(uart_value + diff)*2.0*3.14159/4096.0;
  89. }
  90.  
  91.  
  92. int main(int argc, char** argv)
  93. {
  94.     AS_5600 rotary_encoder{}; // stuff we wrote to get AS5600 reading. Wrapper for reading from UART
  95.     gpioInitialise();
  96.     gpioSetMode(limit_switch, PI_INPUT);
  97.     gpioSetPullUpDown(limit_switch, PI_PUD_DOWN);
  98.     gpioSetISRFunc(limit_switch, RISING_EDGE, 0, limitSwitchISR);
  99.  
  100.  
  101.     gpioInitialise();
  102.     gpioSetMode(motor_pin, PI_OUTPUT);
  103.     gpioSetMode(dir_pin, PI_OUTPUT);
  104.     gpioSetPWMfrequency(motor_pin, 2000);
  105.    
  106.     auto t_old = std::chrono::steady_clock::now();
  107.  
  108.  
  109.     // argv[1] is our k. We currently picked a k of 6
  110.     EnergyController ec{std::stod(argv[1])};
  111.  
  112.  
  113.     pin_me_to_core(1); // our function that pins program to core
  114.     set_my_sched_fifo_priority(2); // our function that gives program a real time priority
  115.    
  116.     int reference_angle = std::stoi(argv[2]); // upright position that the AS5600 measures
  117.     double prev_angle = uart_to_radians(rotary_encoder.getAngleUART(), reference_angle);
  118.     while(!loop_should_stop)
  119.     {
  120.       auto start = std::chrono::steady_clock::now();
  121.       double angle = uart_to_radians(rotary_encoder.getAngleUART(), reference_angle);
  122.  
  123.  
  124.       auto d_angle = angle - prev_angle;
  125.      
  126.  
  127.  
  128.       const auto t_new = std::chrono::steady_clock::now();
  129.  
  130.  
  131.       auto dt = std::chrono::duration<double>(t_new - t_old).count();
  132.       auto angular_vel = d_angle / dt;
  133.  
  134.  
  135.       auto output = ec.control(angle, angular_vel);
  136.  
  137.  
  138.       output_to_motor(output);
  139.  
  140.  
  141.       t_old = t_new;
  142.       prev_angle = angle;
  143.  
  144.  
  145.       auto end = std::chrono::steady_clock::now();
  146.       using namespace std::chrono_literals;
  147.       const auto min_dt{100ms}; // also implicitly the sampling delay
  148.       const std::chrono::duration<double, std::nano> time_spent{end - start};
  149.       // basically want to run every 100ms
  150.       if (time_spent > min_dt) {
  151.         std::cerr << "Skipping sleep\n";
  152.       } else {
  153.         std::this_thread::sleep_for(min_dt - time_spent);
  154.       }
  155.  
  156.  
  157.     }
  158.     gpioPWM(motor_pin, 0);
  159.     gpioTerminate();
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement