Arduino programming

Joined
30 Dec 2008
Messages
2,547
Reaction score
414
Location
Cumbria
Country
United Kingdom
Middle son has to do a school project (an EPQ" they call it). Having lost our last chicken to Mr. Fox, he wants to make a light-activated chicken coop door opener. The door works like a sash window, and the idea is to have a light sensor that opens it when it's daylight and closes it when it's night.

There's a geared DC motor with a pulley on it at the top. It winds a piece of string up or down, depending on the direction in which the motor is running. There's a microswitch top and bottom, so that the Ardunio knows whether the door is up or down. The only other complication, is a solenoid latch that works like a house door. When the chicken house door is on the way down, there is a hasp on the bottom of it. The solenoid latch has a bevelled edge, and is spring-loaded, so when closing the door, the striker just pushes it out of the way. Before opening the door, therefore, a 12V pulse has to be applied to the latch for a second or so, to pull the striker back.

Essentially, (in words, at least!) the program is supposed to work like this:

Check light level.
If light level > 400, go to "opening door" subroutine. If light level < 300, go to "door closing" subroutine.

Door opening subroutine:
apply power to solenoid latch,
run motor forwards for 1 second,
remove power from solenoid latch,
run motor forwards until top limit switch closes.

Door closing subroutine:
run motor backwards until bottom limit switch closes.


Somehow, it's not working though. It doesn't stop the motor when the top limit switch is reached. It's a software problem, I think. (I've put a meter on the switches and they do open and close correctly). I'd be grateful for any thoughts anyone might have. I can help him with the mechanical bits, but I'm hopelessly out of my depth with the programming!

Is there anyone on here who might be wise in the ways of the Arduino, and could maybe cast an eye over the program if I post it up on here, please?
 
I would just pastebin.com the code and post a link? - There are probably better places to get help like discord and some facebook groups?

Could you write a simple program to check the limits are on the correct gpios?
 
Here's the code, if it means anything to anyone?

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
//#define solenoidPin 7 //pin for solenoid
#define topPin 2 //pin for top switch
#define bottomPin 4 // pin for bottom switch

bool topSwitchState = false;
bool bottomSwitchState = true;
const int ldrPin = A1; //pin for
bool isUp = false; //defining state of the door
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
//Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
//Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x57);


Adafruit_DCMotor *myMotor = AFMS.getMotor(1);

int counter = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis; // this is part of something that was recommended by someone as an alternative to using delay() to run the program every second. I'm not rxactly sure how it works


void setup ()
{
//pinMode(7, OUTPUT); //setting the solenoid pins as an output
pinMode(4, INPUT); //setting the switch pins to inputs
pinMode(2, INPUT);

Serial.begin(9600);

pinMode(ldrPin, INPUT); //setting the ldrPin to input

Serial.println("Starting AMS");
AFMS.begin();
Serial.println(" AMS started, setup routine finished");
myMotor->setSpeed(150);
//digitalWrite(solenoidPin, HIGH);
}
void pullSolenoid () { //subroutine for pulling the solenoid back
//digitalWrite(solenoidPin, LOW);
Serial.println("pull solenoid");
}
void releaseSolenoid () { //subroutine for releasing solenoid
//digitalWrite(solenoidPin, HIGH);
Serial.println("release solenoid");
}
void doorUp () { //subroutine for lifitng the door up
pullSolenoid();
delay(500);
myMotor->run(FORWARD);
delay(1000);
myMotor->run(RELEASE);
delay(500);
releaseSolenoid();
/*Serial.println("pull solenoid");
delay(500);
Serial.println("run motor");
delay(500);
Serial.println("release solenoid");*/
if (digitalRead(topPin) == LOW) {
myMotor->run(FORWARD);
//Serial.println("run motor");
//delay(500);
}
else if (digitalRead(topPin) == HIGH){
myMotor->run(RELEASE);
//Serial.println("stop motor");
//delay(500);
}
Serial.println("Can get out of loop");
}
void doorDown () {
Serial.println("entered loop");
if (digitalRead(bottomPin) == LOW) {
myMotor->run(BACKWARD);
//Serial.println("run motor");
//delay(500);
}
else if (digitalRead(bottomPin) == HIGH) {
myMotor->run(RELEASE);
//Serial.println("stop motor");
//delay(500);
}
Serial.println("Can get out of loop");
}

