Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Atmega16 +dht11
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Stiner
Всем привет!
Я только начинаю свой путь. Пишу в Codevisionavr 3.12. В сети кое как нашёл пример по работе с dht11, но он на прерываниях. Вся система из-за этого висит т.к. постоянно генерирует прерывание датчик. Прошу тыкнуть меня что мне нужно исправить.
Большое спасибо
kovigor
Цитата(Stiner @ Nov 24 2014, 21:15) *
Прошу тыкнуть меня что мне нужно исправить.

В вашем исходнике ни одного обработчика прерываний ... нет ! О каких прерываниях вы говорите ?
Если вы хотите работать по прерываниям с I2C на AVR, то сразу скажу, что это не так просто. У Атмела есть апп.ноуты на эту тему, поищите. О сложности я предупредил. Если нет острой необходимости в работе по прерываниям, то я бы вам посоветовал реализовать I2C чисто программно, а не использовать встроенный в АВР аппаратный модуль.

Да, подтяните линию данных датчика к его линии питания (резистором на 4.7КОм) ...
Xenia
Цитата(kovigor @ Nov 25 2014, 03:09) *
Если вы хотите работать по прерываниям с I2C на AVR, то сразу скажу, что это не так просто. У Атмела есть апп.ноуты на эту тему, поищите. О сложности я предупредил. Если нет острой необходимости в работе по прерываниям, то я бы вам посоветовал реализовать I2C чисто программно, а не использовать встроенный в АВР аппаратный модуль.


Насколько я поняла ситуацию, у датчика DHT11 интерфейс не I2C, а 1-Wire. Разница велика - у 1-Wire клока нет вообще.

P.S. Своими бы руками задушила тех, кто экономит провода за счет зверского усложнения протокола, делая его совсем уж заумным и ненадежным. sm.gif
kovigor
Цитата(Xenia @ Nov 25 2014, 03:54) *
Насколько я поняла ситуацию, у датчика DHT11 интерфейс не I2C, а 1-Wire.
P.S. Своими бы руками задушила тех, кто экономит провода за счет зверского усложнения протокола, делая его совсем уж заумным и ненадежным. sm.gif

Я тоже через какое-то время сообразил, что там не I2C (провод-то один), но уже не хотел редактировать сообщение.
Два слова о реализации 1-Wire в Codevision. Огромный недостаток - библиотечные функции, поставляемые с CV, нельзя прерывать, иначе собьется обмен. Для себя я эту проблему решил, написав свою реализацию 1-Wire для обмена с DS1820 ...
Stiner
Там даже не 1-wire,а какой-то свой протокол в котором я не могу пока разобраться.
kovigor
Цитата(Stiner @ Nov 25 2014, 19:31) *
Там даже не 1-wire,а какой-то свой протокол в котором я не могу пока разобраться.

Вот описание. Вроде, все более-менее понятно и вполне можно написать свою реализацию:
http://www.micro4you.com/files/sensor/DHT11.pdf
Dust112
Stiner, поищите в инете библиотеки для Arduino по подключению к ней этого датчика. Некоторые снабжены хорошими комментариями.
Xenia
Цитата(Dust112 @ Nov 25 2014, 21:30) *
Stiner, поищите в инете библиотеки для Arduino по подключению к ней этого датчика. Некоторые снабжены хорошими комментариями.


Так есть оно. Хотя бы это:
Подключение датчика температуры и влажности DHT11 к Arduino
Но что толку, если там все заточено под ардуинов "BIOS"? Т.е. это уже не программа, а скетч для Ардуины. Соответственно этому, он не в прошивку зашивается, а загружается через UART или USB. Да и собой представляет не код, а вызовы каких-то стандартных для Ардуино функций.
kovigor
Цитата(Xenia @ Nov 25 2014, 23:46) *
Но что толку, если там все заточено под ардуинов "BIOS"? Т.е. это уже не программа, а скетч для Ардуины.

И учебная ценность такого решения близка к нулю. Вместо изучения протокола и его реализации предлагается использовать некие "черные ящики". Иногда, конечно, такой подход может быть оправдан, но не в таком же простейшем случае ...
Xenia
Цитата(kovigor @ Nov 25 2014, 23:16) *
И учебная ценность такого решения близка к нулю. Вместо изучения протокола и его реализации предлагается использовать некие "черные ящики". Иногда, конечно, такой подход может быть оправдан, но не в таком же простейшем случае ...


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

