Digital and analog servo reacting differently with arduino - arduino

I have some code controling an old analoge servo and all is working fine.
But when I got a new digital servo, it will not hold position, but return to 0.
Please help, what is needed?
Here is the basic code basen on Sweep:
#include <Servo.h>
Servo myservo;
int pos = 0;
void setup()
{
myservo.attach(A1);
}
void loop()
{
for(pos = 0; pos <= 180; pos++) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}

Right after your for loop put:
while(1);
Before the closing bracket of the loop()
This will stop the program at that point and not keep running your for loop which declares pos = 0 each time.

I see that this question was a bit unpresice.
But I found out that there are one other way of controling a servo, and that is by using writeMicroseconds instead of myservo.write(90).
myservo.writeMicroseconds(1500); //
http://arduino.cc/en/Reference/ServoWriteMicroseconds

Related

My Servo is Not Moving, Only When Trying Write 180 degrees

My servo only starts to "change" (that is what the code tells me anyway) when it is set for 180 degrees.
I've tried searching the website as well as Google, but this seems to be something that has to do very specifically with writing to Servo in an advanced non-repeatable kind of way.
The code that changes the servo is:
#include <SoftwareSerial.h>
#include <Servo.h>
const int rxPin = 12;
const int txPin = 13;
SoftwareSerial bluetooth (rxPin, txPin);
Servo myServo;
boolean canMove = true;
int rotation = 0;
int currentRotation = 0;
void setup() {
Serial.begin(9600); // Begins Serial communication
bluetooth.begin(9600);
myServo.attach(11); // Sets a servo on pin 11
}
void loop() {
// put your main code here, to run repeatedly:
// Checks if Serial has something to read
if (bluetooth.available() > 0) {
rotation = bluetooth.read(); // Reads it and sets it to an integer
}
currentRotation = myServo.read();
if (currentRotation != rotation) {
Serial.println("Current Rotation:");
Serial.println(currentRotation);
Serial.println("Set to:");
Serial.println(rotation);
for (int i = currentRotation; i < rotation; i++) {
Serial.println("Writing to servo");
myServo.write(i);
}
}
}
There is a Processing program that sends the data to the Arduino, but I can perfectly see that the numbers are coming in in the Arduino's Serial Monitor (they vary from 0 to 180)
After doing this the only thing that shows up in the Serial Monitor is:
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
over and over. The servo just twitches back and forth. The only time it changes (the number to set to comes from the Processing program) is when the number it is set to be 180. Then it moves even more back and forth and says:
Current Rotation:
179
Set to:
180
Writing to servo
Current Rotation:
179
Set to:
180
Writing to servo
over and over. What is going on and how can I fix it? Cheers, and thanks for the help!
There are some problems with your code:
You don't need to read current servo value, just save the last gave value.
Moving a servo step by step is not a good option as it may have some error for movement. You need to find a dynamic delay based on a threshold of movement. For example, suppose that your max delay time for the servo to fully move from 0 to 180 is 2 seconds, so if you need to move the servo for 90 degrees you need 1 second delay.
You just need to move your servo when a new data came so set servo when new data comes.
Remember to set max_delay based on your servo.
#include <SoftwareSerial.h>
#include <Servo.h>
const int rxPin = 12;
const int txPin = 13;
SoftwareSerial bluetooth(rxPin, txPin);
Servo myServo;
boolean canMove = true;
int rotation = 0;
int currentRotation = 0;
// how much time takes servo to move
int move_delay = 0;
// maximum time for changing servo state from lowest to highest value
const int max_delay = 2;
void setup()
{
Serial.begin(9600); // Begins Serial communication
bluetooth.begin(9600);
myServo.attach(11); // Sets a servo on pin 11
}
void loop()
{
// put your main code here, to run repeatedly:
// Checks if Serial has something to read
if (bluetooth.available() > 0)
{
rotation = bluetooth.read(); // Reads it and sets it to an integer
Serial.print("New value: ");
Serial.println(rotation);
Serial.print("Current Rotation: ");
Serial.println(rotation);
if (currentRotation != rotation)
{
Serial.println("Setting new value");
// find a proper delay
move_delay = (max_delay / 180) * (abs(rotation - currentRotation)) * 1000;
myServo.write(rotation);
delay(move_delay);
currentRotation = rotation;
}
}
}

I can not forward servo by using keyboard input