void checkUp () { //subroutine checks if the door needs to go up
int ldrStatus = analogRead(ldrPin);
if (ldrStatus > 400) {
doorUp();
isUp = true;
//delay(2000);
}
else {
//delay(2000);
}
}
void checkDown () { //subroutine checks if the door needs to go down
int ldrStatus = analogRead(ldrPin);
if (ldrStatus < 300) {
doorDown();
isUp = false;
//delay(2000);
}
else {
//delay(2000);
}
}
void loop ()
{
int ldrStatus = analogRead(ldrPin); //check the brightness
Serial.println(ldrStatus); //print the brightness to the monitor

currentMillis = millis();

if (currentMillis - previousMillis >= 1000) {

previousMillis = currentMillis;
if (isUp == true) { //check if the door is up and then if it needs to go down
checkDown();
//delay(1000);
}
else if(isUp == false) { // check if the door is down and then if it needs to go up
checkUp();
//delay(1000);
}
else {
//delay(1000);
}


}
}


(The bits involving the solenoid are currently commented out, just while we try to sort this fault). The light sensor works. If we shine a torch on it, the motor runs and lifts the door but when it hits the top limit switch it doesn't cut out. (Yet the switch does work - we've tried it with a meter - and the relevant pin on the Arduino goes "high" when the switch closes. I'm sure it's something to do with the programming rather than any of the hardware!
 
Please fix the indentation by using a code block. There is commented out stuff that should be removed for the purposes of your post here (I know you've given the reason for that, but you're asking for help from the forum, so why clutter it up), and also why do you define e.g. topPin to 2 and then not reference the define in the code? Fix that please.

A circuit diagram wouldn't go amiss. Get your son to draw it up maybe?
 
My very quick look:
when it hits the top limit switch it doesn't cut out.


This is the code you are using to check door position.


currentMillis = millis();
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
if (isUp == true) { //check if the door is up and then if it needs to go down
checkDown();
}
else if(isUp == false) { // check if the door is down and then if it needs to go up.
checkUp();
}
else {
//delay(1000);
}



I am not sure why it has two else commands, but presume that second one is from and earlier IF.
So I have removed this so it looks like this

currentMillis = millis();
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
if (isUp == true) { //check if the door is up and then if it needs to go down
checkDown();
}
else if(isUp == false) { // check if the door is down and then if it needs to go up
checkUp();
}
else {
//delay(1000);
}

So I would be tempted to change this to two commands just to see if the ELSE is causing an issue:

currentMillis = millis();
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
if(isUp == true) checkDown(); //check if the door is up and then if it needs to go down
if(isUp == false) checkUp(); // check if the door is down and then if it needs to go up
}



SFK
 
Last edited:
Please fix the indentation by using a code block. There is commented out stuff that should be removed for the purposes of your post here (I know you've given the reason for that, but you're asking for help from the forum, so why clutter it up), and also why do you define e.g. topPin to 2 and then not reference the define in the code? Fix that please.

A circuit diagram wouldn't go amiss. Get your son to draw it up maybe?

Fair point!
 
My very quick look:



This is the code you are using to check door position.


currentMillis = millis();
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
if (isUp == true) { //check if the door is up and then if it needs to go down
checkDown();
}
else if(isUp == false) { // check if the door is down and then if it needs to go up.
checkUp();
}
else {
//delay(1000);
}



I am not sure why it has two else commands, but presume that second one is from and earlier IF.
So I have removed this so it looks like this

currentMillis = millis();
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
if (isUp == true) { //check if the door is up and then if it needs to go down
checkDown();
}
else if(isUp == false) { // check if the door is down and then if it needs to go up
checkUp();
}
else {
//delay(1000);
}

So I would be tempted to change this to two commands just to see if the ELSE is causing an issue:

currentMillis = millis();
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
if(isUp == true) checkDown(); //check if the door is up and then if it needs to go down
if(isUp == false) checkUp(); // check if the door is down and then if it needs to go up
}



SFK
Thank you very much indeed! I do appreciate this. I'll see what he makes of it (it's all Greek to me)!. However, today we might have come up with a way of simplifying it and getting rid of the separate locking solenoid. Instead, we might be able to do it mechanically, so the program is likely to change anyway. Once again, many thanks!
 
Back
Top