Не люблю "черных ящиков" там, где они не оправданы. В данном случае задача обмена из разряда простейших и может быть решена без всяких высокоуровневых средств. Это даст понимание деталей того, как именно происходит обмен, повысит качество итогового продукта и упростит его сопровождение. А С++ и объекты в такой задаче - это как экскаватор в детской песочнице ...
Dust112
Вод код позаимствованный именно из библиотеки для 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;
}
Stiner
Я находил сотни реализаций для Arduino, но у меня не arduino и код в codevisionavr. В связи с этим и есть проблемы. Я реализовал как смог, но не получается по этому и прошу помоши.
kovigor
Цитата(Stiner @ Nov 26 2014, 14:35) *
... но у меня не arduino и код в codevisionavr. В связи с этим и есть проблемы. Я реализовал как смог, но не получается по этому и прошу помоши.

Повторю два надоедливых совета:
1. Подтяните линию данных датчика к его линии питания (резистором на 4.7КОм).
2. Откройте даташит на датчик (выше я дал на него ссылку), изучите его и напишите свою реализацию. Там работы на день, от силы. Вы на общение на форуме гораздо больше времени потратите ...
Stiner
Цитата(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];
}
kovigor
Цитата(Stiner @ Nov 26 2014, 22:44) *
1. Подтянул, просто в схеме не отразил
2. Я написал своюй реализацию, но датчик так и молчит, не отзываясь на запрос передачи...

У вас МК от чего тактируется ? Вы уверены, что не от внутренней RC - цепочки, а от кварца ? Я - нет. Fuse - биты запрограммированы, как надо, или оставлены по умолчанию ?
Просто этот протокол весьма чувствителен к длительностям полей и битовых интервалов. А если у вас частота в N раз ниже требуемой (и ожидаемой вами), то и результат, который вы привели, вполне закономерен ...
Stiner
Цитата(kovigor @ Nov 27 2014, 00:02) *
У вас МК от чего тактируется ? Вы уверены, что не от внутренней RC - цепочки, а от кварца ? Я - нет. Fuse - биты запрограммированы, как надо, или оставлены по умолчанию ?
Просто этот протокол весьма чувствителен к длительностям полей и битовых интервалов. А если у вас частота в N раз ниже требуемой (и ожидаемой вами), то и результат, который вы привели, вполне закономерен ...

Fuse -биты я не трогал т.к. код написал для протеуса и там не знаю как их зашить. Я поставил на самом мк только частоту 8 мгц и работу от внешнего источника — Нажмите для просмотра прикрепленного файла
kovigor
Цитата(Stiner @ Nov 27 2014, 10:38) *
Fuse -биты я не трогал т.к. код написал для протеуса и там не знаю как их зашить. Я поставил на самом мк только частоту 8 мгц

А на самом деле, там в 8 раз меньшая частота:

Цитата
The device is shipped with CKSEL = ”0001” and SUT = ”10”. The default clock source
setting is therefore the 1 MHz Internal RC Oscillator with longest startup time. This
default setting ensures that all users can make their desired clock source setting using
an In-System or Parallel Programmer.

Поэтому у вас ничего и не работает.
Протеус - как бы это помягче сказать .... уберите подальше. Читайте даташит, разбирайтесь с Fuse - битами и устанавливайте их (программатором, конечно же), как вам нужно. Например, я PonyProg'ом пользуюсь. Многим больше нравится AvReal. Но это не столь важно. До тех пор, пока вы в этом не разберетесь, ничего у вас как положено не заработает ...
Timmy
Цитата(Stiner @ Nov 26 2014, 22:44) *
1. Подтянул, просто в схеме не отразил
2. Я написал своюй реализацию, но датчик так и молчит, не отзываясь на запрос передачи...

У вас для задержек используется функция delay_ms(), которая, согласно названию и одному из комментариев, задерживает на миллисекунды. Однако в других местах она же использется для задержки на микросекунды. Нет ли здесь ошибки?
Stiner
Исправил везде мс и мкс. Сейчас датчик стал отзываться, но передает ахинею, я пока тестирую только температуру (влажность всегда =0).
У меня нет доступа пока к реальнйо плате по этому и моделирую в proteus'e.
Fuse биты выставил как я понял из датиша следующим образом: CKSEL = 1111, SUT =01.
CODE

