/* ```python def get_even_numbers(arr): even_numbers = [] for number in arr: if number % 2 == 0: even_numbers.append(number) return even_numbers ``` This code defines a function called `get_even_numbers` that takes one argument, `arr`. The purpose of this function is to return a list of all the even numbers in the input list `arr`. 1. The function starts by initializing an empty list called `even_numbers`. This list will be used to store the even numbers found in `arr`. 2. Next, the code iterates through each element in the input list `arr` using a for loop. The loop variable `number` takes on the value of each element in the list one by one. 3. Inside the loop, there is an if statement that checks if the current number (`number`) is even. This is done by using the modulo operator `%` to find the remainder when the number is divided by 2. If the remainder is 0, it means the number is even. 4. If the number is even, it is appended to the `even_numbers` list using the `append()` method. 5. After the loop has finished iterating through all the elements in the input list `arr`, the function returns the `even_numbers` list, which contains all the even numbers found in `arr`. The code is a JavaScript function that takes two parameters (x and y) and returns the sum of the two parameters. function add(x, y) { return x + y; } (c) 2023 Blue Wolf Enterprises, Inc. dba(Blue Wolf) THIS SOFTWARE IS SUPPLIED BY Blue Wolf "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL Blue Wolf BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF Blue Wolf HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, Blue Wolf'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO Blue Wolf FOR THIS SOFTWARE. */ /* FUSE SETTINGS HERE FOR MICROPROCESSOR BODLEVEL = DISABLED RSTDISBL = [ ] DWEN = [ ] SPIEN = [X] WDTON = [ ] EESAVE = [X] BOOTSZ = 256W_3F00 BOOTRST = [ ] CKDIV8 = [ ] CKOUT = [ ] SUT_CKSEL = INTRCOSC_8MHZ_6CK_14CK_65MS EXTENDED = 0xFF (valid) HIGH = 0xD7 (valid) LOW = 0xE2 (valid) */ // ***************** RELEASE NOTES ************************ // Modifed code so Brian can change sensitivity levels on the units. // This is release 1.0 for the JAS PC Board // This is release 1.01 for Firmware //Program Begins Here *********************************************************************************************************** //#include "Elevator_hdr.h" #include "C:\Atmel7\Elevator777\Elevator777\ArduinoCore\include\variants\Elevator_hdr.h" #include "C:\Atmel7\Elevator777\Elevator777\ArduinoCore\include\variants\eeprom.h" //Current Firmware information #define FIRMWARE F("Elevator 1 PCB 1.0/1.01F") //Firmware Version put in Flash //Last Updated 5/17/2023 Moved reading data over to interrupt driven data readhy. //********************* TTHIS IS USED FOR DEBUG AND PRINTS INFRO TO A SCREEN FOR VALUATION ******************************** #if defined DEBUG || defined DEBUG_PRINT_BUFFER #include <BasicTerm.h> //If problems, put this file has to be in the same folder as main. BasicTerm term(&Serial); //point to it. #endif //Specific shortened version for the pressure sensor TY_DPS310 preasure_sensor; //Setup Accelerometer, shortened version BW_LSM303 accel_sensor; //************************************************** Main Setup Here ************************************************* void setup(void) { //Addresses for the 2 I2C devices on the board //0x77 is the address of the pressure sensor //0x19 = Accelerometer #if defined DEBUG || defined DEBUG_PRINT_BUFFER Serial.begin(115200); term.init(); term.cls(); term.show_cursor(false); #endif system_IO_setup(); //Go initialize the CPU and board items. //This is for printing out some data on the lower half of the screen #ifdef DEBUG //term.position(40, 50); //EEPROM.get(EE_STORAGE_ADDRESS, EE); //Read in the last known saved EEprom values //ALARM.battery_time = EE.time_when_battery_went_low; #endif preasure_sensor.begin(Wire, 0x77); //Begin pressure sensor ALARM.dps_310_online=preasure_sensor.init(); //initialize sensor /* Initialize the accel sensor */ accel_sensor.begin(Wire, 0x19); ALARM.accel_online=accel_sensor.init(); /* EICA=ISC11 ISC10 Description ISC01 ISC00 Description 0 0 The low level of INT0 generates an interrupt request. 0 1 Any logical change on INT0 generates an interrupt request. 1 0 The falling edge of INT0 generates an interrupt request. 1 1 The rising edge of INT0 generates an interrupt request. */ //This enables the interrupts on the processor for the one coming from the acceleration sensor EICRA |= ( (1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00)); // set change //We turn these on in the settle and recalibrate portion //INT0 = Accelerometer //INT1 = PSI Sensor //EIMSK |= (0 << INT1) | (0 << INT0) ; // Turns on INT1 or INT0 //PSI sensor on, Accel sensor OFF EIMSK =0x00; // Turns on or off INT1 or INT0 //ALARM.accel_trigger_val=BATTERY_CALCULATED_LOW_AD_COUNT; //for testing what the ADC count should be for the calculated battery low voltage timer1_start_stop(ON); //This is the timer for the PWM's on Main LED and side LEDs side_flash_leds(MAIN_SIDE_LED_FLASH_SPD, MAX_PWM_LIMIT); //start the side lights because upon power up, we go into calibrate move check_board_health(); //make sure we're talking to sensors and check battery out #ifndef DEBUG startup_show_leds(); #endif delay(100/2); //lest PSI and Accel get booted watchdogSetup(); //Setup Watch Dog Feature Last }// ********************************* END SETUP ****************************************************** //Main Loop Start ************************************************************************************************ void loop(void) { uint8_t i = 0; volatile static uint32_t now_tick; volatile static uint32_t blink; volatile static uint32_t stable_tick; volatile static uint32_t psi_sensor_scan; volatile static uint8_t health_count=0; volatile static uint8_t accel_stable_cnt=0; //Top of loop here, so reset the Watchdog timer wdt_reset(); // reset the WDT timer now_tick=millis(); //grab current counter tick if((now_tick - blink)>BLINK_RATE_CNT){ blink=now_tick; //reset value health_count++; //increment the health counter #ifdef DEBUG //Used for test //ALARM.byte_value1=health_count; //ALARM.byte_value1=accel_stable_cnt; //ALARM.byte_value2=battery_test_val; #endif if((ALARM.movement_alert_flag==FALSE) && (health_count>=HEALTH_CNT_VAL)){ //go check board health check_board_health(); //Make sure we're still talking to the sensors and check battery. health_count=0; //reset the value }//end health check //if there's an error with the board, then indicated it quickly, else pulse green for //everything is OK if(ALARM.board_error_msg==NO_ERROR_FOUND){ flash_status_led(STATUS_LED_GRN_PIN); //all is good }else{ flash_status_led(STATUS_LED_RED_PIN); //Something is bad }//end if }//end system blink //this fires every 500 msec See header file if((now_tick - stable_tick)> PSI_TICK_CNT ){ stable_tick = now_tick; //reset value if(ALARM.movement_alert_flag==TRUE){ //THIS counter gets incremented because we're looking for a stabilized, no movement value //from the PSI sensor after the accel starts the sequence, if Not it gets reset to 0 because it's still moving. //and this value increments based off the timing of this loop ALARM.no_movement_stable_cnt++; //increment stable counter } //after a movement event, the accel_stabalized flag is automatically set to false //because we want to assure the unit is still not moving around. if(ALARM.accel_stabalized!=TRUE){ side_flash_leds(MAIN_SIDE_LED_FLASH_SPD,MAIN_SIDE_LED_LOW_PWR); //Show we're looking for stable time CB(SYSTEM_STATUS_PORT, STATUS_LED_BLUE_PIN); //Turn On Blink LED get_acceration_data(); //Just looking at the sensor's 3 axis's of data accel_stable_cnt++; //This gets incremented from each "PSI_TICK_CNT" rate //if the unit is not moving around, then after this "period" of no movement from //the accel is good, then everything gets reset for another event. //if the unit is on ANY axis line, then the combined x,y,z value is approx. 1065 counts. //if the unit is moving around or rotating around, then it is outside of these boundaries. if((ALARM.raw_abs_value < ACCEL_SUMMED_LOWER_VALUE) || (ALARM.raw_abs_value > ACCEL_SUMMED_UPPER_VALUE) ){ accel_stable_cnt =0; //reset the counter ALARM.what_axis_detected=0; //reset axis }else{ //now we know what axis we're on. if(accel_stable_cnt>=ACCEL_STABALIZE_CNT){ //find what axis we're on accel_sensor.enable_wakeup_interrupt(0); //Turn off interrupt so we can calibrate the sensor now ALARM.what_axis_detected =accel_sensor.determine_thecurrent_axis(); //Get current Axis accel_sensor.setup_axis_interrupt(ALARM.what_axis_detected); //Now setup the correct interrupt for that axis on the sensor ALARM.detected_sensitivity_level=ACCEL_STARTING_SENS_LEVEL; //set the default value and work up from there wdt_reset(); // reset the WDT timer //now go calibrate the sensitivity threshold for the current axis while(calibrate_for_landed_axis()==0){ //delay(50/2); //delay is done in routine } wdt_reset(); // reset the WDT timer //because of calibration routine chirp_beeper(2); //Finished calibration SB(SYSTEM_STATUS_PORT, STATUS_LED_BLUE_PIN); //Turn ON BLUE LED get_psi_sensor_data(); //get the data //initialize buffers with the current pressure for(i=0;i<PSI_BUFFER_DATA_SIZE;i++){ psi_array_struct[i].sen_val = psi_array_struct[i].fval = ALARM.sensor_pressure; // if(i<MOVING_AVG_WINDOW_SIZE){ ALARM.last_irr_value=ALARM.irr_output = ALARM.sensor_pressure; } } accel_stable_cnt=0; //reset this counter side_flash_leds(0,OFF); delay(600/CPU_MODE); //This lets the accelerometer stabalize //now go store the found thresholds values into the accel chip accel_sensor.set_threshhold_time_value((ALARM.detected_sensitivity_level + ACCEL_DURATION_LEVEL_ADDER),ACCEL_STARTING_DURATION_LEVEL); delay(10/2); //Short delay accel_sensor.readByte(REGISTER_ACCEL_INT1_SOURCE_A); //Clear any pending interrupts prior to re-enabling it accel_sensor.enable_wakeup_interrupt(1); //setup interrupt information so it lets processor know via INT0 delay(10/2); EIMSK |= (1 << INT1) | (1 << INT0) ; // Turn ON INT1 and INT0 for the processor now ALARM.accel_stabalized=TRUE; //now stable } }//end else }//end if }//End if now psi tick //////////////////////////////////////////////////////////////////////////////////////////////////////// //This is basically set by INT1 frequency. //128 Hz=206 mSec 64Hz=105 mSec 32 Hz=53 mSec //so by setting the PSI to the highest accuracy, it samples data at XX Hz //this operation, referring to chip's docs, takes approximately XX mSec to do //Once it's finished getting a reading, the interrupt fires and lets the processor //know that PSI data is available to read //**************************************** note we have to get the PSI data, because if the ACCEL fires off, we need to know what the //starting PSI level is that the unit started at if(ALARM.psi_interrupt_detected==TRUE){ get_psi_sensor_data(); //get the raw data check_for_psi_movement(); //process it and check for movement filter_psi_buffer_array(); ALARM.psi_interrupt_detected=FALSE; //reset it //Note, you have to read this following register, after doing so it resets the interrupt on the PSI Sensor //which then clears it, dropping the INT1 on the processor line low, unit a pressure sensor read is ready to be read //again for the next go around preasure_sensor.readByte(TY_DPS310_INT_STS);//Reads this byte which then clears interrupt register on PSI sensor. }//end PSI Sensor interrupt //if alarm is now stabilized, then go ahead and check for any acceleration movement if(ALARM.accel_stabalized==TRUE){ check_for_accel_movement(); }//end accel stabilized // if there's an event, then make the unit beep. if(ALARM.movement_alert_flag==TRUE){ side_flash_leds(MAIN_SIDE_LED_FLASH_SPD, MAX_PWM_LIMIT); movement_beep_routine(1); check_for_no_more_movement(); //go check to see if we're still moving??? }else{ movement_beep_routine(OFF); ALARM.no_movement_stable_cnt=0; } #ifdef DEBUG // A basic scanner, see if it ACK's //look_for_I2C_devices(40,1); show_debug(); #endif }//End Main Loop ************************************************************************************************ uint8_t calibrate_for_landed_axis(void){ uint8_t temp; //So this routine looks at the interrupt register of the accelerometer //we're looking to define the maximum sensitivity level is for the sensor is depending upon //what axis it's mounted on. //we start with a low value, look for the interrupt, then increment that level by 1 count. //1 count = ~approx 16 mg. //once that level does not trip the interrupt, then we return the last known value that worked. //we also set the "time duration" that interrupt has to be present. at a ODR of 100 hz. //the LSB in the duration register is = 10 ms. See page 33 accel_sensor.set_threshhold_time_value(ALARM.detected_sensitivity_level, ACCEL_STARTING_DURATION_LEVEL); // we disable the interrupt on the accel sensor, because that disables taking the interrupt out to the pin on the chip //therefore the processor does not actually see an interrupt occur. //This gets changed back to "1" after the calibration is done in the code delay(68/2); accel_sensor.enable_wakeup_interrupt(0); temp = accel_sensor.readByte(0x31); //read register #ifdef DEBUG // ALARM.byte_value2 = temp; #endif temp = temp & 0x40; //AND the register with 0x40 which is the global "interrupt" has occurred on the accel sensor //if true, then an interrupt has occurred. if(temp == 0x40){ ALARM.detected_sensitivity_level++; //increment it the level by one now. return 0; //return 0, meaning an interrupt on that level is still causing an interrupt. } //if false, then return the level that DOES NOT make an interrupt occur return (ALARM.detected_sensitivity_level); //return detected level }//end calibrate void check_for_no_more_movement(void){ //static boolean one_shot_flag=FALSE; //This routine ONLY gets called if the movement_alert_flag==TRUE This is from the accel interrupt //So, if it's TRUE, then let's do this: //But then after that, we're going to check and see if there is no more movement //This is done via the pressure sensor since the peizo drives everything crazy. //Once everything is settled, then it gets turned back on if((ALARM.psi_stop_detected==TRUE) || (ALARM.no_movement_stable_cnt>=PSI_STABALIZE_CNT) ){ side_flash_leds(0,OFF); ALARM.movement_alert_flag=FALSE; //reset ALARM.movement_by_accel_sensor=FALSE; ALARM.movement_by_psi_sensor=FALSE; ALARM.psi_stop_counter_cnt=0; ALARM.accel_stabalized=FALSE; //set this FALSE so it goes and auto calibrate on next move } }//end function void movement_beep_routine(uint8_t _alarm_type){ volatile static uint32_t now_tick,beep_time; static bool toggle=0; static bool led_toggle=0; uint8_t i; now_tick=millis(); //grab current counter tick if(_alarm_type==TRUE){ if((now_tick - beep_time)>BEEP_ON_OFF_TIME){ toggle = !toggle; if(toggle==0){ CB(MAIN_LED_ALARM_PORT, SYSTEM_PIEZO_PIN); //Peizo Buzzer for(i=0;i<2;i++){ OCR1A = MAX_PWM_LIMIT; delay(LED_FLASH_TIME); OCR1A = OFF; delay(LED_FLASH_TIME); }//end for }//end toggle if(toggle==1){ #ifdef PIEZO_BUZZER_ON SB(MAIN_LED_ALARM_PORT, SYSTEM_PIEZO_PIN); #endif } beep_time = millis(); }//end if }//end if if(_alarm_type==FALSE){ CB(MAIN_LED_ALARM_PORT, SYSTEM_PIEZO_PIN); //Turn things OFF OCR1A = OFF; } }//end routine ISR (INT0_vect) // Accel Sensor Interrupt { //If we made it here, that means an interrupt from the Accel. was detected, meaning it had data to read or it fired for a setup //detection amount routine. if(ALARM.accel_interpt_detected==FALSE){ ALARM.accel_interpt_detected=TRUE; #ifdef DEBUG //if in debug get data, but since we don't use it during normal we don't grab it. ALARM.accel_trig_value_x = ALARM.raw_x_output; ALARM.accel_trig_value_y = ALARM.raw_y_output; ALARM.accel_trig_value_z = ALARM.raw_z_output; #endif } }//End Interrupts ISR (INT1_vect) //PSI Sensor Interrupt { //if Used, then place INT1_vect code here. This would be for the Pressure sensor on the board //but the resistor for the interrupt connection would have to be placed on the board too. if(ALARM.psi_interrupt_detected==FALSE){ ALARM.psi_interrupt_detected=TRUE; } }//End Interrupts void check_for_accel_movement(void){ uint8_t temp_val; #ifdef DEBUG //don't really need to get this data unless we are debugging/ //accel now fires off of interrupt get_acceration_data(); #endif if(ALARM.accel_interpt_detected==TRUE){ ALARM.psi_stop_detected = FALSE; ALARM.accel_triggers++; //only increment it once ALARM.movement_by_accel_sensor=TRUE; ALARM.movement_alert_flag=TRUE; //indicate a movement is in progress //accel_sensor.enable_wakeup_interrupt(OFF); //Turn Off interrupt now on accelerometer only //No need to do that now, set it to latched //interrupt and it's now cleared in settle routing //But left it here for reference. //accel_sensor.readByte(REGISTER_ACCEL_INT1_SOURCE_A); //clear interrupt, you have to read it to clear it ALARM.accel_interpt_detected=FALSE; //Now turn this OFF, we only fire this event once //Grab current pressure when it fired ALARM.sensor_start_value=psi_array_struct[ALARM.psi_buffer_index].mov_avg; //store newest value //For Testing Only //accel_sensor._write_byte(REGISTER_ACCEL_CTRL_REG3_A, 0x00); //interrupt driven to INT1 pad //ALARM.byte_value2= temp_val = accel_sensor.readByte(REGISTER_ACCEL_INT1_SOURCE_A); } }//end function float movingAverage(float value){ //Moving average filter for what ever window size was set static byte current = 0; // Index for current value static float sum = 0; // Rolling sum sum = sum - ALARM.mov_values[current]; ALARM.mov_values[current] = value; sum += value; current = (current+1) % MOVING_AVG_WINDOW_SIZE; return sum/MOVING_AVG_WINDOW_SIZE; }//End Function void filter_psi_buffer_array(void){ volatile static uint8_t one_flag; uint8_t y; //x is the decay between adjacent samples. Choose any number between 0 and 1 (except 1). const float xpsi = 0.15; //calculate delta from start ALARM.sensor_delta=abs(ALARM.sensor_pressure - ALARM.sensor_start_value); //IRR filter ALARM.irr_output = ALARM.sensor_pressure * xpsi + (ALARM.last_irr_value) * (1-xpsi); ALARM.last_irr_value=ALARM.irr_output; volatile uint8_t temp_index; //Store data into the arrays psi_array_struct[ALARM.psi_buffer_index].sen_val = ALARM.sensor_pressure; //get current value psi_array_struct[ALARM.psi_buffer_index].fval = ALARM.irr_output; //get current filtered value psi_array_struct[ALARM.psi_buffer_index].mov_avg = movingAverage(ALARM.irr_output); //get current moving average filtered value //*************************************************** only logical code between here ***************************************************** //*************************************************** no code below here *********************************************************************************** #ifdef DEBUG_PRINT_BUFFER #define BUFFER_ROW_START 30 #define BUFFER_ROW_COL_DATA_START 3 #define BUFFER_ROW_COL2_DATA_START 14 #define BUFFER_ROW_COL3_START 18 #define BUFFER_ROW_COL4_START 35 #define BUFFER_ROW_COL4_START_DATA 45 term.set_color(DATA_COLOR, BT_BLACK); //yellow term.position(BUFFER_ROW_START-1, 0); term.print("B= "); term.set_color(DATA_COLOR, BT_BLACK); //yellow term.position(BUFFER_ROW_START-1,BUFFER_ROW_COL_DATA_START); term.print(ALARM.psi_buffer_index, DEC); term.position((BUFFER_ROW_START + ALARM.psi_buffer_index), 0); term.print(" "); term.position((BUFFER_ROW_START + ALARM.psi_buffer_index),0); term.print(ALARM.psi_buffer_index,DEC); term.position((BUFFER_ROW_START + ALARM.psi_buffer_index),BUFFER_ROW_COL_DATA_START); term.print(psi_array_struct[ALARM.psi_buffer_index].sen_val,3); //term.print(psi_array_struct[ALARM.psi_buffer_index].fval,3); term.position((BUFFER_ROW_START + ALARM.psi_buffer_index),BUFFER_ROW_COL2_DATA_START); term.print(psi_array_struct[ALARM.psi_buffer_index].mov_avg,3); term.position((BUFFER_ROW_START + ALARM.psi_buffer_index),BUFFER_ROW_COL2_DATA_START+10); //term.print(slope,3); //term.print(abs(psi_array_struct[ALARM.psi_buffer_index].mov_avg - psi_array_struct[temp_index].mov_avg),3); term.print(abs(psi_array_struct[ALARM.psi_buffer_index].mov_avg - ALARM.sensor_start_value),3); #endif //*********************************************************************************************************** **************************** //Here we're testing to see if we are still moving, meaning if the X amount of the samples have not changed, then //we're not moving //This means the accel has started a movement if(ALARM.movement_alert_flag==TRUE){ //if we're at least gone a few periods, but not quite to the end then //We now here looking to see if we're greater than the PSI Thresh hold, if not, we'll let the accell timner time out //but if we are, that means we're moving so set PSI sensor to TRU if( (ALARM.no_movement_stable_cnt >= (2)) && (ALARM.sensor_delta > PSI_THRESH_HOLD_TRIGGER) ){ //so now we have a valid PSI sense ALARM.movement_by_psi_sensor=TRUE; if(one_flag==0){ ALARM.psi_triggers++; //increment counter ALARM.moving_stopped_cnt=0; //reset timing counter one_flag=1; } }//end } //so if the PSI is true and a movement has occurred then... if(ALARM.movement_by_psi_sensor==TRUE){ if( ALARM.no_movement_stable_cnt >= (PSI_STABALIZE_CNT/2)){ //if we're 1/2 way into the stable counter then //because we have to account for the 25 fpm movement rate which is 5" per second roughly ALARM.no_movement_stable_cnt = (PSI_STABALIZE_CNT-2); //Set stable counter to end count - 2 //Look at the staring element, then the last element and see if we've settled if(abs(psi_array_struct[0].mov_avg- psi_array_struct[PSI_BUFFER_DATA_SIZE-1].mov_avg) > PSI_STOP_MOVING_VALUE ){ ALARM.psi_stop_counter_cnt=0; //not settled so reset the moving counter }else{ //If is is greater, then make sure we do it XX amount of times, then we full stop with ALARM.psi_stop_counter_cnt++; if(ALARM.psi_stop_counter_cnt >=PSI_STOP_COUNT){ ALARM.psi_stop_detected=TRUE; //Made the count, so stop one_flag=0; } } } }//end psi true //The rest down is printing #ifdef DEBUG_PRINT_BUFFER #define BUFFER_ROW_START 30 #define BUFFER_ROW_COL_DATA_START 3 #define BUFFER_ROW_COL2_DATA_START 11 #define BUFFER_ROW_COL3_START 12 #define BUFFER_ROW_COL4_START 35 #define BUFFER_ROW_COL4_START_DATA 45 term.set_color(DATA_COLOR, BT_BLACK); //yellow term.position(BUFFER_ROW_START, BUFFER_ROW_COL4_START); term.print("Del Avg: "); term.position(BUFFER_ROW_START,BUFFER_ROW_COL4_START_DATA); term.print(ALARM.sensor_delta_avg, 3); term.position(BUFFER_ROW_START+1, BUFFER_ROW_COL4_START); term.print("S filter: "); term.position(BUFFER_ROW_START+1,BUFFER_ROW_COL4_START_DATA); term.print(ALARM.sensor_filtered, 3); term.position(BUFFER_ROW_START+2, BUFFER_ROW_COL4_START); term.print("Str Delt: "); term.position(BUFFER_ROW_START+2,BUFFER_ROW_COL4_START_DATA); //term.print(ALARM.sensor_delta,3); term.print(abs(ALARM.sensor_pressure - ALARM.sensor_start_value),3); term.position(BUFFER_ROW_START+3, BUFFER_ROW_COL4_START); term.print("Settle: "); term.position(BUFFER_ROW_START+3,BUFFER_ROW_COL4_START_DATA); term.print(ALARM.no_movement_stable_cnt, DEC);