Project tutorial
Contact-less Entry and Contact Tracing

Contact-less Entry and Contact Tracing © CC BY-NC-SA

This project is about creating an IR air remote that has an ID for contact tracing and using gestures for contact-less entry.

  • 1,149 views
  • 0 comments
  • 0 respects

Components and supplies

Apps and online services

About this project

The objective of this project is to reduce contact in everyday life and enable contact tracing by using an inexpensive portable IR remote device.The remote is designed with the following goals:

  • Portable. It is an IR device with just one button so that it can be small enough to be carried conveniently like a key chain.
  • Powerful. It can send out different IR codes by detecting a user's gestures using a gyroscope so that one can perform complex tasks with even just one button.
  • Customizable. It can be customized to send an user defined code to perform a task such as a blind person selecting a desired floor level in an elevator.

Contact Tracing Each remote has a specific ID. When you click a button on your remote, a unique ID assigned to the remote will be sent. For example, in a common public store, you can point your remote to a door controller and click the button. The controller detects the specific header in the ID and saves your ID with a timestamp in a database and will perform the task of opening the door. By doing so, a visit to a grocery store or a movie theater will generate two timestamps for an ID. Big data analysis can be performed to people's exposure to a person infected by Covid-19.

Contact-less Entry Another use for the remote is to in the elevator. In order to go to a floor, you can either use your IR remote or a distance sensor connected to the LCD screen. To use your IR remote, you double click and it will enter sensing mode. You can use gestures to highlight buttons displayed on the LCD screen to make a number up to three digits. Once you are done, you click the button again and it will show floor you are going to. If you use the distance sensor, you can use your hand to choose a floor. The farther away your hand is from a sensor, the higher the floor it will display. The closer your hand is, the smaller the floor level. Once a screen shows the desired floor number, keep your hand steady and you will go to that floor. If you have previously been in the same elevator, it will give you an option go to the floor that you last went to.

Contact-lessElevator Entry In order to go to a floor, you can either use your IR remote or a distance sensor connected to the LCD screen. To use your IR remote, you double click and it will enter sensing mode. You can use gestures to highlight buttons displayed on the LCD screen to make a number up to three digits. If you want to erase the digits, highlight the button with the asterisk on it and it will clear the input buffer. Once you are done, you click the button again and it will show floor you are going to. If you use the distance sensor, you can use your hand to choose a floor. The farther away your hand is from a sensor, the higher the floor it will display. The closer your hand is, the smaller the floor level. Once a screen shows the desired floor number, keep your hand steady and you will go to that floor.

If you have a remote with a unique ID, it can do contact tracing. To do contact tracing, you click a button only once. Then, your ID will pop up on the controller and will be saved on the SD card connected to the device. The next time you walk in the elevator, it will retrieve the last level you went to and ask you if you would like to go to that floor. If you do, then you click the button again and you will be taken to the floor. If you do not want to go to the last floor you went to, then you can double-click the button to activate the number pad.

Code

IR Air RemoteArduino
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <IRLib.h>

IRsend My_Sender;

int buttonPin = 6;
int ledPin = 5;

Adafruit_MPU6050 mpu;

unsigned long firstPressedTime;
unsigned long lastFlashingTime;
bool flashingOn = false;

bool sensing = false;

bool firstPressed = false;
bool firstReleased = false;
bool secondPressed = false;
bool secondReleased = false;

int timeToWaitFor2 = 800;

unsigned long timeout = 60000;

unsigned long myID = 0xC9123456;
unsigned long finalFlag = 0xC9FFFFFF;

void sendCode(unsigned long code){
  My_Sender.send(NEC, code, 32);
  delay(15);  
  My_Sender.send(NEC, code, 32);
}

void resetStates(){
  firstPressed = false;
  secondPressed = false;
  
  firstReleased = false;
  secondReleased = false;

  flashingOn = false;
  sensing = false;
  digitalWrite(ledPin, HIGH);
}

