-=FISHER=-

DS18B20 выдает неадекватные показания при паразитном питании

79 сообщений в этой теме

-=FISHER=-    5

Здравствуйте!

 

В своей поделке применил датчик DS18B20, чтобы сэкономить провода, решил подключить его по двум проводам или при помощи так называемого паразитного питания. Однако, он всегда выдает мне температуру 27,5 С, и не изменяет показания при нагреве. Если же подключить его тремя проводами с отдельным питанием, то он сразу же начинает правильно измерять температуру. Опытные люди, будьте добры, подскажите в чём может быть проблема? Код и схема во вложении. Заранее спасибо!

Схема:

Скрытый текст

1.thumb.jpg.f6685d34d6fc443574e3bdc4ffe00442.jpg

Код для работы с DS18B20:

Скрытый текст

 


#include "DS18B20.h"

//функция определения датчика на шине
char dt_testdevice(void) //dt - digital termomether | определим, есть ли устройство на шине
{
	char stektemp=SREG;// сохраним значение стека
	cli(); //запрещаем прерывание
	char dt;
	DDRTEMP |= 1<<BITTEMP; //притягиваем шину
	_delay_us(485); //задержка как минимум на 480 микросекунд
	DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину
	_delay_us(65); //задержка как максимум на 60 микросекунд
	if ((PINTEMP & (1<<BITTEMP))==0)//проверяем, ответит ли устройство
	{
		dt=1;//устройство есть
	} 
	else dt=0;//устройства нет
	SREG = stektemp;// вернем значение стека
	_delay_us(420); //задержка как минимум на 480 микросекунд, но хватит и 420, тк это с учетом времени прошедших команд
	return dt; //вернем результат
}


//функция записи бита на устройство
void dt_sendbit(char bt)
{
	char stektemp=SREG;// сохраним значение стека
	cli(); //запрещаем прерывание
	DDRTEMP |= 1<<BITTEMP; //притягиваем шину
	_delay_us(2); //задержка как минимум на 2 микросекунды
	if(bt)
		DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину
	_delay_us(65); //задержка как минимум на 60 микросекунд
	DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину
	SREG = stektemp;// вернем значение стека
}
//функция записи байта на устройство
void dt_sendbyte(unsigned char bt)
{
	char i;		
	for(i=0;i<8;i++)//посылаем отдельно каждый бит на устройство
	{
		if((bt & (1<<i)) == 1<<i)//посылаем 1
			dt_sendbit(1);
		else //посылаем 0
			dt_sendbit(0);
	}	
}

//функция чтения бита с устройства
char dt_readbit(void)
{
	char stektemp=SREG;// сохраним значение стека
	cli(); //запрещаем прерывание
	char bt; //переменная хранения бита
	DDRTEMP |= 1<<BITTEMP; //притягиваем шину
	_delay_us(2); //задержка как минимум на 2 микросекунды
	DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину
	_delay_us(13);
	bt = (PINTEMP & (1<<BITTEMP))>>BITTEMP; //читаем бит
	_delay_us(45);
	SREG = stektemp;// вернем значение стека
	return bt; //вернем результат
}

//функция чтения байта с устройства
unsigned char dt_readbyte(void)
{
	char c=0;
	char i;
	for(i=0;i<8;i++)
		c|=dt_readbit()<<i; //читаем бит
	return c;
}

//функция преобразования показаний датчика в температуру
int dt_check(void)
{
	unsigned char bt;//переменная для считывания байта
	unsigned int tt=0;
	if(dt_testdevice()==1) //если устройство нашлось
	{
		dt_sendbyte(NOID); //пропустить идентификацию, тк у нас только одно устройство на шине
		dt_sendbyte(T_CONVERT); //измеряем температуру
		_delay_ms(750); //в 9 битном режиме преобразования - 750 милисекунд
		dt_testdevice(); //снова используем  те же манипуляции с шиной что и при проверке ее присутствия
		dt_sendbyte(NOID); //пропустить идентификацию, тк у нас только одно устройство на шине
		dt_sendbyte(READ_DATA); //даем команду на чтение данных с устройства
		bt = dt_readbyte(); //читаем младший бит
		tt = dt_readbyte(); //читаем старший бит MS
		tt = (tt<<8)|bt;//сдвигаем старший влево, младший пишем на его место, тем самым получаем общий результат
	}
	return tt;
}

