Why does this program drop my digital pin out voltage?

Hey all,

When I run the code that I posted below (originally obtained from Shane Colton: Arduino Interrupt-Driven Servo Routine), my digital pin 6 output voltage drops to near 500 millivolts. However, when I run a simple program that simply sets the pin to high, it is at its normal five volts. This indicates to me that something in this program is creating this large drop in voltage.

It should be noted that I do not have anything connected in my circuit, only the arduino and some wires to connect to my oscilloscope/multimeter.

I tried this with multiple digital pins and it all had the same effect.

Also, this code is being used to run a brushless servo motor through an ESC if that helps. We verified the signal with an oscilloscope (pictures below). I also have an image below of my multimeter setup to prove that the voltage is so low. The voltage can be verified as ~500mV in these images as well.

I took these images to show that the time in between each signal is ~16ms, and the time each signal takes up is ~2ms. I read this is approximately what a brushless servo motor needs. The motor does not work with this code, and I am convinced it is because of this low voltage. I read these motors need anywhere between 3.3V and 6V to operate properly, in addition to the correct step function signal as pictured below.
http://postimg.org/image/l6f42dxgv/
http://postimg.org/image/ca6tx5cef/
http://postimg.org/image/nb1z264nb/

unsigned int servopwm[10];
unsigned char servoindex;

unsigned int val = 375;

ISR(TIMER1_COMPA_vect)  
{
  // interrupt on Timer1 compare match
  // (end of the servo pulse)
  
  // end servo pulse on the appropriate pin
  // faster version of digitalWrite(servoindex, LOW);
  if(servoindex <= 7)
  {
    PORTD &= ~(1 << servoindex);
  }
  else
  {
    PORTB &= ~(1 << (servoindex - 8));
  }
  
  // move on to the next servo (limit to 2-8)
  servoindex++;
  if(servoindex == 10) 
  { 
    servoindex = 2; 
  }
  
  // set the compare match to the new servo pulse duration
  OCR1AH = servopwm[servoindex] >> 8;
  OCR1AL = servopwm[servoindex] & 0xFF;

  return;
}

ISR(TIMER1_OVF_vect)
{
  // interrupt on Timer1 overflow
  // start of the next servo pulse
  
  // start servo pulse on the appropriate pin
  // faster version of digitalWrite(servoindex, HIGH);
  if(servoindex <= 7)
  {
    PORTD |= (1 << servoindex);
  }
  else
  {
    PORTB |= (1 << (servoindex - 8));
  }
      
  return;
}

void setup()
{
  // TIMER1 SETUP FOR SERVOS
  // -----------------------
  // set Timer1 to clk/64 and 9-bit fast PWM
  // this is a period of 2.048ms for 16MHz clk
  // when multiplexed on 8 servos, this gives a 16ms period
  TCCR1A = 0x02; 
  TCCR1B = 0x0B;
  // enable Timer1 compare match and overflow interrupts
  TIMSK1 = 0x03;
  // -----------------------
  
  // set initial servo index  
  servoindex = 2;
  
  // set all servos to neutral (375 = 1.500ms)
  // set all servo pins to outputs
  for(int i = 2; i <= 10; i++)
  {
    servopwm[i] = val;
    pinMode(i, OUTPUT);
  }
}

void loop()
{ 
  // Your loop code here.
  // No need to worry about delays being longer than 20ms!
  
  // Set PWM values like this:
  //  |-----------|-----------|
  // 250         375         500
  // 1ms        1.5ms        2ms
  servopwm[2] = 250;
  servopwm[3] = 275;
  servopwm[4] = 300;
  servopwm[5] = 325;
  servopwm[6] = 350;
  servopwm[7] = 375;
  servopwm[8] = 400;
  delay(20);
}

I also noticed that as I change this value in my code:

  servopwm[6] = 350;

My voltage changes. It can be anywhere between 400 and 700 mV depending on what value I set this to. This value can be set anywhere between 250 and 500.

you can't measure DC voltage on a PWM signal and expect to see the maximum voltage. To me a reading of 700mv sounds about right given the pulse length. I think you might have a connection problem to your ESC. How are you powering your ESC? if your ESC has got more than 5 volts as a supply, then a 5 volt pulse might not be enough to trigger it. I think you might need a transistor or optocoupler between your arduino and ESC so that you can use the ESC's power to pulse it's input with a signal from the Arduino.

Have you got a standard servo that you can try as an alternative to the ESC?

Does your code go through the proper arming sequence for your ESC - most of them require one to prevent propellers chopping off fingers?

Why not just use the normal servo library?

...R

TRex:
you can’t measure DC voltage on a PWM signal and expect to see the maximum voltage. To me a reading of 700mv sounds about right given the pulse length. I think you might have a connection problem to your ESC. How are you powering your ESC? if your ESC has got more than 5 volts as a supply, then a 5 volt pulse might not be enough to trigger it. I think you might need a transistor or optocoupler between your arduino and ESC so that you can use the ESC’s power to pulse it’s input with a signal from the Arduino.

Yes now I realize that measuring that signal with a multimeter simply gives me the “average” voltage of the signal.

However, using the oscilloscope, the peak voltage of the signal is ~600mV to ~700mV. In my oscillocope picture, you can see that the peak voltage is ~500mV. I need that peak voltage to be around 5V, as shown in this guys picture:

Image taken from http://www.oscium.com/blog/oscilloscope-measures-pwm-voltage-pt-2

I have already confirmed that for this ESC and brushless motor to work, the voltage over that signal line needs to be around 5V. 500mV isn’t going to cut it.

Robin2: Have you got a standard servo that you can try as an alternative to the ESC?

Does your code go through the proper arming sequence for your ESC - most of them require one to prevent propellers chopping off fingers?

Why not just use the normal servo library?

...R

That is the issue, we are trying to do the arming sequence. However, the series of beeping noises we gets, according to the instruction manual, indicates the signal is not what it should be. I am convinced this is because the peak voltage of the signal (as can be seen from my oscilloscope picture in the original post) is only around 500mV. I have confirmed that that signal peak voltage needs to be around 5V.

Very confusing...

Maybe I'm blind in one eye and can't see out the other, but the scope traces look like "4.8V" to me.

Maybe you're using a 10:1 scope probe.

kingneptune117:
Very confusing…

That’s why I suggest trying a standard servo. They don’t need an arming sequence. It would be very surprising if the code works with a standard servo and not with your ESC.

There have been many other Threads in which people successfully controlled ESCs with the usual servo.write() commands.

…R

AWOL: Maybe you're using a 10:1 scope probe.

Thank you! This was the issue. I had never even heard of a 10:1 scope probe. I got a 1:1 probe and it was a perfect signal! We increased the frequency to 50Hz and the motors worked! We got the arming sequence down and were able to control them just fine.

Thanks for the help everyone.