In this project, I will show you how to automatically switch between tabs or hide applications on a Windows computer using a Raspberry Pi Pico and a proximity sensor. By detecting the presence of a person in front of the sensor, we will trigger events in a C# application that can change tabs, minimize apps, or hide sensitive information when someone approaches.
This tutorial will walk you through the hardware setup, coding the Raspberry Pi Pico to detect proximity, and integrating the proximity sensor data into a Windows app.
Components Required
- Raspberry Pi Pico
- HC-SR04 Ultrasonic Sensor (or any other proximity sensor)
- Breadboard and Jumper Wires
- USB Cable (for connecting Raspberry Pi Pico to your computer)
- Windows PC with Visual Studio (for C# app development)
Wiring the Raspberry Pi Pico and the Proximity Sensor
We will use the HC-SR04 sensor to detect a person’s presence. The sensor has four pins: VCC, GND, TRIG, and ECHO.
Wiring:
- VCC to Raspberry Pi Pico’s 3.3V pin
- GND to Raspberry Pi Pico’s GND pin
- TRIG to GPIO 15
- ECHO to GPIO 14
This setup allows the Pico to receive distance measurements from the sensor.
Programming the Raspberry Pi Pico
MicroPython Code for Proximity Detection
We will use MicroPython to program the Raspberry Pi Pico. The code will continuously check the distance from the sensor and send the proximity data over a serial connection to the Windows PC.
Install MicroPython on the Pico by following the official guide, then use Thonny IDE for programming.
from machine import Pin, time_pulse_us
import utime
# Initialize pins for sensor
trig = Pin(15, Pin.OUT)
echo = Pin(14, Pin.IN)
def measure_distance():
# Send pulse
trig.low()
utime.sleep_us(2)
trig.high()
utime.sleep_us(10)
trig.low()
# Measure response time
pulse_time = time_pulse_us(echo, 1)
distance_cm = (pulse_time / 2) / 29.1 # Speed of sound = 29.1 us/cm
return distance_cm
while True:
distance = measure_distance()
print(distance)
utime.sleep(1)
This code calculates the distance using the ultrasonic sensor and prints the value over the serial interface.
Flashing the Code
- Save the above code as main.py in Thonny IDE.
- Connect the Raspberry Pi Pico to your computer via USB.
- Run the script. You should see distance readings in the Thonny IDE’s console.
Creating the C# Application
Now that the Pico is sending distance data, we will create a C# application that listens to the serial port and responds by switching tabs or hiding apps when a person is detected.
Setting Up the C# Application
- Open Visual Studio and create a new Windows Forms App (or WPF if preferred).
- Add the following NuGet packages:
- System.IO.Ports for handling serial communication
C# Code to Listen for Sensor Data
Here’s the basic C# code that connects to the Pico via the serial port and changes tabs or minimizes applications based on the proximity data.
using System;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Diagnostics;
class Program
{
private static SerialPort _serialPort;
// Import the necessary WinAPI functions
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder text, int count);
// Constants for showing or hiding the window
const int SW_HIDE = 0;
const int SW_SHOW = 5;
static void Main(string[] args)
{
Console.WriteLine("Starting the serial port listener...");
// Configure SerialPort
_serialPort = new SerialPort("COM3", 9600);
_serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
_serialPort.Open();
Console.WriteLine("Listening for data on COM3... Press any key to exit.");
Console.ReadKey();
//Close serial port before exiting
if (_serialPort.IsOpen)
{
_serialPort.Close();
}
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
string data = _serialPort.ReadLine();
if (double.TryParse(data, out double distance))
{
Console.WriteLine($"Distance received: {distance} cm");
// If person is detected (e.g., distance less than 50 cm)
if (distance < 50) { // Switch to the next window or minimize the current console SwitchTabsOrMinimize(); } } } private static void SwitchTabsOrMinimize() { IntPtr currentForegroundWindow = GetForegroundWindow(); // Get the title of the current window const int nChars = 256; System.Text.StringBuilder windowTitle = new System.Text.StringBuilder(nChars); GetWindowText(currentForegroundWindow, windowTitle, nChars); // Check if there is a current window by inspecting the length of the window title if (windowTitle.ToString().Length > 0)
{
// Hide the window
ShowWindow(currentForegroundWindow, SW_HIDE);
Console.WriteLine("Window is hidden.");
// Find the next window to bring to the foreground
IntPtr nextWindowHandle = GetNextWindowInTaskList();
if (nextWindowHandle != IntPtr.Zero)
{
// Bring the next window to the foreground
SetForegroundWindow(nextWindowHandle);
Console.WriteLine("Switched to another application.");
}
else
{
Console.WriteLine("No other window found to switch to.");
}
}
else
{
Console.WriteLine("The active window is not Chrome.");
}
}
private static IntPtr GetNextWindowInTaskList()
{
IntPtr nextWindowHandle = IntPtr.Zero;
// Simulate pressing Alt+Tab by finding the next process with a window
Process[] processes = Process.GetProcesses();
foreach (var process in processes)
{
if (process.MainWindowHandle != IntPtr.Zero && process.MainWindowHandle != GetForegroundWindow())
{
nextWindowHandle = process.MainWindowHandle;
break;
}
}
return nextWindowHandle;
}
}
Explanation of Code
- The SerialPort is set up to listen on the COM port connected to the Pico.
- When data (the distance) is received from the Pico, the application checks if the value is below a threshold (e.g., 50 cm) to determine if someone is near the sensor.
- If a person is detected, the application switches tabs in a
TabControl
. If the last tab is reached, the app minimizes.
Running the C# Application
- Compile and run the C# application in Visual Studio.
- Place your hand near the sensor and observe the tabs switching or the application minimizing.
To use the Raspberry Pi Pico with C++ (Arduino), we need to install the Arduino core for the Pico, configure the sensor, and write the code in the Arduino IDE. Here’s the conversion of the original MicroPython code to C++ using the Arduino framework.
Setting Up Arduino IDE for Raspberry Pi Pico
Before we write the C++ code, make sure the Raspberry Pi Pico is ready for Arduino development. Follow these steps:
- Open the Arduino IDE.
- Go to File > Preferences, and in the “Additional Boards Manager URLs” field, add:
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
- Go to Tools > Board > Boards Manager, search for Raspberry Pi Pico, and install the package by Earle Philhower.
After this, you’ll be able to select the Raspberry Pi Pico as a board from Tools > Board > Raspberry Pi RP2040 > Raspberry Pi Pico.
C++ Code for Proximity Detection
Here’s the Arduino C++ code for the Raspberry Pi Pico using an HC-SR04 ultrasonic sensor. This code will measure the distance and send the data over the serial port to the Windows PC.
#define TRIG_PIN 15 // GPIO 15 for Trigger
#define ECHO_PIN 14 // GPIO 14 for Echo
void setup() {
Serial.begin(9600); // Initialize serial communication
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void loop() {
long duration, distance_cm;
// Clear the TRIG_PIN by setting it LOW
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
// Trigger the sensor by setting TRIG_PIN HIGH for 10 microseconds
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Read the ECHO_PIN, returns the sound wave travel time in microseconds
duration = pulseIn(ECHO_PIN, HIGH);
// Calculate the distance in cm (Speed of sound = 343 m/s or 29.1 us/cm)
distance_cm = (duration / 2) / 29.1;
// Send the distance data over Serial to the PC
Serial.println(distance_cm);
// Delay for a bit before the next measurement
delay(1000);
}
Explanation of the Code:
- TRIG_PIN is set to GPIO 15, and ECHO_PIN is set to GPIO 14. These pins connect to the sensor’s TRIG and ECHO respectively.
- In the setup() the TRIG_PIN is set to OUTPUT and the ECHO_PIN to INPUT.
- The loop() function:
- Sends a 10 microsecond pulse to the TRIG pin to trigger the sensor.
- Uses pulseIn() to measure the time it takes for the echo to return.
- The distance is calculated by dividing the duration by 2 (since the sound wave travels to the object and back) and dividing by 29.1 (speed of sound in microseconds per centimeter).
- The calculated distance is printed via Serial.println() to send the data to the connected Windows PC.
Uploading the Code
- In the Arduino IDE, select Tools > Board > Raspberry Pi RP2040 > Raspberry Pi Pico.
- Select the correct COM port under Tools > Port.
- Upload the code to the Raspberry Pi Pico by pressing the Upload button.
Testing the Proximity Detection
Once the code is uploaded, open the Serial Monitor in the Arduino IDE (Ctrl+Shift+M). Place an object in front of the sensor, and you should see the distance readings being displayed.
These readings can now be used in the C# app to switch tabs or perform other actions as discussed in the previous steps.
Further Testing and Adjustments
You can adjust the distance threshold for detecting presence based on your needs. If you want more advanced behavior, you could:
- Add conditions for hiding or locking sensitive applications when a person is detected.
- Use other types of proximity sensors for better accuracy.
You can also integrate other actions, like muting the system audio or triggering specific actions based on the proximity data.
Conclusion
Using a Raspberry Pi Pico with a proximity sensor and a simple C# application, you can automate the management of Windows apps, switching tabs or hiding applications based on proximity detection. This setup is perfect for privacy-conscious users or those looking to add some automation to their desktop environment.