#include <Wire.h>
#include <EEPROM.h>
#include <elapsedMillis.h>
#include <JC_Button.h>
#include <OneWire.h>
#include "ABlocks_LiquidCrystal_I2C.h"
boolean b_Error = false;
char Print_Buffer[8] = "";
double Amperage = 0;
double Amp_Max = 0;
double Voltage = 0;
double Joules = 0;
const double Max_Amperes = 27.5;
const double V_Constant = 8.2750;
int Anneal_Time = 2500;
int Case_Program_Num = 0;
int Actual_Time = 0;
int Joule_Time = 0;
int Mode = 0;
int Anneal_Energy = 1200;
int Glow = 1023;
int Glow_Set = 50;
int16_t C_Temp;
int16_t Last_Temp = 20;
const int A_Constant = 530;
const int ls_Case_Name_size = 10;
const int Test_Anneal_Time = 2500;
const int Case_Settle = 500;
const int Drop_Delay = 10;
const int Door_Close = 10;
const int Detector_Threshold = 500;
const int Fan_On_Temp = 120;
const int Test_Anneal_Energy = 1200;
const int Case_Glow_Program_Num = 20;
String s_Case_Text;
String s_Error_Text;
String s_Mode_Text;
String ls_Case_Name[10] = {
String("*AUTO MODE*"),
String("NATO 5.56 "),
String("6.5 PRC "),
String("300 WBY "),
String("Four "),
String("Five "),
String("Six "),
String("Seven "),
String("Eight "),
String("Test ")};
LiquidCrystal_I2C lcd(0x27,20,4);
Button
Tm_Up(2),
Tm_Dn(3),
Pgm_Up(4),
Pgm_Dn(5),
Int_Err(6);
elapsedMillis Annealing;
elapsedMillis Measuring;
void fnc_EEPROM_updateDouble(int ee, double value) {
byte* p = (byte*)(void*)&value;
for (int i = 0; i < sizeof(value); i++)
EEPROM.update(ee++, *p++);
}
double fnc_EEPROM_readDouble(int ee) {
double value = 0.0;
byte* p = (byte*)(void*)&value;
for (int i = 0; i < sizeof(value); i++)
*p++ = EEPROM.read(ee++);
return value;
}
void EEPROM_Initialize() {
fnc_EEPROM_updateDouble((int)(0*4),3000);
fnc_EEPROM_updateDouble((int)(1*4),3000);
fnc_EEPROM_updateDouble((int)(2*4),3000);
fnc_EEPROM_updateDouble((int)(3*4),3000);
fnc_EEPROM_updateDouble((int)(4*4),3000);
fnc_EEPROM_updateDouble((int)(5*4),3000);
fnc_EEPROM_updateDouble((int)(6*4),3000);
fnc_EEPROM_updateDouble((int)(7*4),3000);
fnc_EEPROM_updateDouble((int)(8*4),3000);
fnc_EEPROM_updateDouble((int)(255*4),(-537537));
}
double Measure_A() {
Amperage = (analogRead(A1) - A_Constant) * 5 / 67.584;
if (Amperage >= 0) {
if (Amperage > Amp_Max)
Amp_Max = Amperage;
}
else
Amperage = 0;
}
double Measure_V() {
Voltage = analogRead(A0) * V_Constant * 5 / 1024;
if (Voltage < 0)
Voltage = 0;
}
int16_t Measure_T(int x, byte start) {
OneWire ds(7);
byte i;
byte data[2];
do {
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
for (i=0; i<2; i++) data[i] = ds.read();
C_Temp = (data[1]<<8) | data[0];
C_Temp >>= 4;
if (data[1] & 128) C_Temp |= 61440;
if (data[0] & 8) ++C_Temp;
ds.reset();
ds.write(0xCC);
ds.write(0x44,1);
if (start) delay(1000);
}
while
(start--);
if (C_Temp >= 82) {
digitalWrite(8,LOW);
digitalWrite(10,HIGH);
lcd.setCursor(17,1);
lcd.print("MAX");
s_Error_Text = String (" TEMP HIGH ERROR! ");
b_Error = true;
}
}
void Convert_T() {
Measure_T(7,0);
double F_Temp;
if (C_Temp <= Last_Temp - 20)
return;
Last_Temp = C_Temp;
F_Temp = C_Temp * 9 / 5 + 32;
if
(F_Temp >= Fan_On_Temp) digitalWrite(10,HIGH);
else
digitalWrite(10,LOW);
lcd.setCursor(17,1);
dtostrf(F_Temp,3,0,Print_Buffer);
lcd.print(Print_Buffer);
}
void Anneal_Sub() {
Int_Err.read();
Measure_T(7,0);
Measure_A();
Measure_V();
Glow = analogRead(A3);
Joule_Time = Measuring;
Measuring = Measuring - Joule_Time;
Joules = Joules + (Voltage * Amperage * Joule_Time / 1000);
if (Int_Err.wasPressed()) {
s_Error_Text = String (" ANNEAL INTERUPTED! ");
b_Error = true;
return;
}
if (Amperage >= Max_Amperes) {
s_Error_Text = String (" AMP HIGH ERROR ");
b_Error = true;
}
}
void Anneal_Main() {
b_Error = false;
Joules = 0;
Amp_Max = 0;
Glow = 1023;
Convert_T();
delay(Case_Settle);
digitalWrite(8,HIGH);
Annealing = 0;
Measuring = 0;
lcd.setCursor(0,3);
lcd.print(" ANNEALING CASE ");
if (Case_Program_Num == 0) {
while (Glow > Glow_Set && !b_Error) {
Anneal_Sub();
}
}
else if (Mode == 1) {
while ((Annealing <= Anneal_Time - 10) && !b_Error)
Anneal_Sub();
while (Annealing < Anneal_Time && !b_Error)
delay(1);
}
else
while ((Joules < Anneal_Energy - 2) && !b_Error)
Anneal_Sub();
digitalWrite(8,LOW);
Joule_Time = Measuring;
Actual_Time = Annealing;
Joules = Joules + (Voltage * Amperage * Joule_Time / 1000);
lcd.setCursor(15,2);
dtostrf(Joules,4,0,Print_Buffer);
lcd.print(Print_Buffer);
lcd.setCursor(3,2);
dtostrf(float(Actual_Time)/1000,4,2,Print_Buffer);
lcd.print(Print_Buffer);
lcd.setCursor(9,1);
dtostrf(Amp_Max,3,1,Print_Buffer);
lcd.print(Print_Buffer);
lcd.setCursor(10,2);
dtostrf(Glow,4,0,Print_Buffer);
lcd.print(Print_Buffer);
Convert_T();
if (b_Error)
Error_Loop();
do {
digitalWrite(9,HIGH);
lcd.setCursor(0,3);
lcd.print(" *****CASE JAM***** ");
}
while
(analogRead(A2) < Detector_Threshold);
delay(Drop_Delay);
digitalWrite(9,LOW);
delay(Door_Close);
lcd.setCursor(0,3);
lcd.print(" WAITING FOR CASE ");
}
void Error_Loop() {
delay(26);
do {
lcd.setCursor(0,3);
lcd.print(s_Error_Text);
Convert_T();
Int_Err.read();
} while
(!Int_Err.wasPressed());
b_Error = false;
delay(26);
}
void Anneal_Set() {
if (Case_Program_Num == 0) {
Glow_Set = fnc_EEPROM_readDouble(Case_Glow_Program_Num*4);
return;
}
if (Mode == 1) {
if (Case_Program_Num != (ls_Case_Name_size - 1))
Anneal_Time = fnc_EEPROM_readDouble(Case_Program_Num*4);
else
Anneal_Time = Test_Anneal_Time;
}
else
if (Case_Program_Num != (ls_Case_Name_size - 1))
Anneal_Energy = fnc_EEPROM_readDouble((Case_Program_Num + 10)*4);
else
Anneal_Energy = Test_Anneal_Energy;
}
void Anneal_Change() {
if (Case_Program_Num == 0) {
if (fnc_EEPROM_readDouble(Case_Glow_Program_Num*4) != Glow_Set)
fnc_EEPROM_updateDouble((int)(Case_Glow_Program_Num*4),Glow_Set);
return;
}
if (Mode == 1) {
if ((fnc_EEPROM_readDouble(Case_Program_Num*4) != Anneal_Time) && (Case_Program_Num != (ls_Case_Name_size - 1)))
fnc_EEPROM_updateDouble((int)(Case_Program_Num*4),Anneal_Time);
}
else
if ((fnc_EEPROM_readDouble((Case_Program_Num + 10)*4) != Anneal_Energy) && (Case_Program_Num != (ls_Case_Name_size - 1)))
fnc_EEPROM_updateDouble((int)((Case_Program_Num + 10)*4),Anneal_Energy);
}
void Display() {
s_Case_Text = ls_Case_Name[(Case_Program_Num)];
lcd.setCursor(0,0);
lcd.print(Case_Program_Num);
lcd.setCursor(2,0);
lcd.print(s_Case_Text);
if (Case_Program_Num == 0) {
lcd.setCursor(14,0);
lcd.print("G=");
dtostrf(Glow_Set,4,0,Print_Buffer);
}
else if (Mode == 1) {
lcd.setCursor(14,0);
lcd.print("T=");
dtostrf(float(Anneal_Time)/1000,4,2,Print_Buffer);
}
else {
lcd.setCursor(14,0);
lcd.print("J=");
dtostrf(Anneal_Energy,4,0,Print_Buffer);
}
lcd.setCursor(16,0);
lcd.print(Print_Buffer);
Measure_V();
lcd.setCursor(2,1);
dtostrf(Voltage,3,1,Print_Buffer);
lcd.print(Print_Buffer);
Convert_T();
if (b_Error)
Error_Loop();
}
void setup() {
if ((fnc_EEPROM_readDouble((int)(255*4)) != -537537))
EEPROM_Initialize();
Tm_Up.begin();
Tm_Dn.begin();
Pgm_Up.begin();
Pgm_Dn.begin();
Int_Err.begin();
Measure_T(7,1);
pinMode(8,OUTPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(A0,INPUT);
pinMode(A1,INPUT);
pinMode(A2,INPUT);
pinMode(A3,INPUT);
lcd.begin();
lcd.noCursor();
lcd.clear();
lcd.display();
lcd.setCursor(1,0);
lcd.print(":");
lcd.setCursor(14,0);
lcd.print("T=");
lcd.setCursor(0,1);
lcd.print("V=");
lcd.setCursor(7,1);
lcd.print("A=");
lcd.setCursor(14,1);
lcd.print("F=");
lcd.setCursor(0,2);
lcd.print("Ta=");
lcd.setCursor(19,2);
lcd.print("J");
lcd.setCursor(8,2);
lcd.print("G=");
lcd.setCursor(0,3);
lcd.print(" WAITING FOR CASE ");
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(10,LOW);
}
void loop() {
Display();
Tm_Up.read();
Tm_Dn.read();
Pgm_Up.read();
Pgm_Dn.read();
Int_Err.read();
if (Int_Err.wasPressed()) {
if (Case_Program_Num == 0) {
if (Mode != 0)
Anneal_Change();
if (++Mode > 1)
Mode = 0;
}
else {
if (Mode != 0)
Anneal_Change();
if (++Mode > 2)
Mode = 0;
if (Mode == 2)
Anneal_Set();
}
Display();
}
if (Mode == 0) {
s_Error_Text = String (" PAUSE MODE ");
Error_Loop();
Mode = 1;
Anneal_Set();
lcd.setCursor(0,3);
lcd.print(" WAITING FOR CASE ");
}
if (Tm_Up.wasPressed()) {
if (Mode == 1 && Case_Program_Num != 0) {
Anneal_Time = Anneal_Time + 50;
if (Anneal_Time > 9950)
Anneal_Time = 9990;
}
else if (Mode == 2 && Case_Program_Num != 0) {
Anneal_Energy = Anneal_Energy + 5;
if (Anneal_Energy > 9999)
Anneal_Energy = 9999;
}
else {
if (++Glow_Set > 1023)
Glow_Set = 1023;
}
Display();
}
while (Tm_Up.pressedFor(750)) {
if (Mode == 1 && Case_Program_Num != 0) {
Anneal_Time = Anneal_Time + 50;
if (Anneal_Time > 9950)
Anneal_Time = 9990;
}
else if (Mode == 2 && Case_Program_Num != 0) {
Anneal_Energy = Anneal_Energy + 5;
if (Anneal_Energy > 9999)
Anneal_Energy = 9999;
}
else {
if (++Glow_Set > 1023)
Glow_Set = 1023;
}
Display();
delay(50);
Tm_Up.read();
}
if (Tm_Dn.wasPressed()) {
if (Mode == 1 && Case_Program_Num != 0) {
Anneal_Time = Anneal_Time - 50;
if (Anneal_Time <= 250)
Anneal_Time = 250;
}
else if (Mode == 2 && Case_Program_Num != 0) {
Anneal_Energy = Anneal_Energy - 5;
if (Anneal_Energy <= 100)
Anneal_Energy = 100;
}
else {
if (--Glow_Set < 0)
Glow_Set = 0;
}
Display();
}
while (Tm_Dn.pressedFor(750)) {
if (Mode == 1 && Case_Program_Num != 0) {
Anneal_Time = Anneal_Time - 50;
if (Anneal_Time <= 250)
Anneal_Time = 250;
}
else if (Mode == 2 && Case_Program_Num != 0) {
Anneal_Energy = Anneal_Energy - 5;
if (Anneal_Energy <= 100)
Anneal_Energy = 100;
}
else {
if (--Glow_Set < 0)
Glow_Set = 0;
}
Display();
delay(50);
Tm_Dn.read();
}
if (Pgm_Up.wasPressed()) {
Anneal_Change();
if ((++Case_Program_Num > (ls_Case_Name_size - 1)))
Case_Program_Num = 0;
Anneal_Set();
Display();
}
if (Pgm_Dn.wasPressed()) {
Anneal_Change();
if (--Case_Program_Num < 0)
Case_Program_Num = (ls_Case_Name_size - 1);
Anneal_Set();
Display();
}
if (analogRead(A2) < Detector_Threshold)
Anneal_Main();
}