From 7463c83caec28d972aaaeae42e408042b255dfcd Mon Sep 17 00:00:00 2001 From: Lexzach Date: Tue, 19 Apr 2022 09:49:10 -0400 Subject: [PATCH] first --- facp/.gitignore | 5 + facp/.vscode/extensions.json | 7 + facp/include/README | 39 ++++ facp/lib/README | 46 +++++ facp/platformio.ini | 17 ++ facp/src/eeprom.txt | 7 + facp/src/eol.png | Bin 0 -> 21522 bytes facp/src/main.cpp | 352 +++++++++++++++++++++++++++++++++++ facp/test/README | 11 ++ 9 files changed, 484 insertions(+) create mode 100644 facp/.gitignore create mode 100644 facp/.vscode/extensions.json create mode 100644 facp/include/README create mode 100644 facp/lib/README create mode 100644 facp/platformio.ini create mode 100644 facp/src/eeprom.txt create mode 100644 facp/src/eol.png create mode 100644 facp/src/main.cpp create mode 100644 facp/test/README diff --git a/facp/.gitignore b/facp/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/facp/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/facp/.vscode/extensions.json b/facp/.vscode/extensions.json new file mode 100644 index 0000000..e80666b --- /dev/null +++ b/facp/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/facp/include/README b/facp/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/facp/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/facp/lib/README b/facp/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/facp/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/facp/platformio.ini b/facp/platformio.ini new file mode 100644 index 0000000..721e60c --- /dev/null +++ b/facp/platformio.ini @@ -0,0 +1,17 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32doit-devkit-v1] +platform = espressif32 +board = esp32doit-devkit-v1 +framework = arduino +monitor_speed = 115200 +lib_deps = + marcoschwartz/LiquidCrystal_I2C@^1.1.4 \ No newline at end of file diff --git a/facp/src/eeprom.txt b/facp/src/eeprom.txt new file mode 100644 index 0000000..1f2cbb4 --- /dev/null +++ b/facp/src/eeprom.txt @@ -0,0 +1,7 @@ +Address allocation: +1-6 | "Lexzach" - verify that eeprom is the FACP config eeprom +7 | 0-3 - coding selection +8 | 0-1 - is a key required +9 | 0-1 - is there verification +10 | 1-255 - how long to do verification (value * 0.1 = actual verification time in seconds) +11-71 | 65-90, 97-122, 45-57, 32 - System name \ No newline at end of file diff --git a/facp/src/eol.png b/facp/src/eol.png new file mode 100644 index 0000000000000000000000000000000000000000..e76406d8aa013ec746df7311d6c79fae234c3d3a GIT binary patch literal 21522 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%0AIQ1QI+126Gq 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 W33!d|G;r4Eky{FC^4V~cr~eP*s~Oh- literal 0 HcmV?d00001 diff --git a/facp/src/main.cpp b/facp/src/main.cpp new file mode 100644 index 0000000..b2d7d23 --- /dev/null +++ b/facp/src/main.cpp @@ -0,0 +1,352 @@ +#include +#include +#include + +//RUNTIME VARIABLES +bool fullAlarm = false; //bool to control if this is a full alarm that requres a panel reset to clear +bool keyInserted = false; //if the control panel has a key inserted +bool horn = false; //bool to control if the horns are active +bool strobe = false; //bool to control if the strobes are active +bool trouble = false; //bool to control if the panel is in trouble +bool troubleAck = false; //bool to control if the trouble is acknowledged +int verification = 0; //number to keep track of ms for verification +int drill = 0; //number to keep track of ms for drill +int codeWheelTimer = 0; //code wheel timing variable +int troubleLedTimer = 0; //number to keep track of ms for trouble light +int alarmLedTimer = 0; //alarm led timer +int troubleType = 0; //trouble type 0 - general, 1 - eol resistor +int lcdUpdateTimer = 0; //update delay +int currentScreen = 0; //update display if previous screen is not the same + +//CONFIG VARIABLES +bool keyRequired = true; //determine if key switch is required to operate buttons +bool isVerification = true; //is verification turned on +int codeWheel = 0; //which alarm pattern to use, code-3 default +int verificationTime = 2500; + +LiquidCrystal_I2C lcd(0x27,16,2); + +void setup() { + Serial.begin(115200); //begin serial + Serial.println("Lexzach's Low-Cost FACP v1"); + Serial.println("Booting..."); + + pinMode(13, OUTPUT); //horn + pinMode(12, OUTPUT); //strobe + pinMode(14, OUTPUT); //smoke relay + pinMode(27, OUTPUT); //ready LED + pinMode(26, OUTPUT); //silence LED + pinMode(25, OUTPUT); //alarm LED + pinMode(33, INPUT); //key switch + pinMode(32, INPUT); //reset switch + pinMode(35, INPUT); //silence switch + pinMode(34, INPUT); //drill switch + pinMode(15, INPUT); //pull station + pinMode(4, OUTPUT); //buzzer + + pinMode(22, OUTPUT); //scl + pinMode(21, OUTPUT); //sda + + Serial.println("Initializing LCD..."); + lcd.init(); //initialize LCD + lcd.clear(); + lcd.backlight(); + lcd.setCursor(3,0); + lcd.print("Booting..."); + + Serial.println("Configured all pins"); + + + + + EEPROM.begin(1025); //allocate memory address 0-1024 for EEPROM + Serial.println("Configured EEPROM for addresses 0-1024"); + + EEPROM.write(0,255); //TESTING PURPOSES + EEPROM.commit(); //TESTING PURPOSES + + Serial.println("Verifying EEPROM configuration integrity..."); + + if (EEPROM.read(0) != 76 or EEPROM.read(6) != 104 or EEPROM.read(7) > 3 or EEPROM.read(8) > 1){ //EEPROM verification, check essential-to-run components, listing all conditions that cannot exist in a correct EEPROM + Serial.println("EEPROM verification failed. Re-writing EEPROM"); + for (int i=0; i<=1024; i++){ //write all 255's from 0-1024 address + EEPROM.write(i,255); + } + + EEPROM.write(0,76);EEPROM.write(1,101);EEPROM.write(2,120);EEPROM.write(3,122);EEPROM.write(4,97);EEPROM.write(5,99);EEPROM.write(6,104); //write Lexzach to addresses 0-6 + EEPROM.write(7,0); //code-3 default + EEPROM.write(8,0); //key not required by default + EEPROM.write(9,1); //verification is turned on by default + EEPROM.write(10,25); //default verification time of 2.5 seconds + + EEPROM.commit(); + } else { + Serial.println("EEPROM verification finished"); + } + + Serial.println("Current EEPROM:"); + for (int i=0; i<=1024; i++){ + Serial.print(EEPROM.read(i)); + Serial.print(" "); + } + Serial.println(); + + //CONFIG LOADING ROUTINE + Serial.println("Loading config from EEPROM..."); + codeWheel = EEPROM.read(7); //codeWheel setting address + if (EEPROM.read(8) == 1){ + keyRequired = true; + } else { + keyRequired = false; + } + if (EEPROM.read(9) == 1){ + isVerification = true; + } else { + isVerification = false; + } + verificationTime = EEPROM.read(10)*100; + + Serial.println("Config loaded"); + digitalWrite(27, HIGH); //power on ready LED on startup +} + +void tone() { + ledcSetup(0, 5000, 8); // setup beeper + ledcAttachPin(4, 0); // attach beeper + ledcWriteTone(0, 1500); // play tone +} +void noTone() { + ledcSetup(0, 5000, 8); // setup beeper + ledcAttachPin(4, 0); // attach beeper + ledcWriteTone(0, 0); // stop tone +} + +void checkKey(){ + if (digitalRead(33) == HIGH){ + keyInserted = true; + } else { + keyInserted = false; + } +} + +void checkDevices(){ + + if (analogRead(15) <= 500 and horn != true){ + verification++; + } else { + verification = 0; + } + if (verification == verificationTime or isVerification == false){ //activate the horns and strobes after verification + horn = true; + strobe = true; + fullAlarm = true; + tone(); + } else if (analogRead(15) == 4095) { + trouble = true; + troubleType=1; + } + +} + +void troubleCheck(){ + if (trouble == true){ + if (troubleLedTimer == 0){ + digitalWrite(27, LOW); + if (troubleAck == false and fullAlarm == false){ + noTone(); + } + } else if (troubleLedTimer == 750){ + digitalWrite(27, HIGH); + if (troubleAck == false and fullAlarm == false){ //sound the buzzer if the trouble is not acked + tone(); + } + } else if (troubleLedTimer == 1500){ + troubleLedTimer = -1; + } + + troubleLedTimer++; + } else { + digitalWrite(27, HIGH); + if (troubleLedTimer != 0){ + noTone(); + } + troubleLedTimer=0; + } +} + +void checkButtons(){ + if (digitalRead(32) == HIGH){ //RESET BUTTON + tone(); + digitalWrite(27, HIGH); //ready LED + digitalWrite(26, HIGH); //silence LED + digitalWrite(25, HIGH); //alarm LED + delay(1500); + ESP.restart(); + } + + if (digitalRead(35) == HIGH){ //SILENCE BUTTON + if (horn == true){ //if horns are not silenced, silence the horns + digitalWrite(26, HIGH); + horn = false; + } else if (horn == false and strobe == true){ //if the horns are silenced and the button is pressed again, silence the buzzer + noTone(); + } else if (horn == false and strobe == false and trouble == true){ + troubleAck = true; + noTone(); + } + } + + if (digitalRead(34) == HIGH and horn != true){ //DRILL BUTTON + if (drill == 2000){ + horn = true; + strobe = true; + } else { + drill++; + } + } else { + drill = 0; + } +} + +void alarm(){ + if (horn == true){ + if (codeWheel == 0){ + + if (codeWheelTimer == 0){ //temporal code 3 + digitalWrite(13, LOW); + } else if (codeWheelTimer == 500) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 1000) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 1500) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 2000) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 2500) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 4000) { + codeWheelTimer = -1; + } + + + } else if (codeWheel == 1) { + + if (codeWheelTimer == 0){ //marchtime + digitalWrite(13, LOW); + } else if (codeWheelTimer == 250){ + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 500){ + codeWheelTimer = -1; + } + + } else if (codeWheel == 2) { //4-4 + + if (codeWheelTimer == 0) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 300) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 600) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 900) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 1200) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 1500) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 1800) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 2100) { + digitalWrite(13, HIGH); + + } else if (codeWheelTimer == 2850) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 3150) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 3450) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 3750) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 4050) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 4350) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 4650) { + digitalWrite(13, LOW); + } else if (codeWheelTimer == 4950) { + digitalWrite(13, HIGH); + } else if (codeWheelTimer == 14950) { + codeWheelTimer = -1; + } + + } else if (codeWheel == 3) { //continuous + digitalWrite(13, LOW); + } + + codeWheelTimer++; + alarmLedTimer++; + if (alarmLedTimer >= 750){ + if (digitalRead(25) == true){ + digitalWrite(25, LOW); + alarmLedTimer = 0; + } else { + digitalWrite(25, HIGH); + alarmLedTimer = 0; + } + } + } else { + digitalWrite(13, HIGH); + codeWheelTimer = 0; + } +} + +void lcdUpdate(){ + if (trouble==false and fullAlarm==false and horn==false and strobe==false){ + lcd.clear(); + lcd.setCursor(2,0); + lcd.print("System Normal"); + currentScreen = 0; + } else if (trouble==true){ + if (troubleType == 0 and currentScreen != 1){ + lcd.clear(); + lcd.setCursor(1,0); + lcd.print("*** Trouble ***"); + lcd.setCursor(2,1); + lcd.print("Unknown Trouble"); + currentScreen = 1; + } else if (troubleType == 1 and currentScreen != 2){ + lcd.clear(); + lcd.setCursor(1,0); + lcd.print("*** Trouble ***"); + lcd.setCursor(2,1); + lcd.print("Ground Fault"); + currentScreen = 2; + } else if (fullAlarm == true and currentScreen != 3){ + lcd.clear(); + lcd.setCursor(0,0); + lcd.print("*** FIRE ALARM ***"); + lcd.setCursor(2,1); + lcd.print("zone info here"); + currentScreen = 3; + } + } +} +void loop() { + delay(1); + checkKey(); //check to see if the key is inserted + checkDevices(); //check pull stations and smoke detectors + if (keyInserted == true or keyRequired == false){ + checkButtons(); //check if certain buttons are pressed + } + troubleCheck(); //trouble check + alarm(); //alarm codewheel + if (lcdUpdateTimer == 1000){ + lcdUpdate(); + lcdUpdateTimer=0; + } else { + lcdUpdateTimer++; + } + Serial.println(digitalRead(35)); +} + + + diff --git a/facp/test/README b/facp/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/facp/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html