void setup(void) {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  digitalWrite(ledPin, HIGH);

  while (!Serial) {
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
  }

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }

  mpu.setAccelerometerRange(MPU6050_RANGE_16_G);
  mpu.setGyroRange(MPU6050_RANGE_250_DEG);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  Serial.println("");
  delay(100);
}

void loop() {
  if (sensing){
    unsigned long current = millis();
    
    if (firstPressedTime + timeout < current){
      Serial.println("Sensing timed out!");

      resetStates();
      return;
    }

    if (lastFlashingTime + 600 < current){
      if (flashingOn){
        //Serial.println("Flashing off");

        digitalWrite(ledPin, HIGH);
        flashingOn = false;
      }
      else{
        //Serial.println("Flashing on");
        
        digitalWrite(ledPin, LOW);
        flashingOn = true;
      }

      lastFlashingTime = millis();
      
    }

    if (digitalRead(buttonPin) == LOW){
      Serial.println("Stop sensing");
  
      sensing = false;
      firstPressed = false;
  
      sendCode(finalFlag);
      digitalWrite(ledPin, HIGH);
    }
  }

  if (!sensing & digitalRead(buttonPin) == HIGH & firstPressed & !firstReleased){
    firstReleased = true;
    
    Serial.println("Button released first time.");

  }

  if (!sensing & digitalRead(buttonPin) == HIGH & secondPressed & !secondReleased){
    Serial.println("Button released second time.");
  
    secondReleased = true;
  }
  
  if (!sensing & digitalRead(buttonPin) == HIGH & firstPressed & firstReleased & (firstPressedTime + timeToWaitFor2 < millis())){
    if (secondReleased) {
    //Signal double-click
      sendCode(0xC9E10000 + (unsigned long) 0xFF*256 + (unsigned long) 0xFF);
      Serial.println("Start sensing");
      digitalWrite(ledPin, LOW);
      flashingOn = false;
      lastFlashingTime = millis();
      delay(500);
      sendCode(myID);
      resetStates();
      sensing = true;
    }
    else {
      sendCode(myID);
      resetStates();
    }
  }

  //handling first time button pressed
  if (digitalRead(buttonPin) == LOW & !firstPressed){
    firstPressed = true;
    firstPressedTime = millis();
    digitalWrite(ledPin, LOW);
    Serial.println("Button pressed first time.");
    //sendCode(myID);
    
    
  }
  else if (digitalRead(buttonPin) == LOW & firstReleased & !sensing){
    Serial.println("Button pressed second time.");
    secondPressed = true; 
  }
  
  
  if (sensing){
    /* Get new sensor events with the readings */
  
  
    sensors_event_t a, g, temp;
    mpu.getEvent(&a, &g, &temp);
  
    float x = a.acceleration.x + 10;
  
    if (x < 0) {
      x = 0;
    }
  
    if (x > 20) {
      x = 20;
    }
  
    x = x * 255.0/20;
    
    float y = a.acceleration.y + 10;
  
    if (y < 0) {
      y = 0;
    }
  
    if (y > 20) {
      y = 20;
    }
  
    y = y * 255.0/20;
  
    float z = a.acceleration.z + 10;
  
    if (z < 0) {
      z = 0;
    }
  
    if (z > 20) {
      z = 20;
    }
  
    z = z*255.0/20;
  
    
    
    sendCode(0xC9E10000 + (unsigned long) x*256 + (unsigned long) y);
    Serial.print(a.acceleration.x);
    Serial.print(",");
    Serial.print(a.acceleration.y);
    Serial.print(",");
    Serial.print(a.acceleration.z);
    Serial.print(", ");
    Serial.print(x);
    Serial.print(",");
    Serial.print(y);
    Serial.print(",");
    Serial.print(z);
    Serial.println("");
  }
  delay(50);
}
Elevator ControllerArduino
#include <stdint.h>
#include <TFTv2.h>
#include <SPI.h>
#include <SD.h>
#include <IRremote.h>
#include <ThreeWire.h>  
#include <RtcDS1302.h>

#include "Adafruit_VL53L0X.h"