int D_1=123, D_2=456, D_3=789, D_4=012, D_5= 045;

void DHT_Read_Data(){
int data[50];
int counter = 0, sum = 0, i = 0;
// Очистить массив контролльных сумм
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
DDRD.7 = 1; // делаем вывод мк выходом
// Подготока шины для передачи
PORTD.7 = 1;
delay_ms(250);
// Инициализаруем передачу
PORTD.7 = 0; // прижимаем к земле не менее чем на 18 мс
delay_ms(20);
PORTD.7 = 1; // поднимаем и ждём реакции датчика
delay_us(35);

DDRD.7 = 0; // делаем выход мк входом
delay_us(80);

// если всё ок, идём дальше и ждём пока датчик не подымет до 1 и не начнет передачу
while( PIND.7 == 1)
{
delay_us(30); // ждём появления нуля на шине первый раз
while (counter <= 40) // принимаем 40 бит данных
{
while( PIND.7 == 0)
{
// запускаем по битовый приём
if( PIND.7 == 1)
{
data[counter] = 0;
}
delay_us(40); // если 1 держится более 28 мкс, то передаётся 1
if (PIND.7 == 1)
{
data[counter] = 1;
}
//delay_us(20); // ждём появления нуля на шине
counter++; // увеличиваем счётчик на один
}
}
}
// проверяем всё

/* sum = data[0] + data[1] + data[2] + data[3];
if( sum != data[4]){
data[0] = 999;
} */
D_1 = data[0];
D_1 = D_1 <<1;
D_1 = D_1 | data[1];
D_1 = D_1 <<1;
D_1 = D_1 | data[2];
D_1 = D_1 <<1;
D_1 = D_1 | data[3];
D_1 = D_1 <<1;
D_1 = D_1 | data[4];
D_1 = D_1 <<1;
D_1 = D_1 | data[5];
D_1 = D_1 <<1;
D_1 = D_1 | data[6];
D_1 = D_1 <<1;
D_1 = D_1 | data[7];


D_3 = data[16];
D_3 = D_3 <<1;
D_3 = D_3 | data[17];
D_3 = D_3 <<1;
D_3 = D_3 | data[18];
D_3 = D_3 <<1;
D_3 = D_3 | data[19];
D_3 = D_3 <<1;
D_3 = D_3 | data[20];
D_3 = D_3 <<1;
D_3 = D_3 | data[21];
D_3 = D_3 <<1;
D_3 = D_3 | data[22];
D_3 = D_3 <<1;
D_3 = D_3 | data[23];


D_2 = data[10];
sprintf(lcd_buffer,"d0=%i d3=%i \n%i%i%i%i%i%i%i%i",D_1, D_3, data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
lcd_clear();
lcd_puts(lcd_buffer);
delay_ms(100);
}

kovigor
Цитата(Stiner @ Nov 27 2014, 20:07) *
Сейчас датчик стал отзываться, но передает ахинею

Старшие биты с младшими не перепутаны ?
Stiner
Цитата(kovigor @ Nov 27 2014, 22:35) *
Старшие биты с младшими не перепутаны ?

нет, он считывает не все такты как я понимаю или стартует не с 1 такта...
kovigor
Цитата(Stiner @ Nov 28 2014, 12:09) *
нет, он считывает не все такты как я понимаю или стартует не с 1 такта...

Тогда перечитайте еще раз описание протокола и пройдитесь с целью проверки по своему исходнику. А вообще, такие вещи идеально отлаживать "в железе" (при наличии осциллографа, конечно же) ...
Stiner
На реальном железе теже проблемы, осцилографа нет.
ffs2001
Вот же готовая библиотека на нормальном Си. Там STM, но с адаптацией проблем быть не должно.
Ещё, для "общего развития". Там библиотека для DHT-22, они с 11 похожи. Там где-то есть маленький косяк, если нужно будет, пишите в ЛС, найду и укажу.
kovigor
Цитата(Stiner @ Dec 3 2014, 21:11) *
На реальном железе теже проблемы, осцилографа нет.

Тогда соберите хотя бы тот же Unilogic. Если описываемый вами проект - разовая поделка, должно хватить и Unilogic'а. А если нет, то настоятельно рекомендую купить-таки осциллограф, ибо без него более-менее серьезно заниматься электроникой практически невозможно ...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.