DC motor or stepper motor for Inverted Pendulum?

Hello so I'm trying to do the inverted pendulum porject, here is my assembly

I'm trying to use a 1 amp Nema17 with a498 driver with 24 volt 1.5 amp power supply on a arduino uno. I'm using the stepper library with the following code to just test out the speed of the motor with no load.

#include <AccelStepper.h>


const int step_pin = 4;
const int dir_pin = 5;
const int ms1 = 6;
const int ms2 = 7;
const int ms3 = 8;
AccelStepper stepper(1,step_pin,dir_pin);
const float conversion = 0.1; //steps to arc length (mm)
const float safe_range = 200.0; //mm
bool run = true; //flag varible to turn off
int acceleration = 1000;
int maxspeed = 4000;
int speed = 3700;
int steps = 1200;


void setup()
{
  Serial.begin(9600);
  //setup microstepping
  pinMode(ms1,OUTPUT);
  pinMode(ms2,OUTPUT);
  pinMode(ms3,OUTPUT);
  digitalWrite(ms1,HIGH);
  digitalWrite(ms2,LOW);
  digitalWrite(ms3,LOW);
  //setup speed + acceleration
  stepper.setMaxSpeed(maxspeed);
  stepper.setAcceleration(acceleration);
  stepper.setSpeed(speed);
  //stepper.move(steps);
  delay(2000);
}


void loop()
{
  //float step = stepper.currentPosition();
  //float s = step*conversion;


  if ((Serial.available() > 0))
  {
    run = false;
  }


  if (run == true)
  {
    stepper.runSpeed();
  }
}


float absolute_value(float value)
{
  if (value < 0.0)
  {
    value = -value;
  }


  return value;
}

And it stalls at 3700 steps per second. I've tried to use the motor with the encoder to implement a PID controller, here is the code

#include <AccelStepper.h>

//define pins
#define ENCA 2
#define ENCB 3
const int step_pin = 4;
const int dir_pin = 5;
const int ms1 = 6;
const int ms2 = 7;
const int ms3 = 8;
//stepper parameters
AccelStepper stepper(1,step_pin,dir_pin);
const float conversion = 0.2; //steps to arc length (mm)
const float safe_range = 150.0; //mm
bool run = true; //flag varible to turn off
int acceleration = 10000;
const int maxspeed = 1000;
int steps = 50;
int timestep_count = 0;
int timestep_limit = 5;
//encoder parameters
float count = 0;
const float resolution = 0.3;
const float theta_range = 30.0;
long prev_T = 0.0;
float prev_error = 0.0;
//PD controller gains
const float P = 10.0;
const float D = 10.0;

void setup()
{ 
  Serial.begin(9600);
  //STEPPER
  //setup microstepping
  pinMode(ms1,OUTPUT);
  pinMode(ms2,OUTPUT);
  pinMode(ms3,OUTPUT);
  digitalWrite(ms1,LOW);
  digitalWrite(ms2,LOW);
  digitalWrite(ms3,LOW);
  //setup speed + acceleration
  stepper.setMaxSpeed(maxspeed);
  //ENCODER
  pinMode(ENCA,INPUT_PULLUP);
  pinMode(ENCB,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,CHANGE);
  delay(1000);
  prev_T = micros();  
}

void loop()
{ 
  //record time difference
  long cur_T = micros();
  float T = ((float)(cur_T - prev_T))/(1.0e6); //delta T in seconds
  //compute error and derivative
  float angle = count*resolution;
  float error = -angle;
  float delta_error = (error - prev_error)/T;
  prev_error = error;
  prev_T = cur_T;
  //compute control signal
  int u = P*error + D*delta_error;
  if (u == 0)
  {
    u = 1;
  }
  stepper.setSpeed(limit(-maxspeed,maxspeed,u));

  float step = stepper.currentPosition();
  float s = step*conversion;

  if ((absolute_value(s) >= safe_range))
  {
    run = false;
  }

  if ((run == true) && (abs(angle) <= theta_range))
  {
    stepper.runSpeed();
  }

  Serial.println(u);
}

