Here's the updated project that includes a 4 digit display module, alarm sound, ON LED and power supply.
Note that Attiny85 is set to 8Mhz clock. Programming was done using an Arduino Micro operating as ISP. Will share about the programming board, issues and how to program the Attiny85 in another post.
Due to limited I/O pins on Attiny85, had to utilize some tricks to expand its capability by using the analog input for time adjust also as a digital input. This is achieved by limiting the lower end voltage selected by the potentiometer to about half of vcc, so about 2.5V. So when turned all the way in one direction, analog input will read minimum of 2.5V ( zero seconds timer) and on the other direction 5V (240 seconds timer). Same input will be close to 0V when the start button is pressed, providing the digital check for the start function. In fact, this process can be expanded by subdividing the VCC into smaller buckets, but not required for this project.
Schematics:
Board:
Will post a video of working timer one board is assembled.
Click here for Eagle and Arduino code files
Arduino display library found in GitHub
here. This is a simple library that actually works. I have spent a whole lot of time searching and testing other libraries.
Here's how it operates:
1-Time in seconds is displayed , adjustable by the potentiometer. Range is software defined, example code range is 0 to 240s.
2- After time is adjusted, one quick press (1/2 sec) on the start button will initiate the countdown, relay is commanded, LED will light and time left is displayed until it reaches zero.
3- When count down is completed, relay will release as well as LED will turn OFF. Adjusted time will now be displayed and we are basically back to step 1
4- If start button is pressed again after countdown started, timer will reset and goes back to step1
5- A short beep is added on every touch of the start button and an intermittent alarm will sound at end of countdown. Pressing the start button when alarm is on-going will stop it.
Arduino code is below, also found on the provided link.
#include <TM1637Display.h> //library for display module
#include <elapsedMillis.h> // library for timing
elapsedMillis timer=0; // set timer variable
int timer2=0;
int p=0;
TM1637Display display(2, 0); //defines logic pins which display module is connected in attiny, display(CLK=2,DIO=0)
byte data[] = {0, 0, 0, 0}; // variable array that define values of display digits
void setup() {
pinMode(A3,INPUT);//attiny85 pin 2/PB3/A3
pinMode(1,OUTPUT);//attiny85 pin 6/PB1/D1 output relay
pinMode(0,OUTPUT);//attiny85 pin 5/PB0/D0 display data
pinMode(2,OUTPUT);//attiny85 pin 7/PB2/D2 display clk
pinMode(4,OUTPUT);//attiny85 pin 3/PB4/D4 output buzz
digitalWrite(1,LOW); // initiate relay off
digitalWrite(4,LOW); // initiate buzz off
timer=0;
display.setBrightness(0x0f); // set display brightness to max
}
void loop() {
int8_t TimeDisp[] = {0x00,0x00,0x00,0x00};
int x=0;
if(analogRead(A3)>200 &&digitalRead(1)==LOW ){ // check if start is released. When start is pressed, voltage at pin A3 is close to 0V, otherwise it is defined by the potentiometer but limited to range around 2.5 to 5V
timer2=0;
for (x=1;x<=30;x++){ //number of times the A3 input is read to average input time
timer2=timer2+constrain(map(analogRead(A3),515,1023,0,240),0,240); // reads analog input A3, specify digital range of 515 to 1023 and map to variable from 0 to 240 seconds
}
timer2=timer2/30; //calculate average
}
if (analogRead(A3)<100){//Check if start is pressed. A3 will be close to 0V if pressed.
p=1; // variable to indicate timer is in active mode
digitalWrite(4,HIGH);// short beed
delay(100);
digitalWrite(4,LOW);
delay(100);
}
if(digitalRead(1)==HIGH) //verify if relay output is activated for display mode selection
{
//next 6 commands display the time left for countdown mode
data[0] = display.encodeDigit((timer2-timer/1000) / 1000 % 10);
data[1]= display.encodeDigit((timer2-timer/1000) / 100 % 10);
data[2] = display.encodeDigit((timer2-timer/1000) / 10 % 10);
data[3] = display.encodeDigit((timer2-timer/1000) % 10);
display.setSegments(data); // muestra la variable byte data
delay(100);
}
else
{
//next 6 commands display de setup time, vary with potentiomenter position
data[0] = display.encodeDigit((timer2) / 1000 % 10);
data[1]= display.encodeDigit((timer2) / 100 % 10);
data[2] = display.encodeDigit((timer2) / 10 % 10);
data[3] = display.encodeDigit((timer2)/1 % 10);
display.setSegments(data); // muestra la variable byte data
delay(100);
}
if (p==1){//check if current timer state is activated
if (analogRead(A3)>200){//check if start button is released
digitalWrite(1,!digitalRead(1)); // invert state of relay output when button is pressed. If previsouly active, set it to LOW, if previously OFF, set it to HIGH.
timer=0;
p=0;
delay(500); //timer to wait to avoid long press of button to be interpreted as mutiple pushes
}//C
}//D
if ((timer/1000)>timer2 && digitalRead(1)==HIGH ){//G countdown finished when in active mode
digitalWrite(1,LOW);// release relay
for (x=0;x<=20;x++){ // loop to beep alarm for 20 times
if (analogRead(A3)<100){ // check if start is pressed to interrupt alarm beeping
x=21;//set variable to end value to exit loop
delay(100);
}
digitalWrite(4,HIGH); // alarm beep
delay(100);//define interval of alarme beeps on
if (analogRead(A3)<100){// check if start is pressed to interrupt alarm beeping
x=21; //set variable to end value to exit loop
delay(100);
}
digitalWrite(4,LOW);
delay(100);//define interval of alarme beeps off
if (analogRead(A3)<100){// check if start is pressed to interrupt alarm beeping
x=21;//set variable to end value to exit loop
delay(100);
}
}
}//G
}