/*
Fan Tester created by JIMMY HO - WELLEGION INDUSTRIES
REV 1.0.0
Date: 2023/08/07
MODEL - 3-WIRE DC FAN Tester
Able to test up to 10 differint Fan Model
Function Test lists-
(1)Voltage reading
(2)Current reading
(3)RPM reading
ARDUINO PIN DEFINED
------------------------------------
A0 = Current Sensor
A1 = Voltage Sensor
A2 = PWM Control
A3 = Buzzer
A4 = I2C LCD SDA
A5 = I2C LCD SCL
D2 = FAN RPM read
D3 = TEST RUNNING Indicator LED
D4 = TEST FAIL Indicator LED
D5 = TEST PASS Indicator LED
D6 = VCC_CHECK
D7 = GND_CHECK
D8 = TACHO_CHECK
D9 = Push to Start Testing
D10 = Push to Change Fan Model
D11 = Supply 24VDC to FAN
D12 = Supply 12VDC to FAN
D13 = Supply 5VDC to FAN
------------------------------------
*/
#include <LiquidCrystal_I2C.h> // Using this library for I2C LCD
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x3F for a 20 chars and 4 line display
// integer pin for Relay and Push Button
const int FAN_24VDC = 11;
const int FAN_12VDC = 12;
const int FAN_5VDC = 13;
const int START_BUTTON = 9;
const int CHANGE_MODEL = 10;
// interger pin for BUZZER
const int BUZZER = A3;
// interger count = 1
int model_count = 1;
// integer pin for Indicator LED
const int TEST_RUN = 3;
const int TEST_FAIL = 6;
const int TEST_PASS = 5;
// integer for test pass requirement
float test_voltage = 23;
float test_current = 0.4;
float test_rpm = 5500;
// integer for Short Test before RUN
const int VCC_CHECK = 4;
const int GND_CHECK = 7;
const int TACHO_CHECK = 8;
int value2;
// integer for RPM read
int value;
int count = 0;
int rpm;
unsigned long start_time;
// integer for Voltage Sense
const int VoltageSensor = A1;
int sum = 0;
unsigned char sample_count = 0;
float voltage = 0.0;
float voltage_result = 0.0;
float vOUT = 0.0;
float vIN = 0.0;
float R1 = 30000.0;
float R2 = 7500.0;
// integer for Current Sense
const int CurrentSensor = A0;
float average;
float current;
int value1 = 0;
int i = 0;
unsigned long endTime;
// start create custom characters
byte blank[8] = {B00000, B00000, B01110, B01110,
B01110, B01110, B00000, B00000
};
byte blank1[8] = {B00000, B00000, B00000, B11111,
B11111, B00000, B00000, B00000
};
byte blank2[8] = {B00100, B00100, B00100, B00100,
B00100, B00100, B00100, B00100
};
byte fan1[8] = {B00000, B00000, B00000, B00000,
B01110, B11111, B11111, B00001
};
byte fan2[8] = {B00000, B00000, B00000, B01100,
B01110, B01110, B01110, B11100
};
byte fan3[8] = {B00111, B01110, B01110, B01110,
B00110, B00000, B00000, B00000
};
byte fan4[8] = {B10000, B11111, B11111, B01110,
B00000, B00000, B00000, B00000
};
byte five[8] = {B11111, B11111, B11111, B11111,
B11111, B11111, B11111, B11111
};
// end create custom characters
void counter() {
count++;
}
void setup()
{
Serial.begin(9600); // initializes the Serial Monitor with 9600
lcd.begin(20, 4); // initializes the interface to the LCD screen
lcd.init(); // initialization LCD
lcd.backlight(); // turn on back light
lcd.clear(); // clear LCD screen
// start createchar for custom character
lcd.createChar(0, blank);
lcd.createChar(1, blank1);
lcd.createChar(2, blank2);
lcd.createChar(3, fan1);
lcd.createChar(4, fan2);
lcd.createChar(5, fan3);
lcd.createChar(6, fan4);
lcd.createChar(7, five);
// end createchar for custom character
// set pinMode
pinMode(FAN_24VDC, OUTPUT);
pinMode(FAN_12VDC, OUTPUT);
pinMode(FAN_5VDC, OUTPUT);
pinMode(START_BUTTON, INPUT);
pinMode(CHANGE_MODEL, INPUT_PULLUP);
pinMode(TEST_RUN, OUTPUT);
pinMode(TEST_FAIL, OUTPUT);
pinMode(TEST_PASS, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), counter, RISING); // Blue Wire with 5V pullup
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("W");
delay(50);
lcd.print("E");
delay(50);
lcd.print("L");
delay(50);
lcd.print("L");
delay(50);
lcd.print("E");
delay(50);
lcd.print("G");
delay(50);
lcd.print("I");
delay(50);
lcd.print("O");
delay(50);
lcd.print("N");
delay(50);
lcd.print(" ");
delay(50);
lcd.print("I");
delay(50);
lcd.print("N");
delay(50);
lcd.print("D");
delay(50);
lcd.print("U");
delay(50);
lcd.print("S");
delay(50);
lcd.print("T");
delay(50);
lcd.print("R");
delay(50);
lcd.print("I");
delay(50);
lcd.print("E");
delay(50);
lcd.print("S");
delay(50);
lcd.setCursor(4, 2); // set Cursor to 4,2
lcd.print("(");
delay(50);
lcd.print("M");
delay(50);
lcd.print(")");
delay(50);
lcd.print(" ");
delay(50);
lcd.print("S");
delay(50);
lcd.print("D");
delay(50);
lcd.print("N");
delay(50);
lcd.print(" ");
delay(50);
lcd.print("B");
delay(50);
lcd.print("H");
delay(50);
lcd.print("D");
delay(500);
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.write(0);
delay(50);
lcd.write(1);
delay(50);
lcd.write(1);
delay(50);
lcd.write(0);
delay(50);
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.write(2);
delay(50);
lcd.write(3);
delay(50);
lcd.write(4);
delay(50);
lcd.write(2);
delay(50);
lcd.setCursor(0, 2); // set cursor to 0,2
lcd.write(2);
delay(50);
lcd.write(5);
delay(50);
lcd.write(6);
delay(50);
lcd.write(2);
delay(50);
lcd.setCursor(0, 3); // set cursor to 0,3
lcd.write(0);
delay(50);
lcd.write(1);
delay(50);
lcd.write(1);
delay(50);
lcd.write(0);
delay(50);
lcd.setCursor(9, 0); // set cursor to 10,1
lcd.print("3");
delay(50);
lcd.print("-");
delay(50);
lcd.print("W");
delay(50);
lcd.print("I");
delay(50);
lcd.print("R");
delay(50);
lcd.print("E");
delay(50);
lcd.setCursor(6, 1); // set cursor to 10,1
lcd.print("D");
delay(50);
lcd.print("C");
delay(50);
lcd.print(" ");
delay(50);
lcd.print("F");
delay(50);
lcd.print("A");
delay(50);
lcd.print("N");
delay(50);
lcd.print(" ");
delay(50);
lcd.print("T");
delay(50);
lcd.print("E");
delay(50);
lcd.print("S");
delay(50);
lcd.print("T");
delay(50);
lcd.print("E");
delay(50);
lcd.print("R");
delay(50);
lcd.setCursor(16, 3); // set Cursor to 8,2
lcd.print("V");
delay(50);
lcd.print("1");
delay(50);
lcd.print(".");
delay(50);
lcd.print("0");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("FUNCTION TEST LISTS:-");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("(1) VOLTAGE (V)");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("(2) CURRENT (A)");
lcd.setCursor(0, 3); // set Cursor to 0,3
lcd.print("(3) SPEED (RPM)");
delay(3000);
lcd.clear();
lcd.setCursor(1, 0); // set Cursor to 0,0
lcd.print("------------------");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("|FAN MODEL SELECT: |");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("| (1) 414J/2HH |");
lcd.setCursor(1, 3); // set Cursor to 0,3
lcd.print("------------------");
}
void loop()
{
int value2 = 0;
if (digitalRead(CHANGE_MODEL) == LOW)
{
model_count++;
delay(100);
if (model_count > 5)
{
model_count = 1;
}
switch(model_count)
{
case 1:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
lcd.clear();
lcd.setCursor(1, 0); // set Cursor to 0,0
lcd.print("------------------");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("|FAN MODEL SELECT: |");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("| (1) 414J/2HH |");
lcd.setCursor(1, 3); // set Cursor to 0,3
lcd.print("------------------");
break;
case 2:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
lcd.clear();
lcd.setCursor(1, 0); // set Cursor to 0,0
lcd.print("------------------");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("|FAN MODEL SELECT: |");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("| (2) 624/2HH |");
lcd.setCursor(1, 3); // set Cursor to 0,3
lcd.print("------------------");
break;
case 3:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
lcd.clear();
lcd.setCursor(1, 0); // set Cursor to 0,0
lcd.print("------------------");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("|FAN MODEL SELECT: |");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("| (3) FAN 3 |");
lcd.setCursor(1, 3); // set Cursor to 0,3
lcd.print("------------------");
break;
case 4:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
lcd.clear();
lcd.setCursor(1, 0); // set Cursor to 0,0
lcd.print("------------------");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("|FAN MODEL SELECT: |");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("| (4) FAN 4 |");
lcd.setCursor(1, 3); // set Cursor to 0,3
lcd.print("------------------");
break;
case 5:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
lcd.clear();
lcd.setCursor(1, 0); // set Cursor to 0,0
lcd.print("------------------");
lcd.setCursor(0, 1); // set Cursor to 0,1
lcd.print("|FAN MODEL SELECT: |");
lcd.setCursor(0, 2); // set Cursor to 0,2
lcd.print("| (5) FAN 5 |");
lcd.setCursor(1, 3); // set Cursor to 0,3
lcd.print("------------------");
break;
}
}
else {
if (digitalRead(START_BUTTON) == LOW)
{
switch(model_count){
case 1:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
FAN1();
break;
case 2:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
FAN2();
break;
case 3:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
FAN3();
break;
case 4:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
FAN4();
break;
case 5:
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
FAN5();
break;
}
}
}
}
void FAN1()
{
int value2 = 0;
digitalWrite(TEST_FAIL, LOW);
digitalWrite(TEST_PASS, LOW);
digitalWrite(TEST_RUN, HIGH);
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("MODEL: 414J/2HH");
lcd.setCursor(0,1); // set Cursor to 0,1
lcd.print("Fan Connection Check");
delay(1500);
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("MODEL: 414J/2HH");
lcd.setCursor(0,1); // set Cursor to 0,1
lcd.print("VCC = ");
pinMode(VCC_CHECK, OUTPUT);
pinMode(GND_CHECK, INPUT);
pinMode(TACHO_CHECK, INPUT);
digitalWrite(VCC_CHECK, HIGH);
delay(100);
if (digitalRead(GND_CHECK) == HIGH)
{lcd.print("FAIL");
value2++;}
else
{
if (digitalRead(TACHO_CHECK) == HIGH)
{lcd.print("FAIL");
value2++;}
else
{lcd.print("PASS");}
}
digitalWrite(VCC_CHECK, LOW);
delay(100);
lcd.setCursor(0,2); // set Cursor to 0,1
lcd.print("GND = ");
pinMode(VCC_CHECK, INPUT);
pinMode(GND_CHECK, OUTPUT);
pinMode(TACHO_CHECK, INPUT);
digitalWrite(GND_CHECK, HIGH);
delay(100);
if (digitalRead(VCC_CHECK) == HIGH)
{lcd.print("FAIL");
value2++;}
else
{
if (digitalRead(TACHO_CHECK) == HIGH)
{lcd.print("FAIL");
value2++;}
else
{lcd.print("PASS");}
}
digitalWrite(GND_CHECK, LOW);
delay(100);
lcd.setCursor(0,3); // set Cursor to 0,1
lcd.print("TACHO = ");
pinMode(VCC_CHECK, INPUT);
pinMode(GND_CHECK, INPUT);
pinMode(TACHO_CHECK, OUTPUT);
digitalWrite(TACHO_CHECK, HIGH);
delay(100);
if (digitalRead(VCC_CHECK) == HIGH)
{lcd.print("FAIL");
value2++;}
else
{
if (digitalRead(GND_CHECK) == HIGH)
{lcd.print("FAIL");
value2++;}
else
{lcd.print("PASS");}
}
digitalWrite(TACHO_CHECK, LOW);
delay(100);
lcd.setCursor(8,2);
if (value2 > 0)
{ digitalWrite(TEST_RUN, LOW);
digitalWrite(TEST_FAIL, HIGH);
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
delay(100);
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
delay(100);
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
delay(100);
tone(BUZZER,6000);
delay(100);
noTone(BUZZER);
}
else
{delay(100);
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("MODEL: 414J/2HH");
lcd.setCursor(0,1); // set Cursor to 0,1
lcd.print("Continuity Passed");
lcd.setCursor(0,2); // set Cursor to 0,2
delay(2000);
lcd.clear(); // clear LCD screen
digitalWrite(FAN_24VDC, HIGH); // turn on DUT fan
digitalWrite(TEST_PASS, LOW); // turn off test pass indicator led
digitalWrite(TEST_FAIL, LOW); // turn off test fail indicator led
// set cursor to 0,0
lcd.write(3);
lcd.write(4);
lcd.print(" WARMING UP ");
lcd.write(3);
lcd.write(4);
lcd.setCursor(0, 1); // set cursor to 0,1
lcd.write(5);
lcd.write(6);
lcd.print(" DC FAN ");
lcd.write(5);
lcd.write(6);
lcd.setCursor(0, 2); // set cursor to 0,2
delay(1000);
lcd.write(7);
lcd.write(7);
lcd.write(7);
lcd.write(7);
delay(1000);
lcd.write(7);
lcd.write(7);
lcd.write(7);
lcd.write(7);
delay(1000);
lcd.write(7);
lcd.write(7);
lcd.write(7);
lcd.write(7);
delay(1000);
lcd.write(7);
lcd.write(7);
lcd.write(7);
lcd.write(7);
delay(1000);
lcd.write(7);
lcd.write(7);
lcd.write(7);
lcd.write(7);
endTime = millis() + 11000;
Testing1:
if (millis() <= endTime)
{
digitalWrite(FAN_24VDC, HIGH); // turn on DUT fan
digitalWrite(TEST_PASS, LOW); // turn off test pass indicator led
// Calculation for RPM read and PWM control
start_time = millis();
count = 0;
while ((millis() - start_time) < 1000) {}
rpm = count * 30;
Serial.print("Speed = ");
Serial.print(rpm);
Serial.println(" rpm");
// Calculation for Voltage Sense
while (sample_count < 20)
{
sum += analogRead(VoltageSensor);
sample_count++;
delay(10);
}
voltage = ((float) sum / 20 * 5.0) / 1024;
voltage_result = voltage * 5 ;
Serial.print("Voltage = ");
Serial.print(voltage_result, 3);
Serial.println(" V");
// Calculation for Current Sense
for (i = 0; i < 20; i++)
{
average = average + (.0264 * analogRead(CurrentSensor) - 13.51) / 20;
current = average / 1.35 ;
delay(10); // delay for 0.01 sec
}
Serial.print("Current = ");
Serial.print(current, 3);
Serial.println(" A");
if ( voltage_result < 18 )
{
voltage_result = 0;
}
if ( current < 0)
{
current = 0;
}
// DATA CAPTURED show in LCD
lcd.clear(); // clear LCD screen
lcd.setCursor(0, 0); // set cursor to 0,0
lcd.print("Voltage = ");
lcd.print(voltage_result, 3);
lcd.print(" V");
lcd.setCursor(0, 1); // set cursor to 0,1
lcd.print("Current = ");
lcd.print(current, 3);
lcd.print(" A");
lcd.setCursor(0, 2); // set cursor to 0,2
lcd.print("SPEED = ");
lcd.print(rpm);
lcd.print(" rpm");
average = 0;
sample_count = 0;
sum = 0;
if ( voltage_result > test_voltage && current > test_current && rpm > test_rpm )
{
digitalWrite(FAN_24VDC, LOW); // turn off DUT fan
digitalWrite(TEST_RUN, LOW); // turn off test run indicator led
digitalWrite(TEST_PASS, HIGH); // turn on test pass indicator led
}
else
{goto Testing1;}
}
else
{
digitalWrite(FAN_24VDC, LOW); // turn off DUT fan
digitalWrite(TEST_RUN, LOW); // turn off test run indicator led
digitalWrite(TEST_FAIL, HIGH); // turn on test fail on first loop led
}
}
}
void FAN2()
{
int value2 = 0;
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("FAN2 TEST");
}
void FAN3()
{
int value2 = 0;
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("FAN3 TEST");
}
void FAN4()
{
int value2 = 0;
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("FAN4 TEST");
}
void FAN5()
{
int value2 = 0;
lcd.clear();
lcd.setCursor(0, 0); // set Cursor to 0,0
lcd.print("FAN5 TEST");
}