//преобразование температуры в единицы
char converttemp (unsigned int tt)
{
	char t = tt>>3;//сдвиг и отсечение части старшего байта
	return t;
}

 

Изменено пользователем -=FISHER=-

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

А вы подаете на линию данных 5 вольт "без резистора" - чтобы паразитно его запитать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
27 минут назад, ARV сказал:

А вы подаете на линию данных 5 вольт "без резистора"?

С подтяжкой 4,7к... В даташите правда говорят что нужно ещё мосфет для увеличения тока в момент конвертации и чтения температуры, однако я встречал схемы и без мосфета, где со слов автора паразитное питание и так работает.

321.JPG.60699a60d1469b0a3c6ce08e73c2a8a1.JPG

Вывод - уменьшить номинал подтягивающего резистора?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

какая длина провода до датчика? Подключите датчик пока прямо на разъём.

и что-то странное у вас в коде с сохранением и восстановлением стека, можете получить большие проблемы используя такой код на Си. Похоже код переводили с asm на Си. Лучше сохранять только флаг прерывания (I).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

Darth_Vader    64

В чем смысл сохранять стек? Да и с запретом прерываний все странно.

Включение и выключение pull-up резистора - зачем?

Изменено пользователем Darth_Vader

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

Без принудительного соединения линии данных с 5в (отдельный MOSFET не нужен, у вас МК может выполнить эту функцию) работают только датчики с маркировкой DS18B20P или PAR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Обычные датчики DS18B20 должны работать с паразитным питанием, но там есть несколько условий, одно из них

стр.11

Convert T [44h]

If the device is being used in parasite power mode, within 10μs (max) after this command is issued the master must enable a strong pullup on the 1-Wire bus for the duration of the conversion (t CONV) as described in the Powering the DS18B20 section.

видимо надо подавать "честную" единичку на 10 мкс после команды конвертации [44h]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463
35 минут назад, technik-1017 сказал:

видимо надо подавать "честную" единичку на 10 мкс после команды конвертации [44h]

Только не на 10 мкс, а максимум 10 мкс спустя подачи команды, и держать её не менее длительности измерения.

Изменено пользователем ARV

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
13 часа назад, technik-1017 сказал:

какая длина провода до датчика? Подключите датчик пока прямо на разъём.

Испытываю поделку на столе, длинна провода не более 10 см.

12 часа назад, Darth_Vader сказал:

В чем смысл сохранять стек? Да и с запретом прерываний все странно.

Код работы с датчиком писал не я, взял с урока про программированию МК. С обычным подключением этот код хорошо отрабатывает...

 

11 час назад, technik-1017 сказал:

видимо надо подавать "честную" единичку на 10 мкс после команды конвертации [44h]

11 час назад, ARV сказал:

Только не на 10 мкс, а максимум 10 мкс спустя подачи команды, и держать её не менее длительности измерения.

То есть между вот этими строчками кода? А вы можете на пальцах объяснить пожалуйста, что значит подавать честную единичку?...

		dt_sendbyte(T_CONVERT); //измеряем температуру
		_delay_ms(750); //в 9 битном режиме преобразования - 750 милисекунд

Я так понимаю принудительно подать 1 на ножку, к которой подключен сигнальный контакт датчика, вот типа так?

DDRTEMP &= ~(1<<BITTEMP);

PINTEMP &= (1<<BITTEMP);

 

Изменено пользователем -=FISHER=-

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463
Только что, -=FISHER=- сказал:

А вы можете на пальцах объяснить пожалуйста, что значит подавать честную единичку?...

По стандарту 1-wire ведущее устройство либо притягивает линию данных к нулю, формируя в ней 0, либо "отпускает" её в третье состояние, т.е. как бы бросает неподключенной, и тогда линия за счет подтягивающего резистора сама возвращается к лог.1. Подавать честную единичку - это значит, вместо "отпускания" линии выдать в неё 1 принудительно. Т.е. соединить линию с +5 не через резистор, а напрямую через порт МК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
1 минуту назад, ARV сказал:

