Go Down

Topic: Arduino Fio - increasing output PWM resolution (Read 2 times) previous topic - next topic

MercerProject

Feb 07, 2011, 06:20 pm Last Edit: Feb 07, 2011, 08:47 pm by MercerProject Reason: 1
Hello people,

 So we're currently working on an Arduino project and need more resolution to get better control of our motors.  Currently, our motor drivers only respond to a PWM duty cycle between 20% - 60% duty cycle which only allows us to use 40% of the overall 255 resolution of the Arduino Fio's PWM output (approximately 102 levels).  This brings me to my primary question:

 Is it possible to increase the Arduino Fio's resolution output PWM resolution from 255 to something greater (perhaps 65k?) and if so how?

 Also, if there are ways to allow for the motor drivers to respond to a broader spectrum of the Fio's resolution that would work also.  We're open to all practical ideas.

 Thanks for the read!

*Edit - fixed typo.
*Edit - changed PWM range from 20% - 50% to 20% - 60% which gives 40% of the overall PWM range and 102 levels from 76 levels.

MercerProject

Our motor drivers are:
Mystery 20A ESC In-Build 2A BEC Yellow(PENTIUM-20A IN-BEC)
http://www.lightinthebox.com/Mystery-20A-ESC-In-Build-2A-BEC-Yellow-PENTIUM-20A-IN-BEC-_p115298.html

our motors are:
MYSTERY A2212-13 1000KV Outrunner Brushless Motor
http://www.goodluckbuy.com/mystery-a2212-13-1000kv-outrunner-brushless-motor-for-rc-helicopter.html

Grumpy_Mike

Quote
Currently, our motor drivers only respond to a PWM duty cycle between 20% - 50% duty cycle


What do you mean by respond?

If you mean that greater than 50% it gets no faster then remember that PWM only works on a fully loaded motor. On a lightly loaded motor it simply coasts during the unpowered part of the cycle.

Also do you mean that lower than 20% it stops, then yes it might very well do, again it depends on the load.

MercerProject

By respond I mean...

  When we programmed the motor drivers (sent PWM signal with a particular duty cycle, then hooked up the battery and waited for audio confirmation) we only heard confirmation tones for duty cycles between 20% and 60% duty cycles.

  Thus we continued testing until we found our maximum spectrum/range of duty cycles which the motor drivers would send a confirmation audio beep.  This range was experimentally determined to be 20% - 60%.  Accordingly, our 20% duty cycle was mapped to "no throttle" and 60% duty cycle was mapped to "full throttle." 

  So yes, at 20% duty cycle the motors are stopped and 50% (or perhaps 60%) duty cycle we can only imagine how much louder it will get (we've only tested up to 35% duty cycle as it gets scary loud and atm have no way to recharge our battery thus we've be restricted to limited testing).

MercerProject

We have successfully performed the power-up calibration sequence (to the best of our knowledge). 

