|
Atmega16 +dht11 |
|
|
|
Nov 24 2014, 17:15
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 12-04-14
Пользователь №: 81 348

|
Всем привет! Я только начинаю свой путь. Пишу в Codevisionavr 3.12. В сети кое как нашёл пример по работе с dht11, но он на прерываниях. Вся система из-за этого висит т.к. постоянно генерирует прерывание датчик. Прошу тыкнуть меня что мне нужно исправить. Большое спасибо
Сообщение отредактировал Stiner - Nov 24 2014, 17:18
Эскизы прикрепленных изображений
Прикрепленные файлы
modul.txt ( 9.36 килобайт )
Кол-во скачиваний: 120
|
|
|
|
|
Nov 25 2014, 00:54
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(kovigor @ Nov 25 2014, 03:09)  Если вы хотите работать по прерываниям с I2C на AVR, то сразу скажу, что это не так просто. У Атмела есть апп.ноуты на эту тему, поищите. О сложности я предупредил. Если нет острой необходимости в работе по прерываниям, то я бы вам посоветовал реализовать I2C чисто программно, а не использовать встроенный в АВР аппаратный модуль. Насколько я поняла ситуацию, у датчика DHT11 интерфейс не I2C, а 1-Wire. Разница велика - у 1-Wire клока нет вообще. P.S. Своими бы руками задушила тех, кто экономит провода за счет зверского усложнения протокола, делая его совсем уж заумным и ненадежным.
|
|
|
|
|
Nov 25 2014, 09:30
|
Гуру
     
Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295

|
Цитата(Xenia @ Nov 25 2014, 03:54)  Насколько я поняла ситуацию, у датчика DHT11 интерфейс не I2C, а 1-Wire. P.S. Своими бы руками задушила тех, кто экономит провода за счет зверского усложнения протокола, делая его совсем уж заумным и ненадежным.  Я тоже через какое-то время сообразил, что там не I2C (провод-то один), но уже не хотел редактировать сообщение. Два слова о реализации 1-Wire в Codevision. Огромный недостаток - библиотечные функции, поставляемые с CV, нельзя прерывать, иначе собьется обмен. Для себя я эту проблему решил, написав свою реализацию 1-Wire для обмена с DS1820 ...
|
|
|
|
|
Nov 25 2014, 15:31
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 12-04-14
Пользователь №: 81 348

|
Там даже не 1-wire,а какой-то свой протокол в котором я не могу пока разобраться.
|
|
|
|
|
Nov 25 2014, 18:30
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 6-04-06
Пользователь №: 15 890

|
Stiner, поищите в инете библиотеки для Arduino по подключению к ней этого датчика. Некоторые снабжены хорошими комментариями.
|
|
|
|
|
Nov 25 2014, 20:38
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(kovigor @ Nov 25 2014, 23:16)  И учебная ценность такого решения близка к нулю. Вместо изучения протокола и его реализации предлагается использовать некие "черные ящики". Иногда, конечно, такой подход может быть оправдан, но не в таком же простейшем случае ... Вообще-то не совсем к нулю. Вот тут нашла "библиотеку" (так называется у Ардуин уже скопилированный и загруженный в прошивку модуль, к которому в скетче обращаются, как к объекту), которая с этим DHT11 работает: https://github.com/amperka/dht/tree/master/lib/dhtВ принципе там не так-то сложно, т.к. язык С++, а кода мало. Конечно, он там зовет еще функции от других модулей, но в данном случае не так-то сложно догадаться, что они делают.
|
|
|
|
|
Nov 26 2014, 02:09
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 6-04-06
Пользователь №: 15 890