Т.е. соединить линию с +5 не через резистор, а напрямую через порт МК.

Отпустить и выдать на пин 1 так?:

DDRTEMP &= ~(1<<BITTEMP);

PINTEMP &= (1<<BITTEMP);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

DDRTEMP &= ~(1<<BITTEMP); устанавливает в соответствующем DDR-бите НОЛЬ, т.е. "отпускает" пин в третье состояние. А следующая команда у вас испортит регистр. А надо просто вывести 1 в оба регистра:

PINTEMP |= (1<<BITTEMP);
DDRTEMP |= (1<<BITTEMP);

А после замера вернуть, как было.

Причем именно в том порядке, как я написал: сначала вывести 1, т.е. включить внутреннюю подтяжку, а потом перевести порт на вывод "жесткой" единицы, иначе у вас кратковременно в линии пролетит 0 - мало ли, как датчик на него среагирует...

Изменено пользователем ARV
  • Лайк 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
4 минуты назад, ARV сказал:

 


DDRTEMP |= (1<<BITTEMP);

PINTEMP |= (1<<BITTEMP);

А после замера вернуть, как было.

Я правильно понял смысл, что необходимо отпустить шину и выставить на ней 1 и так продержать весь промежуток вот этой задержки? Как раз пока идёт заполнение регистров датчика?

_delay_ms(750); //в 9 битном режиме преобразования - 750 милисекунд

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

Правильно - датчик будет питаться от этой линии.

Обратите внимание: я подкорректировал свое сообщение - ваша цитата уже не соответствует истине!

  • Лайк 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
3 минуты назад, ARV сказал:

Правильно

Спасибо! Я сейчас пробежался по функциям и понял, что перед тем как "уйти в задержку" на 750мс, шина "отпущена", то есть достаточно дописать только вторую строчку перед задержкой и вот такую после, так?

PINTEMP |= (1<<BITTEMP); //выставляем 1 на шине, шина к этому моменту уже отпущена
_delay_ms(750); //в 9 битном режиме преобразования - 750 милисекунд
PINTEMP &= ~(1<<BITTEMP); //выставляем 0 на шине

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463
Только что, -=FISHER=- сказал:

то есть достаточно дописать только вторую строчку перед задержкой и вот такую после, так?

Не так. Шина отпущена - это значит, режим пина "ввод", а надо ВЫВОД.

  • Лайк 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
1 минуту назад, ARV сказал:

Не так.

