How can I adjust the servo duration?

How can I adjust the servo duration?
The code works for 10 seconds or more. 5 seconds 10 seconds 11 seconds 15 second (ok.:slight_smile: )
But "4 seconds, 3 seconds 2 seconds" (nok :frowning: )

Sample : PetFeeder - Wokwi ESP32, STM32, Arduino Simulator

"" //******************************************************************************

  // AM FEED THE CAT - AM Saatinde Yem Dökülme Zamanı 3 saniye ayarlı
  //******************************************************************************
  if ((now.hour() == amFeedHour && now.minute() == amFeedMinute) && now.second() < 15) {
    feedServo(); // feed now
  }

  //******************************************************************************
  // PM FEED THE CAT - PM Saatinde Yem Dökülme Zamanı 3 saniye ayarlı
  //******************************************************************************
  if ((now.hour() == pmFeedHour && now.minute() == pmFeedMinute) && now.second() < 15) {
    feedServo(); // feed now
  }""
------------------------------------------
Full code:

//******************************************************************************
// RTC ALARM
//******************************************************************************
#include <RTClib.h>
RTC_DS1307 rtc; // no (SDA, SCL) arguments

// AM feeding time
int amFeedHour   = 10;
int amFeedMinute = 00;

// PM feeding time
int pmFeedHour   = 14;
int pmFeedMinute = 50;

// indicator if AM or PM feeding time
bool ampm = 0;

// char weekDays[][10] = { // removed LCD clutter
//   "SUN",
//   "MON",
//   "TUE",
//   "WED",
//   "THU",
//   "FRI",
//   "SAT"
// };

//******************************************************************************
// LCD
//******************************************************************************
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 4, 5, 6, 7); // 12 RS, 11 E, 4 D4, 5 D5, 6 D6, 7 D7

char line1[] = "@Kayrahan"; // this will be centered on the LCD
char line2[] = "Yem MakinasI"; // this will be centered on the LCD

//******************************************************************************
// SERVO
//******************************************************************************
#include <Servo.h>
Servo myServo; // create instance of Servo class to control the servo

int servoPin = 3;
int position  = 0; // starting position of the servo (adjustable)
int direction = 1; // servo direction of travel
int speed = 5; // speed of servo arm. larger value is faster movement

void setup() {
  //******************************************************************************
  // GENERAL SETUP
  //******************************************************************************
  Serial.begin(115200); // Serial monitor for debugging

  //******************************************************************************
  // LCD SETUP
  //******************************************************************************
  lcd.begin(16, 2); // start the LCD
  welcome(); // the welcome screen

  //******************************************************************************
  // SERVO SETUP
  //******************************************************************************
  myServo.attach(servoPin); // attach servo to pwm pin

  //******************************************************************************
  // RTC SETUP
  //******************************************************************************
  if (! rtc.begin()) { // start rtc
    Serial.println("Couldn't find RTC"); // failed to start
    Serial.flush(); // wait for previous Serial.print(); to finish
    while (1); // stops sketch here.
  }
  // this will set RTC Date/Time from PC at compile time. COMMENT-OUT after setting
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // this will set RTC with bespoke Date/Time
  // rtc.adjust(DateTime(2023, 3, 14, 12, 30, 0));  // March 14, 2023 at 12:30am
}

void loop() {
  DateTime now = rtc.now(); // set "now" to the RTC time

  if ((now.hour() >= pmFeedHour) && (now.hour() < amFeedHour)) { // compare hour to now/RTC for "next"
    ampm = 0; // before mid-day
    displayNextFeed(ampm, amFeedHour, amFeedMinute); // display next feed time
  } else {
    ampm = 1; // after mid-day
    displayNextFeed(ampm, pmFeedHour, pmFeedMinute); // display next feed time
  }

  //******************************************************************************
  // AM FEED THE CAT - AM Saatinde Yem Dökülme Zamanı 3 saniye ayarlı
  //******************************************************************************
  if ((now.hour() == amFeedHour && now.minute() == amFeedMinute) && now.second() < 15) {
    feedServo(); // feed now
  }

  //******************************************************************************
  // PM FEED THE CAT - PM Saatinde Yem Dökülme Zamanı 3 saniye ayarlı
  //******************************************************************************
  if ((now.hour() == pmFeedHour && now.minute() == pmFeedMinute) && now.second() < 15) {
    feedServo(); // feed now
  }

  //******************************************************************************
  // displayDate()
  //******************************************************************************
  lcd.setCursor(0, 0);
  lcd.print(now.year(), DEC);
  lcd.print('/');
  if (now.month() < 10) lcd.print("0");
  lcd.print(now.month(), DEC);
  lcd.print('/');
  if (now.day() < 10) lcd.print("0");
  lcd.print(now.day(), DEC);

  //******************************************************************************
  // displayDayOfWeek() // too much data for 16x02 LCD
  //******************************************************************************
  // lcd.print(" ");
  // lcd.setCursor(0, 1);
  // lcd.print(weekDays[now.dayOfTheWeek()]);
  // lcd.print(" ");

  //******************************************************************************
  // displayTime()
  //******************************************************************************
  lcd.setCursor(0, 1);
  if (now.hour() < 10) lcd.print("0"); // pad single digit with "0"
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  if (now.minute() < 10) lcd.print("0"); // pad single digit with "0"
  lcd.print(now.minute(), DEC);
  lcd.print('.');
  if (now.second() < 10) lcd.print("0"); // pad single digit with "0"
  lcd.print(now.second(), DEC);
}

