Making a Servo spin for set amount of time

I have connected my servo with a moisture sensor and am trying to make it spin for a few seconds when there is moisture. then I need it to stop spinning regardless of wether there is still moisture and then wait a few minutes until it reads again.

here is my code at the moment:


#define SensorPin A0 

#include <Servo.h> 

int servoPin=3;
int pos=1500;
int Tval=10;
int stopsig=1400;




Servo Servo1;

float sensorValue = 0; 

void setup() { 
 Serial.begin(9600); 
 Servo1.attach(servoPin); 

} 
void loop() { 
 for (int i = 0; i <= 100; i++) 
 { 
   sensorValue = sensorValue + analogRead(SensorPin); 
   delay(1); 
 } 
 sensorValue = sensorValue/100.0; 
 Serial.println(sensorValue); 
 delay(30); 
 int (valueChangeTime) = millis();





 if (sensorValue > Tval){
  
  Servo1.attach(servoPin);
    Servo1.write(pos);
    delay(1000);
    Servo1.write(stopsig);
} 
  else{
   Servo1.detach();}

}

I know its probably pretty bad but I'm trying my best ahahahah.

Cheers.

Hello
And welcome to this brilliant forum for Arduino friends.
What is your question and what do you expect?
Don´t for get to post the sketch in so called code tags <"/"> .

1 Like

Please follow the advice given in the link below when posting code. Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

1 Like

Did you mean

sensorValue = sensorValue/101.0;

Please remember to use code tags when posting code

1 Like

consider (a bit involved than i expected)
(Capitalize constant)

#include <Servo.h>

Servo Servo1;


const byte LedTimeout = 12;
const byte LedActive  = 13;

const int SensorPin = A0;
const int ServoPin  = 3;

const unsigned long MsecOn   = 3000;    // a few seconds
const unsigned long MsecOff  = 10000;   // change to a few minutes

int   pos           = 1500;
int   posStop       = 1400;

float sensorValue   = 0;
const int  Tval     = 10;

enum { ST_IDLE, ST_ACTIVE, ST_TIMEOUT };
int state = ST_IDLE;

unsigned long msecLst;

enum { Off = HIGH, On = LOW };

// -----------------------------------------------------------------------------
void loop () {
    unsigned long msec = millis ();

    sensorValue += (analogRead (SensorPin) - sensorValue) / 100;
    Serial.println (sensorValue);

    switch (state)  {
    case ST_IDLE:
        if (sensorValue > Tval) {
            Servo1.write (pos);
            digitalWrite (LedActive, On);
            state   = ST_ACTIVE;
            msecLst = msec + MsecOn;
        }
        break;
        
    case ST_ACTIVE:
        if (msec > msecLst)  {
            Servo1.write (posStop);
            digitalWrite (LedActive,  Off);
            digitalWrite (LedTimeout, On);
            msecLst = msec + MsecOff;
            state   = ST_TIMEOUT;
        }
        break;
        
    case ST_TIMEOUT:
        if (msec > msecLst)  {
            digitalWrite (LedTimeout, Off);
            state = ST_IDLE;
        }
        break;
    }
}

// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);

    pinMode      (LedTimeout, OUTPUT);
    digitalWrite (LedTimeout, Off);

    pinMode      (LedActive,  OUTPUT);
    digitalWrite (LedActive,  Off);

    Servo1.attach (ServoPin);
}
1 Like

Thanks man, I appreciate it. Did I fix it? I’m pretty new to this sorry hahah

Wow thanks so much, I’ll try this out tommorow. Is it possible for you to briefly list what I was doing wrong and how you managed to fix it? I’m trying to learn from my mistakes.
Thanks again :slight_smile:

there's no timeout afterwards to prevent action.

so i used 3 states to

  • monitor the sensor to do something
  • wait some time to stop doing something, and
  • wait some time before monitoring the sensor

also, there's no need to attach() the servo each time

and i used running average the sensor measurement

1 Like

for some reason now when I run the code the servo spins regardless of wether there is any moisture on the sensor. any idea why?

add a Serial.print to report the sensor reading

You should probably add this to setup():
Servo1.write (posStop);

Are you sure your 'posStop' value is correct for your servo?

1 Like

Servo.write() takes an angle 0-180. If you want to use values like 1400, 1500 then you should really use writeMicroseconds(). The library will try to use the values you give it but it makes the code confusing to read.

And attach() will send a default of write(90) which is equivalent to your 'pos' which is why the servo runs immediately.

Steve

...but you don't have to; any "angle" above 543us will be treated by write as a microseconds value

1 Like

Yes, as I said, if you prefer to have your code looking confusing to anyone who hasn't read the Servo library code you can do that.

Steve

as others have hinted, are these valid servo angles?

1 Like

it is a modified servo to be continuous, do the angles still apply?

No, of course not.

From Servo.h Library

void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds 
void writeMicroseconds(int value); // Write pulse width in microseconds 
1 Like

Which is why you should always ignore the comments, or at best treat them with extreme mistrust

1 Like

You have to look in the right place :wink:
Servo.cpp:

void Servo::write(int value)
{
  if(value < MIN_PULSE_WIDTH)
  {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)

If you change MIN_PULSE_WIDTH in Servo.h, its again wrong ...

1 Like