int limit(int min, int max, int value)
{
  if (value < min)
  {
    value = min;
  }
  else if(value > max)
  {
    value = max;
  }

  return value;
}

int sign(int a)
{
  if (a >= 0)
  {
    return 1;
  }

  return -1;
}

float absolute_value(float value)
{
  if (value < 0.0)
  {
    value = -value;
  }

  return value;
}

void readEncoder()
{
  int a_state = digitalRead(ENCA);
  int b_state = digitalRead(ENCB);

  if (a_state == b_state) //CCW
  {
    count = count - 1;
  }
  else //CW
  {
    count = count + 1;
  }
}

Although the motor moves in the right direction, it feels choppy and I don' feel confident it can reach the desired speeds to balance. Would a DC motor be better? The only concern I have with DC is that it has lower torque so I'm worried my cart would be too heavy. Any advice would be appreciated, thanks

Lower than what?

Instead of guessing or using junk box parts, buy a motor with the required torque and appropriate weight.

Lots of successful inverted pendulum projects have been posted on the web. Study what others have done and go from there.

I can’t see any reason why a stepper motor couldn’t do the job. I built a self-balancing robot using two 2A steppers, and it controls very well.

However it did not control well when the stepping resolution was one step. I had to use 32 microsteps resolution. You may find the same if your stepper motor has 200 steps (as is common) and direct drive (no gearing other than wheel size).

I used a TB6600 controller.

Check out these balancing robots by remrc that use Nidec 24H brushless servo motors:

did you control motor speed with runspeed? if you did how did you handle changes in acceletration? because at high speeds my nema17 skip steps and stalls

I didn't use a stepper library. I just generated a pulse train directly from the PID loop output, using one of the Arduino's hardware counter / timers in PWM mode.

The pulses go to the "step" pin of the TB6600 controller. The frequency of the pulses and thus the motor speed are directly proportional to the PID output. The scaling factor MOTORCALIBRATIONFACTOR in the code below has to be set low enough that the motor doesn't skip steps at maximum speed.

OK that was a self-balancing robot not an inverted pendulum but the principle should be the same.

This is the core part of the code.

rollControlPIDOutput = rollControlPID.Run(measuredRollCompensated);      // PV input to PID controller is the measured roll. Setpoint is zero (i.e. vertical).

  // Control intent is to map the roll control PID controller output linearly to the drive speed command,
  // with speed increasing with increasing controller output (tilt away from vertical).
  // The stepper motor controller requires to be sent a pulse train with constant duty and variable frequency as the motor speed setpoint.
  // Convert the roll control PID controller output over the required control range, into the required pulse train speed in steps per second.
  // This relationship and the calibration factor used are empirically derived.
  // Then convert the frequency into a period for the PWM to use to generate the pulse train to the stepper controller.

  speedPulsesPerSec = abs(rollControlPIDOutput) * MOTORCALIBRATIONFACTOR + 2;  // empirical conversion factor between PID output and pulse train to stepper controller
  //                                                                             + 2 is an offset to keep the motor above zero when outside the deadband.
    
  // Clock speed is 1MHz, so 1E6 ticks/sec divided by 2 pulses/sec = 500,000 ticks/pulse.
  // This is the PWM period (expressed in microsecond ticks) found to be needed for the slowest speed required, around the balance point.
 
  PWMperiod = (1E6 / speedPulsesPerSec);          // divide into 1E6 since PWM ticks are 1Mhz and that is what TCC0 is counting. 
  REG_TCC0_PERB = PWMperiod;                      // load desired PWM period into TCC0 PER register to generate PWM pulse train on PULSE (D5)
  while(TCC0->SYNCBUSY.bit.PERB);                 // Wait for synchronization 

  REG_TCC0_CCB1 = PWMperiod / 2;                  // Pulse train duty always half the period
  while(TCC0->SYNCBUSY.bit.CCB1);                 // Wait for synchronization