Questions about Programming a Servo Motor [Solved]

spencerkim:
Do you mean servo.attach ?

If that was a question about reply #55 then the answer is no

Then, what do you mean by servo sweep

spencerkim:
Then, what do you mean by servo sweep

Look in the example programs for the Servo library. One of them is named Sweep. Does your servo move as expected when you upload the program ?

Yes, the sweep program in the servo library works. Should I try by making the servo motor loop at 89 and 90 degrees when the water is sensed in the water sensor? Would that work?

1 Like
#include <Servo.h> //include servo library
Servo myservo; //define servo as servo

byte waterSens[] = {A1, A3};
const byte howManySensors = sizeof(waterSens) / sizeof(waterSens[0]);

int servoPos = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("https://forum.arduino.cc/index.php?topic=641224");
  myservo.attach(2);//attach servo to pin 2
  Serial.print("Number of sensors "); Serial.println(howManySensors);
  Serial.println("setup() done");
  delay(1000);
}

void loop() {
  int sensorValue = analogRead(waterSens);//read the water sensor value
          
  sensorValue = map(sensorValue, 0, 1023, 0, 90); 
     if (sensorValue >= 1) {
        for (servoPos = 0; servoPos <= 90; servoPos += 1) { // goes from 0 degrees to 90 degrees
    // in steps of 1 degree
    myservo.write(servoPos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (servoPos = 90; servoPos >= 89; servoPos -= 1) { // goes from 90 degrees to 89 degrees
    myservo.write(servoPos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
      
     }
     
  else{
    myservo.write(0);
  }
                    
  
  
  Serial.println(sensorValue);
  delay(20);        
}

Or, would this be a better code to make the servo motor to stay near 90 degrees?

spencerkim:

#include <Servo.h> //include servo library

Servo myservo; //define servo as servo

byte waterSens[] = {A1, A3};
const byte howManySensors = sizeof(waterSens) / sizeof(waterSens[0]);

int servoPos = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("[MERGED] [MERGED] Coding 5 water sensors and one servo - Project Guidance - Arduino Forum");
  myservo.attach(2);//attach servo to pin 2
  Serial.print("Number of sensors "); Serial.println(howManySensors);
  Serial.println("setup() done");
  delay(1000);
}

void loop() {
  int sensorValue = analogRead(waterSens);//read the water sensor value
         
  sensorValue = map(sensorValue, 0, 1023, 0, 90);
    if (sensorValue >= 1) {
        for (servoPos = 0; servoPos <= 90; servoPos += 1) { // goes from 0 degrees to 90 degrees
    // in steps of 1 degree
    myservo.write(servoPos);              // tell servo to go to position in variable 'pos'
    delay(15);                      // waits 15ms for the servo to reach the position
  }
  for (servoPos = 90; servoPos >= 89; servoPos -= 1) { // goes from 90 degrees to 89 degrees
    myservo.write(servoPos);              // tell servo to go to position in variable 'pos'
    delay(15);                      // waits 15ms for the servo to reach the position
  }
     
    }
   
  else{
    myservo.write(0);
  }
                   
 
 
  Serial.println(sensorValue);
  delay(20);       
}




Or, would this be a better code to make the servo motor to stay near 90 degrees?

You have:

    byte waterSens[] = {A1, A3};
.
.
.

    int sensorValue = analogRead(waterSens);

waterSens is a pointer to an array of bytes. You need to access the element there with something like:

    int sensorValue = analogRead(waterSens[0]);

This will read the sensor on A1. If you want to interleave the sensors you need a variable as an index.

So, if I want to also do it for A3, I need to set the variable of the sensorvalue as an index?

To read A3:

 int sensorValue = analogRead(waterSens[1]);

1 is the index in the []. See the array reference.

Does this come close to what you want (compiles, not tested):

#include <Servo.h> //include servo library

#define MOISTURE_THRESH     450     //ADC counts    base moisture level (you fill in correct value)
#define HYST                20      //ADC counts    +/- from this value will switch
#define SAMPLE_INTERVAL     50      //mS            mS between sensor checks

#define WET_POS             90      //
#define DRY_POS             0       //

Servo myservo; //define servo as servo

byte 
    waterSens[] = {A1, A3};
const byte 
    howManySensors = sizeof(waterSens) / sizeof(waterSens[0]);
int
    grReadings[howManySensors];

void setup()
{
    Serial.begin( 9600 );
    Serial.println( "https://forum.arduino.cc/index.php?topic=641224" );
    myservo.attach( 2 );//attach servo to pin 2
    myservo.write( 0 );
    Serial.print( "Number of sensors " ); Serial.println( howManySensors );
    Serial.println( "setup() done" );
    
}//setup

void loop() 
{
    unsigned long
        tNow;
    static unsigned long
        tSample = 0;
    static byte
        lastbWater = 0,
        bWater = 0;
       
    tNow = millis();
    if( tNow - tSample >= SAMPLE_INTERVAL )
    {    
        tSample = tNow;        
        for( int i=0; i<howManySensors; i++ )
        {
            int sensorValue = analogRead( waterSens[i] ); //read each twice twice due to channel change each pass
            delayMicroseconds( 20 );
            grReadings[i] = analogRead( waterSens[i] );
            
        }//for

        if( bWater == 0 )
        {
            for( int i=0; i<howManySensors; i++ )   
                bWater |= (grReadings[i] >= MOISTURE_THRESH+HYST) ? 1:0;
                
        }//if
        else
        {
            byte bDry = 0;            
            for( int i=0; i<howManySensors; i++ )
                bDry |= (grReadings[i] > MOISTURE_THRESH-HYST) ? 1:0;

            bWater = bDry;
                
        }//else  

        if( bWater != lastbWater )
        {
            lastbWater = bWater;
            myservo.write( (bWater) ? WET_POS : DRY_POS );
                
        }//if
            
    }//if     
    
}//loop

5 pages in, I decided to have a further look at the OPs original code from over 2 weeks ago.

  • First I made it compile. There were a few minor things to do with braces and ;'s
  • Second (and see my post #52) I took out the lines where the servo gets positioned in readTheSensors(), since that's being done (more elegantly) in setTheServo() which gets a bool from readTheSensors()

I don't have the OP's sensors, but analog is analog, so with potentiometers on A0, A1 and A2, and a servo on pin 9, I tested the OP's code as fixed in my 2 bullets above, and it works. (At least according to my understanding of what's supposed to happen: all sensors dry servo goes one way, at least one sensor is wet, it goes the other?)

  • With all 3 analog pins below sensorWetThreshold, the servo goes to servoDryPos and the led is off.
  • With any 1 of the 3 analog pins above sensorWetThreshold, the servo goes to servoWetPos and the led is on.

Here's OP's code from Nov 2, fixed as in the bullets above (all changes commented) and tested successfully with pots on A0, A1 and A2 and with a servo on 9.

Note the servo positions and threshold for my test:

const byte servoDryPos = 70;  
const byte servoWetPos = 110;  
const int sensorWetThreshold = 450;
#include <Servo.h> //include servo library
Servo myservo; //define servo as servo

byte waterSens[] = {A0, A1, A2};
const byte howManySensors = sizeof(waterSens) / sizeof(waterSens[0]);

int servoPos;
const byte servoDryPos = 70;  //
const byte servoWetPos = 110;  //
const int sensorWetThreshold = 450; //

void setup()
{
  Serial.begin(9600);
  Serial.println("https://forum.arduino.cc/index.php?topic=641224");
  myservo.attach(9);//attach servo to pin 9
  //also just going to use led13 as a signal
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.print("Number of sensors "); Serial.println(howManySensors);
  Serial.println("setup() done");
  delay(1000);
}

void loop()
{
  setTheServo(readTheSensors());
  delay(500);
}

bool readTheSensors()
{
  int currentSensorVal;
  bool result = true; //start assuming all dry, if any one (or more) is wet then set false
  for (int i = 0; i < howManySensors; i++)
  {
    currentSensorVal = analogRead(waterSens[i]);
    Serial.print(currentSensorVal); Serial.print(" ");
    if (currentSensorVal > sensorWetThreshold)
    {
      result = false;
      break;
    }
  }

  if (result)
  {
    Serial.println("All dry");
    //servoPos = 0; // was missing ;
    // but have //'d out the above line anyway
    // no point having a setTheServo() function AND doing it here
  } //this was missing

  else
  { //new
    Serial.println("At least one sensor is wet"); //was missing ;
    //  { this { should be on the line before the serial print
    //servoPos = 90; // was missing ;
    // but have //'d out the above line anyway
    // no point having a setTheServo() function AND doing it here
  }
  return result;

}//readTheSensors()

void setTheServo(bool dry)
{
  if (dry)
  {
    myservo.write(servoDryPos);
    digitalWrite(LED_BUILTIN, LOW);
  }
  else
  {
    myservo.write(servoWetPos);
    digitalWrite(LED_BUILTIN, HIGH);
  }
}

Yes, the two codes are close to the one that I want. For the second code, I have tried it already, but it didn't work very well. The servo motor didn't turn when at least one sensor was dry.

spencerkim:
The servo motor didn't turn when at least one sensor was dry.

The way I understood it (but I haven't read every single word in the thread, I must say) if ALL sensors are dry the servo is supposed to go one way, and if AT LEAST one is wet, it goes the other.

Where did "at least one sensor was dry" come from? (Maybe I missed that part...)

Your opening post says:

spencerkim:
I want the servo motor to turn 90 degrees whenever water is detected at one or more of the three water level sensors and the servo motor should come back to the starting position when water is not detected.

... and that's what your code as fixed does, if dry is under the threshold and wet is over. (Although the servo positions I used were 70 and 110 I think.)

sayHovis:
The way I understood it (but I haven't read every single word in the thread, I must say) if ALL sensors are dry the servo is supposed to go one way, and if AT LEAST one is wet, it goes the other.

Where did "at least one sensor was dry" come from? (Maybe I missed that part...)

For that part, I meant to say when at least one sensor was wet

spencerkim:
For that part, I meant to say when at least one sensor was wet

Ok well that's what that code does for me, admittedly without your sensors but using a potentiometer on the basis that an analog signal from a pot is the same as one from an analog sensor, and just comparing to some threshold.

If I start with all 3 below the threshold, I get the message they're all dry, servo one side, led off. If one goes over, servo swings, led goes on, message says at least one is wet. If I make another one go over it obviously stays like that. Then only goes back to dry state when both go dry.

Sorry, can't help any more. On my system, it's doing as you ask.....

Thanks for the help. I will try to do it on my system

Did you actually pour water onto the sensor? My monitor is telling me that it is dry the whole time

I told you I don't have your sensors: I used a potentiometer to mimic your sensors to just give a varying value for the analogRead().

sayHovis:
... admittedly without your sensors but using a potentiometer on the basis that an analog signal from a pot is the same as one from an analog sensor, and just comparing to some threshold.

I certainly was not going to order some sensors that I will never use again, just to test your code.


Let's step back and check if any of your sensors work. Forget the servo stuff for a moment: do you have a simple sketch that reads one of your sensors and gives a different value between it being wet and dry?

Just this in loop() should do the trick:

void loop()
{
Serial.println(analogRead(A0));
delay(100);
}

What values do you get as you move a sensor in and out of a glass of water like this guy who going by your image in #22/23 has the same sensor.

If all you're doing is checking the presence or absence of water rather than the depth then perhaps the threshold needs to be set very low? Totally dry, out of the water, would be 0 maybe, but just touching the surface might be 1 or 2, I don't know.

You need to guarantee the sensors are working and that you know what threshold value you actually need.

Where did this 450 come from?

const int sensorWetThreshold = 450;

Since an analogRead() goes from 0-1023 that would presumably be the sensor about half-way in water? Did you test that value or just chose it randomly?


So do everyone a favour (not least yourself :wink: ), forget the code you have so far, and just print out the values from the sensor as described.

I got the whole thing to work by setting the threshold to 10. Thanks for the help

spencerkim:
I got the whole thing to work by setting the threshold to 10.

Excellent. Now it might be a good idea to go back to the opening post and edit the title there and add [solved] or similar. (Not that this question is about programming a servo :wink: it's about reading an analog sensor and setting its go/no-go threshold.)

edit.. I just looked at your older threads from October, which are presumably on the same project. Back then you had this:

  if (sensorValue >= 50) {

It's a pity you didn't stick with a low value like that, since your code in this thread was basically ok all along, just a bad threshold. But all's well that ends well, I guess.

spencerkim:
Thanks for the help

You're welcome.