Coding Inquire

Hello, I am trying to control a sail winch servo via an analog source, but I believe I have made mistakes in my code as the servo is not turning accordingly. Here is the code I attempted to run. I am using a sail winch servo because I was told here it would be the best to use if you would like to control when to stop and when to start.

#include <Servo.h>

Servo myservo;

int pos = 0;

int analogPin = A0; //Input
int val;

void setup() {
myservo.attach(12); //Servo pin
Serial.begin(9600);
}

void loop() {
Serial.println(analogRead(analogPin)); // Display values for input A0
delay(125); // Delay for one second

int val = analogRead(analogPin);

val = constrain(val, 200, 1000);

val = map(val, 0, 1023, 0, 180); // maps the analog reading to a value between 0 and 180

{ if(val < 300) myservo.write(pos = 0)
;for (pos = 0; pos <= 180; pos +=1)
delay(15);
}

{ if(val > 300) myservo.write(pos = 180)
;for(pos = 180; pos >= 0; pos -=1)
delay(15);
}
}

Perhaps you could tell us what you expect, and how what you observe differs?

Some eccentric bracing you've got there.

Please remember to use code tags when posting code

myservo.write(pos = 0)

What should this do and why is it written that way ?

    for (pos = 0; pos <= 180; pos += 1)
      delay(15);

This does nothing but wait 2.7 seconds. Is that what you meant to do ?

A “winch servo” is like a regular servo except it can do more than one full turn. If you run the sketch below it should turn to one limit, wait a while, and turn to the other limit, wait a while, and repeat. This will give you a chance to count the number of turns.

If the servo spins in one direction for ten seconds and then spins in the other direction for ten seconds, what you have is a “Continuous Rotation Servo” which is more like a gearmotor with a built in motor controller. Some value near 90 should stop the motor while value lower and higher will control speed in both directions.

#include <Servo.h>
Servo myservo;

void setup()
{
  myservo.attach(12);      //Servo pin
}

