Интересный глюк DHT11
- Войдите на сайт для отправки комментариев
Хочу попробовать организовать работу DHT11 и TM1637 на AtTiny13. Вот решил написать свой код ждя датчика DHT11, и обнаружил интересный глюк. Последний сороковой бит с датчика приходит примерно на 60 мкс длиннее, чем все предыдущие)) То есть если приходит логический ноль, то вместо 48 мой счетчик успевает досчитать до 143. А если приходит логическая единица, то вместо 143 счетчик успевает сосчитать до 243. Ничем не смог это объяснить, кроме как кривым датчиком DHT11. Забавно, что если использовать стандартную библиотеку для этого датчика, то , даже если датчик кривой, то будет создаваться видимость нормальной работы. Но Ардуина будет отправлять на дисплей данные с датчика, только когда сумма температуры и влажности будет нечетной. Проверьте, пожалуйста, у вас приходят с датчика значения влажности и температуры, когда их сумма должна быть четной? Пришлось программно скорректировать данный глюк:
//#define F_CPU 16000000UL #include <util/delay.h> #define PIN_DHT 3 unsigned int time_bit[40]; uint8_t data_dht[5]; uint8_t bit_dht; uint8_t word_dht = 0x00; //#include <avr/io.h> void setup(){ Serial.begin(9600); } void start_tmr_ms() { TCNT2 = 0x00; TCCR2B = 0x05; //9,375 ��� } void start_tmr_us() { TCNT2 = 0x00; TCCR2B = 0x02; //1,2 ��� } void start_dht() { DDRB |= (1 << PIN_DHT); PORTB |= (1 << PIN_DHT); start_tmr_ms(); while(TCNT2 < 2){} PORTB &= ~(1 << PIN_DHT); _delay_ms(18); DDRB &= ~(1 << PIN_DHT); PORTB |= (1 << PIN_DHT); while(PINB & (1 << PIN_DHT)){} while(~PINB & (1 << PIN_DHT)){} while(PINB & (1 << PIN_DHT)){} } void get_data() { for(bit_dht = 1; bit_dht < 41; bit_dht++) { while(~PINB & (1 << PIN_DHT)){} start_tmr_us(); while(PINB & (1 << PIN_DHT)){} /*Здесь пришлось скорректировать аппаратный (или программный) глюк датчика DHT11. *Почему-то последний сороковой бит (младший бит контрольной суммы) длится примерно на 60 мкс дольше, чем все остальные. *Тоесть если приходит логический ноль, то вместо 48 счетчик успевает досчитать до 143. А если приходит логическая единица, *то вместо 143 счетчик успевает сосчитать до 243. Очень странный глюк. В принципе, если использовать стандартную библиотеку для датчика, *то всё должно работать, несмотря на эту неисправность, но Ардуина будет отправлять на дисплей данные с датчика, только когда сумма *температуры и влажности будет нечетной. */ if(bit_dht == 40){ time_bit[bit_dht] = TCNT2 - 100;//Вычитаем 100, если это последний 40 бит }else{ time_bit[bit_dht] = TCNT2; } } } void decoder_bit(){ uint8_t bit_number = 0; uint8_t word_number = 1; for(bit_dht = 1; bit_dht < 41; bit_dht++){ //дербаним наш массив из 40 бит (5 байтов), в котором записана длительность каждого полученного бита if(time_bit[bit_dht] > 0x75) //Если длительность бита больше 28 мкс, { word_dht = word_dht << 1; //сдвигаем байт влево и записываем в младший разряд 1 word_dht |= (1 << 0); }else { word_dht = word_dht << 1; //Если меньше 28 мкс, сдвигаем влево байт и записываем 0 word_dht &= ~(1 << 0); } if(bit_number == 7){ //Если имеем дело с восьмым битом, записываем полученный байт в массив data_dht[word_number] = word_dht; word_number += 1; bit_number = -1; //Тут пздц математический парадокс, смотри теорию струн } bit_number +=1; } } void loop(){ int8_t i; start_dht(); get_data(); for(i = 1; i < 41; i++) { Serial.println(time_bit[i]); //Вывести список полученных битов (интервалы времени) } Serial.println(); decoder_bit(); for(i = 1; i < 6; i++) { Serial.println(data_dht[i]); //Вывести список полученных пяти байтов } _delay_ms(5000); }
Товарищи, прошу помощи. Колдунство какое-то. Если убираю цикл (строчки 101-104):
Начинает периодически выводить неправильную контрольную сумму. Например, 57 вместо 56:
Какой либо закономерности не заметил, просто сюда скопировался чередующийся результат. Как такое вообще возможно? Этот цикл просто выводит на печать содержимое массива, никак его не изменяя. Если этот цикл не удалять, то ошибок нет.
Пробовал оставлять пустой цикл без Serial.println - ошибки остаются. Тоесть функция Serial.println каким то волшебным образом влияет на массив.
Массивы в С нумеруются в отличие от Фортрана не с 1, а с 0.
Соответственно, первый элемент массива имеет номер 0, а последний - 39. В цикле Вы выходите за границу массива - отсюда и проблемы.
Массивы в С нумеруются в отличие от Фортрана не с 1, а с 0.
Соответственно, первый элемент массива имеет номер 0, а последний - 39. В цикле Вы выходите за границу массива - отсюда и проблемы.
Спасибо огромное! Четко и лаконично)) Сделал:
Всё заработало отлично. Ушла проблема как с длительностью 40 бита, так и с Serial.println))) Страшно представить, что там на уровне ассемблера происходит.