[Из песочницы] Беспроводные часы-термометр
Сегодня хочу рассказать о своем опыте в работе с AVR-микроконтроллерами.
Ремонтом занимался Папа, и во время ремонта решил установить в комнатах теплый пол. Было решено устанавливать нагревательный кабель в качестве источника тепла. До установки тесты кабеля не проводились потому в теплый пол был еще добавлен один датчик DS18b20 (да, одного безусловно мало, но не было претензий к очень точному измерению температуры, да и цена последних составляет 1$), с заделом на установку на нагревательный элемент регулировки нагрева, но как оказалось в итоге не так он сильно греется чтобы его регулировать. Еще, один температурный датчик был выведен на улицу.
В результате получилось три сигнальных провода от датчиков DS18b20, ну и по три »+» и »-».
Все это дело было помещено в тумбочку под раковиной и зафиксировано до лучших времен (что он собирался делать с ними я не знаю, так как с программированием он почти сталкивался очень мало, старая школа радиотехники — только аналоговые элементы с добавлением интегральных схем).
Спустя некоторое время на просторах интернета мною была замечена интересная платка которая называлась «ARDUINO». На то время я закончил университет по направлению «Радиотехника», и во время учебы нам что-то пытались рассказать о схемотехнике, но не очень успешно, за-то дела с цифровой техникой и МК обстояли лучше и кое-какие знания остались.
В итоге из интереса был сделан заказ на китайском сайте самой дешевой копии платы «ARDUINO». Так и началось тесное знакомство МК.
Изначально были попытки собрать
Далее попробовал
Первое время пробовал писать на стандартном Arduino IDE, но очень быстро перешел на Atmel Studio 6.0 (в связи с чем был еще куплен программатор USBasp_H6). Переход также был обусловлен необходимостью сменить частоту работы МК, так как DS1307 на 16 МГц работать отказался (подружить частоту 1МГц и Arduino IDE мне не удалось). Программатор USBasp_H6 оказался кстати так как МК что был в комплекте я успешно спалил, и заказал 5 новых «чистых» без бутлоадера Arduino.
Вдоволь наигравшись было решено сделать часы, которые кроме времени будут показывать температуру с датчиков, которые были установлены в пол, выведен на улицу ну и температуру внутри помещения.
Далее были муки выбора места установки часов. Возле раковины места подходящего не нашлось, появилась идея поставить их в противоположном углу (но слегка далеко, еще и дверной проем), после чего пришла не очень смелая идея использовать беспроводной способ передачи информации, чтобы вопрос установки часов отпал. За сим порывшись в интернете и в китайских интернет магазинах была заказана пара беспроводных модулей NRF24l01. Для начала собирал все на макетной плате и пытался
Первой проблемой оказался размер LCD-дисплея (64×128 точек). Как оказалось нарисовать что-то на нем — занимает много места. После этого я узнал что 32Кб — это не память программ, а память энергонезависимая и дело пошло проще, все картинки оформил отдельным файлом и все записал в EEPROM.
В результате вышел вот такой
#define F_CPU 1000000UL
#include
#include
#include
#include
#include "my_OWI_ds1820.h"
#include "SPI.h"
#include "nRF24L01.h"
#include "my_i2c_watch.h"
#include "KS0107.h"
void timer_init(void)
void button_init(void)
void get_data(void)
void show_temp
void show_time(void)
ISR (TIMER1_OVF_vect)
void noraml_mode(void)
void set_mode(void)
int main(void)
{
button_init();//инициализация кнопок
ds_init();//инициализация RTC
KS0107_Init();//инициализация LCD
KS0107_Clrscr(0);//очистка LCD
SPI_MasterInit();// SPI для радиомодуля
nRF24L01_init(0b00000011);// инициализация радиомодуля
nrf24l01_RX_TX_mode(PRX);// режим приемника
timer_init();//настройка таймера
if((BUT_1&BUT_2)==0){ds_write(0,0);ds_write(1,0);ds_write(2,0);cond_1=0;cond_2=0;}//full reset 00:00:00
sei();//прием данных с воздуха, смена информации на LCD - по таймеру
while(1){
if(BUT_1==1){cond_1=1;}//условие ненажатости
if(BUT_2==1){cond_2=1;}//условие ненажатости
if (setmode==0){ //обычный режим
if(BUT_1==0){if(cond_1==1){cond_1=0;mode=26;}} //показ температуры пола
if(BUT_2==0){if(cond_2==1){cond_2=0;mode=100;setmode=1;read_ds_data(&ds_time);convert(&ds_time);}}// переход в режим настройки setmode=1
noraml_mode();
} //end if (setmode==0)
else if(setmode==1){//режим настройки часов
set_mode();
}//end if(setmode==1)
}//end while(1)
}//end main
Понятное дело код не очень, но что есть, то есть.
Далее начались попытки написать что-то для передающей стороны. Тут все вышло не так гладко — кривое использование радио модулей. Запустить их смог только для передачи 8 бит информации, потому пришлось бить данные
//измерить и послать с определенного пина
void mSend(char pin)
{
int T=0;
//int x;
char code0,code1,code2;
char pack[3]={0,0,0};
switch (pin){
case 4:
T=temp_18b20_4();
code0=0x10;
code1=0x20;
code2=0x30;
break;
case 3:
T=temp_18b20_3();
code0=0x40;
code1=0x50;
code2=0x60;
break;
case 2:
T=temp_18b20_2();
code0=0x70;
code1=0x80;
code2=0x90;
break;
}
pack[0]=((T>>8)&0x0F)|code0;
pack[1]=((T>>4)&0x0F)|code1;
pack[2]=(T&0x0F)|code2;
for(char i=0;i<3;i++){
nrf24l01_FLUSH_TX;//очищаем буфер передатчика
nrf24l01_Sent_data_Ret(pack[i]);
_delay_ms(100);
}}
То есть при таком способе разбивки во время передачи можно получить только 16 переменных, которые можно различить приемником.
Так же, как Вы могли заметить, не очень хорошо организован способ опроса датчиков DS18b20, а именно новая функция для нового датчика (но так как использовался Atmega328p, и проблем с местом не было, то это не стало большой проблемой), но увы, разобраться как подвешать на одну шину несколько устройств мне не удалось, также как и не удалось в ходе работы программы менять значения макроса указывающего на пин на котором висит датчик.
Получивши более-менее готовый код, занялся изготовлением плат (благо платы нас тоже пытались научить делать во время учебы).
Была нарисована
При проектировании платы передатчика было условие сделать её не очень большой без особых требований по размерам. Сделав плату, установив все компоненты в нужные места, проверил на работоспособность, и как ни странно запустилась с первого раза.
При проектировании же платы приемника стал очевидный вопрос корпуса часов. Так как 3Д принтера я вообще вживую не видел, было решено искать что-то в форме прямоугольного параллелепипеда. Потому на роль коробки для часов была выбрана настенная Ethernet-розетка (начальных фото к сожалению нету). Путем не хитрых
отверстие под порты Ethernet стали размером с LCD-экран. Так как внутреннее устройство коробки оказалось специфическим, появились новые требования к форме и размерам платы.
Процесс сборки приемника оказался сложнее из-за больших размеров и наличия DS1307 в корпусе SO (пока припаял, думал, что те часы сгорели несколько раз), кроме того вышла небольшая промашка с размерами.
Сделав плату, установив все компоненты в нужные места, проверил на работоспособность, и почему-то LCD ничего не показывал. Но к счастью это было лишь большое сопротивление на резисторе что отвечал за контрастность дисплея.
Как должно выглядеть готовое устройство
Вот вроде и все. Осталось только проделать отверстия под кнопки, и по мере возможности закрепить все платы внутри коробки.
При создании кода активно использовал данный ресурс. Библиотеки для работы со всеми устройствами были взяты оттуда.
Ссылка на полный проект на GitHub
Плюсы:
— конфигурация необходимая в конкретном случае;
— обучение, правка рук;
Минусы:
— дорого, в сравнении с китайскими метеостанциями.
— долго, как для человека, имеющего не большие знания в данной теме.
— плохая оптимизация кода.
P.S — если у кого-то есть опыт полноценного запуска NRF24l01, просьба поделится.