Skip to main content

Датчики (Sensing)

Датчики в робототехнике

Датчики (сенсоры) преобразуют физические величины в электрические сигналы. В робототехнике они обеспечивают обратную связь с окружающей средой.


Классификация датчиков

По измеряемой величине

КатегорияПодразделЧто измеряют
Дистанцияdistance/Расстояние до объектов
Окружениеenvironment/Температура, влажность, давление, свет
Навигацияnavigation/Ориентация, положение, движение
Взаимодействиеinteraction/Касание, звук, жесты
Вибрацияvibration/Механические колебания

По типу выходного сигнала

ТипОписаниеПримеры
АналоговыйНапряжение $0..V_{ref}$Фоторезистор, NTC
ЦифровойHIGH/LOWКонцевик, PIR
I²CШина, адресацияMPU6050, BMP280
SPIВысокая скоростьICM-42688-P
UARTSerialGPS, лидар
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_msgsImuАкселерометр + гироскоп
sensor_msgsLaserScan2D лидар
sensor_msgsPointCloud23D лидар
sensor_msgsImageКамера
sensor_msgsRangeЕдиничный дальномер
sensor_msgsTemperatureТемпература
sensor_msgsFluidPressureДавление

Пример драйвера датчика

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УЗ ToF2-400 смGPIO/PWM
VL53L0XЛазер ToF3-200 смI²C
Sharp GP2YИК триангуляция10-80 смAnalog
ДатчикИзмеряетDoFИнтерфейс
MPU6050Accel + Gyro6I²C
BMI088Accel + Gyro6SPI
HMC5883LМагнитное поле3I²C
NEO-6MКоординатыUART
ДатчикИзмеряетТочностьИнтерфейс
BME280T/H/P±1°CI²C/SPI
AHT20T/H±0.3°CI²C
BH1750Освещённость1 lxI²C

Рекомендации по выбору

КритерийВопросы
ДиапазонКакие значения нужно измерять?
ТочностьДопустимая погрешность?
ЧастотаСколько измерений в секунду?
ИнтерфейсСколько GPIO/шин доступно?
ПитаниеБюджет энергопотребления?
СредаВлага, пыль, температура?

Ссылки