VSDSquadron Mini DataSheet

⌘K
  1. Home
  2. Docs
  3. VSDSquadron Mini DataShee...
  4. Projects
  5. Bluetooth automated smart access

Bluetooth automated smart access

Introduction

In an age where technology seamlessly integrates with our daily lives, the concept of a smart home has evolved from a futuristic vision to a tangible reality. Central to this transformation is the “Bluetooth Automated Smart Access” system, which embodies the blend of convenience, security, and innovation. Leveraging the capabilities of a VSD Squadron Mini board, a Bluetooth module, and a servo motor, this project offers practical solutions to everyday challenges, enhancing the way we interact with our living spaces.

Traditional methods of manual operation can be cumbersome, tiresome and inefficient. This technology eliminates such challenges by allowing users to manage various applications through their smartphones, reducing the need for physical interaction. Bluetooth automated smart access can be utilized in a wide range of applications, from controlling water taps to managing lighting and appliances, smart door and security applications and for enhancing efficiency and simplifying everyday tasks across diverse environments.

Overview

The project showcased here introduces an innovative solution utilising a servo motor, Bluetooth module, push-button, and onboard LED to control and monitor door access. Its functionality lies in its ability to initiate open-close mechanism upon delivering a bluetooth instruction message. When the bluetooth module receives an input, it triggers the VSD Squadron Mini to activate the Servo Motor, thereby initiating this mechanism. This technology-driven approach offers a hands-free and user-friendly solution for creating a secure and convenient tool access solution.

  • Servo Motor (Pin PC6): Acts as the locking mechanism, controlled by the microcontroller.
  • Bluetooth Module (Pins PD6, PD7, PC7, GND, 3.3V): Enables wireless communication between the system and a user’s smartphone for remote control and Bluetooth module’s State pin indicates connection status.
  • Onboard LED (LED_BUILTIN): Displays the system status, indicating locked/unlocked states.

Users can control the device via their smartphone using Bluetooth. The onboard LED provides visual feedback, making the system user-friendly and reliable. This project exemplifies the practical application of IoT technology in home security and automation.

Components required with Bill of Materials

ItemQuantityDescriptionLinks to Products
VSD Squadron Mini1Microcontroller boardVSD Squadron Mini
Servo Motor1Standard servo motor (e.g., SG90)SG90 Servo Motor
Bluetooth HC-05 Module1Bluetooth module for serial communicationBluetooth HC-05
Jumper Wires1 setMale-to-male and female-to-male jumper wiresJumper Wires
Micro USB Cable1For programming and power supplyMicro USB Cable

Table for Pin Connections

ComponentVSD Squadron Mini PinDescription
Servo SignalPC6Servo motor’s control signal pin
Servo VCC5VServo motor’s power supply
Servo GNDGNDServo motor’s ground
Bluetooth RXDPD6Bluetooth module’s RXD pin (connect directly to 3.3V logic)
Bluetooth TXDPD7Bluetooth module’s TXD pin (connect directly to 5V logic)
Bluetooth GNDGNDBluetooth module’s ground pin
Bluetooth VCC3.3VBluetooth module’s 3.3V pin (connect to microcontroller’s 3.3V output pin)
Bluetooth StatePC7Bluetooth module’s State pin (indicates connection status)
Onboard LEDLED_BUILTINOnboard LED for status indication

Pinout Diagram

Working Code

// Define the pins using port names
#define MOTOR_PIN PC6 // Pin to which the servo motor is connected
#define BLUETOOTH_STATE_PIN PC7
#define LED_PIN LED_BUILTIN

#define BLUETOOTH_RX_PIN PD6  // Onboard RX pin
#define BLUETOOTH_TX_PIN PD7  // Onboard TX pin

bool doorLocked = true; // Flag to track the door lock state

// Function prototypes
void checkBluetooth();
void openDoor(int openDelay = 5000);
void closeDoor();
void lockDoor();
void setServoAngle(int angle);

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // Wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Smart Door System Initialized");

  pinMode(LED_PIN, OUTPUT);
  pinMode(BLUETOOTH_STATE_PIN, INPUT);

  pinMode(MOTOR_PIN, OUTPUT); // Set the motor pin as an output
  
  lockDoor(); // Lock the door initially
}

