The goal of our project was to build a mechanism that would detect the presence of a person. Specifically, this can help during the pandemic because classmates and teachers can know whether their peers are actually present on zoom when their cameras are off. The device consists of a sonar sensor used to detect the distance between the machine and the person, and a servo motor to turn a wheel that points to whether a person is there or not. Ideally, the mechanism we built would be embedded into the students / teacher computer. Future improvements for the device would be to detect the specific person that is there.

#include <Servo.h&gt;

//================================================================
// Hardware definitions. You will need to customize this for your specific hardware.
const int sonarTriggerPin = 8;    // Specify a pin for a sonar trigger output.
const int sonarEchoPin    = 7;    // Specify a pin for a sonar echo input.
const int SERVO_PIN = 9;
Servo svo;

//================================================================
// Current state of the five output channels.  Each may range 
// from 0 to 100, inclusive.  Illegal values will be clamped 
// to this range on send.  The specific relationship between 
// your sensor inputs and these values will need to be 
// customized for your hardware.

int distance = 0;

// Set the serial port transmission rate. The baud rate is the number of bits
// per second.
const long BAUD_RATE = 115200;    

// The rated distance limit of the sensor, in cm.
const int MAX_DISTANCE = 100;

// A typical speed of sound, specified in cm/sec.
const long SOUND_SPEED = 34000;

// Threshold for when to make a change
const int MAKE_CHANGE = 10;

// Counter used to detect when a change in the servo should be made.
int counter = 0;

// Previous value of received message
int prevVal = 0;


boolean canMove = true;

//================================================================
// This function is called once after reset to initialize the program.
void setup()
{
  // Initialize the Serial port for host communication.
  Serial.begin(BAUD_RATE);

  // Initialize the digital input/output pins.  You will need to customize this
  // for your specific hardware.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(sonarTriggerPin, OUTPUT);
  pinMode(sonarEchoPin, INPUT);
  svo.attach(SERVO_PIN);

}

//================================================================
// This function is called repeatedly to handle all I/O 
// and periodic processing. This loop should never be 
// allowed to stall or block so that all tasks can be
// constantly serviced.
void loop()
{
  serial_input_poll();
  hardware_input_poll();
}

//================================================================
// Polling function to process messages received over the 
// serial port from the remote Arduino.  Each message is a
// line of text containing a single integer as text.

void serial_input_poll(void)
{
  if (Serial.available() &gt; 0) {
    // When serial data is available, process and interpret 
    // the available text.
    // This may be customized for your particular hardware.

    // The default implementation assumes the line contains a single integer
    // which controls the built-in LED state.
    int value = Serial.parseInt();
    
    // Change occured in action to move servo
    if(value != prevVal){
      Serial.print("entered eerearac");
      counter = 0;
      prevVal = value;
      canMove = true;
    }

    counter++;
    if(counter &gt;= MAKE_CHANGE){
      if(canMove){
        if(value == 1){
          linearMove(0, 90, 600);
        } else {
          linearMove(90, 0, 600);
        }
        canMove = false;
      }
      counter = 0;
    }

    // Drive the LED to indicate the value.
    if (value){
      digitalWrite(LED_BUILTIN, HIGH);
    } else {
      digitalWrite(LED_BUILTIN, LOW);
    }

    // Once all expected values are processed, flush any 
    // remaining characters until the line end.  Note that
    // when using the Arduino IDE Serial Monitor, you may 
    // need to set the line ending selector to Newline.
    Serial.find('\n');
  }
}

//================================================================
// Polling function to read the inputs and transmit data whenever needed.

void hardware_input_poll(void)
{
  // Calculate the interval in milliseconds since the last polling cycle.
  static unsigned long last_time = 0;
  unsigned long now = millis();
  unsigned long interval = now - last_time;
  last_time = now;

  // Poll each hardware device.  Each function returns 
  // true if the input has been updated.  Each function 
  // directly updates the global output state variables 
  // as per your specific hardware.  The input_changed flag 
  // will be true if any of the polling functions return 
  // true (a logical OR using ||).
  bool input_changed = poll_sonar(interval);

  // Update the message timer used to guarantee a minimum message rate.
  static long message_timer = 0;
  message_timer -= interval;

  // If either the input changed or the message timer expires, 
  // retransmit to the network.
  if (input_changed || (message_timer < 0)) {
    message_timer = 1000;  // one second timeout to guarantee a minimum message rate
    transmit_packet();
  }
}


//================================================================
// Poll the sonar at regular intervals.
bool poll_sonar(unsigned long interval)
{
  static long sonar_timer = 0;
  sonar_timer -= interval;
  if (sonar_timer < 0) {
    sonar_timer = 250; // 4 Hz sampling rate

    // Generate a short trigger pulse.
    digitalWrite(sonarTriggerPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(sonarTriggerPin, LOW);

    // Measure the echo pulse length.  The ~6 ms timeout 
    // is chosen for a maximum range of 100 cm assuming 
    // sound travels at 340 meters/sec.  With a round trip 
    // of 2 meters distance, the maximum ping time is 
    // 2/340 = 0.0059 seconds.  You may wish to customize 
    // this for your particular hardware.
    const long TIMEOUT = (2 * MAX_DISTANCE * 1000000)/SOUND_SPEED;
    unsigned long ping_time = pulseIn(sonarEchoPin, HIGH, TIMEOUT);

    // The default implementation only updates the data if a 
    // ping was observed, the no-ping condition is ignored.
    if (ping_time &gt; 0) {
      // Convert to a distance.  Note that the speed of sound 
      // is specified in cm/sec, so the duration is scaled 
      // from microsecondst o seconds.  The factor of 2 accounts 
      // for the round-trip doubling the time.
      distance = (ping_time * 1e-6 * SOUND_SPEED) / 2;
      
      return true;
    }
  }
  return false; // No change in state.
}


//================================================================
// Send the current data to the MQTT server over the serial port.  
// The values are clamped to the legal range using constrain().

void transmit_packet(void)
{
  int moveServo = 0;
  if(distance <= MAX_DISTANCE / 4){
    moveServo = 1;
  }
  
  Serial.println(moveServo);
}
//================================================================


void linearMove(int start, int end, int duration){
  // Specify the number of milliseconds to wait between updates.
  const int interval = 20;

  // Calculate the overall angle size that the servo must do
  // to reach a cycle
  float angleSize = start - end;
  if(angleSize < 0){
    angleSize *= (-1);  
  }
  
  // Compute the size of each step in degrees. 
  float step = angleSize / duration * 15;
  Serial.println(step);
  
  // Declare a float variable to hold the current servo angle.
  float angle = start;

  // Begin a do-loop.  This always executes the body at least once, and then
  // iterates if the while condition is met.
  do {
    svo.write(angle);  // update the servo output
    delay(interval);     // pause for the sampling interval

    if (end &gt;= start) {
      angle += step;       // movement in the positive direction
      if (angle &gt; end) angle = end;
    } else {
      angle -= step;      // movement in the negative direction
      if (angle < end) angle = end;
    }
  } while (angle != end);

  // Update the servo with the exact endpoint before returning.
  svo.write(end);  
}