We initialize the motor drivers for our batteries and received a confirmation tone afterwards.  After initializing our motor drivers we were able to step up the pwm one level at a time (starting at 20% duty cycle and we've tested up to 35% whereas we should be able to reach 60% as a maximum theoretically) and the motors have responded by increasing rpm (noticeable by a louder buzzing sound) at each level.

The load on the motors is a plastic propeller.  The motor itself is clamped to a table rendering it unable to move.  The propeller is:
GWS 3-Blade 9x5 Prop, Black, Reverse Rotation
http://www.rcdude.com/servlet/the-838/GWS-3-dsh-Blade--9x5/Detail

retrolefty

#5
Feb 07, 2011, 11:30 pm Last Edit: Feb 07, 2011, 11:32 pm by retrolefty Reason: 1
Perhaps if you posted your code we could see what you are doing. As stated that kind of ESC emulates a servo for input control, so the normal range of speed control is a 1 to 2 millisecond pulse, repeated at a 40-50 hz rate. What is being called the calibration sequence is often referred to as the 'arming sequence' and it tells the motor when it's safe to start and also the end points pulse timing to use for 0% and 100%. So if you do the arming sequence improperly that can limit your resolution to less then the normal 1-2millsecond pulse width length. The proper arming sequence instruction steps must come from the datasheet or information sheet from the specific ESC model/manufacture.

As already stated you probably would be much better off using the Arduino servo library to control the motor and utilize the writeMicroseconds() command to make your speed changes. This would give you 1,000 counts of resolution (1,000-2,000) control over the pulse width, assuming your ESC is armed to accept that full range of control.


http://arduino.cc/en/Reference/ServoWriteMicroseconds

Lefty

MercerProject

  We simply used the default PWM signals generated by the Arduino Fio to initialize our BEC/ESC.  We experimentally measured our frequency to be approximately 240hz with a period of 4.1ms from the Arduino Fio.  With these specs our motor drivers did not respond smoothly to the change in duty cycle (by varying 0-255) after we initialized our BEC/ESCs with the Arduino's default PWM signal.  But when we used an external RC controller coupled with a RC receiver, the ESC/BECs programmed and operated more smoothly seemingly because the RC receiver operated at approximately 50Hz.

Thus it seems that our frequency and period of our Arduino Fio's PWM signal should be adjusted to interface more smoothly with our BEC/ESC like retrolefty suggested. 

Thus, what code could be used to set the frequency and/or period of our PWM signal?  Further, if the servo library could solve our issue, could you provide a link?

Our current code doesn't initialize the period/freq of the PWM signals and simply uses analogWrite() to produce the PWM signals.  The PWM signals, pinout, and function that changes our duty cycle for our PWM signal are as follows:

int M1CurrPWMSignal = 0;    // Current PWM signal of Motor 1  (0 - 255)
int M2CurrPWMSignal = 0;    // Current PWM signal of Motor 2  (0 - 255)
int M3CurrPWMSignal = 0;    // Current PWM signal of Motor 3  (0 - 255)
int M4CurrPWMSignal = 0;    // Current PWM signal of Motor 4  (0 - 255)

int motor1PWM = 3;      // Motor 1 PWM pin
int motor2PWM = 5;      // Motor 2 PWM pin
int motor3PWM = 6;      // Motor 3 PWM pin
int motor4PWM = 9;      // Motor 4 PWM pin

...

void M1ChangePWM(int inByte) {
  switch (inByte) {
      case 43://  enter '+' to increment PWM '1' out of '255'
        M1CurrPWMSignal += 1;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 45://  enter '-' to decrement PWM '1' out of '255'
        M1CurrPWMSignal -= 1;
        analogWrite(motor1PWM,M1CurrPWMSignal-1);
      break;
      case 48:// enter '0' for 0% duty cycle
        M1CurrPWMSignal = 0.00*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 49:// enter '1' for 10% duty cycle
        M1CurrPWMSignal = 0.10*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 50:// enter '2' for 20% duty cycle
        M1CurrPWMSignal = 0.20*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 51: // enter '3' for 30% duty cycle
        M1CurrPWMSignal = 0.30*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 52: // enter '4' for 40% duty cycle
        M1CurrPWMSignal = 0.40*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 53: // enter '5' for 50% duty cycle
        M1CurrPWMSignal = 0.50*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 54: // enter '6' for 60% duty cycle
        M1CurrPWMSignal = 0.60*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 55: // enter '7' for 70% duty cycle
        M1CurrPWMSignal = 0.70*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 56: // enter '8' for 80% duty cycle
        M1CurrPWMSignal = 0.80*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      case 57: // enter '9' for 90% duty cycle
        M1CurrPWMSignal = 0.90*255;
        analogWrite(motor1PWM,M1CurrPWMSignal);
      break;
      default:
        Serial.println("M1ChangePWM().Error - incorrect input.");
  }
}

Thanks again for your help!

MercerProject

Tried using the servo library and the BEC/ESC did not respond with an audio confirmation/beep.  Any other suggestions?

Again, if there's an easy way to increase resolution for the analogWrite() or to set frequency of the analogWrite() function please point us in the right direction.

Servo servo;

int inByte = 0;         // incoming serial byte

int M1CurrPWMSignal = 0;    // Current PWM signal of Motor 1  (0 - 255)
int M2CurrPWMSignal = 0;    // Current PWM signal of Motor 2  (0 - 255)
int M3CurrPWMSignal = 0;    // Current PWM signal of Motor 3  (0 - 255)
int M4CurrPWMSignal = 0;    // Current PWM signal of Motor 4  (0 - 255)

int motor1PWM = 3;      // Motor 1 PWM pin
int motor2PWM = 5;      // Motor 2 PWM pin
int motor3PWM = 6;      // Motor 3 PWM pin
int motor4PWM = 9;      // Motor 4 PWM pin

void setup()
{
  servo.attach(motor1PWM);
  ...
}

void loop()
{   
  ...
  // check for serial data
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();

    // change PWM of motor 1 to value mapped to 'inByte' (1,2,3,4,5,6,7,8,9,+,-)
    M1ChangePWM(inByte);
  }
}

