переделка mySwitch.send через digitalWrite

flie
Offline
Зарегистрирован: 18.02.2020

Всем привет. Есть arduino uno + передатчик на 433 мгц. Написан код для типа кнопки включения с пульта с использованием библиотеки RCSwitch. Пример кода:

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
long i = 0;

void setup() {

  Serial.begin(9600);
//  mySwitch.enableReceive(0);
  pinMode(10, OUTPUT);
  // Transmitter is connected to Arduino Pin #10  
  mySwitch.enableTransmit(10);
  
  // Optional set protocol (default is 1, will work for most outlets)
  // mySwitch.setProtocol(2);

  // Optional set pulse length.
 mySwitch.setPulseLength(170);
  
  // Optional set number of transmission repetitions.
 mySwitch.setRepeatTransmit(2);
  
}

void loop() {
  mySwitch.send(0b011111001101011111000000, 24);

}

Все работает все включает. Но стоит задача отсылки большого количества кодов (типа перебор кодов включения/выключения, никому это не навредит т.к. передатчик дальше 1 метра не работает). Но через mySwitch.send отсылает очень медленно, для моей задачи уйдет минут 20 на перебор кодов включения и еще 20 минут на выключение. В общем озадачился ускорить код и переписать его с использованием digitalWrite. Но не работает, т.е. не включает ничего.

