Hello,
I am working on a program for my Arduino UNO R3.
My goals are the following:
- detect presence of magnetic switch (Magnetic contact switch (door sensor) : ID 375 : $3.95 : Adafruit Industries, Unique & fun DIY electronics and kits)
- IF switch is detected, allow user to set the timer using an encoder (Rotary Encoder + Extras : ID 377 : $4.50 : Adafruit Industries, Unique & fun DIY electronics and kits) and 4 x 7 segment LED display (SparkFun 7-Segment Serial Display - Blue - COM-11442 - SparkFun Electronics)
- IF the encoder button is pressed down, begin counting down AND enable the Relay (SparkFun Beefcake Relay Control Kit (Ver. 2.0) - KIT-13815 - SparkFun Electronics) for a given time period (would alternate between on and off)
- IF the button is pressed again, allow the user to again set the time and turn off the Relay
- When the timer expires, turn off the Relay
- IF the magnetic switch does not detect a magnet, PAUSE everything and wait until it does.
my code looks like this so far:
#include <SoftwareSerial.h>
//CONFIGURATION:////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Connect 7 Segment LED with RX at Pin 7 and SS at Pin 8
SoftwareSerial Serial7Segment(8, 7);
//Configures the pins for the Encoder:
//Connect Pin A of encoder to Pin 14 (A0) and Pin C of encoder to Pin 15 (A1), Pin B goes to ground
//Connect Button to either encoder pins, other goes to ground
enum enDigitalPins
{
dpInEncoderA=14,
dpInEncoderB=15,
dpInEncoderPress=12,
};
#define MagSwitch 13
#define Relay 9
// this value determines how many seconds are incremented each time the encoder is rotated
int increment = 10;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DEFINITIONS:
long millisTimer;
byte seconds = 00;
byte minutes = 00;
byte hours = 00;
int mode = 0;
char tempString[100]; //Used for sprintf
#define COLON 4
#define Set_Timer 0
#define Run_Timer 1
boolean colonOn = false;
boolean Timer_Pause = false;
static void _ResetPins()
{
// Rotary encoder input lines
// Configure as input, turn on pullup resistors
pinMode(dpInEncoderA, INPUT);
digitalWrite(dpInEncoderA, HIGH);
pinMode(dpInEncoderB, INPUT);
digitalWrite(dpInEncoderB, HIGH);
pinMode(dpInEncoderPress, INPUT);
digitalWrite(dpInEncoderPress, HIGH);
digitalWrite(MagSwitch, INPUT);
pinMode(MagSwitch, LOW);
digitalWrite(Relay, OUTPUT);
pinMode(Relay, LOW);
Serial7Segment.write(0x77); // Decimal, colon, apostrophe control command
Serial7Segment.write(1<<COLON);
}
void _lowlevel_ReadEncoder(int &rotate, int& press)
{
rotate = (digitalRead(dpInEncoderB) * 2) + digitalRead(dpInEncoderA);
press = digitalRead(dpInEncoderPress);
}
//////////////////////////////////////////////////////////////////////////////////////////////
void ReadEncoder() //Reads the State of the Encoder and adjust the Display accordingly. CW rotation = + "increment" seconds, CCW = - "increment" seconds
{
int Position, Press;
int isForward = 0;
seconds = constrain (seconds, -1, 60); //constrains the seconds value between -1 and 60
_ResetPins();
_lowlevel_ReadEncoder(Position, Press);
int Position2, Press2;
do
{
_lowlevel_ReadEncoder(Position2, Press2);
}
while ((Position2 == Position) && (Press2 == Press));
if (Position2 != Position) //if there is a poisition change:
{
// "Forward" is shown by the position going from (0 to 1) or (1 to 3)
// or (3 to 2) or (2 to 0). Anything else indicates that the user is
// turning the device the other way. Remember: this is Gray code, not
// binary.
int isFwd = ((Position == 0) && (Position2 == 1)) ||
((Position == 1) && (Position2 == 3)) ||
((Position == 3) && (Position2 == 2)) ||
((Position == 2) && (Position2 == 0));
if (isFwd == 1) //if Encoder is moved forwards (CW), advance seconds by defined increment value
{
delay(50); // prevents bad readings
seconds= seconds + increment;
}
if (isFwd == 0) // if encoder is moved backwards(CCW):
{
delay(50);
if (seconds == 0)// if we are already at zero seconds, check to make sure we can reduce a minute
{
if (minutes > 0)// if the minutes can be reduced (i.e. not zero) then remove one minute and reset seconds to 59
{
minutes --;
seconds = 50;
}
}
else
{
seconds = seconds - increment;//if seconds were not = 0, then decrease seconds value by the increment value
}
}
}
if (seconds>59) // When seconds = 60:
{
minutes++; // Add one minute
seconds -= 60; // Reset seconds
}
if (Press2 != Press) //if the encoder is pressed down:
{
mode = Run_Timer;
}
Position = Position2;
Press = Press2;
Serial7Segment.print('v');
sprintf(tempString, "%02d%02d", minutes, seconds);
Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
void countdownTimer() //this will start counting down from the time set using the encoder. This begins when the encoder button is pressed.
{
seconds = constrain (seconds, -1, 60);
if (Timer_Pause == false)
{
if( (millis() - millisTimer) > 1000)
{
millisTimer += 1000; //Adjust the timer forward 1 second
if (seconds == 0)// if we are already at zero seconds, check to make sure we can reduce a minute
{
if (minutes > 0)// if the minutes can be reduced (i.e. not zero) then remove one minute and reset seconds to 59
{
minutes --;
seconds = 59;
}
}
else{
seconds--;//if seconds were not = 0, then decrease seconds value by the increment value
}
sprintf(tempString, "%02d%02d", minutes, seconds);
Serial7Segment.print('v'); //Send serial string out the soft serial port to the S7S
Serial7Segment.write(0x77); // Decimal, colon, apostrophe control command
Serial7Segment.write(1<<COLON); // Turns on colon, apostrophoe, and far-right decimal
Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S
// Serial.println(tempString);
}
if (minutes == 0 & seconds == 0)
{
//do nothing
}
}
else
{
}
}
void setup()
{
// configure the pins
_ResetPins();
// init serial communication
Serial.begin(9600);
Serial.println("Ready to begin");
Serial7Segment.begin(9600); //Talk to the Serial7Segment at 9600 bps
Serial7Segment.write('v'); //Reset the display - this forces the cursor to return to the beginning of the display
Serial7Segment.print("0000"); //Send the hour and minutes to the display
}
void loop()
{
if (digitalRead(MagSwitch) == LOW){ //if magnetic switch is detected
// switches modes depending on button press
switch(mode){
case (Set_Timer): //reads encoder and sets time
ReadEncoder();
break;
case (Run_Timer): //counts down timer
Timer_Pause = false;
countdownTimer();
digitalWrite(Relay, HIGH); //SHOULD turn on the Relay (loops too fast?)
break;
}
}
else if (digitalRead(MagSwitch) == HIGH) //if no magnetic switch detected
{
Timer_Pause = true; //pause the timer
}
}
I pieced it together with various bits of code I found online. I am pretty new to Arduino programming, and would love some help.
Currently, my program works well to set the time and count down. I am having issues with the timer stopping when the magnetic switch isn't there. In addition, my Relay won't turn off!
Any help is appreciated!
Thanks,
Sam
Moderator edit:
</mark> <mark>[code]</mark> <mark>
</mark> <mark>[/code]</mark> <mark>
tags added.
edit: added links to parts