ServoInput.h and pwm writing no working together

I am using an Arduino Mega and using the ServoInput library to read my RC receiver throttle. I take that input and map it to 0-255 then send it to my motor via pwm pin 9. The code works flawless as long as I comment out the analogWrite(PWM,mappedValue). If I uncomment the line it starts skipping reading values and I get some zeros which then makes the motor not turn smoothly. Here is my code.

#include <ServoInput.h>
byte PWM =9;

// Throttle Setup
const int ThrottleSignalPin = 2;  // MUST be interrupt-capable!
const int ThrottlePulseMin = 900;  // microseconds (us)
const int ThrottlePulseMax =1985; //calibrated values for min/max  
ServoInputPin<ThrottleSignalPin> throttle(ThrottlePulseMin, ThrottlePulseMax);

void setup() { 
  Serial.begin(115200);
  pinMode(PWM, OUTPUT);
   analogWrite(PWM, 0); 
}

void loop() {

  int throttlePercent = throttle.map(0, 255);  // remap to a percentage both forward and reverse

 Serial.print("Throttle: ");Serial.println(throttlePercent);
  //analogWrite(PWM, throttlePercent); //does not work right when I uncomment this line.

}

any idea on why this happens?

Flawlessly. Sorry, just one too many times...

Probably, you have a hardware timer conflict. Try using a PWM pin that uses a different timer.

If I am not mistaken, I have moved the pwm to pin 11 which I believe uses timer2 and pin 2 uses timer 4. I still get skips in my throttle when sending pwm.

Throttle: 101
Throttle: 110
Throttle: 119
Throttle: 119
Throttle: 119
Throttle: 0
Throttle: 0
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 137
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 159
Throttle: 45
Throttle: 45
Throttle: 178
Throttle: 178
Throttle: 178
Throttle: 178

One thing, you should not be performing an analogWrite every time through loop(), it's too often. Try updating it every 50-100ms instead.

Please post a clickable link to the library you are using.

Here is the link: ServoInput

I will see if I can figure out how to do that.

Standard way would be a millis() block like

unsigned long tstamp;
...
if (millis() - tstamp >= 50) {
  tstamp += 50;
  <your code to set PWM output>
}

That made it a lot better but it is still doing it. It doesn't appear to be as often. I have changed from 50 all the way to 350. About 150 seems to be the best but it still happens.

Throttle: 106
Throttle: 74
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 128
Throttle: 139
Throttle: 140
Throttle: 139
Throttle: 0
Throttle: 140
Throttle: 140

I was not thinking correctly, of course it doesn't use timers. It does use a pin interrupt. I think there is some timing issue with the interrupt. It's possible that the servo library depends on interrupts not being disabled, maybe the code for analogWrite turns them off momentarily...

Can you modify the program to do an additional serial debug print, every time a PWM write is performed (atm, in the millis block)?

Also can you please repost the modified test code?

That is where I currently do the print statement. Here is the code:

#include <ServoInput.h>

byte PWM =11;

// Throttle Left Setup
const int ThrottleSignalPin = 2;  // MUST be interrupt-capable!
const int ThrottlePulseMin = 900;  // microseconds (us)
const int ThrottlePulseMax = 2000;  // Ideal values for your servo can be found with the "Calibration" example
//
ServoInputPin<ThrottleSignalPin> throttle(ThrottlePulseMin, ThrottlePulseMax);
unsigned long tstamp;

void setup() {
   Serial.begin(115200);
   pinMode(PWM, OUTPUT);
   analogWrite(PWM, 0);
 }

void loop() {

if (millis() - tstamp >= 150) {
  tstamp += 150;
   int throttlePercent = throttle.map(0, 255);  // remap to a percentage both forward and reverse
      Serial.print("Throttle: ");Serial.println(throttlePercent);
      analogWrite(PWM, throttlePercent);
}
 
}

Try alternating servo sampling and PWM setting:

#include <ServoInput.h>

byte PWM = 11;

// Throttle Left Setup
const int ThrottleSignalPin = 2;  // MUST be interrupt-capable!
const int ThrottlePulseMin = 900;  // microseconds (us)
const int ThrottlePulseMax = 2000;  // Ideal values for your servo can be found with the "Calibration" example
//
ServoInputPin<ThrottleSignalPin> throttle(ThrottlePulseMin, ThrottlePulseMax);
const int cycleInterval = 50;
unsigned long tstampRead;
unsigned long tstampWrite;

void setup() {
  Serial.begin(115200);
  pinMode(PWM, OUTPUT);
  analogWrite(PWM, 0);
  tstampRead = 0;
  tstampWrite = cycleInterval / 2;
}

void loop() {
  static int throttlePercent;

  if ( millis() - tstampRead >= cycleInterval) {
    tstampRead += cycleInterval;
    throttlePercent = throttle.map(0, 255);  // remap to a percentage both forward and reverse
    Serial.print("T: "); Serial.println(throttlePercent);
  }

  if ( millis() - tstampWrite >= cycleInterval) {
    tstampWrite += cycleInterval;
    analogWrite(PWM, throttlePercent);
  }
}

(please update, I edited the code)

That seemed to make it worse.

T: 155
T: 155
T: 155
T: 155
T: 155
T: 242
T: 242
T: 242
T: 242
T: 242
T: 242
T: 242
T: 0
T: 0
T: 0
T: 0
T: 0
T: 0
T: 0
T: 0
T: 99
T: 99
T: 99
T: 0
T: 0
T: 0
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 99
T: 196
T: 196
T: 196
T: 196
T: 196
T: 196
T: 196
T: 196
T: 196
T: 196
T: 196
T: 255
T: 255
T: 255
T: 255
T: 255
T: 255
T: 255
T: 255
T: 255
T: 255
T: 25
T: 25
T: 25
T: 25
T: 25
T: 25
T: 25
T: 25
T: 25
T: 25
T: 0
T: 0
T: 255
T: 255
T: 255

Man, that is weird. I'm stumped. I guess it requires some deep dive.

I have even traded out Megas....

I am using a KBBC-24 as a motor driver and that is what I feed the PWM signal. I have noticed that I can turn it off and the signal is correct. I turn on power to the kbbc board and the problem returns. The only wires that go from the board to the kbbc board is the pwm signal wire and a ground wire.

In the back of my mind, I was wondering about power/EMI problems. We should see a complete wiring diagram. Also images of the actual hardware.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.