If anyone is looking there is a few darkroom enlargers for sale on carousell Malaysia right now.
Edit:
I needed a darkroom timer which I am currently unable to find cheaply or with the right features... so i decided to make a simple one using an Arduino board I had around. So if any one is interested feel free to copy the code.
BOM:
Arduino Uno x1
Arduino LCD Shield x1 (I got both the Arduino and LCD Shield as a package from dx.com
here )
USB power supply x1
Optional Items:
5v Piezo buzzer x1
Jumpers/wire x2
Prototyping PCB x1
Female Headers x4
Soldering Iron x1
Soldering Wire x1
Since my board was already from dfrobot I used their code on their site and edited from there
Arduino LCD KeyPad Shield (SKU: DFR0009). Arduino sketch is in the spoiler bar below. Note that I am a begineer in arduino so my code is quite crappy but it works for me. Feel free to take this and edit to improve it. Basically with this LCD i decided to make a timer that has two independent clocks that can run seperately. By clicking Up (for timer no 1) and Down (for timer no 2) I start the clock and it beeps at every 50 sec and 1 minute mark. I do not have any use for 30 sec audio warnings since rarely do any of my film development or paper printing require 30 sec intervals.
Features:
- 2 Independent timers indicating minutes and seconds with dedicated switches
- Timers are controlled with the Up (Timer 1) and Down (Timer 2) push buttons to Start, Stop and Reset each time they are pressed
- Select button used to stop and reset both timers together
- Audio buzz at every 0, 50 and 60 second marks
- Four buzz indicator that the second timer has passed the 50 and 60 second mark if the two timers are within 10 second of each other
Pictures:
» Click to show Spoiler - click again to hide... «
Arduino Uno and Shield together. Buzzer connected to Digital pin 2 and Ground.
Made a simple box to put it all in.
Couple of cut up disposable chop sticks to make button pressing pssible from outside the box. A red plastic cover from the book shop to provide some safelight capability. This is not 100% safe but I cannot find any rubylith in KL so this will do for now.
All togther now!
Code:
» Click to show Spoiler - click again to hide... «
CODE
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
int bst1 = 0;
const int buzzer = 2;
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
return btnNONE; // when all others fail, return this...
}
// data for timer 1. All notes for timer 1 is applicable for timer 2 which is denoted by number i.e. i1 and i2
int i1 = 0; // data for converted miliseconds to seconds
int m1 = 0; // data for converted seconds to minutes
int s1 = 0; // data to show current seconds of the minute
double a1 = millis(); // start point for timer
double c1; //current point for timer
int st1=0; // state change - 0-reset, 1-running, 2-stopped
// data for timer 2
int i2 = 0;
int m2 = 0;
int s2 = 0;
double a2 = millis();
double c2;
int st2=0;
void setup()
{
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
pinMode(3, OUTPUT);
pinMode(buzzer, OUTPUT);
}
void loop()
{
lcd_key = read_LCD_buttons(); // read the buttons
lcd.clear();
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT: // not in use
{
tone(buzzer, 1000); // Send 1KHz sound signal...
delay(1000); // ...for 1 sec
noTone(buzzer); // Stop sound...
break;
}
case btnLEFT: // not in use
{
break;
}
case btnUP: // button to change timer 1 state
{
if (st1==0) // if state is reset (0) and button is pressed go to state 1 (running) and mark current time in a1
{
st1=1;
a1=millis();
delay(250);
break;
}
else if (st1==1) // if state is running (1) and button is pressed go to state 2 (stopped)
{
st1=2;
delay(250);
break;
}
else if (st1==2) // start timer 2 // if state is stopped and button is pressed go to state 0 (reset)
{
st1=0;
delay(250);
break;
}
break;
}
case btnDOWN: // button to change timer 2 state
{
if (st2==0)
{
st2=1;
a2=millis();
delay(250);
break;
}
else if (st2==1)
{
st2=2;
delay(250);
break;
}
else if (st2==2)
{
st2=0;
delay(250);
break;
}
break;
}
case btnSELECT: // stop both timers and reset by changing state to 0
{
st1=0;
st2=0;
break;
}
case btnNONE: // not in use
{
break;
}
}
if (st1==0) // if state is reset (0) park current and start timer point (a and c) as 0.
{
c1 = 0;
a1 = 0;
i1 = (c1 - a1) / 1000;
m1 = i1 / 60;
s1 = i1-(m1*60);
lcd.setCursor(0,0);
lcd.print ("T1:");
lcd.setCursor(4,0);
lcd.print(m1);
lcd.setCursor(6,0);
lcd.print("Min");
lcd.setCursor (10,0);
lcd.print(s1);
lcd.setCursor(13,0);
lcd.print("Sec");
//lcd.setCursor(0,0);
Serial.println(c1);
Serial.println(a1);
Serial.println(i1);
Serial.println("......");
//delay(250);
};
if (st1==1) //if state is running (1) current timer point is constantly updated with timer. difference between current running time and start timer point gives time since state change
{
c1 = millis(); //updates current time since state change
i1 = (c1 - a1) / 1000; //calculate time since state change
m1 = i1 / 60; //calculate time in minutes that has ecliped
s1 = i1-(m1*60); //calculates time in seconds since last minute has ecliped
lcd.setCursor(0,0);
lcd.print ("T1:");
lcd.setCursor(4,0);
lcd.print(m1);
lcd.setCursor(6,0);
lcd.print("Min");
lcd.setCursor (10,0);
lcd.print(s1);
lcd.setCursor(13,0);
lcd.print("Sec");
//lcd.setCursor(0,0);
Serial.println(c1);
Serial.println(a1);
Serial.println(i1);
Serial.println("......");
//delay(250);
};
if (st1==2) // if state is stopped (2) current timer point (c) is no longer updated but calculation to show time difference between current and start timer points continues (c1 - a1)
{
//c1 = millis();
i1 = (c1 - a1) / 1000;
m1 = i1 / 60;
s1 = i1-(m1*60);
lcd.setCursor(0,0);
lcd.print ("T1:");
lcd.setCursor(4,0);
lcd.print(m1);
lcd.setCursor(6,0);
lcd.print("Min");
lcd.setCursor (10,0);
lcd.print(s1);
lcd.setCursor(13,0);
lcd.print("Sec");
//lcd.setCursor(0,0);
Serial.println(c1);
Serial.println(a1);
Serial.println(i1);
Serial.println("......");
//delay(250);
};
if (st2==0)
{
c2 = 0;
a2 = 0;
i2 = (c2 - a2) / 1000;
m2 = i2 / 60;
s2 = i2-(m2*60);
lcd.setCursor(0,1);
lcd.print ("T2:");
lcd.setCursor(4,1);
lcd.print(m2);
lcd.setCursor(6,1);
lcd.print("Min");
lcd.setCursor (10,1);
lcd.print(s2);
lcd.setCursor(13,1);
lcd.print("Sec");
lcd.setCursor(0,1);
Serial.println(c2);
Serial.println(a2);
Serial.println(i2);
Serial.println("......");
//delay(250);
};
if (st2==1)
{
c2 = millis();
i2 = (c2 - a2) / 1000;
m2 = i2 / 60;
s2 = i2-(m2*60);
lcd.setCursor(0,1);
lcd.print ("T2:");
lcd.setCursor(4,1);
lcd.print(m2);
lcd.setCursor(6,1);
lcd.print("Min");
lcd.setCursor (10,1);
lcd.print(s2);
lcd.setCursor(13,1);
lcd.print("Sec");
lcd.setCursor(0,1);
Serial.println(c2);
Serial.println(a2);
Serial.println(i2);
Serial.println("......");
//delay(250);
};
if (st2==2)
{
//c1 = millis();
i2 = (c2 - a2) / 1000;
m2 = i2 / 60;
s2 = i2-(m2*60);
lcd.setCursor(0,1);
lcd.print ("T2:");
lcd.setCursor(4,1);
lcd.print(m2);
lcd.setCursor(6,1);
lcd.print("Min");
lcd.setCursor (10,1);
lcd.print(s2);
lcd.setCursor(13,1);
lcd.print("Sec");
lcd.setCursor(0,1);
Serial.println(c2);
Serial.println(a2);
Serial.println(i2);
Serial.println("......");
//delay(250);
};
if ((st1==1 && s1==0) || (st2==1 && s2==0) || (st1==1 && s1==50) || (st2==1 && s2==50))
{
tone(buzzer, 2500); // Send 2.5KHz sound signal...
}
delay(250);
if ((s1>0 && s1<10) || (s2>0 &&s2<10) || (s1>50 && s1<59) || (s2>50 &&s2<59))
{
noTone(buzzer); // Stop sound...
}
}
Total time to build including learning the codes: 3-4 hours
Hope this helps!
This post has been edited by CocoMonGo: Jul 14 2018, 02:11 PM