Вот примерный код(сделан на примере найденный на этом форуме:

#define txPin 10
#define Te 170

void setup()
{
  pinMode(10, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
 
  SendCame(0b011111001101011111000000);

 delay(5000);
}

void SendCameBit(byte b)
{
  delayMicroseconds(Te);
  if (!b) digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,LOW);
//  Serial.print(b);
}

void SendCame(long Code)
{  
  for (int j=0;j<=3;j++) // посылку посылаем как и брелок - 4 раза подряд.
  {
    digitalWrite(txPin,HIGH);
    delayMicroseconds(Te);
    digitalWrite(txPin,LOW);// посылаем стартовый импульс
       
    for (byte i=24;i>0;i--){
     SendCameBit(bitRead(Code, i-1));
   
    }
    Serial.println("");

  delay(16);
}
  delay(2000); // сделать паузу после посылки на 2 с
}

в монитор порта выводит правильный код, но приблуда не включается (хотя если отправляю через mySwitch.send(0b011111001101011111000000, 24); включается). Покурил исходник библиотеки rcswitch, но так и не доходит как реализовать алгоритм отправки (mySwitch.send(0b011111001101011111000000, 24);) через digitalWrite. Может кто подскажет хоть небольшой пример реализации ускорения работы mySwitch.send не обязательно через digitalWrite.

 

 

 

b707
Offline
Зарегистрирован: 26.05.2017

ничего не поянл.... почему через mySwitch() медленно? и почему через digitalWrite будет быстрее? а сейчас  mySwitch() не через digitalWrite() работает? Вы исходник смотрели?

Вам нужно начать с того, что разобраться в исходнике mySwitch(), почему эта функция работает так междленно (если это вообще так).  А я, честно говоря, думаю что вы что-то путаете....

flie
Offline
Зарегистрирован: 18.02.2020

Исходники смотрю. Пока не могу разобраться. Наткнулся на статью "Тюнинг Arduino или ускоряем работу платы" там как раз описывается как ускорить штатную digitalWrite(). Вот я и подумал сначала переписать алгоритм отправки не через mySwitch(), а через ускоренный (из статьи) вариант digitalWrite(). И еще вопрос, какова примерная скорость (пропускная способность) работы передатчика (трехпинового) для ардуино? Т.е. хотелось бы ускороть процесс отправки.

b707
Offline
Зарегистрирован: 26.05.2017

flie пишет:

 хотелось бы ускороть процесс отправки.

насколько сейчас отличаются скорости mySwitch.send() и SendCame()? вы их в понятных единицах выразить можете - ну там в миллисекундах? чтобы было о чем говорить.

Та статья, на которую вы ссылаетесь - типа ускоряем Ардуино через переписывание digitalWrite() - она вам не подойдет. Точнее так - даже если вы перепишете функцию по рекомендации статьи - разницы в скорости вы не заметите.

 

flie
Offline
Зарегистрирован: 18.02.2020

В общем есть диапазоны отправляемых кодов, диапазонов 26 шт в каждом диапазоне 1023 кода (десятичных числа) которые отправляю. Ниже код отправки одного диапазона и потом ниже измеренная скорость отправки через mySwitch.send():

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
long i = 0;
long a = 0;
unsigned long _time;

String strToOut = "";

int count=1023;


void setup() {

  Serial.begin(9600);
//  mySwitch.enableReceive(0);
  pinMode(10, OUTPUT);
  // Transmitter is connected to Arduino Pin #10  
  mySwitch.enableTransmit(10);
  
  // Optional set protocol (default is 1, will work for most outlets)
  // mySwitch.setProtocol(2);

  // Optional set pulse length.
 mySwitch.setPulseLength(170);
  
  // Optional set number of transmission repetitions.
 mySwitch.setRepeatTransmit(2);
  
}

void loop() {
  testDWrite(10);
  delay(10000);


}

void testDWrite(int pin) {
  _time = micros();
  Serial.println("Включаем хрень");
  for (i=8126656; i<8388544; i=i+256) {
    mySwitch.send(i, 24);
//     Serial.println(i);
  }
  showResult ("mySwitch.send()", _time, count*2 );
}


void showResult (String func, long timeStart, int iter) {
  unsigned long timeTotal = micros() - _time;
  unsigned long time1 = timeTotal / iter;

  strToOut = func + ". Total time: " + String(timeTotal) + " microsec, AVG time: " + String(time1) + " microseconds. (iterations " + String(iter) + ")";
  Serial.println(strToOut);
}

скорость измеренная в процессе выполнения:

 mySwitch.send(). Total time: 45707484 microsec, AVG time: 22339 microseconds. (iterations 2046)

т.е. 45 сек. (я даже секундомером замерял так и получается). Теперь что получаем 45 сек * 26 диапазонов = 19,5 минут.
 
Через SendCame не замерял т.к. через него не срабатывает и нет уверенности что алгоритм правильный.
 
flie
Offline
Зарегистрирован: 18.02.2020

Может есть вариант параллельной отправки нескольких кодов через mySwitch.send(). Т.е. не один код с длительность. 170 и 2 повтора за раз, а как-то с этими же параметрами отправить одновременно более одного кода. Не нашел пока такого решения. Если оно есть подскажите, чтобы не заморачиваться с низкоуровневым программированием.

b707
Offline
Зарегистрирован: 26.05.2017

ну то есть посылка одного кода ВСЕГО 22 миллисекунды? И что вы тут хотите убыстрить? У вас длина одного кода 24 бита, один бит в этой кодировке занимает от 300 до 700 мкс, плюс заголовк... то есть отсылка 24 бит НИКАК НЕ МОЖЕТ БЫТЬ БЫСТРЕЕ примерно 12-15 миллисекунд.

А у вас 22... И о каком убыстрении идет речь? - если вы убыстрите этот код, шлагбаум перестанет срабатывать

b707
Offline
Зарегистрирован: 26.05.2017

flie пишет:

Может есть вариант параллельной отправки нескольких кодов через mySwitch.send(). Т.е. не один код с длительность. 170 и 2 повтора за раз, а как-то с этими же параметрами отправить одновременно более одного кода.

А шлагбаум примет более одного кода за раз? - вы четче задачку поясните - вы хотите подобрать код к какому-то устройству - или вы хотите просто выпалить в воздух тысячи кодов подряд, не заботясь о том, сможет их кто-то прочитать или нет?

flie
Offline
Зарегистрирован: 18.02.2020

Да хочу подобрать код к какому-то устройству. Только код заранее неизвестен, а диапазон кодов выше описал. Алгоритм через mySwitch.send работает, только ждать в пределах 20 минут. Согласен что параллельная отправка может не обработаться приемником. Хотел бы уточнить:

mySwitch.send отправляет код бит за битом? Т.е. есть код 011111001101011111000000 и на низком уровне ардуино для нуля LOW для 1 HIGH выдает на пин ардуино куда подключен передатчик? В таком случае mySwitch.setPulseLength(170); это пауза между каждым битом отправки? Т.е. для кода 011111001101011111000000 отправка на пин 10 где подключен передатчик выглядит примерно так: LOW-пауза 170 мкрс - HIGH-пауза 170 мкрс - HIGH-пауза 170 мкрс - HIGH и т.д. (хотелось бы разобраться на низком уровне что происходит). Если да то получается 170 микросекунд * 24 длина кода * 2 повтора = 8160 микросекунд примерно отправка одного кода (ну округлим до 10000 микросекунд с служебными битами если таковые есть). Т.е. для отправки одного кода должно уходить 0,01 секунды, умножаем на 1023 кода получаем 10,23 секунды, так? Откуда тогда 45 секунд на отправку 1023 кодов?

b707
Offline
Зарегистрирован: 26.05.2017

flie пишет:

 Хотел бы уточнить:

mySwitch.send отправляет код бит за битом? Т.е. есть код 011111001101011111000000 и на низком уровне ардуино для нуля LOW для 1 HIGH выдает на пин ардуино куда подключен передатчик? В таком случае mySwitch.setPulseLength(170); это пауза между каждым битом отправки? Если да то получается 170 микросекунд * 24 длина кода * 2 повтора = 8160 микросекунд примерно отправка одного кода (ну округлим до 10000 микросекунд с служебными битами если таковые есть). Т.е. для отправки одного кода должно уходить 0,01 секунды, умножаем на 1023 кода получаем 10,23 секунды, так? Откуда тогда 45 секунд на отправку 1023 кодов?

так это вы только длительность пауз посчитали. А длительность передачи самого бита? Откройте библиотеку и посмотрите, скорее всего общая длительность передачи бита в N (от 2х до 4х) раз дольше этих 170 мкс. Кроме того, между передачей одних 24 бит и началом передачи следующих тоже есть пауза - и она обычно в разы дольше пауз между битами

flie
Offline
Зарегистрирован: 18.02.2020

Так вот я и пытаюсь выяснить есть ли хотя бы в теории смысл переписывать алгоритм на более низком уровне, а не на mySwitch.send. Будет ли ускорение отправки. Или может можно какими-то другими методами ускорить процесс?

b707
Offline
Зарегистрирован: 26.05.2017

flie пишет:

Так вот я и пытаюсь выяснить есть ли хотя бы в теории смысл переписывать алгоритм на более низком уровне, а не на mySwitch.send. Будет ли ускорение отправки. Или может можно какими-то другими методами ускорить процесс?

поскольку алгоритм основан на фиксированных задержках - с абсолютной уверенностью можно сказать, что переписывание его "на более низком уровне" абсолютно бессмысленно. От того, отработает ли digitalWrite ха 100 нс или вы ее убыстрите до 50 - ровным счетом ничего не изменится, все равно паузы между включениями в тысячи раз дольше.

А насчет других методов - я бы все-таки внимательено посмотрел исходник mySwitch() в поисках лишних задержек, не относящихся собственно к передаче кода. Например в вашем первом сообщении в коде SendCame между повторными отсылками кода стоит задержка в 16 мс, которая в разы замедляет отправку. Вот что-то подобное и стоит поискать ...

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

flie пишет:

Так вот я и пытаюсь выяснить есть ли хотя бы в теории смысл переписывать алгоритм на более низком уровне, а не на mySwitch.send. Будет ли ускорение отправки. Или может можно какими-то другими методами ускорить процесс?

flie, Вы не с той стороны подходите к задаче. Вам нужно разобраться в протоколе передачи: определить теоретически минимально необходимое время для передачи той последовательности, что Вы задумали. И только после этого сравнивать это время с тем, что получается на практике.

Очень похоже на то, что Вы хотите упихать лыжи в дамскую косметичку.

flie
Offline
Зарегистрирован: 18.02.2020

А как разобраться в этом самом протоколе, если осцилографа нет.

b707
Offline
Зарегистрирован: 26.05.2017

flie пишет:

А как разобраться в этом самом протоколе, если осцилографа нет.

разобраться надо не в сигнале осциллографом, а в коде соответвующей библиотеки. Там, где функция SendCame. Описание протокола есть в Гугле

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

flie пишет:

А как разобраться в этом самом протоколе, если осцилографа нет.

А как Вы собираетесь налаживать электронное устройство без осциллографа?

(Кстати, - да, протокол обычно разбирают, пользуясь дэйташитом, а не осциллографом).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

обычно правят алгоритм перебора кодов (при подборе)

я бы применил комбинацию методов, первое - есть 26 блоков данных, делим каждый блок на 4-ре куска и по восходящей 1-ю комбинацию первого куска из каждого из 26 блоков, потом 2-го куска  каждого из 26 блоков и так по всем 4 кускам, далее берём 2-ю комбинацию и всё повторяем и т.д.

flie
Offline
Зарегистрирован: 18.02.2020

Еще попутно вопрос. Как увеличить дальность передатчика хотя бы до метров 3-5. А то с штатной антенкой (пружинкой закручена и длина сантиметра 3-4) дальность сработки сантиментов 30-40.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

flie пишет:

Еще попутно вопрос. Как увеличить дальность передатчика хотя бы до метров 3-5. А то с штатной антенкой (пружинкой закручена и длина сантиметра 3-4) дальность сработки сантиментов 30-40.

может дело не в бобине (передатчике), а в приёмнике? А по антенне поставьте кусок провода 1/4 волны (17 см) и попробуйте

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Это как минимум тупо, пытаться что то подобное открывать методом перебора.
Вы знаете алгоритм обработки сигнала устройством ?
От такого брутфорса обычно в самом устройстве ставят задержку, скажем принимаем код не чаще чем раз в 100мс.
Посчитать сможете сколько в этом случае займет перебор пароля ?
Может проще сграбить ключ ?

miks69
Offline
Зарегистрирован: 16.02.2020

Библиотека RCSwitch для отправки по умолчанию использует протокол №1, в коде он описан как { 1, 31 }, { 1,  3 }, { 3,  1 }, где цифирки означают кол-во длительностей базовой длительности импульса, которую Вы задаете, т.е. 170 мкс. Первые две цифры (1+31=32) - это общая длительность импульса синхронизации, вторые и третьи (1+3=4) - это длительности передачи бита 0 и бита 1 соответственно. Таким образом, в вашем случае получается 32*170 + 4*24*170 = 21760 мкс, т.е. примерно 22 мс для передачи одной посылки.

miks69
Offline
Зарегистрирован: 16.02.2020

Если Вы самостоятельно перепишите отправку такой посылки скорее всего никакого ускорения Вы не получите. Если Вы будете менять длительности импульсов, тогда приемник скорее всего не сможет принять такую посылку. Поскольку передача происходит модулированным сигналом на одной фиксированной несущей частоте (433 МГц), то никакие параллельные передачи/приемы в принципе невозможны.

flie
Offline
Зарегистрирован: 18.02.2020

Путем уменьшения всяких тайм аутов в библиотеке RCSwitch удалось сократить время с 45 сек до 23 сек. Но остались вопросы, приемник срабатывает первый раз (если циклически запускать включение потом пауза секунд 15 и потом выключение) последующие разы может сработать может нет. Не понятно от чего это зависит. Можно ли как-то на одну ардуино повесить и передатчик и приемник так чтобы приемник через сериалмонитор отображал что посылает передатчик (т.е. одновременно передатчик посылает приемник тут же отображает). Если это возможно подскажите пример кода как такое реализовать. И еще вопрос по дальности передатчика, антену которая шла в комплекте припаял но все равно дальность работы не превышает 40 см. Как можно увеличить дальность хотя бы до 2-3 метров. Одну прямую жилу от витой пары (и зачищенную и в оплетке) с длиной 1/4 длины волны пробовал, но не помогло. 

enot0324
Offline
Зарегистрирован: 10.04.2019

такие передатчики лучше запитывать отдельно, у них допустимый диапазон 5-12В, попробуйте запитать от 12В

а вообще, большинство этих модулей идут бракованные и повысить дальность уже не получится (сам сталкивался с такой проблемой, покупал сразу несколько штук, все работают на разные расстояния)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

miks69
Offline
Зарегистрирован: 16.02.2020

flie пишет:

Путем уменьшения всяких тайм аутов в библиотеке RCSwitch удалось сократить время с 45 сек до 23 сек. Но остались вопросы, приемник срабатывает первый раз (если циклически запускать включение потом пауза секунд 15 и потом выключение) последующие разы может сработать может нет. Не понятно от чего это зависит. Можно ли как-то на одну ардуино повесить и передатчик и приемник так чтобы приемник через сериалмонитор отображал что посылает передатчик (т.е. одновременно передатчик посылает приемник тут же отображает). Если это возможно подскажите пример кода как такое реализовать. И еще вопрос по дальности передатчика, антену которая шла в комплекте припаял но все равно дальность работы не превышает 40 см. Как можно увеличить дальность хотя бы до 2-3 метров. Одну прямую жилу от витой пары (и зачищенную и в оплетке) с длиной 1/4 длины волны пробовал, но не помогло. 

Скорее всего на приемной стороне есть некоторая задержка после приема очередной посылки до начала приема следующей, либо приемник ждет повтора полученного пакета, т.к. обычно в одной посылке идут 3-4 повтора одного пакета для контроля на приемной стороне, разделенные синхроимпульсом, который в вашем случае составляет 5,5 мс. Как вариант попробуйте сделать такую задержку между передачами.

Повесить на одну Arduino одновременно и приемник и передатчик конечно возможно, только вы никак не сможете обеспечить их одновеменную работу, т.к. и передача и прием обеспечиваются программным кодом. Кроме того, в той же библиотеке RCSwitch приемник отключается на время выполнении передачи пакета.

5N62V
Offline
Зарегистрирован: 25.02.2016

Извините за оффтоп.

RCSwitch mySwitch = RCSwitch();

А так можно?  А зачем именно так? Я тут Лафоре докуриваю, ничего подобного не видел.