/
timheadman
/
diy-433-FS1000A-RXB6-RXB8
Обзор
Документация
Войти
/
timheadman
/
diy-433-FS1000A-RXB6-RXB8
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/receiver/main.cpp
258 строк
6 KB
Timur M. Omarov
first_commit
05 авг 2026, 14:05
05 авг 2026, 14:05
6832723
Код
Авторство
О чём код?
#include <Arduino.h> #include <driver/gpio.h> constexpr uint8_t RXB6_PIN = 12; constexpr uint8_t RXB8_PIN = 3; constexpr uint16_t MAGIC = 0xA55A; constexpr uint8_t FRAME_BITS = 40; constexpr uint16_t PULSE_SHORT_MIN = 250; constexpr uint16_t PULSE_SHORT_MAX = 850; constexpr uint16_t PULSE_LONG_MIN = 1100; constexpr uint16_t PULSE_LONG_MAX = 2000; constexpr uint16_t SYNC_MIN = 3500; struct ReceiverState { explicit ReceiverState(uint8_t gpioPin) : pin(gpioPin) {} uint8_t pin; volatile uint32_t lastEdgeUs = 0; volatile bool receiving = false; volatile uint8_t bitCount = 0; volatile uint64_t data = 0; volatile bool frameReady = false; volatile uint64_t completedFrame = 0; volatile uint32_t completedAtUs = 0; uint32_t validPackets = 0; uint32_t invalidPackets = 0; uint32_t missedPackets = 0; bool hasPreviousSequence = false; uint16_t previousSequence = 0; }; ReceiverState rxb6(RXB6_PIN); ReceiverState rxb8(RXB8_PIN); uint8_t calculateChecksum(uint16_t sequence) { return 0xA5 ^ 0x5A ^ static_cast<uint8_t>(sequence >> 8) ^ static_cast<uint8_t>(sequence); } void IRAM_ATTR processEdge(ReceiverState &receiver) { const uint32_t now = micros(); const uint32_t duration = now - receiver.lastEdgeUs; receiver.lastEdgeUs = now; const bool currentLevel = gpio_get_level(static_cast<gpio_num_t>(receiver.pin)); /* * Текущий уровень HIGH означает, что только что закончился LOW. * Длинный LOW является признаком начала кадра. */ if (currentLevel) { if (duration >= SYNC_MIN) { receiver.receiving = true; receiver.bitCount = 0; receiver.data = 0; } return; } /* * Текущий уровень LOW означает, что закончился HIGH. * По длительности HIGH определяем 0 или 1. */ if (!receiver.receiving) { return; } bool bitValue; if (duration >= PULSE_SHORT_MIN && duration <= PULSE_SHORT_MAX) { bitValue = false; } else if ( duration >= PULSE_LONG_MIN && duration <= PULSE_LONG_MAX) { bitValue = true; } else { receiver.receiving = false; receiver.bitCount = 0; receiver.data = 0; return; } receiver.data = (receiver.data << 1) | bitValue; receiver.bitCount++; if (receiver.bitCount == FRAME_BITS) { receiver.completedFrame = receiver.data; receiver.completedAtUs = now; receiver.frameReady = true; receiver.receiving = false; receiver.bitCount = 0; receiver.data = 0; } } void IRAM_ATTR rxb6Interrupt() { processEdge(rxb6); } void IRAM_ATTR rxb8Interrupt() { processEdge(rxb8); } void printTimestamp(uint32_t milliseconds) { const uint32_t hours = milliseconds / 3600000UL; const uint32_t minutes = (milliseconds / 60000UL) % 60; const uint32_t seconds = (milliseconds / 1000UL) % 60; const uint32_t millisPart = milliseconds % 1000; Serial.printf( "[%02lu:%02lu:%02lu.%03lu]", hours, minutes, seconds, millisPart); } void processCompletedFrame( ReceiverState &receiver, const char *receiverName) { uint64_t frame; uint32_t receivedAtUs; noInterrupts(); if (!receiver.frameReady) { interrupts(); return; } frame = receiver.completedFrame; receivedAtUs = receiver.completedAtUs; receiver.frameReady = false; interrupts(); const uint16_t magic = static_cast<uint16_t>((frame >> 24) & 0xFFFF); const uint16_t sequence = static_cast<uint16_t>((frame >> 8) & 0xFFFF); const uint8_t receivedChecksum = static_cast<uint8_t>(frame & 0xFF); const uint8_t expectedChecksum = calculateChecksum(sequence); printTimestamp(receivedAtUs / 1000); if (magic != MAGIC || receivedChecksum != expectedChecksum) { receiver.invalidPackets++; Serial.printf( " %-4s INVALID frame=0x%010llX invalid=%lu\n", receiverName, static_cast<unsigned long long>(frame), receiver.invalidPackets); return; } uint16_t gap = 0; if (receiver.hasPreviousSequence) { const uint16_t difference = static_cast<uint16_t>( sequence - receiver.previousSequence); if (difference > 1) { gap = difference - 1; receiver.missedPackets += gap; } } receiver.previousSequence = sequence; receiver.hasPreviousSequence = true; receiver.validPackets++; Serial.printf( " %-4s packet=%5u missed_now=%u " "received=%lu missed_total=%lu\n", receiverName, sequence, gap, receiver.validPackets, receiver.missedPackets); } void setup() { Serial.begin(115200); delay(1000); pinMode(RXB6_PIN, INPUT); pinMode(RXB8_PIN, INPUT); rxb6.lastEdgeUs = micros(); rxb8.lastEdgeUs = micros(); attachInterrupt( digitalPinToInterrupt(RXB6_PIN), rxb6Interrupt, CHANGE); attachInterrupt( digitalPinToInterrupt(RXB8_PIN), rxb8Interrupt, CHANGE); Serial.println(); Serial.println("Dual 433 MHz receiver started"); Serial.printf("RXB6: GPIO%u\n", RXB6_PIN); Serial.printf("RXB8: GPIO%u\n", RXB8_PIN); } void loop() { processCompletedFrame(rxb6, "RXB6"); processCompletedFrame(rxb8, "RXB8"); delay(1); }