Feasibility: Changing PWM independent of main loop - use an ISR?

Status
Not open for further replies.

owhite

Active member
Folks I've built a robot wheel with a built in custom circuit board with a L6234PD brushless motor driver. I'm using that assembly to make a balancing robot with a teensy 4.0. I'm hoping to make a mashup of this motor driver system with this balancing bot that used brushed motors.

The principle of operation for the motor/L6234PD is described here. This is a code snippet Ive used to drive my boards
Code:
byte motorPins[2][3]={{0, 1, 2}, {5, 6, 9} }; // pins used to analogWrite to motors
uint8_t enablePin = 11;

int32_t sineArraySize = 360;
int32_t phaseShift = sineArraySize / 3; 
int32_t currentStepA = 0;
int32_t currentStepB = currentStepA + phaseShift;
int32_t currentStepC = currentStepB + phaseShift;

const int pwmSin[] = {128, 132, 136, 140, 143, 147, 151, 155, 159, 162, 166,
              170, 174, 178, 181, 185, 189, 192, 196, 200, 203, 207,
              211, 214, 218, 221, 225, 228, 232, 235, 238, 239, 240,
              241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250,
              250, 251, 252, 252, 253, 253, 253, 254, 254, 254, 255,
              255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
              255, 254, 254, 254, 253, 253, 253, 252, 252, 251, 250,
              250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241,
              240, 239, 238, 239, 240, 241, 242, 243, 244, 245, 246,
              247, 248, 248, 249, 250, 250, 251, 252, 252, 253, 253,
              253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255,
              255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253,
              253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246,
              245, 244, 243, 242, 241, 240, 239, 238, 235, 232, 228,
              225, 221, 218, 214, 211, 207, 203, 200, 196, 192, 189,
              185, 181, 178, 174, 170, 166, 162, 159, 155, 151, 147,
              143, 140, 136, 132, 128, 124, 120, 116, 113, 109, 105,
              101, 97, 94, 90, 86, 82, 78, 75, 71, 67, 64, 60, 56, 53,
              49, 45, 42, 38, 35, 31, 28, 24, 21, 18, 17, 16, 15,
              14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3,
              2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
              3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14,
              15, 16, 17, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8,
              7, 6, 6, 5, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8,
              8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 24, 28, 31,
              35, 38, 42, 45, 49, 53, 56, 60, 64, 67, 71, 75, 78, 82,
              86, 90, 94, 97, 101, 105, 109, 113, 116, 120, 124};

void setMotorPosition(uint8_t motor, int index, uint8_t power) {
  int pwm_a, pwm_b, pwm_c;
  
  // if only it was this easy to constrain absolute power!
  power = abs(constrain(power, 0, 255)); 

  // get number from the sin table, change amplitude from max
  pwm_a = (pwmSin[(index + currentStepA) % 360]) * (power / 255.0);
  pwm_b = (pwmSin[(index + currentStepB) % 360]) * (power / 255.0);
  pwm_c = (pwmSin[(index + currentStepC) % 360]) * (power / 255.0);

  analogWrite(motorPins[motor][0], pwm_a);
  analogWrite(motorPins[motor][1], pwm_b);
  analogWrite(motorPins[motor][2], pwm_c);
}

This relies on all changes happening in loop() as shown

Code:
void loop()  {
  if (i > sineArraySize) { i = 0; }
    setMotorPosition(0, i, MAX_PWER * .5);
    setMotorPosition(1, i, MAX_PWER * .5);
    delayMicroseconds(moveDelay);
  i++;
}
I've been controlling the speed of the motors by changing delay in the loop().

Notice that the motor is not driven by sending it a single set of PWMs. A single set of PWMs will simple make the motor hold position. In my case the motor rotates when the PWMs change over time. (Again, the principle is described over here).

So in a sense, balance bots with brushed motors, the wheel turns independent of the main loop by setting a PWM. The user makes a call to analogWrite() the loop can do other things. In my case I'd like to set the rate of change for the PWMs in loop(), and move on to other things.

I want to confirm with people that a sensible way to do that would be with an ISR with a function similar to setMotorPosition() above. So I would:
  • Change all relevant variables to volatile
  • Put the ISR on a timer
  • The variable index establishes the pwm value sent to analogWrite, after X number of calls to the ISR the index will get bumped to next array element, then I'd make a new call to update analogWrite()
  • loop() would control X

Does that logic sound reasonable? Are there other ways to independently change PWM over time? One issue is that the balancing bot code will have other ISRs() at least as he uses them here. I'm curious if that's going to get me into trouble. My familiarity with interrupts is still pretty naive.

thank you for your advice!
 
Status
Not open for further replies.
Back
Top