/*
[ - BTEK SQUAD - ]
Project Manager
62160144 (สัคสรัคร คงเตี้ย) - Code Name : Sincerely
Quality Assurance
62160250 (จิราธิป สุวรรณศิลป์) - Code Name : Bug
Business Analyst
62160303 (ศักดิ์สิทธิ์ แหวนวงค์) - Code Name : JINNIE KIM
Developers
62160246 (จักรฤษณ์ ชาวพรอน) - Code Name : hex
62160345 (วิรภัทร พวงมาลัย) - Code Name : Dio
*/
// Includes
#include <LiquidCrystal_I2C.h>
#include <EveryTimer.h>
// Embed Items & Variables
LiquidCrystal_I2C monitor(0x27,20,4); // set the monitor address to 0x27 for a 16 chars and 2 line display
int motionSensor = 0; // choose the input pin (for PIR sensor)
int potPin = 0; // analog pin used to connect the potentiometer
#define LED_TEMP_CARE_PIN 2 // led for TempCare
#define LED_TREAD_MILL_PIN 3 // led for isHumanOnTreadMill
#define SWITCH_BUTTON_PIN 13 // switch on and off about Temp Care System
#define ALERT_SPEAKER_PIN 8 // pin of Alert Speaker
// NTC pin used to connect at A1
const float ntcBETA = 3950; // should match the Beta Coefficient of the thermistor
// Timer Variables
EveryTimer timer;
#define PERIOD_CHECK_IS_HUMAN_ON_TREAD 1000 // check is human on tread every 1 secs
// Attemp Check Variables
int attempCheckIsHumanOnTread = 50; // attemp check 50 time after human on tread
int cachedATCIHOT = attempCheckIsHumanOnTread;
int attempAlert = 15; // attemp alert every n * 200 ms
// Human Variables
float humanTemp = -1.00; // temp of human
int speed = 0; // speed of Tread Mil
int alertAttemp = 15; // alert human emergency attempt n * 200ms
// Level Speed Control System
float level1StartAtGreatThan = 37.0;
float level2StartAtGreatThan = 37.5;
float levelEmergency = 38.5;
// Boolean Status
bool isHumanOnTreadMill = false; // Check is human on Tread Mill
bool tempCare = false; // basic start with off
bool isStared = false; // is started Tread Mill
bool isEmergency = false; // is emergency action doing
int lastState = HIGH; // last pressed or release value
// Update Fncs
void updateHumanOnTreadMill(){
if(isEmergency)return 0;
if(digitalRead(motionSensor) == 1){
humanOnTread();
return 0;
}
if(digitalRead(motionSensor) == 0 && attempCheckIsHumanOnTread > 0){ // Read Motion and Start TreadMil
Serial.println("Attempt Checking isHumanOnTreadMill -> "+String(attempCheckIsHumanOnTread));
attempCheckIsHumanOnTread--;
return 0;
}
humanOffTread();
}
void humanOffTread(){
attempCheckIsHumanOnTread = cachedATCIHOT;
smoothSetSpeed(0);
isStared = false;
isHumanOnTreadMill = false;
updateTempCare();
updateHumanTemp();
analogWrite(LED_TEMP_CARE_PIN, 0);
analogWrite(LED_TREAD_MILL_PIN, 0);
}
void humanOnTread(){
attempCheckIsHumanOnTread = cachedATCIHOT;
isHumanOnTreadMill = true;
analogWrite(LED_TREAD_MILL_PIN, 255);
if(!isStared){
isStared = true;
updateTempCare();
}
}
void smoothSetSpeed(int kphGoal){
// smooth decrase.
while(speed != kphGoal){
if(speed > kphGoal){
speed--;
}else if(speed < kphGoal){
speed++;
}
updateMonitor();
}
}
void emergencyAlert(){
isEmergency = true;
monitor.clear();
for(int l=0; l < attempAlert; l++){
analogWrite(LED_TEMP_CARE_PIN, l%2==0 ? 0 : 255);
analogWrite(LED_TREAD_MILL_PIN, 0);
tone(ALERT_SPEAKER_PIN, 262, 200);
monitor.setCursor(0, 0);
monitor.println("Emergency Detected");
monitor.setCursor(0, 2);
monitor.println("1911 Calling...");
monitor.setCursor(0, 3);
monitor.println("* TM Stopping *");
delay(200);
}
isEmergency = false;
humanOffTread();
}
void updateSpeed(){
if(!isHumanOnTreadMill){
smoothSetSpeed(0);
}else{
int currentSpeed = analogRead(potPin);
currentSpeed = map(currentSpeed, 0, 1023, 0, 50);
// @ Emergency Case
if(humanTemp > levelEmergency){
smoothSetSpeed(0);
if(humanTemp > levelEmergency && !isEmergency){
emergencyAlert();
}
// @ Speed Control Case with tempCare
}else if(tempCare){
// @ Lv 1 Case
if(humanTemp > level1StartAtGreatThan && humanTemp < level2StartAtGreatThan){
smoothSetSpeed(7);
// @ Lv 2 Case
}else if(humanTemp > level2StartAtGreatThan && humanTemp < levelEmergency){
smoothSetSpeed(3);
// @ Normal Case
}else{
smoothSetSpeed(currentSpeed);
}
}else if(!tempCare){
smoothSetSpeed(currentSpeed);
}
}
}
void updateTempCare(){
tempCare = !tempCare; // If have human on Tread Mill it's must on .
tempCare = tempCare == true && isHumanOnTreadMill == true;
analogWrite(LED_TEMP_CARE_PIN, tempCare ? 255 : 0);
}
void updateSwitchSystemButton(){
if(digitalRead((SWITCH_BUTTON_PIN)) != lastState){
lastState = digitalRead((SWITCH_BUTTON_PIN));
if(lastState == HIGH){
updateTempCare();
}
}
}
void updateHumanTemp(){
int tempValue = analogRead(A1);
humanTemp = 1 / (log(1 / (1023. / tempValue - 1)) / ntcBETA + 1.0 / 298.15) - 273.15;
humanTemp = isHumanOnTreadMill == true ? humanTemp : -1.00;
}
String *getHumanStatusLabels(){
static String status[4];
// temp
status[0] = ("Human Temp: "+String(humanTemp == -1.00 ? " - " : String(humanTemp))+"C");
// speed
status[1] = ("Speed: "+String(speed)+" kph");
// temp care
status[2] = tempCare ? "Temp Care: ON" : "Temp Care: OFF";
// tread mill status
status[3] = isHumanOnTreadMill ? "Tread Mill: ON" : "Tread Mill: OFF";
return status;
}
void updateMonitor(){
// get status labels
String *status = getHumanStatusLabels();
// Human Temp
monitor.setCursor(0, 0);
monitor.println(status[0]);
// Speed
monitor.setCursor(0, 1);
monitor.println(status[1]);
// Temp Care for control speed logic control by Human Temp )
monitor.setCursor(0, 2);
monitor.println(status[2]);
// Tread Mill Status
monitor.setCursor(0, 3);
monitor.println(status[3]);
}
const void BTEK_HUMAN_TEMP_LOOP(){
// update running time of embeds
timer.Update();
if(isEmergency)return;
// update humanTemp
updateHumanTemp();
// update speed
updateSpeed();
// update switch button
updateSwitchSystemButton();
updateMonitor();
}
void setup() {
Serial.begin(9600);
monitor.init();
monitor.backlight();
pinMode(LED_TEMP_CARE_PIN, OUTPUT);
pinMode(LED_TREAD_MILL_PIN, OUTPUT);
pinMode(SWITCH_BUTTON_PIN, INPUT_PULLUP);
pinMode(ALERT_SPEAKER_PIN, OUTPUT);
// Check human on tread mill every 1 sec .
timer.Every(1000, updateHumanOnTreadMill);
}
void loop() {
BTEK_HUMAN_TEMP_LOOP();
}