void M1ChangePWM(int inByte) {
  switch (inByte) {
      case 105://  enter 'i' to increment PWM '1' out of '255'
        M1CurrPWMSignal += 1;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 45://  enter '-' to decrement PWM '1' out of '255'
        M1CurrPWMSignal -= 1;
        //analogWrite(motor1PWM,M1CurrPWMSignal-1);
        servo.write(M1CurrPWMSignal);
      break;
      case 48:// enter '0' for 0% duty cycle
        //M1CurrPWMSignal = 0.00*255;
        M1CurrPWMSignal = 0.00*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 49:// enter '1' for 10% duty cycle
        //M1CurrPWMSignal = 0.10*255;
        M1CurrPWMSignal = 0.10*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 50:// enter '2' for 20% duty cycle
        //M1CurrPWMSignal = 0.20*255;
        M1CurrPWMSignal = 0.20*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 51: // enter '3' for 30% duty cycle
        //M1CurrPWMSignal = 0.30*255;
        M1CurrPWMSignal = 0.30*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 52: // enter '4' for 40% duty cycle
        //M1CurrPWMSignal = 0.40*255;
        M1CurrPWMSignal = 0.40*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 53: // enter '5' for 50% duty cycle
        //M1CurrPWMSignal = 0.50*255;
        M1CurrPWMSignal = 0.50*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 54: // enter '6' for 60% duty cycle
        //M1CurrPWMSignal = 0.60*255;
        M1CurrPWMSignal = 0.60*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 55: // enter '7' for 70% duty cycle
        //M1CurrPWMSignal = 0.70*255;
        M1CurrPWMSignal = 0.70*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 56: // enter '8' for 80% duty cycle
        //M1CurrPWMSignal = 0.80*255;
        M1CurrPWMSignal = 0.80*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 57: // enter '9' for 90% duty cycle
        //M1CurrPWMSignal = 0.90*255;
        M1CurrPWMSignal = 0.90*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      case 102:// enter 'f' for 100% duty cycle
        //M1CurrPWMSignal = 0.00*255;
        M1CurrPWMSignal = 1.00*180;
        //analogWrite(motor1PWM,M1CurrPWMSignal);
        servo.write(M1CurrPWMSignal);
      break;
      default:
        Serial.println("M1ChangePWM().Error - incorrect input.");
  }
  reportPWM("motor1PWM");
}

Erni

#8
Oct 31, 2011, 12:53 pm Last Edit: Oct 31, 2011, 12:54 pm by Erni Reason: 1
For an explanation of how to arm the ESC, see post #8 in this thread.

http://www.wattflyer.com/forums/showthread.php?t=11604

Quote

Throttle down for 5 seconds at *any* time arms the ESC, at which point it plays Twinkle Twinkle Little Star (!) and then throttle is motor speed.


In the same post you will find the manual for the ESC.


Go Up