AtTiny13 + DHT11 + TM1637. Странное поведение.

  • Автор темы Kompas
  • Дата начала
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
Написал код для работы AtTiny13, DHT11, TM1637. Всё удачно уместилось в памяти микрухи. На первый взгляд всё работает. Данные передаются без сбоев, контрольная сумма в норме. Вот видео  ссылка скрыта от гостей , если кому интересно. Но обнаружилась проблема. Периодически, примерно каждые 5-6 запросов данных от датчика DHT11, показания влажности и температуры скачут. На 5 - 10 единиц могут прыгнуть. При этом рассогласования с контрольной суммой нет. Поначалу списал всё на "несерьезность" датчика, но... Залил тот же самый код в Ардуино Уно - нет никаких скачков. Цепляю датчик и дисплей обратно к тиньке - пляшут данные. Подключаю питание непосредственно от этой ардуинки - не помогает, скачут показания. Припаиваю непосредственно к датчику конденсатор по питанию 100 нФ, как рекомендуется в даташите, - бесполезно. Меняю на тиньке частоты: 1.2, 4.8, 9,6 Мгц - никакого результата. Кстати, по ходу дела, заметил еще одну странность: на 9.6 Мгц тинька в этой связке запускается только от 3 вольт, от пяти - не хочет. На дисплей при этом нужно подавать 5 вольт. В общем, у меня закончились предположения, пришел за помощью к вам. В чем подвох может быть, ведь на ардуинке с тем же питанием показания стабильны?
Код:

Код:
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/wdt.h> 

unsigned char word_dht = 0x00;
unsigned char time_bit[40];
unsigned char data_dht[5];
unsigned char bit_dht;


#define Clkpin 3 //Clkpin TM1637
#define Datapin 2 // Datapin TM1637
#define PIN_DHT 0 //Пин датчика DHT

#define DispPort PORTB // обзываем порт

#define  BRIGHT_LCD 7  //Яркость дисплея от 0 до 7
		
		unsigned char _PointFlag; 	//_PointFlag=1:the clock point on
		unsigned char _DispType;
		unsigned char DecPoint;
		unsigned char BlankingFlag;
	
		
static unsigned char TubeTab[10] = {0x3f,0x06,0x5b,0x4f,// знакогенератор
                           0x66,0x6d,0x7d,0x07,
                           0x7f,0x6f};//,0x77,0x7c,
                           //0x39,0x5e,0x79,0x71,
                          // 0x40,0x00};//0~9,A,b,C,d,E,F,"-"," "  

void TM1637_writeByte(char wr_data)// служебная функция записи данных по протоколу I2C, с подтверждением (ACK)
{
  unsigned char i;
    for(i=0;i<8;i++)        
  {
   DispPort &= ~(1<<Clkpin);
    if(wr_data & 0x01)
	{ DispPort |= 1<<Datapin;}
    else {DispPort &= ~(1<<Datapin);}
	_delay_us(3);
    wr_data = wr_data>>1;      
    DispPort |= 1<<Clkpin;
	_delay_us(3);  
  }  
 
  DispPort &= ~(1<<Clkpin);
  _delay_us(5);
  DDRB &= ~(1<<Datapin);// если поменяете порт на какой-то другой кроме DispPort, то тут тоже все DDRB на другие DDRx менять надо будет
  while((PINB & (1<<Datapin))); 
  DDRB |= (1<<Datapin);
  DispPort |= 1<<Clkpin;
  _delay_us(2);
  DispPort &= ~(1<<Clkpin);  
}

void TM1637_start(void) // просто функция "старт" для протокола I2C
{
   DispPort |= 1<<Clkpin; 
   DispPort |= 1<<Datapin;
 _delay_us(2);
  DispPort &= ~(1<<Datapin); 
} 

void TM1637_stop(void) // просто функция "стоп" для протокола I2C
{
  DispPort &= ~(1<<Clkpin);
 _delay_us(2);
  DispPort &= ~(1<<Datapin);
_delay_us(2);
  DispPort |= 1<<Clkpin;;
_delay_us(2);
  DispPort |= 1<<Datapin;
}


void TM1637_init()// Инициализируем дисплей. Как оказалось, можно удалить из этого блока стандартной библиотеки практически всё, кроме инициализации пинов.
{
	DDRB |= (1<<Clkpin) | (1<<Datapin);
}

//---------------------------------------------------------------------
//Здесь код для датчика DHT11. Писал полностью сам.

void start_tmr_us()
{
TCNT0 = 0x00;
TCCR0B = 0x01; //Запускаем таймер0 с частотой 1,2 Мгц
}

void start_dht()                //Отправляем приветствие датчику
{
DDRB |= (1 << PIN_DHT);
DispPort |= (1 << PIN_DHT);
DispPort &= ~(1 << PIN_DHT);
_delay_ms(18);
DDRB &= ~(1 << PIN_DHT);
DispPort |= (1 << PIN_DHT);
while(PINB & (1 << PIN_DHT)){}
while(~PINB & (1 << PIN_DHT)){}
while(PINB & (1 << PIN_DHT)){}

}