Затупил(( спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5

@ARV Чтобы не создавать отдельную тему, не могли бы Вы глянуть схему, приведенную мной в первом посте. Всё вроде бы работает, но почему-то наблюдается писк дросселя... Дроссель вроде как рекомендуют включать для дополнительной точности опорного напряжения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

КАК может пищать дроссель, по которому не течет силовой пульсирующий ток?! 

5b6fd0cb62e048e48d26b04993b96622_2440a91

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
52 минуты назад, ARV сказал:

КАК может пищать дроссель?! 

Но если его убрать с платы, писк пропадает... Я кстати использую SMD дроссель.

И ещё плата потребляет 120-140 мА (мне кажется это многовато или нет?), да так что МС L78M05CDT ощутимо греется, хотя рассчитана на ток до 500мА.

Изменено пользователем -=FISHER=-

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
KomSoft    309

Какой ток через сегменты задает MAX? 7 сегментов по 15мА - это 105мА. (например). А (12-5)*0.12 - 0.8Вт, это много для работы без радиатора, будет ощутимо греться, что вы и получаете. Тут главное не ток, а рассеиваемая мощность. 

Судя по резистору R1 вы задали ток через сегменты 30-40мА. Увеличьте его - яркость упадет, но ток уменьшится. Если использован нормальный индикатор, то 40мА даже пикового тока - это много. Если яркость устраивает, то можно увеличивать его до 60кОм (примерно)

Screenshot_2018-08-08-10-21-01-653_com.google.android.apps.docs.png

  • Лайк 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

Если дроссель пищит, это однозначно свидетельствует о том, что через него течет пульсирующий ток. Это может быть только в одном случае: у вас по питанию гуляют страшные пульсации - больше взяться току через дроссель не из-за чего, потребление опорного источника AVR мизерное. Так же я могу предположить, что на С6 тоже пульсации будут - проконтролируйте осциллографом. Если там окажутся пульсации больше 2 мВ - это будет свидетельствовать о том, что толку от ADC будет не много. 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
-=FISHER=-    5
7 часов назад, ARV сказал:

В качестве теста отключите программно индикацию - пропадет писк?

Писка нет, если плата работает от программатора. Писк только если подключаю плату к 12В от ЛБП.

9 часов назад, ARV сказал:

Не так.

Сделал вот так, теперь показывает всегда 85 С...

		DDRTEMP |= 1<<BITTEMP; //притягиваем шину
		PINTEMP |= (1<<BITTEMP); //выставляем 1 на шине
		_delay_ms(750); //в 12 битном режиме преобразования - 750 милисекунд
		PINTEMP &= ~(1<<BITTEMP); //выставляем 0 на шине
		DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину

Что я сделал не так?

Изменено пользователем -=FISHER=-

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DDRTEMP &= ~ (1<<BITTEMP); // настраиваем порт на ввод. Подтяжка к "1" за счёт внешнего резистора
PINTEMP |= (1<<BITTEMP);   // включаем подтяжку к "1" внутри контроллера
DDRTEMP |= 1<<BITTEMP; 	   // настраиваем порт на вывод, появляется честная "1"
_delay_ms(750); //в 12 битном режиме преобразования - 750 милисекунд
DDRTEMP &= ~(1<<BITTEMP);  // настраиваем порт на ввод. Осталась подтяжка к "1" внутри контроллера
PINTEMP &= ~(1<<BITTEMP);  // отключаем подтяжку к "1" внутри контроллера. Осталась только подтяжка за счёт внешнего резистора

а PINTEMP это случайно не PINx?
Должно быть PORTTEMP, т.е. PORTx

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

По крайней мере, 85 - это показания датика "по умолчанию", т.е. после того, как подали на него питание, но не подали команду "старт преобразования". Иначе говоря, датчик не получил команду, но отвечает корректно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сообщения

    • Увы не позволяет. Октавный фильтр с включенной компенсацией будет давать соответствующий подъём, а не горизонтальную линию. 
    • то просто проседает с 12 до 9 вольт
    • Андрюх, ты читать умеешь? Ее Админ закрыл, а не я. несколько раз порывался с ним это обсудить. Я тоже там никаких особо грешных грехов не нашел. Мож напишем совместное письмо? Народ, подключайтесь!
    • Точка совпадения фаз в пас фильтре может находится в стороне . И никто не не знает толком где она , ведь никто не проверяет . В активном фильтре совпадение полное во всей полосе совместной работы головок . И главное , прозрачность звучания на высоте . Можно услышать в фонограмме много нового на заднем плане .
    • Плохо, что по факту невозможно определить очередность (если она есть) выгорания элементов. Сгорание диода преобразователя вообще в ступор вводит - ведь накопительный конденсатор играет роль развязки между двумя, работающими в импульсном режиме, частями схемы. Мысль про то, что виноват какой-то поплывший, но работающий элемент в схеме правильная - те что сгорали как раз могут быть не при чем, их уже меняли. А не хочешь попробовать поездить по схеме с постоянно включенным на время искры верхним транзистором или, как вариант, с включением его только на время искрения? Вдруг не заметишь разницы в работе двигателя. Время импульсов для нижнего придется конечно изменить, но это уже делалось и знакомо, как их настроить.
    • Для ремонта схем с 38хх редко применяю осцил, обхожусь тестером. А вот посмотреть форму сигнала выходных ключей это да, нужен иной. DCO 150 развязанный от сети и ему ничего не случится, если он достоверно показывает форму сигнала то пойдет, а технику безопасности в любом случае нужно соблюдать. Я пользую старенький С1-112А. Но для ремонта сварочников этого мало, нужны ЗНАНИЯ и другие приспособления.