As I would like to test my servo's movement on forehand.
As I am using the writeMicroseconds from the servo library, I was looking for a sweep sketch using that. But no sucess finding anything I decided to adapt the origional sketch found in the example section. Keeping in mind that 0 degree is 100 mS and 180 degree is 200 mS. code below
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 0; // variable to store the servo position
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
for (pos = 1000; pos <= 2000; pos += 10) { // goes from 0 degrees to 180 degrees
myservo.writeMicroseconds(pos);
delay(25); // waits 25ms for the servo to reach the position
}
delay(1000);
for (pos = 2000; pos >= 1000; pos -= 10) { // goes from 180 degrees to 0 degrees
myservo.writeMicroseconds(pos);
delay(25); // waits 25ms for the servo to reach the position
}
delay(1000);
}
In basic this sketch should do the same as the origional sketch but it doesnt.
testing my servo's with the basic sweep the move perfect from 0-90-180 degree
But my changed sketch moves from som angle to 90 and some other angel.
So what could be wrong with my sketch??
Used servo's are DS3218mg, SG900s ,g90, and RDS3120mg, all showing the same behaivior.
You did mean to say 0 is 1000 uS and 180 is 2000 uS? That’s what you’ve written in code, where it matters…
The servo example works for you? Then your change to it should work, yes.
the servo attach can take two more parameters, min_pikse_width and max_pukse_width, try calling it with plausible values or experiment with the values, viz:
Writes a value in microseconds (uS) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle.
Note that some manufactures do not follow this standard very closely so that servos often respond to values between 700 and 2300. Feel free to increase these endpoints until the servo no longer continues to increase its range. Note however that attempting to drive a servo past its endpoints (often indicated by a growling sound) is a high-current state, and should be avoided.
#include <ESP32Servo.h>
// create four servo objects
Servo servo1;
Servo servo2;
Servo servo3;
// Servo servo4;
// Published values for SG90 servos; adjust if needed
#define MINservo 1400
#define MAXservo 1600
#define ServoIncrement 11
#define SerialDataBits 115200
#define iX_90z 1475 // 1400 is to the right
#define iX_90y 1435 // 1400 tilts forward
#define iX_90x 1500
// These are all GPIO pins on the ESP32
// Recommended pins include 2,4,12-19,21-23,25-27,32-33
int servo1Pin = 4;
int servo2Pin = 32;
int servo3Pin = 33;
// int servo4Pin = 23;
int pos = 500; // position in microseconds
void setup()
{
Serial.begin( SerialDataBits );
servo1.setPeriodHertz(50); // Standard 50hz servo
servo2.setPeriodHertz(50); // Standard 50hz servo
servo3.setPeriodHertz(50); // Standard 50hz servo
// servo4.setPeriodHertz(50); // Standard 50hz servo
servo1.attach(servo1Pin);
servo2.attach(servo2Pin, MINservo, MAXservo);
servo3.attach(servo3Pin, MINservo, MAXservo);
// servo4.attach(servo4Pin, MINservo, MAXservo);
servo1.writeMicroseconds( iX_90z );
delay(20);
servo2.writeMicroseconds( iX_90y );
delay(20);
servo3.writeMicroseconds( iX_90x );
delay(20);
}
void loop()
{
for (pos = MINservo; pos <= MAXservo; pos += ServoIncrement) { // sweep from A degrees to Z degrees
Serial.print ( "+" );
Serial.println ( pos );
servo1.writeMicroseconds ( pos ); // z servo
delay(10); // waits Xms for the servo to reach the position
servo2.writeMicroseconds ( pos );
delay(10); // waits Xms for the servo to reach the position
servo3.writeMicroseconds ( pos );
delay(10); // waits 20ms for the servo to reach the position
}
for (pos = MAXservo; pos >= MINservo; pos -= ServoIncrement) { // sweep from A degrees to Z degrees
Serial.print ( "-" );
Serial.println ( pos );
servo1.writeMicroseconds ( pos );
delay(10); // waits Xms for the servo to reach the position
servo2.writeMicroseconds ( pos );
delay(10);
servo3.writeMicroseconds ( pos );
delay(10); // waits Xms for the servo to reach the position
}
}
A servo sweep using us written for an ESP32 adapted from Uno code. I'm sure it can be adapted back to Uno code.
How about a POT and a servo with the serial monitor showing the resulting pulse width?
I'm not positive this'll work. I don't have a POT here to test it with. But I put in some values and the servo runs. It would be good to see what the servo likes as end points..
#include <blinker.h>
#include <mapper.h>
#define SERVO_PIN 4
#define SERVO_MAX_MS 2.0
#define SERVO_MIN_MS 1.0
blinker servoSignal(SERVO_PIN,1.5,19.0); // Set up servo at 1.5 ms every 19 ms. Little less than 20 ms.
mapper pwMapper(0,1023,SERVO_MIN_MS/2.0,SERVO_MAX_MS*2.0); // We'll map 1/2 * Servo min to 2 * Servo max. Just to see how it works.
int gPOTVal; // A global to save our last POT reading.
void setup() {
Serial.begin(9600); // Fire up serial.
gPOTVal = -1; // Impossible value as flag.
setServo(); // Set up siganl to match the POT.
servoSignal.setOnOff(true); // Fire up servo signal.
}
void setServo(void) {
float pulseWidth;
int localPOTVal;
localPOTVal = analogRead(A0); // Read the POT.
if ( localPOTVal != gPOTVal) { // If the POT value has changed since last time..
gPOTVal = localPOTVal; // Update the global POT value.
pulseWidth = pwMapper.map(gPOTVal); // Map the POT value to the desired pulse width.
servoSignal.setPulse(pulseWidth); // Update the pulse width.
Serial.print("PW : "); // Lets show the user what we did.
Serial.println(pulseWidth); //
}
}
void loop(void) {
idle(); // Run background stuff, like the squarewave.
setServo(); // Do the read POT set servo thing.
}
If you're interested in trying this. You'll need LC_baseTools from the library manager installed to compile it.
@IDwalker you have 11 uS steps and it take ~180 of them for your loops, but
where did 1400 and 1600 come from? ‘A’ data sheet I found for the SG90 just shows the more or less standard 50 Hz signal with pulse width ranging from 1000 uS to 2000 uS.
In any case, some experiments should help. An oscilloscope might help more, but.
alto777: @jimLee no pot, huh? I got pot, no servo...
a7
Haha no. I'm sitting at the kitchen table. I did have a servo in my briefcase (lunchbox). But no POT. I do have a button though. Couple handhelds, mp3 player and the home made cellphone. A few Teensy 3.2s..
The default values for the Servo library when not specified in the attach() are 544us = 0 and 2400us = 180 (defined in Servo.h). Try those in place of 1000 - 2000 and it should move to the same positions as the original Sweep.
Normally, 0 degrees = 544 micros, 90 = 1472, 180 = 2400, but play with this tester:
/*
Try this test sketch with the Servo library to see how your
servo responds to different settings, type a position
(0 to 180) or if you type a number greater than 180 it will be
interpreted as microseconds(544 to 2400), in the top of serial
monitor and hit [ENTER], start at 90 (or 1472) and work your
way toward zero (544) 5 degrees (or 50 micros) at a time, then
toward 180 (2400).
*/
#include <Servo.h>
Servo servo;
void setup() {
// initialize serial:
Serial.begin(9600); //set serial monitor baud rate to match
servo.write(90);
servo.attach(9);
prntIt();
}
void loop() {
// if there's any serial available, read it:
while (Serial.available() > 0) {
// look for the next valid integer in the incoming serial stream:
int pos = Serial.parseInt();
pos = constrain(pos, 0, 2400);
servo.write(pos);
prntIt();
}
}
void prntIt()
{
Serial.print(" degrees = ");
Serial.print(servo.read());
Serial.print("\t");
Serial.print("microseconds = ");
Serial.println(servo.readMicroseconds());
}
JCA34F:
OK I uploaded the sketch and i have the same results 544mS=0degree and 2400 mS=180degree.
Maybe I have missed somthing but in my other sketch I am working on, where a X/Y position is received in degree such as 135.8 or 22.4 . at the moment I am using this code to convert to mS
unsigned int degree2ms(float degrees) {
return 1000 + degrees * 150 / 27;
}
an * subsitute the 111111000+degrees ... with 544+degrees..... ??*
If you want the range 544 to 2400 to represent 0 to 180 degrees, multiply degrees by ((2400-544) /180.0) and add 544.
return 544 + degrees * ((2400-544) /180.0);
Don't worry about pre-calculating anything, like putting in 1856 in place of (2400-544) because the compiler will do all the constant math at compile time and multiply 'degrees' by the constant '10.31111'.