//******************************************************************************
// Welcome screen LCD and Serial Monitor
//******************************************************************************
void welcome() {
  lcd.setCursor(8 - (sizeof(line1) / 2 - 1), 0); // center line1 of the title
  lcd.print(line1);
  lcd.setCursor(8 - (sizeof(line2) / 2 - 1), 1); // center line 2 of the title
  lcd.print(line2);
  delay(1000);
  lcd.clear();
  lcd.setCursor(11, 0);
  lcd.print("Next:");

  Serial.println("Edit feeding times in the RTC ALARM section");
}

//******************************************************************************
// FEED THE CAT
//******************************************************************************
void feedServo() {
  myServo.write(0);  // set positions of servo arm
  position += direction * speed; // calculate new position
  delay(3000); // delay between movements. smaller value is faster movement
  myServo.write(90); // set position of servo arm
}

//******************************************************************************
// NEXT FEEDING TIME
//******************************************************************************
void displayNextFeed(int ampm, int nextHour, int nextMinute) { // display next feeding time
  lcd.setCursor(9, 1);
  lcd.print(nextHour);
  lcd.print(":");
  if (nextMinute < 10)
    lcd.print("0");
  lcd.print(nextMinute);

  lcd.setCursor(14, 1);
  if (ampm) // the "1" or "0" from above for AM or PM
    lcd.print("PM"); // next feed
  else
    lcd.print("AM"); // next feed
}

void displayTime() {
  // move the display-time code from void-loop() to here
}

void displayDate() {
  // move the display-date code from void-loop() to here
}

Please describe what feedServo() is meant to do.

What do you mean when you say less than a certain time in that expression fails? How does it fail?

Reading the code it looks like you are trying to keep the feeding servo from executing many backs and forths at the two feeding times.

Is that the problem you try to solve by making that time in seconds shorter?

a7

what you do is when you are within the first 15 seconds of a feed time

you call continuously feedServo(); which does this:

you move to 0° wait a bit (3s) and move back to 90°

you keep calling this repetitively until the 15 second window elapsed and as there are just a few microseconds between the myServo.write(90); at the end of the function and the next call to myServo.write(0); you don't see the servo moving back to 90 really - it tries but microseconds later it gets the order to stay at 0°. Then the 15 second window is finished and thus you don't call feedServo() anymore and so the servo has the time to really go back to 90°

➜ this is not a great way to handle things. You should not have to repeat orders to move between 0° and 90°, you should know when it's time to feed and then wait for some time (in an async way if you want the rest of the code to run and not have the time stuck whilst the delay() executes) and then move the servo back to its original position

I want the servo motor to run for only 3 seconds. Let it open and close in 3 seconds.

Should I write where 15 is written?
From there I can't type a number in under 10 seconds. Because it doesn't work.

if ((now.hour() == amFeedHour && now.minute() == amFeedMinute) && now.second() < 15) {
    feedServo(); // feed now
  }
  //******************************************************************************
  // PM FEED THE CAT - PM Saatinde Yem Dökülme Zamanı 3 saniye ayarlı
  //******************************************************************************
  if ((now.hour() == pmFeedHour && now.minute() == pmFeedMinute) && now.second() < 15) {
    feedServo(); // feed now
  }

did you understand what I explained above?

when it's time your code does this (5 iteration roughy for 15 seconds since you have a 3s delay)

write 0°
wait 3s
write 90°

write 0°
wait 3s
write 90°

write 0°
wait 3s
write 90°

write 0°
wait 3s
write 90°

write 0°
wait 3s
write 90°

as those writes in the sequence

write 90°
write 0°

are very close in time, the servo does not have time to move and so what you really see is like that

write 0°
wait 3s
wait 3s
wait 3s
wait 3s
wait 3s
write 90°

this is a crappy approach but if you want shorted feeding time you need to modify the 15s AND the 3s inside the function (the one in the function is the minimum wait time guaranteed)

I am trying to understand. This is for an automatic dog food.
Then how many seconds can I do minimum?
because the dog food will spill too much.
can you review it from here?

please answer

Yes, I understand a bit.
This is ready code but needs editing.
But I guess I can't do this.
Thanks.

You can't, yet, but it can be done.

Does it matter how fast the servo moves? Or just that it move, stay moved for a period, and then move back, however rapidly?

Do you want one such motion (swing from 0 to 90 and back) per feeding?

It is easy to make that happen just once, instead of happening over and over for 15 seconds. Besides which as you wrote it, and @J-M-L tires to make you see, the motion will be unsatisfactory.

Maybe you want a feeding to be

  (servo is at 0 by initial value and the logic)
then
  move servo to 90
  wait three seconds
  move servo back to 0 (leave it back at 0)

a7

Yeah, you have delay of 3 seconds in your feedServo() function.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.