From 8fa1ffb1b0e23e36d5a0e171d3d04a37fe2fd595 Mon Sep 17 00:00:00 2001 From: Corwin Perren Date: Sat, 13 Apr 2019 18:52:27 -0700 Subject: [PATCH] Added old AutoTap used at Kent Lab --- .../AutoTap/Auto Tap V1.0 Instructions.docx | Bin 0 -> 7988 bytes .../AutoTap/AutoTap.ino | 500 ++++++++++++++++++ 2 files changed, 500 insertions(+) create mode 100644 OSU SARL/Control Board Firmware/AutoTap/Auto Tap V1.0 Instructions.docx create mode 100644 OSU SARL/Control Board Firmware/AutoTap/AutoTap.ino diff --git a/OSU SARL/Control Board Firmware/AutoTap/Auto Tap V1.0 Instructions.docx b/OSU SARL/Control Board Firmware/AutoTap/Auto Tap V1.0 Instructions.docx new file mode 100644 index 0000000000000000000000000000000000000000..fc73ffceb74a3cabaaf50059cb6da815b6fd6965 GIT binary patch literal 7988 zcmaKR1y~%*wly}mGlAgl65QS0El3~)1{mDk-4YxE1lQm$!QI{6CAb6$_DJ44_vD`c zzjx2~^;bPztGlXt@7k-^R+fW?0YbpT!$W+Cl2Cy7!!TdkE;jbYZ>*iHj7;p!txcI+ ztt^jISF9JAUk8^P-uRLoS8NM0Pmc#^eBsoXs&T?G#EjGap|s6CzWOLH+Np#jr_HL^ znghRdYSA{@cazqByn>XI^D2=CgP;AV(j=1kleoMqCSF?xk#&AAjaF!1DB?%4tyg=! zD-T`A?!8EL?W*PY=1A#d+CaP_)rDd9OPU_!oeweZ%czq?S#z(XJ|`m&?2&y7gBgk@ zLlO;h=O7$Hj4X|Uj}pCDnB5GHkq*~mn2}_~8lnt4yH=q$PW7T6XbD9OZlrTzr_BF} z?7v4laIqMr|2?02YSGwYmrn{v~+8$0HA4I@a6}u zxkir^s!kr_0&trWTO~aAE6P44s=D|X_fzC8B1aDab?M+;KP?qaOz3eq`{@

abAH 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 literal 0 HcmV?d00001 diff --git a/OSU SARL/Control Board Firmware/AutoTap/AutoTap.ino b/OSU SARL/Control Board Firmware/AutoTap/AutoTap.ino new file mode 100644 index 0000000..2156acc --- /dev/null +++ b/OSU SARL/Control Board Firmware/AutoTap/AutoTap.ino @@ -0,0 +1,500 @@ +////////// Includes ////////// +#include +#include + +////////// Pin Definitions ////////// +// LCD +#define LCD_RS_PIN 12 +#define LCD_EN_PIN 11 +#define LCD_D4_PIN 10 +#define LCD_D5_PIN 9 +#define LCD_D6_PIN 8 +#define LCD_D7_PIN 7 +#define LCD_VO_PIN 6 + +// Front Panel Buttons +#define STOP_BUTTON_PIN 5 +#define START_BUTTON_PIN 4 + +// Rotary Encoder +#define CHANNEL_A_PIN 3 +#define CHANNEL_B_PIN 2 +#define ENCODER_BUTTON_PIN A0 + +// Relay +#define LATCH_SIDE_1_PIN A4 // This is the side that connects the relay +#define LATCH_SIDE_2_PIN A5 // This one disconnects it + +////////// Class Instantiations ///////// +LiquidCrystal lcd(LCD_RS_PIN, LCD_EN_PIN, LCD_D4_PIN, LCD_D5_PIN, LCD_D6_PIN, LCD_D7_PIN); + +////////// Global Variables ////////// +// #define DEBUG +#define PROG_VERSION 1.0 + +// Timeouts and timing variables +#define DEBOUNCE_TIMEOUT 350 + +unsigned int start_time = 0; +unsigned int prev_time = 0; + +// Encoder Variables +#define ENCODER_SCALE_VAL 8 +volatile int encoder0Pos = 0; +volatile int encoder0PosScaled = 0; +int prev_encoder_scaled_pos = 0; + +// System State Variables and Enums +enum system_states { + system_init, + wait_for_start, + settings_configuration, + run_tap_program +}; + +system_states current_system_state = wait_for_start; +system_states previous_system_state = system_init; + +// Tap Test Variables and Enums +enum tap_test_states { + settle_init, + settle_period, + normal_run +}; + +tap_test_states current_tap_state = settle_period; +tap_test_states previous_tap_state = settle_init; + +int settle_seconds = 180; +int tap_period_seconds = 30; +unsigned int cycle_length_seconds = 3600; + +char has_tapped = 0; + +// Settings Configuration Variables and Enums +enum setting_scroller_states{ + settings_init_pg, + settle_duration_pg, + tap_period_pg, + test_duration_pg +}; + +setting_scroller_states current_editing_state = settle_duration_pg; +setting_scroller_states previous_editing_state = settings_init_pg; + +void setup() { + // Sets the relay to not be engaging the relay + pinMode(LATCH_SIDE_1_PIN, OUTPUT); + digitalWrite(LATCH_SIDE_1_PIN, LOW); + pinMode(LATCH_SIDE_2_PIN, OUTPUT); + digitalWrite(LATCH_SIDE_2_PIN, HIGH); + delay(50); + digitalWrite(LATCH_SIDE_2_PIN, LOW); + + // Sets up front panel buttons + pinMode(STOP_BUTTON_PIN, INPUT); + digitalWrite(STOP_BUTTON_PIN, HIGH); + + pinMode(START_BUTTON_PIN, INPUT); + digitalWrite(START_BUTTON_PIN, HIGH); + + // Sets up the rotary encoder + pinMode(CHANNEL_A_PIN, INPUT); + digitalWrite(CHANNEL_A_PIN, HIGH); + + pinMode(CHANNEL_B_PIN, INPUT); + digitalWrite(CHANNEL_B_PIN, HIGH); + + pinMode(ENCODER_BUTTON_PIN, INPUT); + digitalWrite(ENCODER_BUTTON_PIN, HIGH); + + attachInterrupt(0, doEncoderA, CHANGE); + + attachInterrupt(1, doEncoderB, CHANGE); + + // Sets up serial debug if needed +#ifdef DEBUG + Serial.begin(9600); + Serial.print("------ Auto Tap V"); Serial.print(PROG_VERSION); Serial.println(" ------"); + Serial.println("------ www.caperren.com ------"); + Serial.println("------CURRENTLY IN DEBUG MODE------"); +#endif + + // Sets lcd contrast + pinMode(LCD_VO_PIN, OUTPUT); + analogWrite(LCD_VO_PIN, 128); + + // Sets up and displays intro message on lcd + lcd.begin(16, 2); + lcd.setCursor(0, 0); + lcd.print(" Auto Tap V"); + lcd.print(PROG_VERSION); + lcd.setCursor(0, 1); + lcd.print("www.caperren.com"); + + delay(3000); + + // Imports settings from EEPROM + if(!digitalRead(STOP_BUTTON_PIN)){ + lcd.setCursor(0, 0); + lcd.print(" Restoring "); + lcd.setCursor(0, 1); + lcd.print(" Settings "); + + EEPROMWritelong(0, settle_seconds); + EEPROMWritelong(4, tap_period_seconds); + EEPROMWritelong(8, cycle_length_seconds); + + delay(3000); + } + + settle_seconds = int(EEPROMReadlong(0)); + tap_period_seconds = int(EEPROMReadlong(4)); + cycle_length_seconds = int(EEPROMReadlong(8)); + + + +} + +void loop() { + if (current_system_state == wait_for_start) { + if (previous_system_state != wait_for_start) { + lcd.setCursor(0, 0); + lcd.print(" Auto Tap "); + lcd.setCursor(0, 1); + lcd.print("STOP|V"); + lcd.print(PROG_VERSION); + lcd.print("|START"); + previous_system_state = wait_for_start; + } + + if (!digitalRead(ENCODER_BUTTON_PIN)) { + delay(DEBOUNCE_TIMEOUT); + current_system_state = settings_configuration; + } else if (!digitalRead(START_BUTTON_PIN)) { + delay(DEBOUNCE_TIMEOUT); + current_system_state = run_tap_program; + } + + } else if (current_system_state == settings_configuration) { + if (previous_system_state != settings_configuration) { + prev_encoder_scaled_pos = encoder0PosScaled; + current_editing_state = settle_duration_pg; + previous_system_state = settings_configuration; + } + + if (current_editing_state == settle_duration_pg){ + lcd.setCursor(0, 0); + lcd.print(" Edit Setting "); + lcd.setCursor(0, 1); + lcd.print("Settle Duration "); + + if(!digitalRead(ENCODER_BUTTON_PIN)){ + delay(DEBOUNCE_TIMEOUT); + lcd.setCursor(0, 0); + lcd.print("Settle Duration "); + prev_encoder_scaled_pos = encoder0PosScaled; + while(digitalRead(ENCODER_BUTTON_PIN)){ + lcd.setCursor(0, 1); + lcd.print(settle_seconds); + lcd.print(" "); + + if(encoder0PosScaled != prev_encoder_scaled_pos){ + settle_seconds += (encoder0PosScaled - prev_encoder_scaled_pos); + settle_seconds = constrain(settle_seconds, 0 , 32767); + prev_encoder_scaled_pos = encoder0PosScaled; + } + } + delay(DEBOUNCE_TIMEOUT); + prev_encoder_scaled_pos = encoder0PosScaled = 0; + } + + check_if_page_should_change(); + + }else if (current_editing_state == tap_period_pg){ + lcd.setCursor(0, 0); + lcd.print(" Edit Setting "); + lcd.setCursor(0, 1); + lcd.print(" Tap Period "); + + if(!digitalRead(ENCODER_BUTTON_PIN)){ + delay(DEBOUNCE_TIMEOUT); + lcd.setCursor(0, 0); + lcd.print(" Tap Period "); + prev_encoder_scaled_pos = encoder0PosScaled; + while(digitalRead(ENCODER_BUTTON_PIN)){ + lcd.setCursor(0, 1); + lcd.print(tap_period_seconds); + lcd.print(" "); + + if(encoder0PosScaled != prev_encoder_scaled_pos){ + tap_period_seconds += (encoder0PosScaled - prev_encoder_scaled_pos); + tap_period_seconds = constrain(tap_period_seconds, 1 , cycle_length_seconds); + prev_encoder_scaled_pos = encoder0PosScaled; + } + } + delay(DEBOUNCE_TIMEOUT); + prev_encoder_scaled_pos = encoder0PosScaled = 0; + } + + check_if_page_should_change(); + }else if (current_editing_state == test_duration_pg){ + lcd.setCursor(0, 0); + lcd.print(" Edit Setting "); + lcd.setCursor(0, 1); + lcd.print(" Test Duration "); + + if(!digitalRead(ENCODER_BUTTON_PIN)){ + delay(DEBOUNCE_TIMEOUT); + lcd.setCursor(0, 0); + lcd.print(" Test Duration "); + prev_encoder_scaled_pos = encoder0PosScaled; + while(digitalRead(ENCODER_BUTTON_PIN)){ + lcd.setCursor(0, 1); + lcd.print(cycle_length_seconds); + lcd.print(" "); + + if(encoder0PosScaled != prev_encoder_scaled_pos){ + cycle_length_seconds += (encoder0PosScaled - prev_encoder_scaled_pos); + cycle_length_seconds = constrain(cycle_length_seconds, 0 , 32767); + prev_encoder_scaled_pos = encoder0PosScaled; + } + } + delay(DEBOUNCE_TIMEOUT); + prev_encoder_scaled_pos = encoder0PosScaled = 0; + } + + check_if_page_should_change(); + } + + if(!digitalRead(START_BUTTON_PIN)){ + lcd.setCursor(0, 0); + lcd.print("Saving Settings "); + lcd.setCursor(0, 1); + lcd.print(" Please Wait "); + delay(2000); + + EEPROMWritelong(0, settle_seconds); + EEPROMWritelong(4, tap_period_seconds); + EEPROMWritelong(8, cycle_length_seconds); + + current_system_state = wait_for_start; + } else if(!digitalRead(STOP_BUTTON_PIN)){ + current_system_state = wait_for_start; + } + + } else if (current_system_state == run_tap_program) { + if (previous_system_state != run_tap_program) { + lcd.setCursor(0, 0); + lcd.print(" Start Pressed "); + lcd.setCursor(0, 1); + lcd.print(" Beginning Test "); + delay(2000); + + current_tap_state = settle_period; + previous_tap_state = settle_init; + previous_system_state = run_tap_program; + } + + if (current_tap_state == settle_period) { + if (previous_tap_state == settle_init) { + lcd.setCursor(0, 0); + lcd.print(" Settle Remain "); + start_time = get_system_seconds(); + previous_tap_state = settle_period; + } + lcd.setCursor(0, 1); + lcd.print(" "); + lcd.print(settle_seconds - (get_system_seconds() - start_time)); + lcd.print(" "); + + if ((get_system_seconds() - start_time) > settle_seconds) { + current_tap_state = normal_run; + } else if (!digitalRead(STOP_BUTTON_PIN)) { + delay(DEBOUNCE_TIMEOUT); + current_tap_state = normal_run; + } + + } else if (current_tap_state == normal_run) { + if (previous_tap_state == settle_period) { + lcd.setCursor(0, 0); + lcd.clear(); + lcd.print("Cycle |Tap "); + start_time = get_system_seconds(); + has_tapped = 0; + previous_tap_state = normal_run; + } + + int cycle_left = cycle_length_seconds - (get_system_seconds() - start_time); + int tap_left = tap_period_seconds - ((get_system_seconds() - start_time) % tap_period_seconds); + + lcd.setCursor(0, 1); + lcd.print(cycle_left); + print_spaces_for_number(7 - get_digits_in_number(cycle_left)); + lcd.setCursor(7 , 1); + lcd.print("|"); + lcd.print(tap_left - 1); + lcd.print(" "); + + + + if ((tap_left == 1) && !has_tapped) { + do_tap(); + has_tapped = 1; + } else if (tap_left == 5) { + has_tapped = 0; + } + + if ((get_system_seconds() - start_time) > cycle_length_seconds) { + lcd.setCursor(0, 0); + lcd.print(" Test Finished! "); + lcd.setCursor(0, 1); + lcd.print("Duration: "); + lcd.print(cycle_length_seconds); + delay(2000); + current_system_state = wait_for_start; + } else if (!digitalRead(STOP_BUTTON_PIN)) { + delay(DEBOUNCE_TIMEOUT); + current_system_state = wait_for_start; + } + } + } + +} + +void check_if_page_should_change(){ + int rot_amount = encoder0PosScaled - prev_encoder_scaled_pos; + + // #ifdef DEBUG + // Serial.print("Rotation Amount: "); + // Serial.println(rot_amount); + // #endif + + if(abs(rot_amount) > 2){ + if(rot_amount < 0){ + + if(current_editing_state == settle_duration_pg){ + }else if(current_editing_state == tap_period_pg){ + current_editing_state = settle_duration_pg; + }else if(current_editing_state == test_duration_pg){ + current_editing_state = tap_period_pg; + } + + }else if(rot_amount > 0){ + + if(current_editing_state == settle_duration_pg){ + current_editing_state = tap_period_pg; + }else if(current_editing_state == tap_period_pg){ + current_editing_state = test_duration_pg; + }else if(current_editing_state == test_duration_pg){ + } + } + prev_encoder_scaled_pos = encoder0PosScaled; + } + +} + +void print_spaces_for_number(int number) { + for (int i = 0 ; i < number ; i++) { + lcd.print(" "); + } +} + +int get_digits_in_number(unsigned int number) { + return number > 0 ? (int) log10 ((double) number) + 1 : 1; +} + +unsigned long get_system_seconds() { + return millis() / 1000; +} + +void doEncoderA() { + + // look for a low-to-high on channel A + if (digitalRead(CHANNEL_A_PIN) == LOW) { + // check channel B to see which way encoder is turning + if (digitalRead(CHANNEL_B_PIN) == HIGH) { + encoder0Pos = encoder0Pos + 1; // CW + } + else { + encoder0Pos = encoder0Pos - 1; // CCW + } + } + else // must be a high-to-low edge on channel A + { + // check channel B to see which way encoder is turning + if (digitalRead(CHANNEL_B_PIN) == LOW) { + encoder0Pos = encoder0Pos + 1; // CW + } + else { + encoder0Pos = encoder0Pos - 1; // CCW + } + } + + encoder0PosScaled = encoder0Pos / ENCODER_SCALE_VAL; +} + +void doEncoderB() { + + // look for a low-to-high on channel B + if (digitalRead(CHANNEL_B_PIN) == LOW) { + // check channel A to see which way encoder is turning + if (digitalRead(CHANNEL_A_PIN) == LOW) { + encoder0Pos = encoder0Pos + 1; // CW + } + else { + encoder0Pos = encoder0Pos - 1; // CCW + } + } + // Look for a high-to-low on channel B + else { + // check channel B to see which way encoder is turning + if (digitalRead(CHANNEL_A_PIN) == HIGH) { + encoder0Pos = encoder0Pos + 1; // CW + } + else { + encoder0Pos = encoder0Pos - 1; // CCW + } + } + encoder0PosScaled = encoder0Pos / ENCODER_SCALE_VAL; +} + +void EEPROMWritelong(int address, long value) + { + //Decomposition from a long to 4 bytes by using bitshift. + //One = Most significant -> Four = Least significant byte + byte four = (value & 0xFF); + byte three = ((value >> 8) & 0xFF); + byte two = ((value >> 16) & 0xFF); + byte one = ((value >> 24) & 0xFF); + + //Write the 4 bytes into the eeprom memory. + EEPROM.write(address, four); + EEPROM.write(address + 1, three); + EEPROM.write(address + 2, two); + EEPROM.write(address + 3, one); + } + +long EEPROMReadlong(long address) + { + //Read the 4 bytes from the eeprom memory. + long four = EEPROM.read(address); + long three = EEPROM.read(address + 1); + long two = EEPROM.read(address + 2); + long one = EEPROM.read(address + 3); + + //Return the recomposed long by using bitshift. + return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF); + } + +void do_tap() { + digitalWrite(LATCH_SIDE_1_PIN, HIGH); + delay(50); + digitalWrite(LATCH_SIDE_1_PIN, LOW); + + delay(150); + + digitalWrite(LATCH_SIDE_2_PIN, HIGH); + delay(50); + digitalWrite(LATCH_SIDE_2_PIN, LOW); +}