|
Вод код позаимствованный именно из библиотеки для Arduino. Великолепно работающий в моем проекте. CODE unsigned char DHT_Read(int *temperature, int *humidity, uint8_t *sign) { int temp; uint8_t data[5] = {0}; if (SENSOR_is_low) { // bus not free return 1; }
SENSOR_sda_out; SENSOR_sda_low; // MCU start signal _delay_ms(20); // start signal (pull sda down for min 0.8ms and maximum 20ms) SENSOR_sda_in;
// Bus master has released time min: 20us, typ: 30us, max: 200us uint8_t timeout = 200; while(SENSOR_is_hi) {_delay_us(1); if (!timeout--) {return 1;}}
// AM2302 response signal min: 75us typ:80us max:85us timeout = 85; while(SENSOR_is_low) {_delay_us(1); if (!timeout--) {return 1;}} // response to low time timeout = 85; while(SENSOR_is_hi) {_delay_us(1); if (!timeout--) {return 1;}} // response to high time
/* * time in us: min typ max * signal 0 high time: 22 26 30 (bit=0) * signal 1 high time: 68 70 75 (bit=1) * signal 0,1 down time: 48 50 55 */ // uint8_t data[5]={0}; for(uint8_t i = 0; i < 5; i++) { uint8_t sensor_byte = 0; for(uint8_t j = 1; j <= 8; j++) // get 8 bits from sensor { timeout = 55; while(SENSOR_is_low) {_delay_us(1); if (!timeout--) {return 1;}} // signal "0", "1" low time _delay_us(30); sensor_byte <<= 1; // add new lower byte if (SENSOR_is_hi) // if sda high after 30us => bit=1 else bit=0 { sensor_byte |= 1; timeout = 45; // 30us - 75us = 45us while(SENSOR_is_hi) {_delay_us(1); if (!timeout--) {return 1;}} } } data[i] = sensor_byte; } uint8_t sum = data[0] + data[1] + data[2] + data[3]; if(data[4] != sum) return DHT_ERROR; temp = data[2] & 0x7F; temp = (temp << 8)+data[3]; if (data[2] & 0x80) { // temp *= -1; *sign = 0; } else { *sign = 1; } *temperature = temp; temp = (data[0] << 8)+data[1]; *humidity = temp; return DHT_SUCCESS; }
Сообщение отредактировал Dust112 - Nov 26 2014, 02:11
|
|
|
|
|
Nov 26 2014, 10:35
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 12-04-14
Пользователь №: 81 348

|
Я находил сотни реализаций для Arduino, но у меня не arduino и код в codevisionavr. В связи с этим и есть проблемы. Я реализовал как смог, но не получается по этому и прошу помоши.
|
|
|
|
|
Nov 26 2014, 19:44
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 12-04-14
Пользователь №: 81 348

|
Цитата(kovigor @ Nov 26 2014, 14:41)  Повторю два надоедливых совета: 1. Подтяните линию данных датчика к его линии питания (резистором на 4.7КОм). 2. Откройте даташит на датчик (выше я дал на него ссылку), изучите его и напишите свою реализацию. Там работы на день, от силы. Вы на общение на форуме гораздо больше времени потратите ... 1. Подтянул, просто в схеме не отразил 2. Я написал своюй реализацию, но датчик так и молчит, не отзываясь на запрос передачи... CODE int data[5], counter = 0, sum = 0, i = 0; int D_1=123, D_2=456; void DHT_Read_Data(){ // Очистить массив контролльных сумм data[0] = data[1] = data[2] = data[3] = data[4] = 0; DDRD.7 = 0; // делаем вывод мк выходом // Подготока шины для передачи PORTD.7 = 1; delay_ms(250); // Инициализаруем передачу PORTD.7 = 0; // прижимаем к земле не менее чем на 18 мс delay_ms(25); PORTD.7 = 1; // поднимаем и ждём реакции датчика delay_ms(40); DDRD.7 = 1; // делаем выход мк входом delay_ms(60); // начинаем саму передачу if (PIND.7 ==1) { // если на выходе всё так же 1, значит датчик не ответил и мы выодим из процедуры return; } // если всё ок, идём дальше и ждём пока датчик не подымет до 1 и не начнет передачу
while( PIND.7 == 1) { delay_ms(30); // ждём появления нуля на шине первый раз while (counter <= 40) // принимаем 40 бит данных { while( PIND.7 == 0) { // запускаем по битовый приём if( PIND.7 == 1) { data[i] <<= 0; } delay_ms(40); // если 1 держится более 28 мкс, то передаётся 1 if (PIND.7 == 1) { data[i] <<= 1; } } // подсчёт значения для числа CRC if (counter < 8) i = 0; else if (counter <16) i = 1; else if (counter < 24) i = 2; else if (counter < 32) i = 3; else i = 4; counter++; // увеличиваем счётчик на один delay_ms(30); // ждём появления нуля на шине } } // проверяем всё sum = data[0] + data[1] + data[2] + data[3]; if( sum != data[4]){ data[0] = 999; } D_1 = data[0]; D_2 = data[2]; }
Сообщение отредактировал IgorKossak - Nov 26 2014, 20:06
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|