Управление люстрой 315mhz.

Rgsv

✩✩✩✩✩✩✩
23 Ноя 2023
5
1
Есть люстра управляемая с пульта, появилась идея сделать так, чтобы совместно с будильником в комнате включался свет,так как я часто не слышу будильника.
Открыл коробку с мозгами люстры , внутри модуль приёмника от FS1000A (XD-RF-5V).

При реализации прошлого проекта ,"радиоуправление для гусеничного вездехода на основе джойстика от SEGA", мною были куплены модули (приёмник/передатчик) на 315 и 433 mhz. Я их немного по тестировал и забросил, так как реализовал проект на NRF24L01.

Установил библиотеку RCSwitch, и подключил по очереди приёмники. Стандартный скетч из примера библиотеки отреагировал на пульт при приёмнике 315 mhz

Код примера получения данных:
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
}

void loop() {
  if (mySwitch.available()) {
    
    Serial.print("Received ");
    Serial.print( mySwitch.getReceivedValue() );
    Serial.print(" / ");
    Serial.print( mySwitch.getReceivedBitlength() );
    Serial.print("bit ");
    Serial.print("Protocol: ");
    Serial.println( mySwitch.getReceivedProtocol() );

    mySwitch.resetAvailable();
  }
}
Вывод получился такой при нажатии на 3 разные кнопки.

Received 7672067 / 24bit Protocol: 1
Received 7672256 / 24bit Protocol: 1
Received 7672076 / 24bit Protocol: 1

После этого , я подключил передатчик на 315 mzh и отправляю те же данный но люстра не реагирует.


Код отправки разными способами взятыми из примера:
#include <RCSwitch.h>


RCSwitch mySwitch;

void setup() {
  Serial.begin(115200);
  Serial.println("Started");
  mySwitch.enableTransmit(2);
  mySwitch.setProtocol(1);
  //mySwitch.setPulseLength(320);

  // Optional set number of transmission repetitions.
  //mySwitch.setRepeatTransmit(15);


  // put your setup code here, to run once:
}
/*
17:49:39.914 -> Data: 7672067
17:49:39.914 -> Data: 7672256
17:49:39.914 -> Data: 7672076
*/

void loop() {
  // put your main code here, to run repeatedly:


  if (Serial.available() > 0) {
    // get incoming byte:
    uint8_t inByte = Serial.read();
    switch (inByte) {
      case '1':
        Serial.println("send 1 ");
        mySwitch.send(7672067, 24);

        break;
      case '2':

        Serial.println("send 2 ");
        mySwitch.sendTriState("751103");// hex
        break;
      case '3':
        Serial.println("send 3 ");
        mySwitch.send("00000000011101010001000100000011"); // bin

        break;

      default: break;
    }
  }
}
Фактически накосячить тут трудно, но видимо есть какой то секрет , работы или с библиотекой или с модулем, которого я не знаю. В чем может быть дело ?
Антенна к модулю передатчика нужной длины припаяна(230 мм ).
 

Rgsv

✩✩✩✩✩✩✩
23 Ноя 2023
5
1
Мысль хорошая , но для этого надо иметь две ардуины , а с этим придётся мне подождать.
Раньше , когда я пробовал эти модули для Джойстика , приёмник верно принимал то , что передавал передатчик .
Кейсы 2 и 3 я так понимаю неверные , я не так понял как это работает судя по всему.

Возможно протокол не так прост, и надо вручную посмотреть на то, что там в канале. Например библиотека принимает только половину транзакции , как вариант.

UPD,передатчик сделан на микросхеме SC2260-R4 даташит на неё не густой, диаграмм сигналов и таймингов я не нашёл , кто нибудь эмулировал сигнал с неё на Ардуино ?

UPD
Нашёл китайский даташит с таймингами. На эту микросхему.
1701469091763.png
Проверил код работы библиотеки. Там всё верно , библиотека работать должна и соответствует даташиту . Ничего не понимаю , почему не работает.


C++:
struct Protocol {
        /** base pulse length in microseconds, e.g. 350 */
        uint16_t pulseLength;
        HighLow syncFactor;
        HighLow zero;
        HighLow one;
      
        bool invertedSignal;
    };

...
static const RCSwitch::Protocol PROGMEM proto[] = {
#endif
  { 350, {  1, 31 }, {  1,  3 }, {  3,  1 }, false },    // protocol 1
  { 650, {  1, 10 }, {  1,  2 }, {  2,  1 }, false },    // protocol 2

...

void RCSwitch::send(unsigned long code, unsigned int length) {
  if (this->nTransmitterPin == -1)
    return;

#if not defined( RCSwitchDisableReceiving )
  // make sure the receiver is disabled while we transmit
  int nReceiverInterrupt_backup = nReceiverInterrupt;
  if (nReceiverInterrupt_backup != -1) {
    this->disableReceive();
  }
#endif

  for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
    for (int i = length-1; i >= 0; i--) {
      if (code & (1L << i))
        this->transmit(protocol.one);
      else
        this->transmit(protocol.zero);
    }
    this->transmit(protocol.syncFactor);
  }

  // Disable transmit after sending (i.e., for inverted protocols)
  digitalWrite(this->nTransmitterPin, LOW);

#if not defined( RCSwitchDisableReceiving )
  // enable receiver again if we just disabled it
  if (nReceiverInterrupt_backup != -1) {
    this->enableReceive(nReceiverInterrupt_backup);
  }
#endif
}

/**
 * Transmit a single high-low pulse.
 */
