переделка mySwitch.send через digitalWrite
- Войдите на сайт для отправки комментариев
Всем привет. Есть 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.
ничего не поянл.... почему через mySwitch() медленно? и почему через digitalWrite будет быстрее? а сейчас mySwitch() не через digitalWrite() работает? Вы исходник смотрели?
Вам нужно начать с того, что разобраться в исходнике mySwitch(), почему эта функция работает так междленно (если это вообще так). А я, честно говоря, думаю что вы что-то путаете....
Исходники смотрю. Пока не могу разобраться. Наткнулся на статью "Тюнинг Arduino или ускоряем работу платы" там как раз описывается как ускорить штатную digitalWrite(). Вот я и подумал сначала переписать алгоритм отправки не через mySwitch(), а через ускоренный (из статьи) вариант digitalWrite(). И еще вопрос, какова примерная скорость (пропускная способность) работы передатчика (трехпинового) для ардуино? Т.е. хотелось бы ускороть процесс отправки.
хотелось бы ускороть процесс отправки.
насколько сейчас отличаются скорости mySwitch.send() и SendCame()? вы их в понятных единицах выразить можете - ну там в миллисекундах? чтобы было о чем говорить.
Та статья, на которую вы ссылаетесь - типа ускоряем Ардуино через переписывание digitalWrite() - она вам не подойдет. Точнее так - даже если вы перепишете функцию по рекомендации статьи - разницы в скорости вы не заметите.
В общем есть диапазоны отправляемых кодов, диапазонов 26 шт в каждом диапазоне 1023 кода (десятичных числа) которые отправляю. Ниже код отправки одного диапазона и потом ниже измеренная скорость отправки через mySwitch.send():
скорость измеренная в процессе выполнения:
mySwitch.send(). Total time: 45707484 microsec, AVG time: 22339 microseconds. (iterations 2046)
Может есть вариант параллельной отправки нескольких кодов через mySwitch.send(). Т.е. не один код с длительность. 170 и 2 повтора за раз, а как-то с этими же параметрами отправить одновременно более одного кода. Не нашел пока такого решения. Если оно есть подскажите, чтобы не заморачиваться с низкоуровневым программированием.
ну то есть посылка одного кода ВСЕГО 22 миллисекунды? И что вы тут хотите убыстрить? У вас длина одного кода 24 бита, один бит в этой кодировке занимает от 300 до 700 мкс, плюс заголовк... то есть отсылка 24 бит НИКАК НЕ МОЖЕТ БЫТЬ БЫСТРЕЕ примерно 12-15 миллисекунд.
А у вас 22... И о каком убыстрении идет речь? - если вы убыстрите этот код, шлагбаум перестанет срабатывать
Может есть вариант параллельной отправки нескольких кодов через mySwitch.send(). Т.е. не один код с длительность. 170 и 2 повтора за раз, а как-то с этими же параметрами отправить одновременно более одного кода.
А шлагбаум примет более одного кода за раз? - вы четче задачку поясните - вы хотите подобрать код к какому-то устройству - или вы хотите просто выпалить в воздух тысячи кодов подряд, не заботясь о том, сможет их кто-то прочитать или нет?
Да хочу подобрать код к какому-то устройству. Только код заранее неизвестен, а диапазон кодов выше описал. Алгоритм через 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 кодов?
Хотел бы уточнить:
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 бит и началом передачи следующих тоже есть пауза - и она обычно в разы дольше пауз между битами
Так вот я и пытаюсь выяснить есть ли хотя бы в теории смысл переписывать алгоритм на более низком уровне, а не на mySwitch.send. Будет ли ускорение отправки. Или может можно какими-то другими методами ускорить процесс?
Так вот я и пытаюсь выяснить есть ли хотя бы в теории смысл переписывать алгоритм на более низком уровне, а не на mySwitch.send. Будет ли ускорение отправки. Или может можно какими-то другими методами ускорить процесс?
поскольку алгоритм основан на фиксированных задержках - с абсолютной уверенностью можно сказать, что переписывание его "на более низком уровне" абсолютно бессмысленно. От того, отработает ли digitalWrite ха 100 нс или вы ее убыстрите до 50 - ровным счетом ничего не изменится, все равно паузы между включениями в тысячи раз дольше.
А насчет других методов - я бы все-таки внимательено посмотрел исходник mySwitch() в поисках лишних задержек, не относящихся собственно к передаче кода. Например в вашем первом сообщении в коде SendCame между повторными отсылками кода стоит задержка в 16 мс, которая в разы замедляет отправку. Вот что-то подобное и стоит поискать ...
Так вот я и пытаюсь выяснить есть ли хотя бы в теории смысл переписывать алгоритм на более низком уровне, а не на mySwitch.send. Будет ли ускорение отправки. Или может можно какими-то другими методами ускорить процесс?
flie, Вы не с той стороны подходите к задаче. Вам нужно разобраться в протоколе передачи: определить теоретически минимально необходимое время для передачи той последовательности, что Вы задумали. И только после этого сравнивать это время с тем, что получается на практике.
Очень похоже на то, что Вы хотите упихать лыжи в дамскую косметичку.
А как разобраться в этом самом протоколе, если осцилографа нет.
А как разобраться в этом самом протоколе, если осцилографа нет.
разобраться надо не в сигнале осциллографом, а в коде соответвующей библиотеки. Там, где функция SendCame. Описание протокола есть в Гугле
А как разобраться в этом самом протоколе, если осцилографа нет.
А как Вы собираетесь налаживать электронное устройство без осциллографа?
(Кстати, - да, протокол обычно разбирают, пользуясь дэйташитом, а не осциллографом).
обычно правят алгоритм перебора кодов (при подборе)
я бы применил комбинацию методов, первое - есть 26 блоков данных, делим каждый блок на 4-ре куска и по восходящей 1-ю комбинацию первого куска из каждого из 26 блоков, потом 2-го куска каждого из 26 блоков и так по всем 4 кускам, далее берём 2-ю комбинацию и всё повторяем и т.д.
Еще попутно вопрос. Как увеличить дальность передатчика хотя бы до метров 3-5. А то с штатной антенкой (пружинкой закручена и длина сантиметра 3-4) дальность сработки сантиментов 30-40.
Еще попутно вопрос. Как увеличить дальность передатчика хотя бы до метров 3-5. А то с штатной антенкой (пружинкой закручена и длина сантиметра 3-4) дальность сработки сантиментов 30-40.
может дело не в бобине (передатчике), а в приёмнике? А по антенне поставьте кусок провода 1/4 волны (17 см) и попробуйте
Это как минимум тупо, пытаться что то подобное открывать методом перебора.
Вы знаете алгоритм обработки сигнала устройством ?
От такого брутфорса обычно в самом устройстве ставят задержку, скажем принимаем код не чаще чем раз в 100мс.
Посчитать сможете сколько в этом случае займет перебор пароля ?
Может проще сграбить ключ ?
Библиотека RCSwitch для отправки по умолчанию использует протокол №1, в коде он описан как { 1, 31 }, { 1, 3 }, { 3, 1 }, где цифирки означают кол-во длительностей базовой длительности импульса, которую Вы задаете, т.е. 170 мкс. Первые две цифры (1+31=32) - это общая длительность импульса синхронизации, вторые и третьи (1+3=4) - это длительности передачи бита 0 и бита 1 соответственно. Таким образом, в вашем случае получается 32*170 + 4*24*170 = 21760 мкс, т.е. примерно 22 мс для передачи одной посылки.
Если Вы самостоятельно перепишите отправку такой посылки скорее всего никакого ускорения Вы не получите. Если Вы будете менять длительности импульсов, тогда приемник скорее всего не сможет принять такую посылку. Поскольку передача происходит модулированным сигналом на одной фиксированной несущей частоте (433 МГц), то никакие параллельные передачи/приемы в принципе невозможны.
Путем уменьшения всяких тайм аутов в библиотеке RCSwitch удалось сократить время с 45 сек до 23 сек. Но остались вопросы, приемник срабатывает первый раз (если циклически запускать включение потом пауза секунд 15 и потом выключение) последующие разы может сработать может нет. Не понятно от чего это зависит. Можно ли как-то на одну ардуино повесить и передатчик и приемник так чтобы приемник через сериалмонитор отображал что посылает передатчик (т.е. одновременно передатчик посылает приемник тут же отображает). Если это возможно подскажите пример кода как такое реализовать. И еще вопрос по дальности передатчика, антену которая шла в комплекте припаял но все равно дальность работы не превышает 40 см. Как можно увеличить дальность хотя бы до 2-3 метров. Одну прямую жилу от витой пары (и зачищенную и в оплетке) с длиной 1/4 длины волны пробовал, но не помогло.
такие передатчики лучше запитывать отдельно, у них допустимый диапазон 5-12В, попробуйте запитать от 12В
а вообще, большинство этих модулей идут бракованные и повысить дальность уже не получится (сам сталкивался с такой проблемой, покупал сразу несколько штук, все работают на разные расстояния)
можно к передатчику добавить каскадик усиления на одном транзисторе, хоть отсюда...

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