ThreeWire myWire(32,30,34); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

int RECV_PIN = 19;

char buff1[32];

char buff2[32];

char prevLabel1[3];

char label1[3];

char label2[3];

char label3[3];

char buff[32];


int DELAY_INTERVAL = 200;

IRrecv irrecv(RECV_PIN);
decode_results results;

unsigned long oldID = 0;

unsigned long prevID = 0;

unsigned long prevIDTime = 0;

unsigned long oldDistance = 0;

unsigned long prevLevelChangeTime = 0;

unsigned long lastIRDetected = 0;

unsigned long idleTime = 1600;

unsigned long currentID = 0;

unsigned long finalFlag = 0xc9ffffff;

unsigned long doubleFlag = 0xc9e1ffff;

unsigned long doubleFlagTime = 0;

char IDStr[11];

const int maximum = 100;

const int minimum = 5;

int prevMark = 0;

uint16_t measures[20];

int b_h = 1;
int b_t = 0;

int textx = 0, texts = 3;

//File myFile;

int unit_size = 3;

int oldLevel = (int)(maximum - minimum)/unit_size + 2;

int savedLevel = -1;

int sensitivity = 0.2 * 29 * 2;
const int pingPin = 16; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 15; // Echo Pin of Ultrasonic Sensor

const int PIN_SD_CS = 4;  

bool drawingButton = false;

bool prompting = false;

unsigned long promptingTime = 0;

unsigned long promptingTimeout = 4000;

unsigned long lastTimeIRDetected = 0;

bool displayingSelection = false;

char buttonLetter[][12] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"};

int highlightedButton = -1;

int digit1 = -1;

int digit2 = -1;

int digit3 = -1;


int prevDigit1 = -1;

int prevDigit2 = -1;

int prevDigit3 = -1;

unsigned long buttonHighlightedTime = 0;

bool hasHighlightedButton =  false;

void drawButton(int bn, unsigned int bc, unsigned int fc){
  drawButton(20 + (bn%3) * 80, 80 + ((int)bn/3) * 65, buttonLetter[bn], bc, fc);
}

void drawButton(int x, int y, char *s, unsigned int bc, unsigned int fc){
  Tft.fillRectangle(x, y, 40, 40, bc);
  Tft.drawString(s, x+7, y+5, 4, fc);
}

void drawButtons(){
  Tft.drawString(buff2, textx, 100, texts, BLACK);
  for (int i = 0; i < 12; i++){
     drawButton(i, WHITE, BLUE);
  }
}

void clearButtons(){
  for (int i = 0; i < 12; i++){
     drawButton(i, BLACK, BLACK);
  }
}
void inputSelected(){
  int level = 0;
    //this is going to level selected
    if (digit1 != 10){
      //the first digit is not zero
      level = level + (digit1 + 1) * 100;
    } 

    if (digit2 != 10){
      //the first digit is not zero
      level = level + (digit2 + 1) * 10;
    }
      if (digit3 != 10){
      //the first digit is not zero
      level = level + (digit3 + 1);
    }

  if (level == 0){
    return;
  }
        
    clearButtons();
    levelSelected(level);
    
    digit1 = -1;
    digit2 = -1;
    digit3 = -1;
          
}

void levelSelected(int level){
  char t[32];

  if (level == 0){
    return;
  }
  
  String s = String("Going to level ") + String(level);
  s.toCharArray(t, s.length() + 1);
   
  //Tft.fillScreen(MIN_X, MAX_X, MIN_Y, MAX_Y, GREEN);
  //clearButtons();
  Tft.drawString(t,5,155,2, WHITE);
  delay(2000);
  //Tft.fillScreen();
  Tft.drawString(t,5,155,2, BLACK);
  //drawButtons();      
  saveLevelForID(IDStr, level);
  strcpy(IDStr, "Default");
  prevLevelChangeTime = millis(); 
}

