Датчики (Sensing)
Датчики в робототехнике
Датчики (сенсоры) преобразуют физические величины в электрические сигналы. В робототехнике они обеспечивают обратную связь с окружающей средой.
Классификация датчиков
По измеряемой величине
По типу выходного сигнала
| Тип | Описание | Примеры |
|---|
| Аналоговый | Напряжение $0..V_{ref}$ | Фоторезистор, NTC |
| Цифровой | HIGH/LOW | Концевик, PIR |
| I²C | Шина, адресация | MPU6050, BMP280 |
| SPI | Высокая скорость | ICM-42688-P |
| UART | Serial | GPS, лидар |
| PWM | Широтно-импульсный | HC-SR04 (Echo) |
Проприоцептивные vs Экстероцептивные
| Тип | Назначение | Примеры |
|---|
| Проприоцептивные | Внутреннее состояние | Энкодеры, IMU, ток двигателя |
| Экстероцептивные | Внешняя среда | Камеры, лидары, УЗ-датчики |
Физические принципы
Преобразователи энергии
| Принцип | Физика | Датчики |
|---|
| Резистивный | $R = \rho \frac{L}{A}$ | NTC, фоторезистор, тензодатчик |
| Ёмкостной | $C = \varepsilon \frac{A}{d}$ | Влажность, прикосновение |
| Пьезоэлектрический | $V = d \cdot F$ | Ударные, вибрация, УЗ |
| Индуктивный | $e = -N \frac{d\Phi}{dt}$ | Proximity, резольвер |
| Эффект Холла | $V_H = \frac{I \cdot B}{n \cdot e \cdot t}$ | Магнитные энкодеры, компас |
| Фотоэлектрический | $I_{ph} \propto \Phi$ | Фотодиод, камера |
| Термоэлектрический | $V = \alpha \Delta T$ | Термопара |
Time-of-Flight
$$d = \frac{v \cdot \Delta t}{2}$$| Среда | Скорость | Точность 1 см |
|---|
| Звук (воздух) | 343 м/с | $\Delta t = 58\ \mu s$ |
| Свет | $3 \times 10^8$ м/с | $\Delta t = 67\ ps$ |
Интерфейсы и протоколы
I²C (Inter-Integrated Circuit)
#include <Wire.h>
#define SENSOR_ADDR 0x68
void setup() {
Wire.begin();
Wire.setClock(400000); // Fast mode 400 kHz
}
uint8_t readRegister(uint8_t reg) {
Wire.beginTransmission(SENSOR_ADDR);
Wire.write(reg);
Wire.endTransmission(false); // Repeated start
Wire.requestFrom(SENSOR_ADDR, 1);
return Wire.read();
}
SPI (Serial Peripheral Interface)
#include <SPI.h>
#define CS_PIN 10
void setup() {
SPI.begin();
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
}
uint8_t readSPI(uint8_t reg) {
digitalWrite(CS_PIN, LOW);
SPI.transfer(reg | 0x80); // Read bit
uint8_t data = SPI.transfer(0x00);
digitalWrite(CS_PIN, HIGH);
return data;
}
ROS 2 Sensor Integration
Стандартные типы сообщений
| Пакет | Тип | Назначение |
|---|
sensor_msgs | Imu | Акселерометр + гироскоп |
sensor_msgs | LaserScan | 2D лидар |
sensor_msgs | PointCloud2 | 3D лидар |
sensor_msgs | Image | Камера |
sensor_msgs | Range | Единичный дальномер |
sensor_msgs | Temperature | Температура |
sensor_msgs | FluidPressure | Давление |
Пример драйвера датчика
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Range
import board
import adafruit_vl53l0x
class ToFPublisher(Node):
def __init__(self):
super().__init__('tof_publisher')
self.pub = self.create_publisher(Range, 'range', 10)
i2c = board.I2C()
self.sensor = adafruit_vl53l0x.VL53L0X(i2c)
self.timer = self.create_timer(0.05, self.publish) # 20 Hz
def publish(self):
msg = Range()
msg.header.stamp = self.get_clock().now().to_msg()
msg.header.frame_id = 'tof_link'
msg.radiation_type = Range.INFRARED
msg.field_of_view = 0.436 # 25° in radians
msg.min_range = 0.03
msg.max_range = 2.0
msg.range = self.sensor.range / 1000.0 # mm to m
self.pub.publish(msg)
def main():
rclpy.init()
node = ToFPublisher()
rclpy.spin(node)
Обработка сигналов
Фильтрация шума
$$y[n] = \frac{1}{N} \sum_{k=0}^{N-1} x[n-k]$$$$y[n] = \alpha \cdot x[n] + (1 - \alpha) \cdot y[n-1]$$Медианный фильтр (устойчив к выбросам):
float medianFilter(float *buffer, int size) {
std::sort(buffer, buffer + size);
return buffer[size / 2];
}
Kalman Filter (1D)
class KalmanFilter {
float Q = 0.001; // Process noise
float R = 0.1; // Measurement noise
float x = 0; // State estimate
float P = 1; // Error covariance
public:
float update(float measurement) {
// Predict
P = P + Q;
// Update
float K = P / (P + R);
x = x + K * (measurement - x);
P = (1 - K) * P;
return x;
}
};
Каталог датчиков
| Датчик | Принцип | Диапазон | Интерфейс |
|---|
| HC-SR04 | УЗ ToF | 2-400 см | GPIO/PWM |
| VL53L0X | Лазер ToF | 3-200 см | I²C |
| Sharp GP2Y | ИК триангуляция | 10-80 см | Analog |
| Датчик | Измеряет | DoF | Интерфейс |
|---|
| MPU6050 | Accel + Gyro | 6 | I²C |
| BMI088 | Accel + Gyro | 6 | SPI |
| HMC5883L | Магнитное поле | 3 | I²C |
| NEO-6M | Координаты | — | UART |
| Датчик | Измеряет | Точность | Интерфейс |
|---|
| BME280 | T/H/P | ±1°C | I²C/SPI |
| AHT20 | T/H | ±0.3°C | I²C |
| BH1750 | Освещённость | 1 lx | I²C |
Рекомендации по выбору
| Критерий | Вопросы |
|---|
| Диапазон | Какие значения нужно измерять? |
| Точность | Допустимая погрешность? |
| Частота | Сколько измерений в секунду? |
| Интерфейс | Сколько GPIO/шин доступно? |
| Питание | Бюджет энергопотребления? |
| Среда | Влага, пыль, температура? |
Ссылки