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>
//================================================================
// 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() > 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 >= 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 > 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 >= start) {
angle += step; // movement in the positive direction
if (angle > 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);
}
Leave a Reply
You must be logged in to post a comment.