diff --git a/pfg_security.ino b/pfg_security.ino index 8c2d88e..15c174b 100644 --- a/pfg_security.ino +++ b/pfg_security.ino @@ -1,210 +1,319 @@ #include -// Needed for LiquidCrystal_I2C.h -#include -// from https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/ -#include +#include +#include +//#include +// display setup + +#define CS 18 +#define DC 19 +#define RESET 17 -// as per http://funduino.de/nr-06-zwei-i%C2%B2c-displays-gleichzeitig -LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); -boolean setup_ok=true; // false will stop loop() -const int N=16; // number of sample averages +// create an instance of the library +TFT TFTscreen = TFT(CS, DC, RESET); + +boolean setup_ok = true; +const int N = 16; // number of sample averages volatile unsigned int deltas[N]; // array of time deltas between interrupt volatile unsigned int n = 0; // run variable unsigned long total; float flow; -int prescaler; -char buff[10]; // temp. buffer for string manipulation/formatting -char serialbuff[16]; // temp. buffer for string manipulation/formatting +struct rgb { + int red=0; + int green=0; + int blue=0; + }; + + + +// begin user configuration parameters +/* + This is the prescaler setting for timer1: + The time base of the timer counter TCNT1 + t_step or seconds/tick = prescaler/clock + + Note: Maximum TCNT1 value is 65535, i.e. + Maximum time lengths (and thus timeouts) are: + 8 0.0327675 s + 64 0.26214 s + 256 1.04856 s + 1024 4.19424 s +*/ +#define PRESCALER 256 // todo: make this dependent on timeout /* -User configuration -================== - -Flow meter -========== - -The PFG flow meter can measure from 0.24 to 17 l/min at 4 pulses/s per l/min -max period about 1s, i.e. min flow of 0.24l/min -min period about 15 ms i.e. max flow of 17l/min - -The time base of the timer counter TCNT1 -t_step or seconds/tick = prescaler/clock - -Note: Maximum TCNT1 value is 65535, i.e. -Maximum time lengths (and thus timeouts) per prescaler value are: -8 0.0327675 s -64 0.26214 s -256 1.04856 s -1024 4.19424 s - -For accuracy the prescaler is set automatically fitting to the TIMEOUT. + The flow meter can measure from 0.24 to 17 l/min at 4 pulses/s per l/min + max period about 1s, i.e. min flow of 0.24l/min + min period about 15 ms i.e. max flow of 17l/min */ #define TIMEOUT 1.0 // measurement timeout in Hz (needs to be less than timer1 limits above) #define DISPLAY_INTERVAL 1.0 // display update interval (and serial send interval) -const float conversion = 4.0; // conversion factor, pulses/s per l/min -const float flow_threshold = 1.0; // alarm threshold for flow +const float conversion = 4.0; // conversion factor, pulses/s per l/min +const float flow_threshold = 0.5; // alarm threshold for flow +// end user configuration parameters -/* -Hardware configuration / wiring setup -===================================== +// begin hardware configuration / wiring setup +// Pin 13 has an LED connected on most Arduino boards. +// alarm LED pin +#define ALARM_LED_PIN 4 +// interlock pin +#define INTERLOCK_PIN 5 +#define OVERTEMP_PIN 14 -Pin 13 has an LED connected on most Arduino boards. -This is the alarm LED pin -*/ -#define ALARM_LED_PIN 13 -// interlock output pin -#define INTERLOCK_PIN 12 +// end hardware configuration / wiring setup -/* -Setup routine -============= +// temp. buffer for string manipulation/formatting +char buff[10]; +char old_flow_string[32]; +char new_flow_string[32]; +char old_status_string[16] = "yyyyyyyyyyyyyyy"; +char new_status_string[16]; + + +boolean status_change = true; +boolean status_safety = false; -Run once upon startup -*/ void setup() { - lcd.begin(16,2); // start LCD (16x2 characters) - lcd.home (); // go home - lcd.print("PFG security"); // string first line - lcd.setCursor ( 0, 1 ); // go to the next line - lcd.print (""); // string second line + SPI.setClockDivider(SPI_CLOCK_DIV2); + TFTscreen.begin(); + // clear the screen with a black background + struct rgb bg; + bg.red = 0; + bg.green = 0; + bg.blue = 0; + TFTscreen.background(bg.red, bg.green, bg.blue); + // write the static text to the screen + // set the font color to white + TFTscreen.stroke(255, 255, 255); + // set the font size + TFTscreen.setTextSize(2); + // write the text to the top left corner of the screen + TFTscreen.text("PFG Safety", 0, 0); + + Serial.begin(19200); // serial line speed /* Interrupt pins - UNO: - interrupt 1 is pin 3 - interrupt 0 is pin 2 + UNO: + interrupt 1 is pin 3 + interrupt 0 is pin 2 */ attachInterrupt(0, get_time, FALLING); pinMode(ALARM_LED_PIN, OUTPUT); pinMode(INTERLOCK_PIN, OUTPUT); + pinMode(OVERTEMP_PIN, INPUT); + + // starting values for the deltas array + // otherwise the array values are maybe zero at the beginning and we get very high (wrong) flow values + for (int k = 0; k < N; k++) { + deltas[k] = UINT_MAX; + } - /* - Set sensible default starting values for the deltas array, - otherwise the array values are maybe zero at the beginning - and we get very high (wrong) flow values. + /* + timer1 setup */ - for (int k=0; k 0.0327675) { + interrupts(); + //lcd.setCursor (0,1); // char 0 on line 0 or 1 + //lcd.print ("CFGERR TIMEOUT"); + setup_ok = false; + return; + } + } + else if (PRESCALER == 64) { + if (TIMEOUT > 0.26214) { + interrupts(); + //lcd.setCursor (0,1); // char 0 on line 0 or 1 + //lcd.print ("CFGERR TIMEOUT"); + setup_ok = false; + return; + } + TCCR1B |= (1 << CS11) | (1 << CS10); + } + else if (PRESCALER == 256) { + if (TIMEOUT > 1.04856) { + interrupts(); + //lcd.setCursor (0,1); // char 0 on line 0 or 1 + //lcd.print ("CFGERR TIMEOUT"); + setup_ok = false; + return; + } TCCR1B |= (1 << CS12); - else if (prescaler == 1024) - TCCR1B |= (1 << CS12)|(1 << CS10); - + } + else if (PRESCALER == 1024) { + if (TIMEOUT > 4.19424) { + interrupts(); + //lcd.setCursor (0,1); // char 0 on line 0 or 1 + //lcd.print ("CFGERR TIMEOUT"); + setup_ok = false; + return; + } + TCCR1B |= (1 << CS12) | (1 << CS10); + } + else { + interrupts(); + // lcd.setCursor (0,1); // char 0 on line 0 or 1 + // lcd.print ("CFGERR prescaler"); + setup_ok = false; + return; + } TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt interrupts(); // enable all interrupts - delay(500); + delay(100); } // if after OCR1A seconds no pulse from flow meter occured an interrupt will force a very high delta value -ISR(TIMER1_COMPA_vect) { // interupt service routine which will be called when an interrupt occurs at timer1 +ISR(TIMER1_COMPA_vect) { // function which will be called when an interrupt occurs at timer1 deltas[n] = UINT_MAX; // add maximum value in the current array position n++; - if (n==N) n=0; // wrap around + if (n == N) n = 0; // wrap around } - + void loop() { - if (!setup_ok) return; - delay((int) (DISPLAY_INTERVAL*1000)); - total = 0; - // sum up all deltas in array - for (int k=0; k= strlen(newtext)) { + TFTscreen.stroke(bg.red, bg.green, bg.blue); + TFTscreen.rect(curPos, y, TFTscreen.width() - curPos, textWidth * 10); + break; + } + // advance position + curPos += charWidth; + + } +} void get_time() { deltas[n] = TCNT1; // save current timer1 count n++; - if (n==N) n=0; // wrap around + if (n == N) n = 0; // wrap around TCNT1 = 0; // reset timer1 counter }