Hello,
I'm trying to create an automatic door for my chicken coop.
I'm using:
- a 20Kg servo motor ( SF3218MG) to rotate the door
- a LDR sensor (with analog and digital outputs) to detect dawn and dusk
- a DfRobot Solar Power Manager 5V with a 18650 and a 5V 3W solar panel to power everything up
- an Arduino Nano
My code is fine and I can easily detect dawn and dusk using digital output (it's easier that analog one as I don't have to bring my computer to the coop to adjust the light level).
The servo motor rotate correctly when the battery is fully charged but I can only hear the servo is trying to rotate but nothing moves after a while.
I've set the Nano to low power mode using LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); in a 60s loop. Even though, the LEDs might be drawing battery faster than the solar panel can charge the 18650.
Is the servo stuck because it needs more amps ?
Here is my full code if it helps:
/*******************************/
/* VENDORS DEPENDENCIES */
/*******************************/
// Install library "Low-Power" made by Rocket Scream Electronics
// If you get troubles uploading the code to the Nano, go to Tools and swicth Processor to Old Bootloader
/*******************************/
/* CONFIGURATION VARIABLES */
/*******************************/
//#define DEBUG // Uncomment to enable logs (Might be required to calibrate the light sensor and the servo angles)
#define SERVO_PIN 9 // You probably don't need to change this value
#define LIGHT_SENSOR_PIN 2 // You probably don't need to change this value
#define LOW_LIGHT_MINUTES 10 // Minutes before closing the door
#define HIGH_LIGHT_MINUTES 10 // Minutes before opening the door
#define SERVO_OPEN_ANGLE 22 // The angle at which the door is considered as open
#define SERVO_CLOSED_ANGLE 140 // The angle at which the door is considered as closed
#define SERVO_PULSE_WDITH_MIN 500 // Based on SF3218MG specifications
#define SERVO_PULSE_WDITH_MAX 2500 // Based on SF3218MG specifications
/*****************************************************************************************/
/* DO NOT EDIT BELOW THIS LINE */
/*****************************************************************************************/
/*******************************/
/* Import dependencies */
/*******************************/
#include <Servo.h>
#ifndef DEBUG
#include "LowPower.h"
#endif
/*******************************/
/* Global variables */
/*******************************/
enum DoorState { OPEN,
CLOSED,
UNKNOWN };
int low_light_count = 0;
int high_light_count = 0;
DoorState door_state = UNKNOWN;
Servo door_servo;
/*******************************/
/* Setup function */
/*******************************/
void setup() {
#ifdef DEBUG
Serial.begin(115200);
Serial.println("-------------------");
Serial.println("| Eglu is ready |");
Serial.println("-------------------");
#endif
// Set default motor position to OPEN
door_servo.write(SERVO_OPEN_ANGLE);
door_servo.attach(SERVO_PIN, SERVO_PULSE_WDITH_MIN, SERVO_PULSE_WDITH_MAX);
delay(500);
door_servo.detach();
door_state = OPEN;
// Enable Digital input from light sensor
pinMode(LIGHT_SENSOR_PIN, INPUT);
// Enable builtin LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
}
/*******************************/
/* Infinite loop function */
/*******************************/
void loop() {
// LED indicates the program is running
digitalWrite(LED_BUILTIN, HIGH);
// Read LM393 light sensor
int current_light_level = digitalRead(LIGHT_SENSOR_PIN);
set_light_level(current_light_level);
// Check if the light level has been the same during X minutes
if (high_light_count >= HIGH_LIGHT_MINUTES) {
if (door_state != OPEN) {
#ifdef DEBUG
Serial.println("> Opening door");
#endif
// Open the Door
open_door();
} else {
#ifdef DEBUG
Serial.println("> Door was already open");
#endif
}
} else if (low_light_count >= LOW_LIGHT_MINUTES) {
if (door_state != CLOSED) {
#ifdef DEBUG
Serial.println("> Closing door");
#endif
// Close the Door
close_door();
} else {
#ifdef DEBUG
Serial.println("> Door was already closed");
#endif
}
}
// Wait 500ms before turning LED off (Code is too fast otherwise)
delay(500);
digitalWrite(LED_BUILTIN, LOW);
#ifdef DEBUG
// In DEBUG mode, light level is read every second (0.5+0.5)
delay(500);
#else
// Power down the board to save battery
// Light level is read every minute
//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,SPI_OFF, USART0_OFF, TWI_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF);
#endif
}
/*******************************/
/* Sensor and Servo functions */
/*******************************/
void set_light_level(int level) {
#ifdef DEBUG
Serial.println("----------");
Serial.print("Light sensor: ");
Serial.println(level);
#endif
// Darkness detected
if (level == HIGH) {
high_light_count = 0;
if (low_light_count < LOW_LIGHT_MINUTES) low_light_count = low_light_count + 1;
#ifdef DEBUG
Serial.print("Low light minutes: ");
Serial.print(low_light_count);
Serial.print("/");
Serial.println(LOW_LIGHT_MINUTES);
#endif
}
// Light detected
else {
low_light_count = 0;
if (high_light_count < HIGH_LIGHT_MINUTES) high_light_count = high_light_count + 1;
#ifdef DEBUG
Serial.print("High light minutes: ");
Serial.print(high_light_count);
Serial.print("/");
Serial.println(HIGH_LIGHT_MINUTES);
#endif
}
}
void open_door() {
door_servo.attach(SERVO_PIN, SERVO_PULSE_WDITH_MIN, SERVO_PULSE_WDITH_MAX);
for (int pos = SERVO_CLOSED_ANGLE; pos >= SERVO_OPEN_ANGLE; pos -= 1) {
door_servo.write(pos);
delay(50);
}
door_servo.detach();
door_state = OPEN;
}
void close_door() {
door_servo.attach(SERVO_PIN, SERVO_PULSE_WDITH_MIN, SERVO_PULSE_WDITH_MAX);
for (int pos = SERVO_OPEN_ANGLE; pos <= SERVO_CLOSED_ANGLE; pos += 1) {
door_servo.write(pos);
delay(50);
}
door_servo.detach();
door_state = CLOSED;
}