void loop() {
  // Check Bluetooth connection status
  if (digitalRead(BLUETOOTH_STATE_PIN) == HIGH) {
    checkBluetooth();
  } else {
    Serial.println("Bluetooth not connected");
    // Handle Bluetooth disconnection here (e.g., close the door)
    if (!doorLocked) {
      closeDoor();
    }
  }
}

void checkBluetooth() {
  if (Serial.available()) {
    char command = Serial.read();
    if (command == 'O') {  // Command to open the door
      openDoor();
    } else if (command == 'C') {  // Command to close the door
      closeDoor();
    }
  }
}

void openDoor(int openDelay) {
  Serial.println("Access Granted");
  digitalWrite(LED_PIN, HIGH);
  
  // Set PWM signal to open the door
  setServoAngle(90); // Assuming 90 degrees to open the door
  delay(openDelay); // Keep door open for the specified delay
  closeDoor();
}

void closeDoor() {
  Serial.println("Door Closing");
  digitalWrite(LED_PIN, LOW);
  
  // Set PWM signal to close the door
  setServoAngle(0); // Assuming 0 degrees to close the door
  doorLocked = true; // Update door lock state
}

void lockDoor() {
  doorLocked = true; // Update door lock state
  setServoAngle(0); // Initially lock the door by setting servo to 0 degrees
}

// Function to set the servo angle
void setServoAngle(int angle) {
  // Constants for the servo control
  const int minPulseWidth = 544;  // Minimum pulse width in microseconds
  const int maxPulseWidth = 2400; // Maximum pulse width in microseconds
  const int refreshInterval = 20000; // Refresh interval in microseconds (20 ms)

  // Map the angle to the pulse width
  int pulseWidth = map(angle, 0, 180, minPulseWidth, maxPulseWidth);
  
  // Generate the PWM signal on PC6
  digitalWrite(MOTOR_PIN, HIGH);
  delayMicroseconds(pulseWidth);
  digitalWrite(MOTOR_PIN, LOW);
  
  // Wait for the remainder of the refresh interval
  delayMicroseconds(refreshInterval - pulseWidth);
}

Demo Video

Application Video – Aqua Control System

Application Video – Railway Gate Modulator

Fault Injection

Fault injection is a testing technique used to evaluate the robustness and error-handling capabilities of a system by deliberately introducing faults or errors into it. The goal is to observe how the system behaves under fault conditions and to ensure that it can handle these situations gracefully. This technique is commonly used in software, hardware, and system testing to identify and fix potential weaknesses or vulnerabilities.

Objectives

  • Identify Weaknesses: Detect vulnerabilities and weak points in the system that could lead to failures.
  • Improve Robustness: Enhance the system’s ability to handle faults gracefully without crashing or producing incorrect results.
  • Validate Error Handling: Ensure that error handling mechanisms and failover processes work correctly under fault conditions.

Challenges

Software Fault Injections

Simulate faultCondition

  • “faultCondition” is a boolean flag initialized to false. It’s used to simulate a fault state in the system.
  • The fault condition is triggered by a Bluetooth command within the checkBluetooth() function.
  • Any single character command between ‘A’ and ‘Z’ (excluding ‘O’ and ‘C’) will set the faultCondition flag to true.
  • This fault locks the door and skips the rest of the loop when detected, deeming any further inputs null and void.

Simulate rebootSystem

  • “rebootSystem()” is a function that simulates a system reboot by resetting specific variables and calling setup() to reinitialize the system.
  • The reboot is randomly triggered based on a timer within the loop() function.
  • Every second (rebootCheckInterval), the system checks if a random event should trigger a reboot with a 10% chance.

Code for Software Fault Injection

// Define the pins using port names
#define MOTOR_PIN PC6 // Pin to which the servo motor is connected
#define BLUETOOTH_STATE_PIN PC7
#define LED_PIN LED_BUILTIN

#define BLUETOOTH_RX_PIN PD6  // Onboard RX pin
#define BLUETOOTH_TX_PIN PD7  // Onboard TX pin

bool doorLocked = true; // Flag to track the door lock state
bool faultCondition = false; // Flag to simulate a fault condition
unsigned long lastRebootCheck = 0; // Time of the last reboot check
const unsigned long rebootCheckInterval = 1000; // Check for reboot every 1 second

