How to Mimic lifting weights/aerobic/rowing machine

I like the idea of a all in one exercise machine and am new to simplefoc. Is it possible to make a motor that’s tied to a spindle of some sort that has some string and have it attached to the motor to give variable resistance as we pull on the string or slowly release it? If anyone can send to the right direction of what type of control that would be like.

You can do that with torque control.

If I have torque control on, can I still have a rotating motor? Because for it to function like a rowing machine I still need it to draw the string back in along with the torque

I’ve made a machine that does what you described. Essentially, you use torque control mode along with some code that controls when the torque is active as a function of the angle of the motor. That way, at rest, the motor isn’t spinning. You’ll need to use a battery system to absorb the energy generated when you spin the motor against a torque - otherwise, the voltage will rise and damage your power supply or motor controller.

1 Like

Do you have a hackaday or writeup of how you went through doing it? I did suspect that I had to do something about that cuz it would essentially be like a generator.

Using only a battery doesn’t work, when said battery is already fully charged.
You’ll need a brake resistor too.

@Jelivan_Lolz I made my rowing machine using angle mode with adjustable max. torque.(external potmeter) The string will automatically be pulled back to start.

1 Like

What motor did you use. A gimbal motor or a high Kv motor with a gearbox?

I’ve used both. Ill dig out my old tiny prototype and share my code I used. Need a few days to find it and the old code I wrote…

1 Like

That would be fantastic, I’ve ordered a 5010 motor just to try a setup. I’m thinking of using both velocity control and torque control. Maybe use a 2 phase control loop when the machine is getting pulled and when it is being returned

I couldn’t find the code I used for a prototype I built a while back, so i put together a little demo system and barebones code to demonstrate how it can be done using torque control alone. For the controller, I’m using a board I got from AliExpress that can control two motors, which uses an ESP32 for the mcu. The motor is a 6010 gimbal motor, and the encoder is an AMT102 set to 2048 CPR.

Controller: https://www.aliexpress.us/item/3256804880223412.html

This board is really fantastic for prototyping with SimpleFOC, provided you don’t need a ton of I/O connections or CAN capability.

I’m using SimpleFOC v2.3.4 with the code below. I develop in VSCode with PlatformIO. With the code as is, the motor will be at rest initially, and will gradually develop torque over 1/2 a turn, until it reaches the maximum torque (Iq) limit set by iq_limit_a - here, 0.5 amps. Once max Iq is reached, it present a constant torque that is independent of rotational speed, at least until the maximum motor voltage is reached. The motor will freewheel at zero torque if spun in the opposite direction.

#include <SimpleFOC.h>

Encoder gimbal_sensor = Encoder(18, 5, 2048); 
void doA(){gimbal_sensor.handleA();}
void doB(){gimbal_sensor.handleB();}

//Motor Parameters
BLDCMotor motor_gimbal = BLDCMotor(11);                          
BLDCDriver3PWM driver_gimbal = BLDCDriver3PWM(32, 33, 25, 22);  // Motor 0    

InlineCurrentSense current_sense_gimbal = InlineCurrentSense(0.01, 50.0, 39, 36, _NC);

float initial_angle_rads = 0.0;
float normalized_angle_rads = 0.0;
float iq_target_a = 0.0;
float iq_limit_a = 0.5;

void setup() {

  motor_gimbal.motion_downsample = 2.0;

  // Supply Voltage 
  driver_gimbal.voltage_power_supply = 12.0;

  // Motor voltage limits
  motor_gimbal.voltage_limit = 7.0; 
  motor_gimbal.voltage_sensor_align = 1.3;
  
  // Motor control params
  motor_gimbal.torque_controller = TorqueControlType::foc_current;
  motor_gimbal.controller = MotionControlType::torque;
  motor_gimbal.foc_modulation = FOCModulationType::SpaceVectorPWM;
 
  // current q loop PID
  motor_gimbal.PID_current_q.P = 2;
  motor_gimbal.PID_current_q.I = 150.0;
  motor_gimbal.PID_current_q.D = 0.0;
  motor_gimbal.PID_current_q.output_ramp = 0.0;
  motor_gimbal.PID_current_q.limit = 12.0;
  motor_gimbal.LPF_current_q.Tf = 0.001;
 
  // current d loop PID
  motor_gimbal.PID_current_d.P = 2;
  motor_gimbal.PID_current_d.I = 150.0;
  motor_gimbal.PID_current_d.D = 0.0;
  motor_gimbal.PID_current_d.output_ramp = 0.0;
  motor_gimbal.PID_current_d.limit = 12.0;
  motor_gimbal.LPF_current_d.Tf = 0.001;

  Serial.begin(115200);
  motor_gimbal.useMonitoring(Serial);

  // Sensor setup and linking to motor
  gimbal_sensor.init();
  gimbal_sensor.enableInterrupts(doA, doB);
  motor_gimbal.linkSensor(&gimbal_sensor);
  
  // Driver init
  driver_gimbal.init();

  // Link current sense
  current_sense_gimbal.linkDriver(&driver_gimbal);

  // Connect the Motor and Driver Objects
  motor_gimbal.linkDriver(&driver_gimbal);

  // Initialize the Motor
  motor_gimbal.init();
  
  // Current Sense Init
  current_sense_gimbal.init();
  motor_gimbal.linkCurrentSense(&current_sense_gimbal);
 
  // Initialize FOC
  motor_gimbal.initFOC();

  initial_angle_rads = gimbal_sensor.getAngle();

}

void loop() {

  normalized_angle_rads = gimbal_sensor.getAngle() - initial_angle_rads;

  if (normalized_angle_rads <= 0) {
    iq_target_a = 0.0;
  } else {
    iq_target_a = -1.0 * min((normalized_angle_rads / 3.14f), iq_limit_a);
  }

  motor_gimbal.loopFOC();
  motor_gimbal.move(iq_target_a);

}

Hardware Setup:

3 Likes