Термометр с беспроводной передачей данных

…на ультрадешевых радиомодулях по 5 долларов за пучок.83978c65e3de8688afc39deef603928d.jpgКомплект содержит радиопередатчик и сверхрегенеративный приемник. Количество контактов, фактически по 3 штуки, два из которых питание, намекает на крайнюю простоту работы с ними. Правда комплект больше ориентируется на дистанционное управление и чаще используется в паре с кодерами и декодерами на специализированных микросхемах, но мы это упустим, т.к. свой велосипед всегда дороже.d2e21f0a40aa15f885ea9ceadd7f6114.gifПередатчик с амплитудной модуляцией на частоту 433 МГц, частота стабилизирована ПАВ. Передатчик близкий родственник всяким одно-, двух-, трехтранзисторным жучкам и маячкам, которые делали все, кто когда-либо занимался радиотехникой (много схем на vrtp.ru). Питание на передатчик допускается до 12 В. Вход data фактически открывает транзистор и запускает генерацию, при низком уровне на входе генерация прекращается. Соответственно выставляя Hi и Lo на входе с определенной частотой мы можем передавать данные.910c613d9c421deae57f2a8ab27a3c0b.jpg

Приемник относится к классу сверхрегенеративных. Нынче такая схема практически полностью вышла из употребления и заменена супергетеродинными, но десятилетия назад на ней выпускали даже промышленные приемники для прослушивания радиоэфира.Сверхрегенерат это дальнейшее развитие приемника прямого усиления. Во входной контур за счет положительной обратной связи в прерывистом режиме, на частотах десятки кГц, вносится энергия источника питания в виде колебаний той же частоты, на которую настроен контур. Этим компенсируются потери в контуре и улучшается его добротность. На выходе радиомодуля стоит компаратор, выдающий на линию Data Hi или Lo.

72cf5eccec4ee7b45d9de41a43568a54.gifДостоинства сверхрегенеративных приемников:

Простота и дешевизны конструкции Очень высокая чувствительность Широкая полоса пропускания Автоматическая регулировка усиления Недостатки, вытекающие из достоинств: Широкая полоса пропускания, в которую всегда что-то попадает. Величина порядке единиц МГц. Высокая чувствительность, хоть передатчик включен, хоть выключен, на выходе приемника всегда есть какой-то шум (см. далее). Сложность в настройке, т.к. сверхрегенеративный каскад выполняет одновременно две-три функции (усилитель, генератор, детектор). Но нам-то уже настраивать ничего не надо. На обоих модулях оставлено отверстие под антенну. После того как рядом лежащие модули, были наконец разнесены, я понял, что без антенны делать нечего и прицепил к модулям в качестве антенн под руку попавшие крокодильчики с проводками. В таком виде дальность действия собранных устройств составила свыше 10 метров по прямой при питании передатчика от Кроны 9В. Напоминаю, что в качестве антенны может использоваться кусок провода равный примерно ¼ или ½ длины волны, в нашем случае будет 17 или 34 см. Общий провод (GND), если есть возможность, лучше подключить к противовесу, которым может быть металлический корпус или другой кусок провода, направленный в противоположную от антенны сторону.

Эта картинка при удалении передатчика на 10 метров. Несмотря на то, что мощность сигнала визуально сильно уменьшилась, приемный модуль данные получает уверенно.ccdb43e10b368fc8b77cbe66a956609e.jpg

Теперь непосредственно к передаче данных. Как же наивен я был когда подключил передатчик к UART на одном контроллере, и к UART на другом. Я увидел переданный байт, хотя он и был в окружении десятков лишних! Посмотрите следующую картинку, приемник всегда что-то ловит. И только когда есть устойчивый периодический (!) сигнал, он четко проявляется во всем входящем мусоре. UART передает данные побитно, без разделения каждого бита, если передается 0×00, то это будет низкий уровень на всем протяжении передачи байта, т.е. передатчик будет просто отключен, а если передается 0xff, то это будет высокий уровень, но и при этом приемник вскоре начнет видеть в нем неоднородности и выдавать случайную последовательность.

ea93a7257deaaaf3285f1c49985ef360.gif

Т.е. я включаю передатчик, сажу линию данных на питание, передатчик во всю мощь передает несущую, а на приемнике я вижу несколько единиц, а потом мусор 11111111110100101001. Отпускаю линию данных, появляются нули и снова мусор 000000000110101010. Вывод: приемнику нужны периодические перепады уровня.

И такой код есть у нас. Манчестерский. В манчестерском коде биты кодируются перепадом из низкого уровня вверх (пусть будет 1), или из верхнего вниз (пусть будет 0). Соответственно перед началом передачи каждого бита уровень должен быть выставлен в начальное положение, а в середине измениться. Опытным путем выяснено, что оптимальная скорость передачи данных примерно 5–10–20 килобит в секунду. Это позволит добиться достаточно устойчивого приема, и будет использоваться в прототипе устройства, которое я и начну далее описывать.

c5070db081db6f6cf6090135c5901bbf.gif

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

a25ef354267b2197bfe4286ceeafdb13.jpg