// Function prototypes
void checkBluetooth();
void openDoor(int openDelay = 1000);
void closeDoor();
void lockDoor();
void setServoAngle(int angle);
void rebootSystem();

void setup() {
  Serial.begin(9600);
  delay(100); // delay to ensure serial connection is established
  while (!Serial) {
    ; // Wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("System Initialized");

  pinMode(LED_PIN, OUTPUT);
  pinMode(BLUETOOTH_STATE_PIN, INPUT);

  pinMode(MOTOR_PIN, OUTPUT); // Set the motor pin as an output

  randomSeed(analogRead(0)); // Initialize random seed
  
  lockDoor(); // Lock the door initially
}

void loop() {
  // Check for fault condition
  if (faultCondition) {
    Serial.println("Fault Detected! System is locking the door.");
    lockDoor(); // Lock the door immediately
    return; // Skip the rest of the loop
  }

  // Check Bluetooth connection status
  if (digitalRead(BLUETOOTH_STATE_PIN) == HIGH) {
    checkBluetooth();
  } else {
    Serial.println("Bluetooth not connected");
    // Handle Bluetooth disconnection here (e.g., close the door)
    if (!doorLocked) {
      closeDoor();
    }
  }

  // Check if it's time to randomly reboot
  if (millis() - lastRebootCheck > rebootCheckInterval) {
    lastRebootCheck = millis();
    if (random(0, 100) < 10) { // 10% chance to reboot
      Serial.println("Random reboot triggered!");
      rebootSystem();
    }
  }
}

void checkBluetooth() {
  if (Serial.available()) {
    char command = Serial.read();
    if (command == 'O') {  // Command to open the door
      openDoor();
    } else if (command == 'C') {  // Command to close the door
      closeDoor();
    } else if ((command >= 'A' && command <= 'Z') && command != 'O' && command != 'C') {  // Command to simulate a fault
      faultCondition = true;
      Serial.println("Fault simulation command received");
    }
  }
} 

void openDoor(int openDelay) {
  Serial.println("Access Granted");
  digitalWrite(LED_PIN, HIGH);

  // Set PWM signal to open the door
  setServoAngle(90); // Assuming 90 degrees to open the door
  delay(openDelay); // Keep door open for the specified delay
}

void closeDoor() {
  Serial.println("Door Closing");
  digitalWrite(LED_PIN, LOW);

  // Set PWM signal to close the door
  setServoAngle(0); // Assuming 0 degrees to close the door
  doorLocked = true; // Update door lock state
}

void lockDoor() {
  doorLocked = true; // Update door lock state
  setServoAngle(0); // Initially lock the door by setting servo to 0 degrees
}

// Function to set the servo angle
void setServoAngle(int angle) {
  // Constants for the servo control
  const int minPulseWidth = 544;  // Minimum pulse width in microseconds
  const int maxPulseWidth = 2400; // Maximum pulse width in microseconds
  const int refreshInterval = 20000; // Refresh interval in microseconds (20 ms)

  // Map the angle to the pulse width
  int pulseWidth = map(angle, 0, 180, minPulseWidth, maxPulseWidth);

  // Generate the PWM signal on PC6
  digitalWrite(MOTOR_PIN, HIGH);
  delayMicroseconds(pulseWidth);
  digitalWrite(MOTOR_PIN, LOW);

  // Wait for the remainder of the refresh interval
  delayMicroseconds(refreshInterval - pulseWidth);
}

void rebootSystem() {
  // Simulate a system reboot by resetting variables and re-initializing
  Serial.println("Rebooting system...");
  doorLocked = true;
  faultCondition = false;
  lastRebootCheck = millis();

  setup(); // Call setup to re-initialize the system
}

Software Fault Protection

  1. Authorization: Added a verifyAuthorization function that prompts the user to enter an authorization code before critical commands are processed.
  2. Debounce Protection: Added a debounceProtection function to ensure commands aren’t processed too frequently.
  3. Scheduled Reboots: Reboots the system at regular intervals to prevent long-term instability.
  4. Reboot System: Resets critical variables and simulates a system reboot at predetermined intervals based on the loopCounter.

These protections ensure that only authorized users can issue critical commands, and that these commands can’t be spammed to disrupt the system.

Code for Software Fault Protection

// Define the pins using port names
#define MOTOR_PIN PC6 // Pin to which the servo motor is connected
#define BLUETOOTH_STATE_PIN PC7
#define LED_PIN LED_BUILTIN

#define BLUETOOTH_RX_PIN PD6  // Onboard RX pin
#define BLUETOOTH_TX_PIN PD7  // Onboard TX pin

bool doorLocked = true; // Flag to track the door lock state
bool faultCondition = false; // Flag to simulate a fault condition
unsigned long lastRebootTime = 0; // Time of the last reboot
const unsigned long rebootInterval = 60000; // Reboot every 60 seconds 

// Counter for controlling reboots
unsigned long loopCounter = 0;
const unsigned long rebootThreshold = 6000; // Reboot after 6000 loops 

const String authorizedCode = "OK"; // Example authorization code
bool authorized = false; // Flag to indicate if the user is authorized
unsigned long lastCommandTime = 0; // Time of the last received command
const unsigned long commandInterval = 5000; // Minimum interval between commands in milliseconds

// Function prototypes
void checkBluetooth();
void openDoor(int openDelay = 1000);
void closeDoor();
void lockDoor();
void setServoAngle(int angle);
void rebootSystem();
bool verifyAuthorization(String command);
bool debounceProtection();

void setup() {
  Serial.begin(9600);
  delay(100); // delay to ensure serial connection is established
  while (!Serial) {
    ; // Wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("System Initialized");

  pinMode(LED_PIN, OUTPUT);
  pinMode(BLUETOOTH_STATE_PIN, INPUT);

  pinMode(MOTOR_PIN, OUTPUT); // Set the motor pin as an output

  randomSeed(analogRead(0)); // Initialize random seed

  // Initialize the last reboot time
  lastRebootTime = millis();

  lockDoor(); // Lock the door initially
}

void loop() {
  // Increment loop counter
  loopCounter++;

  // Check for fault condition
  if (faultCondition) {
    Serial.println("Fault Detected! System is locking the door.");
    lockDoor(); // Lock the door immediately
    return; // Skip the rest of the loop
  }

  // Check Bluetooth connection status
  if (digitalRead(BLUETOOTH_STATE_PIN) == HIGH) {
    checkBluetooth();
  } else {
    Serial.println("Bluetooth not connected");
    // Handle Bluetooth disconnection here (e.g., close the door)
    if (!doorLocked) {
      closeDoor();
    }
  }

  // Check if it's time to reboot based on loop counter
  if (loopCounter >= rebootThreshold) {
    Serial.println("Rebooting system...");
    rebootSystem();
  }
}

void checkBluetooth() {
  if (Serial.available()) {
    String command = Serial.readString();
    command.trim(); // Remove any leading/trailing whitespace

    if (!authorized) {
      if (verifyAuthorization(command)) {
        authorized = true;
        Serial.println("Authorization successful.");
      } else {
        Serial.println("Unauthorized command attempt.");
      }
    } else {
      if ((command == "O" || command == "C" || (command >= "A" && command <= "Z")) && debounceProtection()) {
        if (command == "O") {  // Command to open the door
          openDoor();
        } else if (command == "C") {  // Command to close the door
          closeDoor();
        } else {  // Command to simulate a fault
          faultCondition = true;
          Serial.println("Fault simulation command received");
        }
        authorized = false; // Reset authorization after a command is executed
      }
    }
  }
}

void openDoor(int openDelay) {
  Serial.println("Access Granted");
  digitalWrite(LED_PIN, HIGH);
  // Set PWM signal to open the door
  setServoAngle(90); // Assuming 90 degrees to open the door
}

void closeDoor() {
  Serial.println("Door Closing");
  digitalWrite(LED_PIN, LOW);
  // Set PWM signal to close the door
  setServoAngle(0); // Assuming 0 degrees to close the door
  doorLocked = true; // Update door lock state
}

void lockDoor() {
  doorLocked = true; // Update door lock state
  setServoAngle(0); // Initially lock the door by setting servo to 0 degrees
}

// Function to set the servo angle
void setServoAngle(int angle) {
  // Constants for the servo control
  const int minPulseWidth = 544;  // Minimum pulse width in microseconds
  const int maxPulseWidth = 2400; // Maximum pulse width in microseconds
  const int refreshInterval = 20000; // Refresh interval in microseconds (20 ms)

  // Map the angle to the pulse width
  int pulseWidth = map(angle, 0, 180, minPulseWidth, maxPulseWidth);

  // Generate the PWM signal on PC6
  digitalWrite(MOTOR_PIN, HIGH);
  delayMicroseconds(pulseWidth);
  digitalWrite(MOTOR_PIN, LOW);

  // Wait for the remainder of the refresh interval
  delayMicroseconds(refreshInterval - pulseWidth);
}

void rebootSystem() {
  // Perform actions to save critical state before rebooting
  doorLocked = true;
  faultCondition = false;
  loopCounter = 0;
  lastRebootTime = millis(); // Update last reboot time
  // Code to reset the microcontroller or perform software reset
}

// Function to verify authorization
bool verifyAuthorization(String command) {
  return command == authorizedCode;
}

// Function for debounce protection
bool debounceProtection() {
  unsigned long currentTime = millis();
  if (currentTime - lastCommandTime > commandInterval) {
    lastCommandTime = currentTime;
    return true;
  } else {
    Serial.println("Command ignored due to debounce protection.");
    return false;
  }
}

Hardware Fault Injections

1. Disrupting Servo Motor using external Arduino 5V Power Source

Arduino board here is given as an external power supply (additional 5V) to the control of the servo motor. Since this is outside the working power range for the SG90 motor, the circuitry is either damaged or the device shuts itself down to protect its internal wiring, hence simulating a fault in the system.

Fault Video

Protection against Fault

This fault can be protected by ensuring a safe enclosure where access is denied to manipulate the input voltage levels to the servo motor.

2. Inducing fault in HC-05 using potentiometer to corrupt receiver signal (RX)

Another method is to inject noise into the signal lines of the HC-05 module. This can be done by connecting the potentiometer to the RX or TX lines. Connect the middle pin of the potentiometer to the RX pin of the HC-05 module, one of the outer pins of the potentiometer to a stable 5V power source and the other outer pin to GND. Adjust the potentiometer to vary the voltage on the RX pin, simulating noise or signal degradation to observe how the HC-05 module handles the noisy signal and it affects communication with the microcontroller.

Fault Video

Protection against Fault

The capacitors added in this circuit act as a low pass filter which smoothen out any irregularities in the voltage fluctuations caused by varying the voltages levels in the potentiometer. The functioning of the circuit is hence optimised and the noise injected is managed efficiently.

Protection against Fault Video

3. Disrupting Bluetooth Signal using EM Waves

Bluetooth operates in the 2.4 GHz ISM band, which is shared with various other devices like Wi-Fi routers, microwaves, and cordless phones. This makes Bluetooth susceptible to electromagnetic interference (EMI).

EMI can cause disruptions in the Bluetooth signal, leading to data corruption, intermittent connections, or complete communication failure. The noise introduced by EMI can lead to an increase in the error rate of the transmitted and received data. The HC-05 module might behave erratically due to EMI, causing unexpected resets, incorrect data processing, or failure to connect to paired devices.

Protection against Fault

A Faraday cage can be employed to shield sensitive components of a Bluetooth device from external electromagnetic interference. By enclosing the components in a conductive material, the cage blocks external static and non-static electric fields. The cage should be made from materials with high electrical conductivity such as copper, aluminum, or conductive polymers and must be properly grounded to ensure that any absorbed EMI is safely conducted away from the device.

The mesh size of the cage needs to be smaller than the wavelength of the frequencies to be blocked (in the case of Bluetooth, smaller than 12.5 cm for effective shielding at 2.4 GHz). The mesh size of the cage needs to be smaller than the wavelength of the frequencies to be blocked (in the case of Bluetooth, smaller than 12.5 cm for effective shielding at 2.4 GHz). Thorough testing in environments with known EMI sources ensures the effectiveness of the Faraday cage and other shielding measures.

Result

The system successfully demonstrated resilience to simulated faults, maintaining security and stability. It locked the door upon detecting unauthorized commands and rebooted as expected under controlled conditions.

Conclusions

The implementation of robust fault injection and protection techniques significantly improved system reliability and security. These measures effectively mitigated risks associated with random reboots and unauthorized access, ensuring the system’s robustness in real-world scenarios.

Presentation

bluetooth_automated_smart_access_system

https://github.com/rmahathi/NoRisk