I am using Arduino UNO and I have 5 MG995 servo motors. But when i test the machine using 1 servo motor, it does not work.
My connections are not wrong. Ports are okay but i don't know why it doesn't work.
My code for one servo motor.
#include<Servo.h> // include server library
Servo ser; // create servo object to control a servo
int poser = 0; // initial position of server
int val; // initial value of input
void setup() {
Serial.begin(9600); // Serial comm begin at 9600bps
ser.attach(9);// server is connected at pin 9
}
void loop() {
if (Serial.available()) { // if serial value is available
val = Serial.read();// then read the serial value
if (val == 'd') { //if value input is equals to d
poser += 1; //than position of servo motor increases by 1 ( anticlockwise)
ser.write(poser);// the servo will move according to position
delay(15);//delay for the servo to get to the position
}
if (val == 'a') { //if value input is equals to a
poser -= 1; //than position of servo motor decreases by 1 (clockwise)
ser.write(poser);// the servo will move according to position
delay(15);//delay for the servo to get to the position
}
}
}
There isn't anything very obvious wrong with the code, as long as you press d more than a so poser stays in range.
to test your hardware, run one of the examples such as sweep.
you should put in limits for poser so it stays between 0 and 180
try also lighting a led when 'a' or 'd' is received so you know that is working

How to program ESC to increase/decrease PWM in increments