void clearScreen(){
   clearButtons();
   digit1 = -1;
   digit2 = -1;
   digit3 = -1;
   updateInputBuffer();
   
   Tft.drawString(buff2, textx, 100, texts, BLACK);
   Tft.drawString(label1, 10, MAX_Y-30, 2, BLACK);
   Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, BLACK);
   Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, BLACK);
   Tft.drawVerticalLine(prevMark, MAX_Y - 15, 15, BLACK);
   
   for(int i = 0; i < 20; i++){
     Tft.drawHorizontalLine(MAX_X - 15, measures[i], 15, BLACK);
  }
  

          
}

int cmToLevel(int cm){
  int level = (int)(cm - minimum)/unit_size + 1;
  return level;
}

#define countof(a) (sizeof(a) / sizeof(a[0]))

void saveIDForTracing(char* ID){
  RtcDateTime  dt = Rtc.GetDateTime();

  char dateString[20];

    snprintf_P(dateString, 
            countof(dateString),
            PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
            dt.Month(),
            dt.Day(),
            dt.Year(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
    
  if (strlen(ID) != 8){
    return;
  }

  char* fn = "tracing.csv";

  

  File tracing = SD.open(fn, FILE_WRITE);
  if (tracing) {
    Serial.println("Writing to file: ");
    Serial.println(fn);
    tracing.print(dateString);
    tracing.print(",");
    tracing.println(ID);
    Serial.print(dateString);
    Serial.print(",");
    Serial.println(ID);

    // close the file:
    tracing.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.print("error opening tracing file: ");
    Serial.println(fn);
  }
}

void displayTracingData(){
  File tracing = SD.open("tracing.csv");
  if (tracing) {
    Serial.println("tracing.csv");
    
    // read from the file until there's nothing else in it:
    while (tracing.available()) {
      Serial.write(tracing.read());
    }
    // close the file:
    tracing.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening tracing.csv");
  }
}


void saveLevelForID(char* ID, int level){
  if (strlen(ID) != 8){
     Serial.println("Error: ID size is wrong.");
     Serial.println(ID);


    return;
  }

  char fn[13];

  strcpy(fn, ID);
  strcat(fn, ".txt");

  if (SD.exists(fn)){
    SD.remove(fn);
  }

  File saveLevel = SD.open(fn, FILE_WRITE);
  if (saveLevel) {
    Serial.print("Writing to file: ");
    Serial.print(fn);
    saveLevel.println(level);
  // close the file:
    saveLevel.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.print("error opening file: ");
    Serial.println(fn);

  }
  
}

int getSavedLevel(char* ID){
  char fn[13];
  String level = "";
  
  strcpy(fn, ID);
  strcat(fn, ".txt");
   
  File myFile = SD.open(fn);
  if (myFile) {
    Serial.print("reading from file: ");
    Serial.println(fn);
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      char c = myFile.read();

      if( c == '\n'){
        break;
      }

      level = level + c;
    }
    // close the file:
    myFile.close();

    
    
    return level.toInt();
  } else {
    // if the file didn't open, print an error:
    Serial.print("error opening file: ");
    Serial.println(fn);
    return -1;
  }
}

void updateInputBuffer(){
  if (digit1 == -1){
        if (prevDigit1 == -1){
          //do nothing
        }
        else {
          //to erase the old one
          //Tft.drawString(buttonLetter[prevDigit1], 80, 5, 4, BLACK);
          drawButton(80, 5, buttonLetter[prevDigit1], BLACK, BLACK);
          prevDigit1 = -1;

        }
    }
   else {
    if (prevDigit1 != -1 & prevDigit1 != digit1){
          //erase the old one
          //Tft.drawString(buttonLetter[prevDigit1], 80, 5, 4, BLACK);
          drawButton(80, 5, buttonLetter[prevDigit1], BLACK, BLACK);

          //draw the new one
          //Tft.drawString(buttonLetter[digit1], 80, 5, 4, BLUE);
          drawButton(80, 5, buttonLetter[digit1], WHITE, BLUE);

          //remember the new one.
          prevDigit1 = digit1;
        }
        else if (prevDigit1 != digit1){
          //draw the new one 
          
          drawButton(80, 5, buttonLetter[digit1], WHITE, BLUE);
          //remember the new one.
          prevDigit1 = digit1;
    }
   }
   
   if (digit2 == -1){
        if (prevDigit2 == -1){
          //do nothing
        }
        else {
          //to erase the old one
          //Tft.drawString(buttonLetter[prevDigit2], 110, 5, 4, BLACK);
          drawButton(110, 5, buttonLetter[prevDigit2], BLACK, BLACK);

          prevDigit2 = -1;

        }
    }
   else {
    if (prevDigit2 != -1 & prevDigit2 != digit2){
          //erase the old one
          //Tft.drawString(buttonLetter[prevDigit2], 110, 5, 4, BLACK);
          drawButton(110, 5, buttonLetter[prevDigit2], BLACK, BLACK);

          //draw the new one
          //Tft.drawString(buttonLetter[digit2], 110, 5, 4, BLUE);
          drawButton(110, 5, buttonLetter[digit2], WHITE, BLUE);
          //remember the new one.
          prevDigit2 = digit2;
        }
        else if (prevDigit2 != digit2) {
          //draw the new one
          //Tft.drawString(buttonLetter[digit2], 110, 5, 4, BLUE);
          drawButton(110, 5, buttonLetter[digit2], WHITE, BLUE);
          //remember the new one.
          prevDigit2 = digit2;
    }
   }

   if (digit3 == -1){
        if (prevDigit3 == -1){
          //do nothing
        }
        else {
          //to erase the old one
          //Tft.drawString(buttonLetter[prevDigit3], 140, 5, 4, BLACK);
          drawButton(140, 5, buttonLetter[prevDigit3], BLACK, BLACK);
          prevDigit3 = -1;

        }
    }
   else {
    if (prevDigit3 != -1 & prevDigit3 != digit3){
          //erase the old one
          //Tft.drawString(buttonLetter[prevDigit3], 140, 5, 4, BLACK);
          drawButton(140, 5, buttonLetter[prevDigit3], BLACK, BLACK);
          //draw the new one
          //Tft.drawString(buttonLetter[digit3], 140, 5, 4, BLUE);
          drawButton(140, 5, buttonLetter[digit3], WHITE, BLUE);
          //remember the new one.
          prevDigit3 = digit3;
        }
        else if (prevDigit3 != digit3){
          //draw the new one
          //Tft.drawString(buttonLetter[digit3], 140, 5, 4, BLUE);
          drawButton(140, 5, buttonLetter[digit3], WHITE, BLUE);
          //remember the new one.
          prevDigit3 = digit3;
    }
   }
}

void clearPrompting(){
  Tft.drawString(buff1, textx, 100, texts, BLACK);
          
  Tft.drawString(buff2, textx, 150, texts, BLACK);

}
void setup(){
  buff[0] = 0;
  
  strcpy(IDStr, "Default");
  
  Serial.begin(9600);
  pinMode(pingPin, OUTPUT);
  pinMode(echoPin, INPUT);
  strcpy(label1, "");
  strcpy(label2, "");
  strcpy(label3, "");
  irrecv.enableIRIn(); // Start the receiver

  for(int i = 0; i < 20; i++){
    measures[i] = 0;
  }
  
  Serial.println("Adafruit VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }

    pinMode(PIN_SD_CS,OUTPUT);
    digitalWrite(PIN_SD_CS,HIGH);

    TFT_BL_ON;      // turn on the background light
    
    Tft.TFTinit();
    
    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS); 
    
    if(!SD.begin(PIN_SD_CS))              
    { 
        Serial.println("failed!");
        while(1);                               // init fail, die here
    }
    
  Serial.println("SD OK!");

  Rtc.Begin();

  //RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);

  if (!Rtc.IsDateTimeValid()) 
    {
        // Common Causes:
        //    1) first time you ran and the device wasn't running yet
        //    2) the battery on the device is low or even missing

        Serial.println("RTC lost confidence in the DateTime!");
    //    Rtc.SetDateTime(compiled);
    }

    if (!Rtc.GetIsRunning())
    {
        Serial.println("RTC was not actively running, starting now");
        Rtc.SetIsRunning(true);
    }

}

void loop()

{

  long duration, inches, cm, mark;
   int level;

   int kx, ky;
   bool hasIRValue = false;

    
   unsigned long current = millis();

    if (prompting & promptingTime + promptingTimeout < current){
      Tft.drawString(buff1, textx, 100, texts, BLACK);
          
      Tft.drawString(buff2, textx, 150, texts, BLACK);

      prompting = false;
    }

   //Hover over a button has timed out for selection.
   if (highlightedButton != -1 & buttonHighlightedTime + idleTime < current){
      buttonHighlightedTime = current;
      drawButton(highlightedButton, WHITE, BLUE);
      //delay(1000);
             
      //button is selected
      if (highlightedButton == 9){
        //Erase input buffer
        digit1 = -1;
        digit2 = -1;
        digit3 = -1;
      }
      else if (highlightedButton == 11){
          inputSelected();
          buttonHighlightedTime = millis();
          highlightedButton = -1;
          //drawButtons();
      }
      else {
          digit1 = digit2;
          digit2 = digit3;
          digit3 = highlightedButton;
      }

      highlightedButton = -1;
      
   }

   //Update input buffer display
   updateInputBuffer();
   
  
   // Check IR input
   if (irrecv.decode(&results)) {
    if (results.value >= 0xC9000000 & results.value <= 0xC9FFFFFF ){
      lastTimeIRDetected = millis();
    
      Serial.print(results.value, HEX);
      Serial.print("  ");
      Serial.println(results.value, BIN);
    
      String o = String(results.value, HEX);

      //this is final flag
      if (results.value == finalFlag){
        Serial.println("Handling Final Flag.");
        inputSelected();
        buttonHighlightedTime = millis();
        highlightedButton = -1;
        delay(100);
        
        irrecv.resume(); // Receive the next value}
        return; 
      }

      if (results.value == doubleFlag){
        Serial.println("Handling double Flag.");

        doubleFlagTime = millis();

        if (prompting){
          clearPrompting();
        }
        
        prevID = 0;
        irrecv.resume(); // Receive the next value}
        return; 
      }
      if ((results.value > 0xc9000000 & results.value < 0xc9FFFFFF) & !(results.value > 0xc9e10000 & results.value < 0xc9e1FFFF)){
        //this is an ID code
        

        if (results.value == prevID & prevIDTime + 5000 > millis()){
          RtcDateTime  dt = Rtc.GetDateTime();

          char dateString[20];

          snprintf_P(dateString, 
            countof(dateString),
            PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
            dt.Month(),
            dt.Day(),
            dt.Year(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
  
          Serial.print("Recieved second ID at ");
          Serial.println(dateString);

          
          Tft.drawString(buff1, textx, 100, texts, BLACK);
          
          Tft.drawString(buff2, textx, 150, texts, BLACK);

          levelSelected(savedLevel);

          prompting = false;

          prevID = 0;
            
        }
        else {
          RtcDateTime  dt = Rtc.GetDateTime();

          char dateString[20];

          snprintf_P(dateString, 
            countof(dateString),
            PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
            dt.Month(),
            dt.Day(),
            dt.Year(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
  
          Serial.print("Recieved ID at ");
          Serial.println(dateString);
          
          currentID = results.value;
          String s = String(results.value, HEX);
          s.toCharArray(IDStr, 11);  
          saveIDForTracing(IDStr);

          if (doubleFlagTime + 3000 < millis()){
            savedLevel = getSavedLevel(IDStr);
          }
          else {
            savedLevel = -1;
          }

          Serial.print("Current ID: ");
          Serial.println(IDStr);

          if (savedLevel != -1){
            //promptUser(savedLevel);
            clearScreen();
            strcpy(buff1,"Press Button");
            
            strcpy(buff2, "To Go To Level:");
            char temp[11];
            String s = String(savedLevel);
            s.toCharArray(temp, 11);
            strcat(buff2, temp);
            textx = 5;
            texts = 2;
            prompting = true;
            promptingTime = millis();
            clearButtons();
            
            Tft.drawString(buff1, textx, 100, texts, WHITE);
          
            Tft.drawString(buff2, textx, 150, texts, WHITE);
          }
        }
        
        prevIDTime = millis();
        prevID = results.value;
      }
      
      if (results.value > 0xc9e10000 & results.value < 0xc9e1FFFF){
        if (prompting){
          clearScreen();
          prompting = false;
          drawButtons();
        }
    
      if (!drawingButton){
        drawButtons();
        drawingButton = true;
      }
      
        lastIRDetected = millis();
        unsigned long encoded = results.value - 0xc9e10000;
        unsigned long y = (unsigned long) encoded / 256;
        unsigned long x = encoded % 256;
        /*
        Serial.print("x = ");
        Serial.print(x);
        Serial.print(", y = ");
        Serial.print(y);
        Serial.println();
        */
        
        cm = map(x, 0, 255, 0, 80);

        duration = map(x, 0, 255, 0, 80 * 29 * 2);
        hasIRValue = true; 

        
        if (x < 115){
          x = 115;
        }
        else if (x > 175){
          x = 175;
        }

        x = 175 - x;

      if (y < 95){
          y = 95;
        }
        else if (y > 155){
          y = 155;
        }

        y = y - 95;


        

        ky = map(x, 0, 60, 0, 3);
        kx = map(y, 0, 60, 0, 2);

        int bi = ky*3 + kx;

         Serial.print("kx = ");
         Serial.print(kx);
         Serial.print(" kY = ");
         Serial.print(ky);
         Serial.print(" bi = ");
         Serial.println(bi);

         //
         if (highlightedButton != -1 & highlightedButton != bi){
          buttonHighlightedTime = millis();
           drawButton(highlightedButton, WHITE, BLUE);
           drawButton(bi, GREEN, YELLOW);
            highlightedButton = bi;
         }
         else if (highlightedButton == -1) {
          drawButton(bi, GREEN, YELLOW);
          buttonHighlightedTime = millis();
          highlightedButton = bi;
         }
           
           delay(10);
   
        irrecv.resume(); // Receive the next value} 
      }
      /*
      else {
          if (!drawingButton){
              o.toCharArray(buff, o.length() + 1);
              buff[o.length()+1] = 0;
              Tft.drawString(buff,60,220,3, WHITE);    
          }
          
          delay(200);
          
          irrecv.resume(); // Receive the next value} 
      
      }
      */
    }
    irrecv.resume(); // Receive the next value} 
          
      
    
   }

    if (!prompting & drawingButton & lastTimeIRDetected + idleTime < millis()){
      drawingButton = false;
      clearScreen();
    }

    if (!(drawingButton | prompting)) {      
         VL53L0X_RangingMeasurementData_t measure;
          
      //  Serial.print("Reading a measurement... ");
        lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
      
        
        if (measure.RangeStatus != 4) {  // phase failures have incorrect data
          //Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
        } else {
         // Serial.println(" out of range ");
        }
      
  //      irrecv.resume(); // Receive the next value}
        
        measures[b_t] = map(measure.RangeMilliMeter, 0, 400, MIN_Y, MAX_Y);
        
        Tft.drawHorizontalLine(MAX_X - 15, measures[b_t], 15, RED);
        
        Tft.drawHorizontalLine(MAX_X - 15, measures[b_h], 15, BLACK);
         
        b_t++;
        b_h++;
      
        if (b_t == 15){
          b_t = 0;
        }
      
        if (b_h == 15){
          b_h = 0;
        }
        
        cm = measure.RangeMilliMeter/10;
      
        duration = measure.RangeMilliMeter * 29 * 2 / 10;

    }
    
   
   if (drawingButton | prompting){
    return;
   }
   
   if (cm <= maximum & cm >= minimum){
     level = cmToLevel(cm);
     String d = String(level);
         if (oldLevel == level){
          unsigned long currentTime = millis();
          if (prevLevelChangeTime + idleTime < currentTime & level < 48){
            Tft.drawString(buff2, textx, 100, texts, BLACK);
            prevLevelChangeTime = currentTime;
            levelSelected(level);
          }
   //       Tft.drawString(buff2, textx, 100, texts, WHITE);
      
          mark = map(duration, ((level-1)*unit_size + minimum)*2*29, ((level-1)*unit_size + minimum + unit_size)*2*29, MIN_X, MAX_X);
          //
          
          if (abs(mark - prevMark) > sensitivity){
              Tft.drawVerticalLine(prevMark, MAX_Y - 15, 15, BLACK);
             //   
              Tft.drawVerticalLine(mark, MAX_Y - 15, 15, GREEN);
             //
              prevMark = mark;
              delay(10);   
                
          }
          return; 
         }
         else {
          prevLevelChangeTime = millis(); 
          oldDistance = cm;
          oldLevel = level;
         }
         
     Tft.drawString(buff2, textx, 100, texts, BLACK);
     Tft.drawString(label1, 10, MAX_Y-30, 2, BLACK);
     Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, BLACK);
     Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, BLACK);

    
     d.toCharArray(buff2, d.length() + 1);
     strcpy(label2, buff2);
     Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, WHITE);

     d = String(level+1);
     d.toCharArray(label3, d.length() + 1);
     Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, WHITE);

     d = String(level-1);
     d.toCharArray(label1, d.length() + 1);
     
     Tft.drawString(label1, 10, MAX_Y-30, 2, WHITE);
     
     
     textx = MAX_X/2 - 60;
     texts = 18;

     if (strlen(buff2) == 2){
      textx = textx - 50;
     }

   }
   else if (lastIRDetected + idleTime < millis() & strcmp(buff2, "Not Detected") != 0){
    Tft.drawString(buff2, textx, 100, texts, BLACK);
    Tft.drawString(label1, 10, MAX_Y-30, 2, BLACK);
    Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, BLACK);
    Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, BLACK);

    strcpy(buff2, "Not Detected");
    textx = 5;
    cm = 101;
    level = 48;
    texts = 3;
   }
   
   
   mark = map(duration, ((level-1)*unit_size + minimum)*2*29, ((level-1)*unit_size + minimum + unit_size)*2*29, MIN_X, MAX_X);

   Tft.drawVerticalLine(prevMark, MAX_Y - 15, 15, BLACK);
      
   Tft.drawVerticalLine(mark, MAX_Y - 15, 15, GREEN);
   
   prevMark = mark;
    
   oldID = results.value;
   Tft.drawString(buff, 60, 220, 3, WHITE);

   if (!drawingButton){
       Tft.drawString(buff2, textx, 100, texts, WHITE);    
   }

   Tft.drawHorizontalLine(MIN_X, MAX_Y, MAX_X, RED);
   Tft.drawString(buff2, textx, 100, texts, WHITE);

   delay(100);
}

Schematics

IR Air Remote
IR Air Remote
Ir air remote qmhahbzivw
Elevator Controller
Elevator controller bujuanir9l

Comments

Similar projects you might like

Test the Effectiveness of Your DIY Face Mask

Project tutorial by Chris Munz

  • 3,880 views
  • 1 comment
  • 7 respects

AutoSteri

Project tutorial by David Bershadsky

  • 5,221 views
  • 4 comments
  • 18 respects

Remote Lamp

Project tutorial by Kutluhan Aktar

  • 4,559 views
  • 0 comments
  • 9 respects

S(mart) - Coop

Project showcase by Nadeem Ahmed

  • 3,974 views
  • 3 comments
  • 10 respects

Blind's Companion

Project tutorial by Kumaresh PV

  • 1,028 views
  • 0 comments
  • 0 respects

Android App-Based Home Automation System Using IOT

Project tutorial by Team Autoshack

  • 74,384 views
  • 23 comments
  • 174 respects
Add projectSign up / Login