// CONTROLS TESTER MARK II
// V2.0.0
// COPYRIGHT NOTICE:
// This code is the intellectual property of Zachary C. Filka © Sep 2024. All rights
// reserved. Unauthorized use, distribution, or modification of this code is prohibited.
//Refference
// Libraries
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Perameters
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C //0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Digital pin allocations
#define Relay1Pin 2 //Relay. HIGH = Controls, LOW = Continuity
#define LED1 8 //Green LED (Signal 1)
#define LED2 9 //Amber LED (Signal 2)
#define SwitchesEn 10 //Enables the output switches
#define BuzzEnSw 11 //Enables the buzzer
#define BuzzerPin 12 //Buzzer
#define ChargeDet 13 //Detects a charger
// Variables
int Probe0; //Analog value of A0
int Probe1; //Analog value of A1
int Probe2; //Analog value of A2
float v0; //Voltage on pin A0
float v1; //Voltage on pin A1
float v2; //Voltage on pin A2
int Batt; //Battery level read from pin A7
int SelSw; //Mode switch read from pin A6
int EMOTrig; //Int = 1 when EMO is triggered successfully
int DeadBatt; //If battery is under an operatable voltage, int = 1
int Buzzer;
int LastBuzzSwState;
int BuzzCount;
int Blink0;
int Blink1;
int Blink2;
int Count1;
int Count2;
//
void setup() {
//Don't delete
Serial.begin(9600);
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
for(;;);
}
//Digital pin setups
pinMode(ChargeDet, INPUT_PULLUP);
pinMode(BuzzEnSw, INPUT_PULLUP);
pinMode(BuzzerPin, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(SwitchesEn, OUTPUT);
digitalWrite(SwitchesEn, HIGH); //OFF
//Start dead battery screen, R.I.P. battery ),:
Batt=analogRead(A7);
if(Batt<200) {
DeadBatt = 1;
}
//Welcome effect
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.drawRect(30, 35, 68, 1, SSD1306_WHITE);
display.setCursor(24,18);
display.println(F("MARK II"));
display.setTextSize(1);
display.setCursor(37,39);
display.println(F("FILKA KIM"));
display.display();
delay(200);
digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED2, HIGH);
delay(200);
digitalWrite(LED1, LOW);
delay(200);
digitalWrite(LED2, LOW);
delay(800);
}
void loop() {
//Reset Screen
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
//Convert analog values to real voltages
Probe0=analogRead(A0);
v0=(Probe0*0.06)*0.92;
Probe1=analogRead(A1);
v1=(Probe1*0.06)*0.92;
Probe2=analogRead(A2);
v2=(Probe2*0.06)*0.92;
//Start charging battery screen
if(digitalRead(ChargeDet) == LOW) { //Pin that detects charger
ChargingScreen();
return;
}
//Start low battery screen
if(DeadBatt == 1) {
DeadBatteryScreen();
return;
}
//Tab line
display.drawRect(0, 14, 128, 1, SSD1306_WHITE);
//Battery Indicator
Batt=analogRead(A7);
if(Batt>800) {
display.fillRect(108, 4, 3, 6, SSD1306_WHITE);
}
if(Batt>600) {
display.fillRect(112, 4, 3, 6, SSD1306_WHITE);
}
if(Batt>400) {
display.fillRect(116, 4, 3, 6, SSD1306_WHITE);
}
if(Batt>200) {
display.fillRect(120, 4, 3, 6, SSD1306_WHITE);
display.drawRect(106, 2, 19, 10, SSD1306_WHITE);
display.fillRect(104, 4, 2, 6, SSD1306_WHITE);
} else if(Blink0 == 0) {
display.setCursor(69,55);
display.drawRect(106, 2, 19, 10, SSD1306_WHITE);
display.fillRect(104, 4, 2, 6, SSD1306_WHITE);
Blink0 = 1;
} else {
Blink0 = 0;
}
//Main buzzer enable indicator
if(digitalRead(BuzzEnSw) == LOW) {
display.fillRect(4, 4, 3, 6, SSD1306_WHITE);
display.fillRect(7, 3, 1, 8, SSD1306_WHITE);
display.fillRect(8, 2, 1, 10, SSD1306_WHITE);
display.fillRect(11, 5, 1, 4, SSD1306_WHITE);
display.fillRect(14, 4, 1, 6, SSD1306_WHITE);
display.drawPixel(13, 3, SSD1306_WHITE);
display.drawPixel(13, 10, SSD1306_WHITE);
}
//Selector Switch
SelSw=analogRead(A6);
if(SelSw < 256) {
Controls();
} else if(SelSw > 256 && SelSw < 512) {
EMO();
} else if(SelSw > 512 && SelSw < 768) {
Continuity();
} else if(SelSw > 768 && SelSw < 1024) {
AuxPower();
}
}
void Controls() {
//Static Text
display.setCursor(40,4);
display.println(F("CONTROLS"));
//IO
digitalWrite(SwitchesEn, LOW); //ON
digitalWrite(Relay1Pin, LOW);
if(v1 > 22) {
digitalWrite(LED1, HIGH);
} else {
digitalWrite(LED1, LOW);
}
if(v2 > 22) {
digitalWrite(LED2, HIGH);
} else {
digitalWrite(LED2, LOW);
}
//Power voltage meter
display.setCursor(20,24);
display.println(F("POWER:"));
display.setCursor(110,24);
display.println(F("V"));
display.setCursor(75,24);
display.println(v0);
//Signal 1 voltage meter
display.setCursor(10,36);
display.println(F("SIGNAL 1:"));
display.setCursor(110,36);
display.println(F("V"));
display.setCursor(75,36);
display.println(v1);
//Signal 2 voltage meter
display.setCursor(10,48);
display.println(F("SIGNAL 2:"));
display.setCursor(110,48);
display.println(F("V"));
display.setCursor(75,48);
display.println(v2);
//Buzzer
if(digitalRead(BuzzEnSw) == LOW) {
if (LastBuzzSwState == HIGH) {
BuzzCount = (BuzzCount + 1) % 3;
}
if(BuzzCount == 0 || BuzzCount == 2) { //Signal 1 Buzzer
display.fillRect(0, 38, 3, 3, SSD1306_WHITE);
display.fillRect(3, 36, 1, 7, SSD1306_WHITE);
display.drawPixel(2, 37, SSD1306_WHITE);
display.drawPixel(2, 41, SSD1306_WHITE);
display.drawPixel(5, 37, SSD1306_WHITE);
display.drawPixel(5, 41, SSD1306_WHITE);
display.drawRect(6, 38, 1, 3, SSD1306_WHITE);
if(v1 > 22) {
BuzzerLoop();
}
}
if(BuzzCount == 1 || BuzzCount == 2) { //Signal 2 Buzzer
display.fillRect(0, 50, 3, 3, SSD1306_WHITE);
display.fillRect(3, 48, 1, 7, SSD1306_WHITE);
display.drawPixel(2, 49, SSD1306_WHITE);
display.drawPixel(2, 53, SSD1306_WHITE);
display.drawPixel(5, 49, SSD1306_WHITE);
display.drawPixel(5, 53, SSD1306_WHITE);
display.drawRect(6, 50, 1, 3, SSD1306_WHITE);
if(v2 > 22) {
BuzzerLoop();
}
}
}
LastBuzzSwState = digitalRead(BuzzEnSw);
//Draw screen
display.display();
delay(300);
}
void EMO() {
//Static Text
display.setCursor(38,4);
display.println(F("EMO TEST"));
display.setCursor(24,42);
display.println(F("SAFETY 1:"));
display.setCursor(24,54);
display.println(F("SAFETY 2:"));
//IO
digitalWrite(SwitchesEn, HIGH); //OFF
digitalWrite(Relay1Pin, LOW);
//Check signal 1
if(v1 > 22) {
display.setCursor(86,42);
display.println(F("OK"));
digitalWrite(LED1, HIGH);
} else {
display.setCursor(83,42);
display.println(F("N/A"));
digitalWrite(LED1, LOW);
}
//Check signal 2
if(v2 > 22) {
display.setCursor(86,54);
display.println(F("OK"));
digitalWrite(LED2, HIGH);
} else {
display.setCursor(83,54);
display.println(F("N/A"));
digitalWrite(LED2, LOW);
}
//EMO overall status
if(v1 > 22 && v2 > 22) {
display.setTextSize(2);
display.setCursor(12,19);
display.println(F("TENSIONED"));
EMOTrig = 1;
} else if((v1 > 22 && v2 < 22) || (v1 < 22 && v2 >22)) {
display.setTextSize(2);
display.setCursor(28,19);
display.println(F("FAULTY"));
} else if(EMOTrig == 1) {
EMOtriggered(); //Send to triggered sub routine
EMOTrig = 0;
} else {
display.setTextSize(2);
display.setCursor(28,19);
display.println(F("NO EMO"));
}
//Draw screen
display.display();
delay(300);
}
void Continuity() {
//Static text
display.setCursor(34,4);
display.println(F("CONTINUITY"));
//IO
digitalWrite(SwitchesEn, HIGH);
digitalWrite(Relay1Pin, HIGH);
//Draw screen
display.display();
delay(300);
}
void AuxPower() {
//Static text
display.setCursor(39,4);
display.println(F("AUX TEST"));
//IO
digitalWrite(SwitchesEn, HIGH);
digitalWrite(Relay1Pin, LOW);
//Check circuit A
display.setCursor(10,19);
display.println(F("CIRCUIT A:")); //Probe from pin A0
display.setCursor(110,19);
display.println(F("V"));
display.setCursor(75,19);
display.println(v0);
//Check circuit B
display.setCursor(10,31);
display.println(F("CIRCUIT B:")); //Probe from pin A1
display.setCursor(110,31);
display.println(F("V"));
display.setCursor(75,31);
display.println(v1);
display.setCursor(8,43);
display.println(F("BLK: WHT: RED: GRN:"));
if(v0 < 18 && v1 < 18) {
display.setCursor(8,55);
display.println(F("N/A N/A N/A N/A"));
} else {
//Check red conductor
if(v0 > 18) {
display.setCursor(72,55);
display.println(F("OK"));
} else if(Blink1 == 0) {
display.setCursor(69,55);
display.println(F("BAD"));
Blink1 = 1;
} else {
Blink1 = 0;
}
//Check green conductor
if(v1 > 18) {
display.setCursor(102,55);
display.println(F("OK"));
} else if(Blink2 == 0) {
display.setCursor(99,55);
display.println(F("BAD"));
Blink2 = 1;
} else {
Blink2 = 0;
}
}
//Draw screen
display.display();
delay(300);
}
void ChargingScreen() {
//IO
digitalWrite(SwitchesEn, HIGH);
digitalWrite(Relay1Pin, LOW);
//Battery indicator
display.fillRect(27, 15, 81, 35, SSD1306_WHITE);
display.fillRect(20, 22, 7, 21, SSD1306_WHITE);
display.fillRect(30, 18, 75, 29, SSD1306_INVERSE);
display.fillRect(88, 22, 12, 21, SSD1306_WHITE);
//Filling Battery animation
Count1++;
if(Count1 >= 2) {
display.fillRect(71, 22, 12, 21, SSD1306_WHITE);
}
if(Count1 >= 3) {
display.fillRect(54, 22, 12, 21, SSD1306_WHITE);
}
if(Count1 >= 4) {
display.fillRect(37, 22, 12, 21, SSD1306_WHITE);
Count1 = 0;
}
//Draw screen
display.display();
delay(500);
}
void DeadBatteryScreen() {
digitalWrite(Relay1Pin, LOW);
//Battery indicator
display.fillRect(27, 15, 81, 35, SSD1306_WHITE);
display.fillRect(20, 22, 7, 21, SSD1306_WHITE);
display.fillRect(30, 18, 75, 29, SSD1306_INVERSE);
//Flashing battery bar
if(Blink1 == 0) {
display.fillRect(93, 22, 7, 21, SSD1306_WHITE);
Blink1 = 1;
} else {
Blink1 = 0;
}
//Draw screen
display.display();
delay(500);
}
void EMOtriggered() {
for(int Count1 = 0; Count1 < 2; Count1++) {
display.setTextSize(2);
display.setCursor(12,19);
display.println(F("TRIGGERED"));
display.display();
if(digitalRead(BuzzEnSw) == LOW) {
BuzzerLoop();
} else {
delay(1300);
}
display.setTextColor(SSD1306_INVERSE);
display.setCursor(12,19);
display.println(F("TRIGGERED"));
display.setTextColor(SSD1306_WHITE);
display.setCursor(12,19);
display.println(F("CORRECTLY"));
display.display();
delay(1000);
display.setTextColor(SSD1306_INVERSE);
display.setCursor(12,19);
display.println(F("CORRECTLY"));
display.display();
}
}
void BuzzerLoop() {
tone(BuzzerPin, 1000);
delay(800);
noTone(BuzzerPin);
for(int Count2 = 0; Count2 < 3; Count2++) {
delay(100);
tone(BuzzerPin, 1000);
delay(50);
noTone(BuzzerPin);
}
}