I've coded with Python before however, I am in the process of learning C and from what I have been told Arduino is quite similar to C in some aspects (at least with coding). I noticed that my when I run the code on my robot it jolts due to the quick changes in PWM. So I'd like some guidance as to how to do an if statement on Arduino because I am trying to increase/decrease the PWM in increments.
//On Roboclaw set switch 1 and 6 on. // <-- what does this refer to?
//mode 2 option 4 // <-- my note based on user manual pg 26
#include <Servo.h>
Servo myservo1; // create servo object to control a Roboclaw channel
Servo myservo2; // create servo object to control a Roboclaw channel
//int pos = 0; // variable to store the servo position //<-- left-over from arduino ide servo sweep example?
void setup()
{
myservo1.attach(9); // attaches the RC signal on pin 5 to the servo object (Left Motor)
myservo2.attach(11); // attaches the RC signal on pin 6 to the servo object (Right Motor)
}
void loop()
{
//forward
myservo1.writeMicroseconds(1000);
myservo2.writeMicroseconds(1000);
delay(2000);
//backward
myservo1.writeMicroseconds(2000);
myservo2.writeMicroseconds(2000);
delay(2000);
//left
myservo1.writeMicroseconds(1500);
myservo2.writeMicroseconds(1000);
delay(2000);
//right
myservo1.writeMicroseconds(1000);
myservo2.writeMicroseconds(1500);
delay(2000);
}
Ok, whenever you write a different value to the servo it will move to that position as fast as possible. So you will need to move your servo step by step.
For this task, however, you will not be able to use delays, since they block the processor. You will need to mimic the "blink with no delay" example (i.e. using the millis() function to do something when time passes by.
The acceleration control simply moves 1° every X milliseconds (in this case 6ms, which makes a full movement - 180° - last for about one second). Every X milliseconds, so, the uC moves 1° in the direction of a target position. In the other code you should just set the target to your desired position and you are done.
Here is the code I wrote. Let me know if it works for you
#include <Servo.h>
Servo myservo1;
Servo myservo2;
unsigned long prevMillisAccel = 0, prevMillisAction = 0;
uint8_t servo1_target;
uint8_t servo2_target;
uint8_t currAction;
#define TIME_FOR_ONE_DEGREE_MS 6
void setup()
{
myservo1.attach(9)
myservo2.attach(11);
prevMillisAccel = millis();
prevMillisAction = millis();
servo1_target = 0;
servo2_target = 0;
myservo1.write(0);
myservo2.write(0);
currAction = 0;
}
void moveServoTowardsTarget(Servo *servo, uint8_t target)
{
uint8_t pos = servo->read();
if (pos > target)
servo->write(pos-1);
else if (pos < target)
servo->write(pos+1);
}
void loop()
{
unsigned long currMillis = millis();
if (currMillis - prevMillisAccel >= TIME_FOR_ONE_DEGREE_MS)
{
prevMillisAccel += TIME_FOR_ONE_DEGREE_MS;
moveServoTowardsTarget(&myservo1, servo1_target);
moveServoTowardsTarget(&myservo2, servo2_target);
}
if (currMillis - prevMillisAction >= 2000)
{
prevMillisAction += 2000;
currAction = (currAction + 1) % 4;
switch(currAction)
{
case 0: // forward
servo1_target = 0;
servo2_target = 0;
break;
case 1: // backward
servo1_target = 180;
servo2_target = 180;
break;
case 2: // left
servo1_target = 90;
servo2_target = 0;
break;
case 3: // right
servo1_target = 0;
servo2_target = 90;
break;
}
}
}
PS. I used the write function instead of the writeMicroseconds because you can read the value you wrote. If you really need to use writeMicroseconds (which is pretty useless in my opinion, since servo precision is less than 1°, so write is more than sufficient) just store the target as a uint16_t and store also the last set value (and use that instead of the read function)

Arduino - combine sketches

New to programming and Arduino..
I'm currently making a project for my son's Gold Rush diorama with added electronics. From my understanding, it does not like reading delay() codes.
Please, any suggestions are appreciated. Thank you.
I'm trying to combine two sketches;
One that has random fluctuating LEDS (acts as the lanterns in the mine shafts)
The other, a servo that pulls a string up and down (acts as an elevator pulley)
Each sketch alone works properly. I'm not sure the proper way to combine the two without using "delay()"
Leds sketch below;
/*random fluctuating leds*/
void setup() {
// put your setup code here, to run once:
pinMode(12,LOW);
pinMode(11,LOW);
pinMode(10,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
analogWrite(12, random(120)+135);
analogWrite(11, random(120)+135);
analogWrite(10, random(120)+135);
delay(random(100));
}
Servo Sweep Sketch below;
/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.
modified 8 Nov 2013
by Scott Fitzgerald
http://arduino.cc/en/Tutorial/Sweep
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
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 = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
In general you can replace delay(1000) with the following code:
unsigned long interval=1000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.
void setup() {
//...
}
void loop() {
if ((unsigned long)(millis() - previousMillis) >= interval) {
previousMillis = millis();
// ...
}
}
So you need something like the following code, that I have not tested, but hopefully gives you a starting point:
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
int pos_direction=0; // motor direction
unsigned long interval=1000; // the time we need to wait (analogwrite)
unsigned long previousMillis=0; // millis() returns an unsigned long.
unsigned long interval1=15; // the time we need to wait (servo)
unsigned long previousMillis1=0; // millis() returns an unsigned long.
void setup() {
interval = random(100);
pinMode(12,LOW);
pinMode(11,LOW);
pinMode(10,LOW);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
if ((unsigned long)(millis() - previousMillis) >= interval) {
previousMillis = millis();
analogWrite(12, random(120)+135);
analogWrite(11, random(120)+135);
analogWrite(10, random(120)+135);
interval = random(100);
}
if ((unsigned long)(millis() - previousMillis1) >= interval1) {
previousMillis1 = millis();
if(pos_direction==0){
if(pos==180) pos_direction=1;
else pos++;
}
else if(pos_direction==1){
if(pos==0) pos_direction=0;
else pos--;
}
myservo.write(pos);
// ...
}
}

Ardiuno : Servo Connected to a Button

I am new to Arduino and trying to just create a simple application so a servo goes forward 50 degrees when a button is pushed(not continuous) and when let go of it will go back 50 degrees. For some reason my servo just keeps running. What should I do to debug this.
#include <Servo.h>
Servo myservo; // creating myservo object
int buttonPin = 2;
int servoPin = 3;
int buttonState = 0; // set buttonState
void setup()
{
myservo.attach(servoPin);
pinMode(buttonPin, INPUT);
}
void loop()
{ buttonState = digitalRead(buttonPin); // read and save to the variable "buttonState" the actual state of button
if (buttonState == HIGH)
myservo.write(50); else
myservo.write(0);
}
You should use the Bounce library library to catch the edge's you are looking for. Your script as written is continuously updating the PWM with 50 or 0. It is never getting a chance to actually do it. Hence you only want to update it on a change; either depress or release.
I have not tested the below. It does compile and is a simple hack from the examples and your above.
#include <Servo.h>
#include <Bounce.h>
#define BUTTON 2
#define servoPin 3
#define LED 13
Servo myservo; // create servo object to control a servo
Bounce bouncer = Bounce( BUTTON, 5 );
void setup() {
pinMode(BUTTON,INPUT);
pinMode(LED,OUTPUT);
digitalWrite(LED, HIGH);
myservo.attach(servoPin);
}
void loop() {
if ( bouncer.update() ) {
if ( bouncer.fallingEdge()) {
myservo.write(50);
digitalWrite(LED, LOW);
} else if ( bouncer.risingEdge()) {
myservo.write(0);
digitalWrite(LED, HIGH);
}
}
// foo bar...
}
I am going to take a wild guess that you have a continuous rotation servo. These servos have the position feedback from the potentiometer removed/disconnected so when you apply any rotation to the servo it will continuously spin thinking that it is not yet at the desired position. These servos have three control positions: off (likely 90 degrees) clockwise (anything larger than 90) and counterclockwise (anything less than 90). Some do allow you to control speed as well (I think the VEX one you cite having may be one - look up the spec sheet).
I might have my no movement value wrong (it may not be 90) and my counter/clockwise reversed, but I am almost certain this is your issue. Basically your motor is not what you think it is :)
myServo.writeMicroseconds(1500);
This will make it stop if its not broken and its a continuous digital servo.

Resources