void get_data()                            //Получаем 40 бит от датчика и записываем в массив
{
for(bit_dht = 0; bit_dht < 40; bit_dht++)
{
while(~PINB & (1 << PIN_DHT)){}
start_tmr_us();
while(PINB & (1 << PIN_DHT)){}
time_bit[bit_dht] = TCNT0;
}
}

void decoder_bit(){
unsigned char bit_number = 1;
unsigned char word_number = 0;
for(bit_dht = 0; bit_dht < 40; bit_dht++){  //дербаним наш массив из 40 бит (5 байтов), в котором записана длительность каждого полученного  бита

if(time_bit[bit_dht] > 50)                //Если длительность бита больше 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 == 8){                     //Если имеем дело с восьмым битом, записываем полученный байт в массив
data_dht[word_number] = word_dht;
word_number += 1;
bit_number = 0;       
}
bit_number +=1;
}
}



ISR (WDT_vect){
TM1637_writeByte(0x40);    //Выводим на дисплей Err1
TM1637_stop();
TM1637_start();
TM1637_writeByte(0xC0);
TM1637_writeByte(0x79);
TM1637_writeByte(0x50);
TM1637_writeByte(0x50);
TM1637_writeByte(0x06);
TM1637_stop();
TM1637_start();
TM1637_writeByte(0x8F);
TM1637_stop();
}




int main(void)
{
wdt_reset();            //Запускаем вотч дог
wdt_enable(WDTO_4S);
WDTCR |= (1 << WDTIE);
sei();
TM1637_init();
_delay_ms(1500);  //Зачем-то тупим немного. Иначе, вроде как, дисплей может не зажечься.
 
while(1)
{
start_dht();                         
get_data();
decoder_bit();
if((data_dht[0] + data_dht[1] + data_dht[2] + data_dht[3]) != data_dht[4])
{
	TM1637_writeByte(0x40);    //Выводим на дисплей Err0
	TM1637_stop();
	TM1637_start();
	TM1637_writeByte(0xC0);
	TM1637_writeByte(0x79);
	TM1637_writeByte(0x50);
	TM1637_writeByte(0x50);
	TM1637_writeByte(0x3f);
	TM1637_stop();
	TM1637_start();
	TM1637_writeByte(0x8F);
	TM1637_stop();
	_delay_ms(3500);
	wdt_reset();
	_delay_ms(3500);
	wdt_reset();	
}

TM1637_start();                     //Выводим на дисплей влажность.  
TM1637_writeByte(0x40);
TM1637_stop();
TM1637_start();
TM1637_writeByte(0xC0);
TM1637_writeByte(0x76);
TM1637_writeByte(0x00);
TM1637_writeByte(TubeTab[(data_dht[0] / 10) % 10]);
TM1637_writeByte(TubeTab[data_dht[0] % 10]);
TM1637_stop();
TM1637_start();
TM1637_writeByte(0x8F);
TM1637_stop();
_delay_ms(2000);
wdt_reset();

TM1637_start();                                    //Выводим на дисплей температуру
TM1637_writeByte(0x40);
TM1637_stop();
TM1637_start();
TM1637_writeByte(0xC0);
TM1637_writeByte(TubeTab[(data_dht[2] / 10) % 10]);
TM1637_writeByte(TubeTab[data_dht[2] % 10]);
TM1637_writeByte(0x63);
TM1637_writeByte(0x39);
TM1637_stop();
TM1637_start();
TM1637_writeByte(0x8F);
TM1637_stop(); 
_delay_ms(2000);
wdt_reset();
}
}
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
Пара вопросов:
1. Контрольная сумма чего имеется ввиду?
2. Как настроен и используется ли вач дог таймер?
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
1. Датчик передает информацию следующим образом. Пять байтов. Первые четыре data_dht[0 - 3] - значение влажности и температуры. Последний пятый data_dht[4] - это сумма первых четырех для контроля ошибок передачи. На видео она высвечивается после влажности и температуры. В показанном здесь коде немного другой алгоритм, просто идет проверка контрольной суммы. Высвечивается ошибка, если сумма не совпадает с данными.
2. Вотч дог настроен на прерывания по переполнению. Если обрыв связи с датчиком, контроллер зависает в цикле ожидания, срабатывает программа обработки прерывания. На дисплей выводится Ошибка. Сброс.
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
Т.е. получается, что WDT не может быть причиной этих сбоев?

Более того! Получается, что те данные, которые выводятся на индикатор, это именно те самые данные, которые получаются с датчика т.к. сами данные и чексумм совпадает! Ну тогда надо смотреть на датчик! А не может ли быть такой вот сценарий... У датчика не может быть определено время преобразования? Я немного экспериментировал с преобразователями (АЦП) у которых в даташите указывается время преобразования и если при этом устроить им опрос раньше времени, то на выходе получаем кашу...
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
Васисуалий сказал(а):
Т.е. получается, что WDT не может быть причиной этих сбоев?