void RCSwitch::transmit(HighLow pulses) {
  uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH;
  uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW;
 
  digitalWrite(this->nTransmitterPin, firstLogicLevel);
  delayMicroseconds( this->protocol.pulseLength * pulses.high);
  digitalWrite(this->nTransmitterPin, secondLogicLevel);
  delayMicroseconds( this->protocol.pulseLength * pulses.low);
}
 
Изменено:

Rgsv

✩✩✩✩✩✩✩
23 Ноя 2023
5
1
Собрал второй приёмник . Залил в него скетч приёмника с полным логом .


Сигнал с пульта

Decimal: 7672067 (24Bit) Binary: 011101010001000100000011 Tri-State: F1FF0F0F0001 PulseLength: 234 microseconds Protocol: 1
Raw data: 6552,208,644,624,216,620,236,604,240,184,656,612,236,188,656,612,232,192,652,192,652,192,652,612,236,188,656,184,660,192,652,612,232,192,656,188,656,184,664,184,656,188,656,188,660,604,240,608,240,

Сигнал с моего передатчика.
Decimal: 7672067 (24Bit) Binary: 011101010001000100000011 Tri-State: F1FF0F0F0001 PulseLength: 235 microseconds Protocol: 1
Raw data: 6592,148,796,604,340,608,336,608,352,132,796,608,336,140,808,604,340,136,804,140,804,140,804,596,336,144,804,136,812,136,808,588,336,144,816,124,800,140,804,136,792,144,792,148,788,608,328,608,324,
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
По идее все идентично, должен хавать. Может быть вариант, что приемник и передатчик лампы более требовательны к выставленной частоте и требуют большего схождения интервалов, тут я не подскажу.
Не думаю что люстра будет отвечать пульту, т.е. наличие обратной связи маловероятно.
 

Rgsv

✩✩✩✩✩✩✩
23 Ноя 2023
5
1
Изучил библиотеку, написана не совсем корректно, так как при таймингах в мкс создатель не учел, что умножения , сравнения, и вызовы функций тоже занимают время, в результате соотношение импульсов у него получилось не 3 к 1 , а 3 к 2. так как второй тайминг в импульсе сильно подрос за счёт того, что в него включилось всё время логики. Впрочем это стандартная ошибка программистов привыкших писать для corei5,где давно уже в расчёт идет только сложность алгоритмов .

Исправив код и взяв поправку для времени второго импульса получилось так. Raw data это пары чисел , первое число время сигнала high , второе low
Raw data: 6520,208,692,684,248,684,252,684,256,204,692,684,252,208,700,672,252,208,692,212,696,204,692,680,244,212,692,208,696,204,688,676,260,200,696,204,684,212,684,212,684,208,688,212,684,684,232,696,228,

Люстра по прежнему не реагирует :) :) :)

UPD: написал следующий тестовый код для отправки данных, для минимизации всех паразитных задержек.


C++:
 //7672067 (24Bit) Binary: 011101010001000100000011

constexpr uint16_t T   = 230;
constexpr uint16_t Tx3 = 3*T;
constexpr uint8_t  t_pin  = 2;

inline void transmit(bool bit  ) {   
    digitalWrite( t_pin, HIGH);
    delayMicroseconds( bit ? Tx3 : T );
    digitalWrite(t_pin, LOW);
    delayMicroseconds( bit ? T : Tx3 );
}

#define transmit_1 \   
    digitalWrite( t_pin, HIGH);\
    delayMicroseconds( Tx3 ); \
    digitalWrite(t_pin, LOW); \
    delayMicroseconds( T  ); \

#define transmit_0 \   
    digitalWrite( t_pin, HIGH);\
    delayMicroseconds( T ); \
    digitalWrite(t_pin, LOW); \
    delayMicroseconds( Tx3 ); \




void send(unsigned long code, uint8_t length ,  int rep) {
 
  for (int nRepeat = 0; nRepeat < rep; ++nRepeat) {
    
    
    for (int8_t i = length-1; i >= 0; --i) {             
      transmit(  code & (1L << i)  );
    }   

    transmit(0);
    //digitalWrite(t_pin, LOW);   
    delayMicroseconds(28*T); /// sync
  }

}

void sendFast(unsigned long code, uint8_t length ,  int rep) {
 
  for (int nRepeat = 0; nRepeat < rep; ++nRepeat) {
    for (int8_t i = length-1; i >= 0; --i) {             
      if (  code & (1L << i)  ) {
        transmit_1;
      } else {
        transmit_0;
      }
    }   

    transmit_0;
    //digitalWrite(t_pin, LOW);   
    delayMicroseconds(28*T); /// sync
    
  }

}


void setup() {
  Serial.begin(115200);
  pinMode(t_pin, OUTPUT); 
  Serial.println("");
  Serial.println("---Started");
 
}


void loop() {
 
    sendFast(7672067 , 24 ,10  );
    delay(1000);
}
Реакции нет , тайминги максимально "чистые" насколько это возможно. Замер показал что отправка пакета , без синхропаузы == 100*T , что чётко попадает в даташит .

Сравнивая схемотехнику передатчиков пульта и FS1000A видно , что на FS1000A есть катушки. А в пульте их нет. Возможно на таких скоростях с T < 320, эти катушки вносят инерционность, которая мешает передачи сигнала на дальние расстояния.
Заказал отдельно генераторы R315 ,буду делать свой передатчик на схеме передатчика пульта.
 
Изменено: