Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DS18B20 + ATMEGA8
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
isx
Здравствуйте! Помогмте пожалуйста с датчиком температуры. Что то не так с этой хернёй у меня...
Вот сделал проект в CVAVR и протеусе. Как видите, там единственная строка, и та работает с ошибкой. В протеусе выставляю температуру 20
градусов, и делаю проверку (если температура не равна 20, то PORTB.4 = 1)
С какого то чёрта значение температуры в один момент резко сглюкивает (раньше был у меня дисплей в проекте, он показывал в этот момент
хрень какую-то, а потом сразу значение температуры восстанавливалось). Убрал из кода всё пока искал в чём косяк. Косяк в строчке где присваивается значение переменной temper (больше там и ничего не осталось ) Кварц сделал 4МГц, как в хелпе на библиотеку - не помогло. Посмотрите пожалуйста свойства проекта и правильность использования библиотеки, ато я впервые с датчиком работаю этим, и уже часов 6 не могу причину найти.... Светодиод загорится не сразу. Нужно время от 1 до 5мин. Процесс ускоряется, если к любой ноге порта В подключить светодиод, катодом к
пину.

Файл проекта. Залить не могу на форум, та как с телефона сижу, поэтому ссылка(
radiokot.ru/forum/download/file.php?id=169462
domowoj
Цитата(isx @ Dec 14 2013, 15:43) *
Помогмте пожалуйста с датчиком температуры. Что то не так с этой хернёй у меня...

Если у вас с языками программирования так же как и с русским(не русским матерным),
то не мудрено.
Abell
Почитайте книгу хорошую, что-то типа "Микроконтроллеры AVR: от простого к сложному", "Микроконтроллеры AVR семейств Tiny и Mega фирмы Atmel", а для начала неплохо бы "Электроника - шаг за шагом" sm.gif
А так - "Учиться, учиться и учиться" (с) В.И.Ленин
isx
За слово плохое прошу прощения. Торопился когда писал и не заметил.
А по существу предложения есть?
kovigor
Цитата(isx @ Dec 14 2013, 13:37) *
А по существу предложения есть?

Есть. Протеус - в сторону. Похоже на то, что от датчика приходит битый пакет с неправильным CRC, а ваша программа к этой ситуации не готова.
В CodeVision есть библиотека, которая поддерживает этот датчик. С ней все делается за один вечер ...
domowoj
И проверьте времянки.
kovigor
Цитата(domowoj @ Dec 14 2013, 14:27) *
И проверьте времянки.

И прерывания надо бы запрещать на время обращения к датчику ...
isx
Дык у меня какмраз родная библиотека и используется(выше я давал ссылку на архив с проектом cvavr и протеуса).
А что-за времянки?
kovigor
Цитата(isx @ Dec 14 2013, 14:32) *
Дык у меня какмраз родная библиотека и используется ...
А что-за времянки?

Тогда временные диаграммы должны быть корректными, если вы впаяли кварц, на который рассчитан проект, и фьюзами не задали никаких делителей.
Остается одно - запрещать прерывания, как я только что писал.
И еще, подтяните линию данных датчика к питанию резистором на 4.7К. Питание, надеюсь, не паразитное ?
isx
Кварца нет впаянного. Используется внутренний на 4 МГц (фьюзами выставлен разумеется). Питание не паразитное. Резистор имеется, без него датчик бы вообще не опазнался.
И о каких прерываниях идёт речь? Стандартная библиотека чтоли их использует?
mempfis_
Цитата(isx @ Dec 14 2013, 17:36) *
Кварца нет впаянного. Используется внутренний на 4 МГц (фьюзами выставлен разумеется).


Откалибруйте тогда тактовый генератор, если Вы это ещё не сделали. По старту программы в OSCCAL заносятся калибровочные константы для выбранной частоты RC-цепочки.
kovigor
Цитата(mempfis_ @ Dec 14 2013, 16:54) *
Откалибруйте тогда тактовый генератор, если Вы это ещё не сделали.

И приготовьтесь к тому, что его частота крепко плывет с изменением температуры, посему сбои почти наверняка будут повторяться. Впаяйте кварц и не мучайтесь.


Цитата(isx @ Dec 14 2013, 16:36) *
И о каких прерываниях идёт речь?

Если ваша программа не использует прерываний, то дело не в них. Вот если бы использовала, например, от таймера, тогда было бы сложнее ...
isx
Дык протеус на это не отреагировал бы....
mempfis_
Цитата(isx @ Dec 14 2013, 19:34) *
Дык протеус на это не отреагировал бы....


Знать бы что происходит в процедурах w1_init(), ds18b20_init( 0, -50, 60, DS18B20_10BIT_RES ) и ds18b20_temperature( 0 );
Например для того, чтобы прочитать температуру, предварительно нужно подать команду CONVERT_TEMP и выждать время конвертирования, и только потом можно читать.
Касательно AVR - на нём очень легко самостоятельно реализовать поддержку 1-wire.
Посмотрите как это реализовано в одной из моих программ. В ней правда нет чтения температуры, но зато есть всё, чтобы самостоятельно ввести его.

CODE
#ifndef _1wire_h
#define _1wire_h

#define BUF_SIZE 16
#define MASK (BUF_SIZE-1)

// Message "Error CRC" == -77.7
#define ERROR_CRC -(77<<4)// 0xFB25//175
//Location 1 Wire Net in PORTE B pin 0.
#define OW_PIN PINB
#define OW_DDR DDRB
#define OW_PORT PORTB

#define OW_DQ_1 PINB0


// 1 Wire Commands
#define WRITE_ROM 0x4e
#define COPY_ROM_TO_EE 0x48
#define SKIP_ROM 0xCC
#define MATCH_ROM 0x55
#define CONVERT_T 0x44
#define READ_SCRATCHPAD 0xBE
#define WRITE_SCRATCHPAD 0x4E


//--------------------------------------------
//таблица уонстант для записи в термодатчик
__flash unsigned char sens_val[5][3] =
{
{0, 172, 127},
{1, 157, 127},
{2, 206, 127},
{3, 255, 127},
{4, 104, 127}
};
//--------------------------------------------

#endif //_1wire_h


CODE
//--------------------------------------------
//Вычисляет CRC8
unsigned char OW_ComputeCRC8(unsigned char inData, unsigned char seed)
{
unsigned char bitsLeft;
unsigned char temp;

for (bitsLeft = 8; bitsLeft > 0; bitsLeft--)
{
temp = ((seed ^ inData) & 0x01);
if (temp == 0)
{
seed >>= 1;
}
else
{
seed ^= 0x18;
seed >>= 1;
seed |= 0x80;
}
inData >>= 1;
}
return seed;
}
//--------------------------------------------

//--------------------------------------------
//Сброс шины 1-wire: 2 таймслота 480мкс - мастер тянет шину вниз (RESET PULSE)
//480 мкс - датчик тянет шину вниз (присутствие на шине)
unsigned char OW_reset(void)
{
unsigned char answer;
//формируем RESET PULSE
OW_PORT &= ~(1<<OW_DQ_1); //set PORT in 0
OW_DDR |= (1<<OW_DQ_1); //set DDR in 1
//удерживаем 480 мкс
delay_us(240);
delay_us(240);

//переводим линию DQ на вход с подтяжкой
OW_PORT |= (1<<OW_DQ_1); //set PORT in 1
OW_DDR &=~(1<<OW_DQ_1); //set DDR in 0
//установление pull-up + установление состояния шины термодатчиком
delay_us(100);

//считываем состояние линии DQ
answer = (OW_PIN & (1<<OW_DQ_1));

// выжидаем время необходимое для завершения операции
delay_us(190);
delay_us(190);
return (answer&(1<<OW_DQ_1)); //0-есть устройства, 1-нет устройств

}
//--------------------------------------------

//--------------------------------------------
//Запись бита
void OW_write_bit(unsigned char bit)
{
//формируем 0 (START OF SLOT)
OW_PORT &= ~(1<<OW_DQ_1); //set PORT in 0
OW_DDR |= (1<<OW_DQ_1); //set DDR in 1
delay_us(10);

//устанавливаем состояние выхода
if(bit)
{
//формируем 1
OW_PORT |= (1<<OW_DQ_1); //set PORT in 0
}
else
{
//формируем 0
OW_PORT &= ~(1<<OW_DQ_1); //set PORT in 1
}

//время захвата данных термодатчиком
delay_us(45);

//переводим линию DQ на вход с подтяжкой
OW_PORT |= (1<<OW_DQ_1); //set PORT in 1
OW_DDR &=~(1<<OW_DQ_1); //set DDR in 0

}
//--------------------------------------------


//--------------------------------------------
//Чтение бита
unsigned char OW_read_bit()
{

unsigned char result;

//формируем 0 (START OF SLOT)
OW_PORT &= ~(1<<OW_DQ_1); //set PORT in 0
OW_DDR |= (1<<OW_DQ_1); //set DDR in 1
//задержка на
delay_us(2);

//переводим линию DQ на вход с подтяжкой
OW_PORT |= (1<<OW_DQ_1); //set PORT in 1
OW_DDR &=~(1<<OW_DQ_1); //set DDR in 0
//ожидаем установление данных
delay_us(10);

//захват данных с шины
result = (OW_PIN & (1<<OW_DQ_1));



//время ожидания завершения операции
delay_us(45);
return(result);


}
//--------------------------------------------

//Запись байта
void OW_write_byte(unsigned char command)
{
for (unsigned char i = 0; i < 8; i++)
{
OW_write_bit(command & 0x01); //send one bit
command >>= 1; //shift to next bit
}
//__delay_cycles(0.00012*F_CLK);
//delay_us(120);
}
//--------------------------------------------

//--------------------------------------------
//Чтение байта
unsigned char OW_read_byte()
{
unsigned char i;
unsigned char value = 0;
/*~~~~~~~~~~~~~~~~~~~~~~*/

for(i = 0; i < 8; i++)
{
if(OW_read_bit()) value |= 0x01 << i;/* читаем один бит и записываем его в разряд i */

/* ожидаем окончания временного интервала */
//__delay_cycles(F_CLK*0.00012);
//delay_us(120);

}

return(value);

}
//--------------------------------------------



//--------------------------------------------
//Чтение Scratchpad
unsigned char ReadScratchpad(unsigned char* scratchpad)
{
unsigned char crc = 0;

// initiate array to 0
for (unsigned char a1 = 0; a1 < 9; a1++) scratchpad[a1] = 0;


OW_reset();
OW_write_byte(SKIP_ROM); // skip ROM
OW_write_byte(READ_SCRATCHPAD); // read scratchpad 0xBE

//Recive data in 1 Wire
for (unsigned char c1 = 0; c1 < 9; c1++)
{
scratchpad[c1] = OW_read_byte();
}

//Check CRC8 to 1 Wire data
for(unsigned char i = 0; i < 8; i++)
{
crc = OW_ComputeCRC8(scratchpad[i], crc);
}

if (crc == scratchpad[8])
{
return 1;
}
else
{
return 0;
}

}
//--------------------------------------------

//--------------------------------------------
//запись данных в сенсор
unsigned char writeTsens(unsigned char index)
{

//запись данных в сенсор
OW_reset();
OW_write_byte(SKIP_ROM); // skip ROM
OW_write_byte(WRITE_SCRATCHPAD); // write scratchpad 0xBE
OW_write_byte(sens_val[index][0]); // нижний триггер
OW_write_byte(sens_val[index][1]); // верхний триггер
OW_write_byte(sens_val[index][2]); // разрешение 9 бит

OW_reset();
OW_write_byte(SKIP_ROM); // skip ROM
OW_write_byte(COPY_ROM_TO_EE);


//верификация записи
unsigned char buff[9];

if(ReadScratchpad(buff) != 0)
{
//данные считаны корректно

//проверям реальные данные
if(buff[2] != sens_val[index][0]) return 0; //ошибка соответствия
if(buff[3] != sens_val[index][1]) return 0; //ошибка соответствия
if(buff[4] != sens_val[index][2]) return 0; //ошибка соответствия

return 1; //полное совпадение данныех
}

return 0;
}
//--------------------------------------------


Кстати temper в вашей программе float. Я не знаю в каком виде возвращает температуру ds18b20_temperature, но от самого датчика она приходит как знаковое число, в котором 4 младших бита определяют доли градуса, а все остальные биты - градусы.
isx
Сегодня гонял собранную в железе схему. За 2 часа глюков не было. Теперь вот только решить проблему с миганием индикатора.
Как я понимаю, пока выполняется преобразование МК висит в delay все 350мс., отсюда и мигание. Можно ли переделать задержку с delay на программный таймер?
По поводу кода. Спасибо конечно, но я вообще там не понимаю что происходит sad.gif
По поводу float. Если оставить int, то дробная часть отсекается... Библиотека походу формирует готовое число с дробной частью.
kovigor
Цитата(isx @ Dec 15 2013, 15:48) *
Теперь вот только решить проблему с миганием индикатора.

Тут два варианта: или забыть о библиотеке, поставляемой с CodeVision для этого датчика, и писать свою реализацию, которую можно прерывать, или воздействовать на ассемблерный файл, который генерирует СodeVision. Т.е., открываем этот файл и вручную вписываем в него "cli" и "sei", запрещая прерывания на время чтения и записи бита по 1-wire и выполнения функции "_w1_init" (откройте асм - файл и найдите там эти места). А потом этот файл компилируем. Я так делал, работает отлично ...
isx
Решил подредактировать родную библиотеку.
Нашел блок чтения температуры, убрал обращение к нему, и поставил этот код в свою программу:
CODE
if (ontemp == 0) {

ontemp = 1;
if (ds18b20_read_spd(0)==0) {temper = -9999; goto endoff;}
if (ds18b20_select(0)==0) {temper = -9999; goto endoff;}
w1_write(0x44);
} else {


ontemp = 0;
if (ds18b20_read_spd(0)==0) {temper = -9999; goto endoff;}
w1_init();
temper = (*((int *) &__ds18b20_scratch_pad.temp_lsb) & ((int) bit_mask[resolution]))*0.0625;


Код выполняется раз в пол секунды (программный таймер так настроил). Датчик в системе один, иначе ругается на не найденную переменную addr. Я хотел её глобально объявить, но не смог найти, кто знает где она, скажите, вдруг понадобится несколько датчиков подключить.
В протеусе вроде работает, протестирую на железе отпишу...
Инициализация и прочие функции делаются через стандартную библиотеку...
kovigor
Цитата(isx @ Dec 15 2013, 21:42) *
Решил подредактировать родную библиотеку.

Что бы вы ни делали, прерывания не должны возникать во время чтения/записи битов по 1-wire. Иначе будут сбои
Еще вариант - воздействуя на ассемблерный файл, засинхронизировать чтение/запись битов с прерываниями, чтобы последние не возникали в "неподходящие" моменты. В моем случае это было возможно ...
isx
Ды нет у меня прерываний никаких... Я это сделал, чтобы индикатор не мигал, пока получаем инфу с датчика...
kovigor
Цитата(isx @ Dec 15 2013, 22:03) *
Ды нет у меня прерываний никаких... Я это сделал, чтобы индикатор не мигал, пока получаем инфу с датчика...

Индикация динамическая ? По прерыванию от таймера ? Или она у вас в фоновом процессе реализована ?
isx
динамическая, в фоновом режиме..
isx
Всё пучком sm.gif Код работает.... Только выкинул строчку w1_init();
Не знаю, зачем каждый раз инициализацию проводить там было...
_basile
Цитата(isx @ Dec 16 2013, 00:26) *
Всё пучком Код работает.... Только выкинул строчку w1_init();
Не знаю, зачем каждый раз инициализацию проводить там было...

Наверное, чтобы обнаруживать "подключаемые на ходу" датчики.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.