Более того! Получается, что те данные, которые выводятся на индикатор, это именно те самые данные, которые получаются с датчика т.к. сами данные и чексумм совпадает! Ну тогда надо смотреть на датчик! А не может ли быть такой вот сценарий... У датчика не может быть определено время преобразования? Я немного экспериментировал с преобразователями (АЦП) у которых в даташите указывается время преобразования и если при этом устроить им опрос раньше времени, то на выходе получаем кашу...
Да, я тоже предполагаю, что проблема кроется где-то непосредственно на этапе обработки параметров тока на измерительном элементе микросхемой датчика. Так как с передачей данных всё нормально. Но каким образом и что именно влияет на этот процесс - моих знаний не хватает.
В даташите датчика говорится, что запрашивать данные у датчика нужно не ранее одной секунды после подачи питания. В программе установлено 1,5 секунды. Интервалы запросов пробовал увеличивать вплоть до 20 секунд - не помогает. Да и на ардуинке то нет проблем. Наверное, нужно искать аппаратные отличия на портах Atmega328P и AtTiny13V. Но разве они есть?
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
А чем тогда вообще отличается работа программы в "Дуньке" и в отдельном чипе "Тини"? Ведь по идее это практически одно и то же с точки зрения выполнения этой программы.? :upset:

Может стоит повергнуть эту алгебру осциллографом? :lol: Ну в смысле посмотреть, что происходит на линии передачи данных в одном и в другом случае? Да и по питанию глянуть... Ну вдруг? :pain25:
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
Отличие получается в частоте. Дунька на 16 МГц, Тинька проверялась максимум на 9,6 МГц. Ну и таймер считает на Дуньке с частотой 16/8 = 2 МГц. На тиньке 1,2 МГц. В остальном , вроде, все также. Имена битов в вотч доге только чуть отличаются. Осциллографа у меня нет. Если кто проверит - было бы хорошо)
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
А если запихать тиньке кварц на 16 мег? Выпаять из дуньки на время, например? Ведь проц заработает, я практически уверен. Оставлять его там, конечно, не стОит, но попробовать можно?
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
У меня есть такой кварц. Но, судя по даташиту, AtTiny13V максимум 10 МГц.


 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
Есть? Ставь! Не сгорит, максимум, что плохого получится - не запустится ну или на границе реального предела будет глючить, но я почему то думаю, что реальный предел у него гораздо выше. Проверить хватит...
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
Вьехал... Чет сразу не дошло... :lol: А ведь к тини13 не так то легко подключить внешний кварц?
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
Собрал вчера снова макетку с тинькой. До сих пор ниодного скачка))) В чем была проблема , видимо, останется тайной. До этого ведь несколько раз все пересобирал. Проверял и дома, и на работе. Что еще заметил. На ардуинке стоит пальцем прижать контакты датчика, начинает выскакивать ошибка Err0 (ошибка контрольной суммы). На тиньке, как не прикасался, передача стабильно идет.
P.S. Зато после прикасаний скачки начались :lol:
Резистор подтяжки, может, внутренний убрать из программы.
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
Осциллограф нужен категорически! :one: Иначе любая подобная задача превращается в гадание на кофейной гуще! :lol:
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
В общем, подключил датчик от другой линии питания. Стабильно поработал он у меня минут 15. Потом я нечаянно полярность перепутал и спалил микросхему датчика))) Ну... есть вероятность, что раздельное питание просто надо делать, чтобы не было проблем.
P.S. Если быть точнее, непосредственно с датчиком удар случился))
 ссылка скрыта от гостей 
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
Бывает! Обидно, но так случается... Придется купить еще один! :gigi:

А вот с отдельным питанием вопрос - а почему? Категорически надо исследовать это дело осциллографом! Я уверен, что все грабли всплывут! :stopud:
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
Васисуалий сказал(а):
Бывает! Обидно, но так случается... Придется купить еще один! :gigi:

А вот с отдельным питанием вопрос - а почему? Категорически надо исследовать это дело осциллографом! Я уверен, что все грабли всплывут! :stopud:
Ну мне тут академики подсказывают, что разводка цифровой и аналоговой части всегда сложным процессом было)
 
В

Васисуалий

Команда форума
Регист
11 Ноя 2005
Сообщения
4.060
На эту тему есть хорошая книжка -"Искусство схемотехники" (The art of electronics) , Авторы Пауль Оровиц и Уинфелд Хилл. Там в первом (если не ошибаюсь) томе есть на эту тему целый раздел :umnik: Книжка переведена на Русский и свободно находится в сети...

Вот >>  ссылка скрыта от гостей 
 
K

Kompas

Участник
Регист
25 Авг 2008
Сообщения
155
Спасибо!
 
D

dsp155

Участник
Регист
6 Мар 2012
Сообщения
1.369
Или попробуй другой проц что ли..
Например мега 8 ,32.
Ещё задам возможно глупый вопрос. Тайминги соблюдены?
Если rc генератор то возможны сбои .
 


Верх