[Из песочницы] Беспроводные часы-термометр

Сегодня хочу рассказать о своем опыте в работе с AVR-микроконтроллерами.

Предыстория
И так, дело началось с момента ремонта кухни и ванной комнаты.

Ремонтом занимался Папа, и во время ремонта решил установить в комнатах теплый пол. Было решено устанавливать нагревательный кабель в качестве источника тепла. До установки тесты кабеля не проводились потому в теплый пол был еще добавлен один датчик DS18b20 (да, одного безусловно мало, но не было претензий к очень точному измерению температуры, да и цена последних составляет 1$), с заделом на установку на нагревательный элемент регулировки нагрева, но как оказалось в итоге не так он сильно греется чтобы его регулировать. Еще, один температурный датчик был выведен на улицу.

В результате получилось три сигнальных провода от датчиков DS18b20, ну и по три »+» и »-».

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

Спустя некоторое время на просторах интернета мною была замечена интересная платка которая называлась «ARDUINO». На то время я закончил университет по направлению «Радиотехника», и во время учебы нам что-то пытались рассказать о схемотехнике, но не очень успешно, за-то дела с цифровой техникой и МК обстояли лучше и кое-какие знания остались.

В итоге из интереса был сделан заказ на китайском сайте самой дешевой копии платы «ARDUINO». Так и началось тесное знакомство МК.
Изначально были попытки собрать

3Д-куб.

Потом был семисегментный элемент, часы на МК + семисегментном элементе.

Далее попробовал

часы-термометр на микросхеме RTC DS1307, МК и семисегментном элементе

потом это же на графическом LCD 128×64 точек.


Первое время пробовал писать на стандартном 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, и проблем с местом не было, то это не стало большой проблемой), но увы, разобраться как подвешать на одну шину несколько устройств мне не удалось, также как и не удалось в ходе работы программы менять значения макроса указывающего на пин на котором висит датчик.

Получивши более-менее готовый код, занялся изготовлением плат (благо платы нас тоже пытались научить делать во время учебы).
Была нарисована

схема электрическая принципиальная для передатчика
image


по которой была создана печатная плата (по средству ЛУТ)
image


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

Готовый передатчик
image


При проектировании же платы приемника стал очевидный вопрос корпуса часов. Так как 3Д принтера я вообще вживую не видел, было решено искать что-то в форме прямоугольного параллелепипеда. Потому на роль коробки для часов была выбрана настенная Ethernet-розетка (начальных фото к сожалению нету). Путем не хитрых

манипуляций с ножом
image


отверстие под порты Ethernet стали размером с LCD-экран. Так как внутреннее устройство коробки оказалось специфическим, появились новые требования к форме и размерам платы.

Внутреннее устройство коробки
image


Схема электрическая принципиальная приемника
image


Печатная плата приемника
image


Протравленая плата
image


Процесс сборки приемника оказался сложнее из-за больших размеров и наличия DS1307 в корпусе SO (пока припаял, думал, что те часы сгорели несколько раз), кроме того вышла небольшая промашка с размерами.
Сделав плату, установив все компоненты в нужные места, проверил на работоспособность, и почему-то LCD ничего не показывал. Но к счастью это было лишь большое сопротивление на резисторе что отвечал за контрастность дисплея.

Собраная плата приемника
image


Как должно выглядеть готовое устройство


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

Информация
Код написан в Atmel Studio 6.0. Программировалось через SinaProg2.1.1. Рисовалось в Splan70 и layout 6.0 (хотя я думаю это очевидно). Картинки для LCD делались с помощью LCDAssistant.

При создании кода активно использовал данный ресурс. Библиотеки для работы со всеми устройствами были взяты оттуда.

Ссылка на полный проект на GitHub

Плюсы:
— конфигурация необходимая в конкретном случае;
— обучение, правка рук;

Минусы:
— дорого, в сравнении с китайскими метеостанциями.
— долго, как для человека, имеющего не большие знания в данной теме.
— плохая оптимизация кода.

P.S — если у кого-то есть опыт полноценного запуска NRF24l01, просьба поделится.

© Geektimes