Передатчик собран на контроллере Attiny13, с термодатчиком LM335. Термодатчик аналоговый, выдает 100 мВ на 1К. Источник опорного напряжения МК используется внутренний 1,1В.Т. к. значения с датчика свыше 3В, то данные на АЦП передаются через делитель. Контроллер просыпается раз в 30 минут, а в режиме отладки раз в 4 секунды, подает питание на термодатчик, включает передатчик, и в течение примерно 1–2 секунд передает текущую температуру тысячу раз. Да! Именно тысячу раз подряд, т.к. даже со 100 подряд передачами я пропускал данные в некоторых сеансах. Современные города, с десятками автомобильных сигналок на 433МГц не самое спокойное место.Температура передается в виде одного единственного байта с манчестерским кодированием.

a61ec6e541da9125cd2595e99d483396.gif

0b10101011 на стороне приемника превратиться в 21°С.

Передача байта void send1() { PORT_TX&=~B_TX; _delay_us (DELAY_US); PORT_TX|=B_TX; _delay_us (DELAY_US); }

void send0() { PORT_TX|=B_TX; _delay_us (DELAY_US); PORT_TX&=~B_TX; _delay_us (DELAY_US); }

void send (char c) { send1(); for (uint8_t i=128; i>0; i>>=1) { if (c & i) send1(); else send0(); } PORT_TX&=~B_TX; } Засыпание после передачи данных до поступления прерывания от сторожевого таймера if (debug_mode) { cli (); wdt_reset (); WDTCR=1<

Схема передатчика, как не надо делать! 5d0ea1e07e2c12885e9e677de229acb3.gif Приемник собран на базе Attiny85 с дисплеем от Nokia 5110. Верхняя строка отведена под индикацию текущей температуры, нижняя показывает наибольшую и наименьшую. Центральная область 84×32 отображает гистограмму от 0 до 32С. Все что свыше или ниже просто обрезается.

117c1d77d0f99fae7cf51785c34bb9fe.jpg

Прием ведется непрерывно. При переходе на линии приема с Lo в Hi делается попытка принять 8 бит данных. В первоначальном варианте прием бит выглядел примерно так: т.к. первый переход с Lo в Hi это середина стартового бита 1, то от него отмеряется время немногим меньше длительности бита, фиксируется значение на входе, а чуть погодя, когда наступает время прихода второй половины бита, снова фиксируется значение на порту. Таким образом определяется переход к верхнему или нижнему уровню. Дальше видно, что это сработало плохо.

Схема приемника 8d7a0078a95be5e787589b6170f93da4.gif Для отсеивания мусора я ожидаю три посылки подряд, и если они совпадают, то это и будет текущая температура. При этом она отображается и на 0,5 сек. отображается индикатор приема. Раз в 15 минут гистограмма сдвигается, а если в течение 45 минут не было получено новой температуры, то индикация текущей температуры гаснет, а гистограмма продолжит сдвигаться с пустой колонкой. Если бы char в настройках GCC не оказался unsigned, то все заработало бы с пол пинка, но странные глюки до ночи выклевывали мне мозг. А по утру включив приемник, при выключенном передатчике, я в течение получаса словил помеху, получив -91 градус.Тогда я не растерялся и сделал ожидание четырех посылок подряд. И словил ложную посылку опять в течение получаса. Я сделал ожидание двух подряд одинаковых байт и подтверждение их CRC8. И через часок опять словил ложную температуру, все согласно теореме о бесконечных обезьянах.«Полдюжины обезьян, будь у них пишущие машинки и одна-другая вечность в запасе, создадут все книги, которые хранятся сегодня в Британском музее«И, наконец, вернувшись к тройной посылке, но изменив алгоритм приема отдельных битов, я вроде успокоился, хотя понимаю, что обезьяны не дремлют.

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

Было int8_t read_bit () { _delay_us (160); // ожидаем середины бита char rx=PIN_RX & B_RX; // после этого ждем переход for (uint8_t i=0; i<6; i++) { if((PIN_RX & B_RX) != rx) { if(rx) return 0; else return 1; } } return -1; } Стало int8_t read_bit() { char rx=PIN_RX & B_RX; for(uint8_t i=0; i<5; i++) { if((PIN_RX & B_RX) != rx) return -1; // несвоевременный переход } _delay_us(40); // здесь граница бит и может быть переход

rx=PIN_RX & B_RX; for (uint8_t i=0; i<5; i++) { if((PIN_RX & B_RX) != rx) return -1; // несвоевременный переход } rx=PIN_RX & B_RX;

for (uint8_t i=0; i<6; i++) // здесь ожидаем переход вверх или вниз { if((PIN_RX & B_RX) != rx) { if(rx) return 0; else return 1; } } return -1; } Несмотря на то, что для серьезного применения в качестве модулей передачи данных эти радиомодули вряд ли годятся, но для сбора статистики, с последующие обработкой и отбраковкой явно недостоверных данных вполне.

Т.к. устройства носят лишь демонстрационную функцию, то печатные платы я намеренно не выкладываю, тем более их стоит переразвести для исправления багов.Исходный криворукий Си-код и hex файлы в архиве. Fuse-биты по-умолчанию.

© Habrahabr.ru