Pages: [1]   Go Down
Author Topic: Creating your own PWM to control a servo.  (Read 2277 times)
0 Members and 1 Guest are viewing this topic.
Westbrook, CT
Offline Offline
Full Member
***
Karma: 2
Posts: 139
"Why should I bother with made-up games when there are so many real ones going on." (c) Kurt Vonnegut
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Huy guys, I just got a package from Hobby King with servo's and they are HEXTRONIC HXT500 5gr minis'.

Iv'e tested them out with the Servo Library and they worked Perfetto! However i bought such little ones (they almost fit on your thumb!) for a special purpose. I want to make a light weight and little insect robot. If i want to build it and make it light then I have no option but remove the Arduino Uno from the project and use it only for prototyping. Instead, the robot's brain will be a Attiny 85.

The Attiny has a problem however, it doesn't support the Servo library for the Arduino. I know that there are Servo libraries for little Attinie's but I prefer to do the code by myself.

I wrote a code to control my servo by pulsing a pulse of between 1ms and 2ms and then a stop period of 19- 18ms (20 - 1 = 19 ms; 20 - 2 = 18 ms). The standard stop period is 20ms, which is 50HZ exactly suitable for the servo's. But the servo just sits still when i upload my sketch to my Arduino Uno. smiley-sad

I have no idea how to alter the PWM signal from 500HZ (default) to 50HZ, so instead i decided to do it with the help of digitalWrite() and delay() functions.  

Please suggest me how to create a suitable PWM signal for controlling a servo.

Here is the code:
Code:
int servo = 14;
 
void setup() {
  
  pinMode(servo, OUTPUT); //OUTPUT setup
  
  for ( int i = 0; i > 5; i++){ // Set the possition to 90 degrees
   digitalWrite(servo, HIGH);
    delayMicroseconds(1500);
    digitalWrite(servo, LOW);
  }
  delay(2000);
}
 
 
void loop() {
  for ( int i = 0; i > 50; i++){
    digitalWrite(servo, HIGH);
    delayMicroseconds(1000); // Set the possition to 0 degrees
    digitalWrite(servo, LOW);
    delay(19);
  }
  for ( int i = 0; i > 50; i++){
    digitalWrite(servo, HIGH);
    delayMicroseconds(2000); //Set the possition to 180 degrees
    digitalWrite(servo, LOW);
    delay(18);
  }
}

  

Thank you guys.


* Untitled-165.jpg (20.91 KB, 392x203 - viewed 63 times.)

* Untitled-159.jpg (9.02 KB, 345x70 - viewed 35 times.)
« Last Edit: November 16, 2012, 10:47:27 am by mixania » Logged

Arduino Uno R3
Mac OSX Lion


Offline Offline
Full Member
***
Karma: 2
Posts: 200
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

  ? int servo = 14;

Have not looked at the pin def's for the tiny85 which is a 8 pin device but pin 14 sounds wrong.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 202
Posts: 8711
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think he 50Hz rate is a requirement, particularly not a lower limit.  I'd try just sending a pulse to each servo each time through loop().  If your servos don't like that you could use the BlinkWithoutDelay example to send pulses only every 20 ms.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
 for ( int i = 0; i > 5; i++){ // Set the possition to 90 degrees
   digitalWrite(servo, HIGH);
    delayMicroseconds(1500);
    digitalWrite(servo, LOW);
  }
this loop has no delay after digitalWrite(servo, LOW); so it is effectively a high for 7.5 ms ?

Are you familiar with the blink without delay sketch?
It is a way to do timing more precise and it removes the blocking delays.
You need several extra variables to hold state.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
  If you decide to follow this approach, for each servo that you add, you will use up 10% of your processing power, it  also means that you will not be able to respond to inputs while your timing code is running. For a small robot that moves slowly and has few sensors to respond to, it should be fine, but its worth mentioning these limitations.

Duane B

rcarduino.blogspot.com
Logged


Denmark
Offline Offline
Edison Member
*
Karma: 35
Posts: 1057
Happy Hobbyist
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There is this servo library made specific for the Attiny 45/85

http://www.cunningturtle.com/servo8bit-library-version-0-6-released/
Logged

Westbrook, CT
Offline Offline
Full Member
***
Karma: 2
Posts: 139
"Why should I bother with made-up games when there are so many real ones going on." (c) Kurt Vonnegut
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for your responses guys! there were many helpful ones! smiley)
Logged

Arduino Uno R3
Mac OSX Lion


Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I succeded to control a servo on an attiny 84 and attiny 85  with the following code

//Tested on attiny 84 with servo towerpro microservo 90 SG90
// 08/jan/2014   servo data on www.servodatabase.com
int servoPin = 6;   // servo connected to digital pin 6
      
void setup()    
{   
         pinMode(servoPin, OUTPUT);   // sets the servoPin to be an output
}    
      
void loop()    // run over and over again
{    
       servowrite(servoPin, 0, 500, 2400); 
       servowrite(servoPin, 90, 500, 2400); 
       servowrite(servoPin, 180, 500, 2400); 
       // servotest();
}     
 
void servowrite(int pin, int angle, int microzero, int micro180)
{
  // pin for servo, angle to move, microseconds for zero degrees, microseconds for 180 degrees
  int microvalue= map(angle, 0, 180, microzero, micro180); //map angle to microseconds
  int i;
  for (i = 0; i < 50; i++)   //Send 50 pwm pulses with width microvalue uS
      {
        analogWrite(servoPin,255);              //Pulse high for microvalue uS     
        delayMicroseconds(microvalue);
        analogWrite(servoPin,0);                //Pulse low for 15mS
        delay(15);
       }
   delay(10);            //Pause
}

void servotest()
// test servo
{
   int i;

    for (i = 0; i < 50; i++)   //Send 50 pulses with width 500 uS
      {
        analogWrite(servoPin,255);                //Pulse high for 500uS     
        delayMicroseconds(500);
        analogWrite(servoPin,0);                //Pulse low for 15mS
        delay(15);
       }
      delay(100);            //Pause for 100mS
     
    for (i = 0; i < 50; i++)   //Send 50 pulses with width 1.25mS
     {
        analogWrite(servoPin,255);
        //Pulse high for 1.4 mS
        delayMicroseconds(1400); 
        analogWrite(servoPin,0);
        delay(15);
      }
      delay(100);

     for (i = 0; i < 50; i++) //Send 50 pulses with width 2.4ms
     {
        analogWrite(servoPin,255);
        delayMicroseconds(2400); 
        analogWrite(servoPin,0);
        delay(15);
      }
      delay(100);
   
                 
 }
Logged

Pages: [1]   Go Up
Jump to: