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;
}
}
}
Related
The goal of our project is to follow a person with a emitter IR, we have also one receiver and 2 motor servo. The first one is use to save the angle of the person and the second to follow the person.
It is necessary to know that we have an other program for the emitter.
However, the save of the angle is still false and our second motor servo does not work.
We want the 2nd motor to go to the last angle saved when our receiver has results.
#include <Servo.h>
#include <IRLibRecvPCI.h>
IRrecvPCI myReceiver(2);//pin number for the receiver
Servo monServo;
Servo monServo1;
void setup() {
Serial.begin(9600);
delay(2000); while (!Serial);
myReceiver.enableIRIn(); // Start the receiver
Serial.println(F("Ready to receive IR signals"));
monServo.attach(9);
monServo1.attach(7);// relier le servomoteur au port 9
monServo.write(0); // positionner le servomoteur à l'angle absolu 0°
}
int angle = 0;
int increment = 1;
void loop() {
monServo.write(angle);
angle = angle + increment;
if (angle == 0); increment = 1;
if (angle == 180); increment = -1;
if (myReceiver.getResults()) {
monServo1.write(angle);
Serial.print("detection");
myReceiver.enableIRIn();
Serial.println(monServo.read());
;
}
}
if (angle == 0); increment = 1;
if (angle == 180); increment = -1;
Is equivalent to increment = -1;
You have two empty if statements here. Remove the first semicolon in each line if you want to change the increment value conditionally.
You should also add some delay as your servo won't be able to move 1° in a few milliseconds.
There is also one superfluous semicolon at the end of your code
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)
I am building a laser that is to be controlled by a joystick. The joystick uses 2 servo motors to move the laser in the direction I want. I am using an arduino board that uses C++ coding.
I get a "too many arguments" error on my outputs.
#include <Servo.h>
const int servo1 = 11; // first servo
const int servo2 = 10; // second servo
const int joy1 = 5; // switch 1
const int joy2 = 4; // switch 2
const int joy3 = 3; // switch 3
const int joy4 = 2; // switch 4
int servoVal; // variable to read the value from the digital pin
Servo myservo1; // create servo object to control a servo
Servo myservo2; // create servo object to control a servo
void setup() {
// Servo
myservo1.attach(servo1); // attaches the servo
myservo2.attach(servo2); // attaches the servo
// Inizialize Serial
Serial.begin(9600);
}
void loop(){
// Display Joystick values using the serial monitor
outputJoystick();
// Read the horizontal joystick value (value between 0 and 180)
servoVal = digitalRead(joy1, joy2, joy3, joy4);
servoVal = map(servoVal, 0, 45, 135, 180); // scale it to use it with the servo (result between 0 and 180)
myservo2.write(servoVal); // sets the servo position according to the scaled value
// Read the horizontal joystick value (value between 0 and 180)
servoVal = digitalRead(joy1, joy2, joy3, joy4);
servoVal = map(servoVal, 0, 45, 135, 180); // scale it to use it with the servo (result between 0 and 180)
myservo1.write(servoVal); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
/**
* Display joystick values
*/
void outputJoystick(){
Serial.print(digitalRead(joy1, joy2, joy3, joy4));
Serial.print ("---");
Serial.print(digitalRead(joy1, joy2, joy3, joy4));
Serial.println ("----------------");
}
Would the joystick actually give a digital value or should have been an analogRead? Also I'm pretty sure you can only sample one item at a time with the digitalRead.
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);
// ...
}
}
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