How to control MG90S servos

I am trying to control MG90S full rotation (360 degrees) servo. Using a PCA9685 servo driver board.

I have managed to hook it up and use the adafruit pca servo board library. But I can’t get it to stop at angle it’s keep spinning.

Thank you.

Edit:

I have these servos:
Dealikee 4 Pcs MG90S 9G Metal Geared Micro Servo Motor Kit Mini Servos for RC Robot Arm/Hand/Walking Project Car Helicopter Airplane Car Boat Control with Cable

I think we might need to see some code for this one. But, do you need the servo board? Can you test using a PWM pin from the Arduino, obviously being careful to power the motor independently (not from an Arduino pin).

Sounds like there a quite a few things that could potentially be missed out with that board as it’s a 16 channel board with I2C connectivity, so we’d need to carefully check that everything’s set up correctly.

I have made a edit to my post you can now see which servos I am using. Just so you know I don’t feel there is a mechanical stop on servo though I assume 360 servos would have one since it would allow full 360.

The code I am using is fruit adafruit servo example for the board.

/***************************************************
This is an example for our Adafruit 16-channel PWM & Servo driver
Servo test - this will drive 8 servos, one after the other on the
first 8 pins of the PCA9685
Pick one up today in the adafruit shop!
------> Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface [PCA9685] : ID 815 : $14.95 : Adafruit Industries, Unique & fun DIY electronics and kits

These drivers use I2C to communicate, 2 pins are required to
interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);

// Depending on your servo make, the pulse width min and max may vary, you
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN 150 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 600 // This is the 'maximum' pulse length count (out of 4096)
#define USMIN 600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX 2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

// our servo # counter
uint8_t servonum = 0;

void setup() {
Serial.begin(9600);
Serial.println("8 channel Servo test!");

pwm.begin();
/*

  • In theory the internal oscillator (clock) is 25MHz but it really isn't
  • that precise. You can 'calibrate' this by tweaking this number until
  • you get the PWM update frequency you're expecting!
  • The int.osc. for the PCA9685 chip is a range between about 23-27MHz and
  • is used for calculating things like writeMicroseconds()
  • Analog servos run at ~50 Hz updates, It is importaint to use an
  • oscilloscope in setting the int.osc frequency for the I2C PCA9685 chip.
    1. Attach the oscilloscope to one of the PWM signal pins and ground on
  • the I2C PCA9685 chip you are setting the value for.
    1. Adjust setOscillatorFrequency() until the PWM update frequency is the
  • expected value (50Hz for most ESCs)
  • Setting the value here is specific to each individual I2C PCA9685 chip and
  • affects the calculations for the PWM update frequency.
  • Failure to correctly set the int.osc value will cause unexpected PWM results
    */
    pwm.setOscillatorFrequency(27000000);
    pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates

delay(10);
}

// You can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. It's not precise!
void setServoPulse(uint8_t n, double pulse) {
double pulselength;

pulselength = 1000000; // 1,000,000 us per second
pulselength /= SERVO_FREQ; // Analog servos run at ~60 Hz updates
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000000; // convert input seconds to us
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}

void loop() {
// Drive each servo one at a time using setPWM()
Serial.println(servonum);
for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
pwm.setPWM(servonum, 0, pulselen);
}

delay(500);
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
pwm.setPWM(servonum, 0, pulselen);
}

delay(500);

// Drive each servo one at a time using writeMicroseconds(), it's not precise due to calculation rounding!
// The writeMicroseconds() function is used to mimic the Arduino Servo library writeMicroseconds() behavior.
for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
pwm.writeMicroseconds(servonum, microsec);
}

delay(500);
for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
pwm.writeMicroseconds(servonum, microsec);
}

delay(500);

servonum++;
if (servonum > 7) servonum = 0; // Testing the first 8 servo channels
}

What is commonly called a "360 degrees rotation servo", it is a geared motor that controls the rotation speed by servo PWM signals and doesn't have a function to stop at an some angle.

Is there a way to stop it from spinning when required and slowing it’s rotation speed

I just need it to very slowly rotated clockwise and anti clockwise when a buttons pressed down otherwise stop.

A standard rotation servo will stop at a 1500us pulse.
If you increase the value from there, the rotation speed will increase and if you decrease it will rotate in the opposite direction.

Can you help with code please, thank you

I can't do that because the code that "work with the button" you made isn't presented.
The code already posted is a exactly the same as the sample from library.

I just need the basic coding to set the pulses with as you said.

The button code is simple as 123, using int command to assign the digital pins to the buttons. Then using the if command to rotate the servo if int variable is true/false (0-1).

It’s ok if you don’t know because that’s why the programming forum section is there for where I can post. Please tell me this though so I can move on.

Ya.

Is this.

I am stuck on the functions I have simpler find the code and experimenting but I haven’t quite got it.

What does uint8_t & uint16_t mean, from my understanding and by looking at the code and library website unit8... assigns the PIN number on the board whilst unit16... I am not sure.

uint8_t as byte
uint16_t as unsigned int
First Parameter is the number of the servo you want to control.
Second parameter is the length of the pulse to be sent. (1500 for stops if rotation servo.)

I have tried for couple of hours not getting anywhere.

I have been using pwm.setPWM(servo1, 0, 2571)

Pulse length 2571 makes it go slowest but very jittery and some times not at all.

I don’t know how to reverse it either.

According to the mg90s spec sheets online a pulses between o 1-2 ms duty cycle can it get from 0 to 90 then 180 at a frequency of 50hz (20ms)

So I tried with the pwm.setPWMFreq(50) command with all ranges of numbers and still no luck, though I can start it at high speeds with less pulses not with 1-2 though or in ms option command either.

I just need help getting it to go slowly counter clockwise and slowly clockwise, the code for both actions needs to be separate so I can assign the buttons to them.

Why use setPWM?
Use writeMicroseconds for set to pulse length.

Hi,
How many servos are you trying to control?
If only one servo, you do not need the 9685 driver board.

All you can do with 360/continuous rotation servos is control their speed and rotation, not control position like a normal 0 to 180 servo.

This link should help you understand;
https://classes.engineering.wustl.edu/ese205/core/index.php?title=Servo_Motor_(Continuous_Rotation)_%2B_Arduino

google arduino continuous rotation servo

Tom... :grinning: :+1: :coffee: :australia:

Thanks Chris, finally got it done using pwm.writeMicroseconds(1500)

I hope that’s the correct function, the servo does make a high pitch sound when at values, 1360 (clockwise) and 1560(anti-clockwise).

Is that normal, I do have the pwmfreq to 50 and the setOsili...functions in set up as normal from the sample code.

Don't worry.
That can't be prevented that cheap servos singing.
If you don't want sing it, use high-grade servos but expensive.

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