void loop()
{
   myservo.write(0);
   delay(10000);
   myservo.write(180);
   delay(10000);
}
val = map(val, 0, 1023, 0, 180);        // maps the analog reading to a value between 0 and 180
300
 { if(val < 300) myservo.write(pos = 0)

Plus if you map val so it is always between 0 and 180 then you can be pretty sure that it is always going to be < 300.

Steve

Well I’m really new to coding so this is the product of the basics I’ve learned in the past week. What I wish to accomplish is to stop the servo at a certain location and hold until the next analog reading is reached.

acdavis1999: What I wish to accomplish is to stop the servo at a certain location and hold until the next analog reading is reached.

For a servo, you send a value from 0 to 180 to servo.write() and the servo will go to that position and stop. A "winch servo" maps the 0-180 value into its range of motion, typically 4 to 10 revolutions. Can you provide any identifying information for your "winch servo"? I don't know what you mean by "until the next analog reading is reached". Could describe that behavior in more detail?

I have a Hitec HS-785HB servo. The reaction I’m getting is continuous turning in one direction. What I would like to have is rotation in both direction based on the analog readings. For example, say I would be using a photoresistor as the analog input. As the intensity of the light increased beyond a certain threshold I’d like it to increase, but go back to start position if it is not at that threshold and hold while at both the increased position and the start position.

If you are getting continuous rotation then it is not really a servo at all but an electronically controlled motor. You cannot command it to move to a particular position because it has no means of knowing its position.

The HS-785HB servo is unique due to its ability to rotate multiple turns while retaining positioning feedback. While most servos are limited to approximately 180 degrees absolute max, the HS-785HB can rotate just over 8 turns given the proper PWM signal range. With most hobby radio systems the HS-785HB servo range is likely to be just shy of 4 rotations (assuming a 1050-1950usec PWM signal) however when using the servo with a servo controller capable of sending a wider PWM range (Arduino, Raspberry Pi, Pololu Servo Controller, etc.), the servo is able to be driven further without any modifications necessary.

acdavis1999: I have a Hitec HS-785HB servo. The reaction I’m getting is continuous turning in one direction.

How long do you wait to tell if it is really going to carry on turning for ever and not just for 6-8 turns?

If you are really getting continuous rotation then the servo is bad/broken. HS785HB servos can't do that.

Steve

It is not full rotation it stops at the 8 as supposed to, but it is not following the commands because my one is likely messed up. It follows the simple sample code in the arduino from 0-180 and back with no issues at all. I’m needing it to stop at the 180 position and hold until the analog input of a photoresistor drops below a threshold and then return to normal and hold until the threshold is again surmounted.

acdavis1999: It is not full rotation it stops at the 8 as supposed to, but it is not following the commands because my one is likely messed up. It follows the simple sample code in the arduino from 0-180 and back with no issues at all. I’m needing it to stop at the 180 position and hold until the analog input of a photoresistor drops below a threshold and then return to normal and hold until the threshold is again surmounted.

Show us the sketch you are using, just in case you made a programming error.

Have you written a simple sketch to show that the photoresistor input is producing the values you expect?

The sketch I’ve been using is listed in the first post. I would repost, but am away from my computer at at this time. I am fairly certain it’s likely an error in my code as I am very new to coding and have been basically hacking and piecing together from sample codes and including some bits I learned along the way.

The code you posted has problems already pointed out to you, so you will have fixed those by now. We need to see the new code. In code tags, this time please.

Try this version. It still won’t work but the comments show you WHY it still won’t work.

#include <Servo.h>
Servo myservo;

const byte LDRPin = A0;     // Light Dependent Resistor
const byte ServoPin = 12;

void setup()
{
  Serial.begin(115200);  // 9600 baud was fast... in 1974
  myservo.attach(ServoPin);
}

void loop()
{
  int lightLevel = analogRead(LDRPin);// Value from 0 to 1023

  Serial.print("Raw value: ");
  Serial.print(lightLevel);
  
  lightLevel = constrain(lightLevel, 200, 1000);    // Value from 200 to 1000 (WHY CONSTRAIN?!?)
  lightLevel = map(lightLevel, 0, 1023, 0, 180);    // Value from 35 to 175 (WHY MAP?!?)

  Serial.print(", Cooked value: ");
  Serial.println(lightLevel);

  if (lightLevel < 300)  // ALWAYS TRUE!?!  Get rid of the constrain() and the map(). Adjust your threshold instead.
    myservo.write(0);
  else
    myservo.write(180);
}

Thank you very much! I’ll tweek it tonight and get back with what I’m able to come up with!

Here is the new tweaked version I have. That is showing more promising results. While using a light if it if it is below the threshold it will rotate one direction (continuous), but if it is above threshold and it will rotate (further than desired) and hold as long as it remains above threshold.

Any suggestions to eliminate continuous rotation when not above threshold? I recall johnwasser had suggested removing the mapping and constraints and adjusting threshold instead. Could this correct this issue?

In addition, I believe I am getting rotation further than desired due to the microsecond code I have listed as “myservo.writeMicroseconds(1200);”. I am not well versed in microseconds, so I felt it is likely to be the cause of the larger rotations but I’ve attempted to decrease the microsecond which in turn actually increased the rotation.

Finally, the only other issue I experience is with the threshold. It is rather insignificant and I can manage with it, but I had listed the threshold as 5 because using 10 as the threshold it would not actually engage until the serial monitor displayed 60 and using 5 drops it down to 30. It appears the threshold is multiplied by six in some manner possibly the mapping or constraints in some way, but I am unsure.

#include <Servo.h>

Servo myservo; // create servo object to control a servo

int photopin = 0; // analog pin used to connect the photoresistor
int lightlevel; // variable to read the value from the analog pin
int pos = 0;
const int threshold = 5;

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
}

void loop1(void){
analogRead(photopin);
Serial.println(analogRead(photopin));
delay(2000);
lightlevel = analogRead(photopin); // reads the value of the potentiometer (value between 0 and 1023)
lightlevel = map(lightlevel, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)

}

void loop2(void){
if (lightlevel > threshold){
myservo.writeMicroseconds(1200);
}
else {
myservo.writeMicroseconds(600);
}
}

void loop() {
loop1();
loop2();

}

acdavis1999: Finally, the only other issue I experience is with the threshold. It is rather insignificant and I can manage with it, but I had listed the threshold as 5 because using 10 as the threshold it would not actually engage until the serial monitor displayed 60 and using 5 drops it down to 30. It appears the threshold is multiplied by six in some manner possibly the mapping or constraints in some way, but I am unsure.

Maybe that has something to do with you displaying the value while it is in the range 0-1023 and then mapping it to change its range to 0-180 before you test for the threshold.

Steve

You are likely correct. I feel the mapping is likely to be causing a few of my issues, but am unsure of how to rephrase the mapping or remove it to keep it working. Do you have any suggestions to tweak it or if I should completely remove it?