DS18B20 - определение присутствия датчика на шине

chkiko
Offline
Зарегистрирован: 25.06.2015

Здравствуйте форумчане!

есть простой скетч

#include <OneWire.h>
OneWire ds(10);
 
void setup() {
Serial.begin(9600); 

}
 
void loop() {
 
byte data[2];
ds.reset(); 
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read(); 
data[1] = ds.read();
int Temp = (data[1]<< 8)+data[0];
Temp = Temp>>4;
Serial.println(Temp);
}

в нем идет опрос датчика и вывод показаний измереной ним температуры.

при отключении датчика от контроллера выводится температура равная -1 градус цельсия

подскажите пожалуйста как изменить скетч чтобы при отсутствии датчика контроллер выводил не ложное показание температуры а сообщение о отсутствии связи с датчиком.

Спасибо.

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

Если(температура == -1) выведи_сообщение("Датчик не подключен")

Это если не нужно измерять отрицательные.

А иначе, надо лезть чуть в недра OneWire.

chkiko
Offline
Зарегистрирован: 25.06.2015

необходимый диапазон измерения от -20 до +50

поэтому данный метод определения неподходит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

По идее вот такая программа должна напечатать количество реально подключённых датчиков.

#include <OneWire.h>
OneWire ds(10);

typedef uint8_t SensorAddress[8];


bool validAddress(uint8_t* sAddress) {
	return (ds.crc8(sAddress, 7) == sAddress[7]);
}

int8_t sensorAmount(void) {
	SensorAddress sAddress;
	ds.reset_search();
	int8_t sensors = 0; 
	while (ds.search(sAddress)) {
		if (validAddress(sAddress)) sensors++;
	}
	return sensors;	
}


void setup() {
	Serial.begin(115200);
	Serial.print("Total devices found: ");
	Serial.print(sensorAmount());
}

void loop() {}

Правда, проверить её в работе сейчас не могу. Проверьте сами и если я где-нибудь облажался, завтра дожмём.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

Читайте не два байта как Вы это делаете, а скречпад целиком. В нём есть контрольная сумма. Неисправный или отсутствующий датчик никогда не дадут правильной контрольной суммы.

Как проверять контрольную сумму есть в примере выше в функции validAddress.

chkiko
Offline
Зарегистрирован: 25.06.2015

Было бы не плохо отслеживать потерю связи при чтении данных, но я не настолько продвинутый юзер, чтобы справиться с этим самостоятельно. В примере выше строки с 4-й по 18-ю для меня - темный лес. Хорошо бы коментарии к этим строкам. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А, так это не Ваш код.

А мой счётчик-то заработал? А то я сам не проверял. Скажите.

А почему Вы не пользуетесь библиотекой DallasTemperature? Там всё это уже есть и контроль ошибок в том числе.

Единственный минус этой библиотеки - она очень ресурсоёмкая по памяти. Но если в Вашем проекте она в память влазит, так пользуйтесь на здороовье и не парьтесь.

А если не влазит, то я могу подсказать как уменьшить её аппетит на 1000-1200 байтов.

Если же с памятью критично и никак - у меня есть очень короткий по памяти код, но там есть ограничение - только один датчик.

Всё же попрбуйте DallasTemperature - если влезет, то ничего лучше и не надо.

Logik
Offline
Зарегистрирован: 05.08.2014

Если известно что изначально был только один датчик, то проварить подключен он или нет можна и без crc. Если нет  presence pulse в ответ на ресет шины - нет и девайса. В принципе ни одного на шине. Перед этим полезно проверить находится ли отпущеный канал в 1, чтоб закоротку не словить. Обычный алгоритм начала работы с шиной у меня такой: проверка отпущеного канала что он в 1, ели ОК то делаем ресет, если в ответ на него  есть presence pulse, начинаем поиск устройств ( в приведеном коде  это ds.search(..)) далее опрос найденых устройств снова с контролем presence pulse и в конце только проверка crc ответа. Вообще по одному crc  нельзя будет отличить отвалилось устройство или просто помеху поймали. При одном устройстве на шине presence pulse надежно показывает есть ли устройство или отвалилось, надежней crc. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

Вообще по одному crc  нельзя будет отличить отвалилось устройство или просто помеху поймали. 

Это верно. Но по логике вопрос не столько в том, отвалилось ли устройство, сколько в том, можно ли доверять полученному результату. А тут crc самое то и ничем его не заменишь.

Logik
Offline
Зарегистрирован: 05.08.2014

Это по вашей логике. И тема называется

определение присутствия датчика 

и вопрос

"как изменить скетч чтобы при отсутствии датчика контроллер выводил не ложное показание температуры а сообщение о отсутствии связи с датчиком."

И ошибка crc не дает возможности вывести такое сообщение, т.к может быть вызвана просто помехой. Но если датчик всего один, то решение есть через presence pulse.

А отсутствие  возможности проверить presence pulse (как впрочем и вобще диагнозировать отсутствие) - ну очередной булыжник (два булыжника) в сторону стандартной либы.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

А отсутствие  возможности проверить presence pulse (как впрочем и вобще диагнозировать отсутствие) - ну очередной булыжник (два булыжника) в сторону стандартной либы.

Не знаю, кто такая стандартная либа, но библиотека DallasTemperature позволяет проверить факт наличия или отсутствия датчика.

Logik
Offline
Зарегистрирован: 05.08.2014

ЕвгенийП пишет:

Не знаю, кто такая стандартная либа, но библиотека DallasTemperature позволяет проверить факт наличия или отсутствия датчика.

Низнайка какой...

 А то что в DallasTemperature блокировка на 750мс тоже видно не знаете? так читайте http://arduino.ru/forum/programmirovanie/ryvki-servoprivoda-v-svyazke-s-temperaturnymi-datchikami и в куче подобных тем. В них все обычно заканчивается так

"В Dallas библиотеке задержка в 750мС от которой просто так вы не уйдете. Делайте на OneWire, код"

Так что выбор либы ТС верный, в отличии от вашего совета.

 Зачем такое советовать??? Проблема же решаема в пару строк...

Вот код, проверяющий наличие датчика по presence pulse

  pinMode(ONE_WIRE_PIN, OUTPUT);
  digitalWrite(ONE_WIRE_PIN, LOW);
  delayMicroseconds(300);
  pinMode(ONE_WIRE_PIN, INPUT);
  delayMicroseconds(40);
  if(digitalRead(ONE_WIRE_PIN))
    Serial.println("нет");
  else
    Serial.println("есть!");

Код проверен, датчик обнаруживает, величины задержек может потребоватся корректировать. Там кстати не полный диапазон задержек приведенных в даташите работает.  Этот код исполнять в то время, когда датчик не опрашивается. Перед кодом и после желательны небольшие, порядка 1мс паузы до работы с датчиком.

chkiko
Offline
Зарегистрирован: 25.06.2015

Спасибо за подсказки - буду экспериментировать....

toc
Offline
Зарегистрирован: 09.02.2013

ЕвгенийП пишет:
Неисправный или отсутствующий датчик никогда не дадут правильной контрольной суммы.

Менее категоричная оценка вероятности события: 1/256.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

 

 А то что в DallasTemperature блокировка на 750мс тоже видно не знаете? так читайте http://arduino.ru/forum/programmirovanie/ryvki-servoprivoda-v-svyazke-s-temperaturnymi-datchikami и в куче подобных тем. В них все обычно заканчивается так

"В Dallas библиотеке задержка в 750мС от которой просто так вы не уйдете. Делайте на OneWire, код"

Мало ли что напишут люди не знающие этой библиотеки? В библиотеке есть все средства для неблокирующего чтения температуры и она это отлично делает, просто надо на неё посмотреть внимательно. А если пользовать на уровне простейших примеров, ни хрена не зная, не понимая и не желая ни знать, ни понимать, то конечно "просто так не уйдёшь".

У этой библиотеки есть серьёзный минус - больно много памяти жрёт. И понятно почему - на кой-то хрен они температуру как флоат возвращают. Все остальные страшилки типа блокирующей задержки или невозможности проверить подключён ли датчик - просто от незнания библиотеки.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

toc пишет:
ЕвгенийП пишет:
Неисправный или отсутствующий датчик никогда не дадут правильной контрольной суммы.
Менее категоричная оценка вероятности события: 1/256.
Вот это верно! Тут не поспоришь. А насчёт блокирующих задержек и невозможности определить подключён ли датчик - пусть логик своей бабушке расскажет.

Datak
Offline
Зарегистрирован: 09.10.2014

ЕвгенийП пишет:
toc пишет:
ЕвгенийП пишет:
Неисправный или отсутствующий датчик никогда не дадут правильной контрольной суммы.
Менее категоричная оценка вероятности события: 1/256.
Вот это верно! Тут не поспоришь. .....

А я бы поспорил. Во всяком случае, насчёт отсутствующего датчика.

При отсутствующем датчике с шины будет достаточно уверенно читаться единица. Другие значения погут появиться, теоретически, только из-за каких-то помех.

Значит, вероятность_ошибочно_определить_наличие_датчика = ( вероятность_помехи * 1/256 ).

По-моему примерно так, если не ошибся. :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Datak пишет:

Значит, вероятность_ошибочно_определить_наличие_датчика = ( вероятность_помехи * 1/256 ).

По-моему примерно так, если не ошибся. :)

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

Logik
Offline
Зарегистрирован: 05.08.2014

Datak пишет:

ЕвгенийП пишет:
toc пишет:
ЕвгенийП пишет:
Неисправный или отсутствующий датчик никогда не дадут правильной контрольной суммы.
Менее категоричная оценка вероятности события: 1/256.
Вот это верно! Тут не поспоришь. .....

А я бы поспорил. Во всяком случае, насчёт отсутствующего датчика.

При отсутствующем датчике с шины будет достаточно уверенно читаться единица. Другие значения погут появиться, теоретически, только из-за каких-то помех.

Значит, вероятность_ошибочно_определить_наличие_датчика = ( вероятность_помехи * 1/256 ).

По-моему примерно так, если не ошибся. :)

Угу именно так, не ошибаетесь. Мало того, вероятность_ошибочно_определить_наличие_датчика получается равнв вероятности искажения сообщения необнаруженого по crc. А этой штукой пренебрегают, считая если сrc сошлось то все верно, но именно с точностью до этой вероятности. Вот и получается что при отсутствии датчика всегда, с точностью до пренебрежимого, будет одно и тоже значение crc. Но использовать этот факт как признак отсутствия тоже нельзя, т.к. такое же значение crc может оказатся и у вполне нормального сообщения. И вот тут уже с вероятностю 1/256 )))

Datak
Offline
Зарегистрирован: 09.10.2014

Logik пишет:
Но использовать этот факт как признак отсутствия тоже нельзя, т.к. такое же значение crc может оказатся и у вполне нормального сообщения. И вот тут уже с вероятностю 1/256

Да, тут уж и я не поспорю. Вероятность ошибочно определить отсутствующий датчик не равна вероятности ошибочно не определить присутствующий.

"Короче, они совсем зас..ли мне мозги" ©

:)

chkiko
Offline
Зарегистрирован: 25.06.2015

ЕвгенийП пишет:

А почему Вы не пользуетесь библиотекой DallasTemperature? Там всё это уже есть и контроль ошибок в том числе.

Послушал совет покопался в примерах скетчей к библиотеке и набросал скетч контроля присутствия датчика. Получилось вот так:

#include <OneWire.h>
#include <DallasTemperature.h>
OneWire temp1(2);
DallasTemperature sensors1(&temp1);
DeviceAddress insideThermometer;
void setup(){
pinMode(13, OUTPUT);
sensors1.begin();
}
void loop() {
if (!sensors1.getAddress(insideThermometer, 0)) {digitalWrite(13, HIGH);}
else {
digitalWrite(13, LOW);
}
}
 
теперь осталось адаптировать скетч под мою прогу.
 
ЕвгениюП спасибо за совет.
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, это не проверка, это определение адреса. В первый раз адрес, конечно, нужно получить, а потом проверять можно более простой функцией isConnected

Кстати, как делать неблокирующее чтение температуры, чтобы не было задержки в 750мс, разобрались? А то тут некоторые прогеры по незнанию считают, что это невозможно и Вас пугают. Разобрались или показать?

chkiko
Offline
Зарегистрирован: 25.06.2015

Вы знаете, для меня задержка пока не критична. Если вопрос станет остро я обязательно к Вам обращусь. Спасибо

Hibernator
Offline
Зарегистрирован: 18.10.2015

ЕвгенийП пишет:

Ну, это не проверка, это определение адреса. В первый раз адрес, конечно, нужно получить, а потом проверять можно более простой функцией isConnected

Кстати, как делать неблокирующее чтение температуры, чтобы не было задержки в 750мс, разобрались? А то тут некоторые прогеры по незнанию считают, что это невозможно и Вас пугают. Разобрались или показать?

Показать, благодарю!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну,во-первых, в самой бибилиотеке возможность неблокирующего вызова предусмотрена, просто там есть элементраная ошибка из-за которой ничернта не работает. Можно исправить ошибку и всё будет нормально. А можно ошибку просто обойти - не вызывать те функции, на которые она влияет. Вот в этом примере так и сделано. Запустите, посмотрите сколько времени занимает запрос температуры.

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

#include <OneWire.h>
#include <DallasTemperature.h>

#define SENSOR_PIN 6

OneWire oneWire(SENSOR_PIN);
DallasTemperature sensors(&oneWire);
DeviceAddress deviceAddress;


void setup(void) {
  Serial.begin(115200);
  Serial << "Non blocking Dallas Temperature Demo\n";
  sensors.begin();
  sensors.getAddress(deviceAddress, 0);
  sensors.setWaitForConversion(false);
}

void loop(void) {
	static bool didNotSendYet = true;
	static unsigned long start;
	if (didNotSendYet) {
		 start = millis();
		sensors.requestTemperaturesByAddress(deviceAddress); 
		didNotSendYet = false;
	} else if (sensors.isConversionAvailable(deviceAddress)) {
		const float temp = sensors.getTempC(deviceAddress);
		const unsigned long duration = millis() - start;
		Serial << "Temperature: " << temp << " (" << duration << " ms)\n"; 
		delay(2000);
		didNotSendYet = true;
	}
}

Весрия библиотеки с которой работает, а то народ жалуется, что с какими-то не компилируется.

https://drive.google.com/file/d/1KaWWTHU3KcSg2R8Hcx6CyIyO1a9iSOt5/view

toc
Offline
Зарегистрирован: 09.02.2013

у меня на даче работает такой алгоритм
1. в епроме есть место для хранения 10 адресов датчиков (вроде 7 байт*10=70 байт)
2. если на шине появляется новый датчик, его адрес добавляется в список
3. когда нужно измерить, посылаю команду каждому зарегистрированному датчику, в результате получаю список температур, разделённных символом ";", если один датчик не ответит в отчёте будет пустая температура.

Пример, скопировал из смс:
t-3.19;-3.81;-3.44;
три датчика на шине, все работают.

bwn
Offline
Зарегистрирован: 25.08.2014

ЕвгенийП пишет:

У этой библиотеки есть серьёзный минус - больно много памяти жрёт. И понятно почему - на кой-то хрен они температуру как флоат возвращают. Все остальные страшилки типа блокирующей задержки или невозможности проверить подключён ли датчик - просто от незнания библиотеки.

Так плюсов от нее не нашел в принципе, а минус начиная от лишних 2К и дальнейших извращений. OneWire делает все тоже самое, проще и быстрее. ИМХО.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

bwn пишет:

Так плюсов от нее не нашел в принципе, а минус начиная от лишних 2К и дальнейших извращений. OneWire делает все тоже самое, проще и быстрее. ИМХО.

Так оно ж понятно. Я в нормальных проектах на тиньках и OneWire не пользую, просто сам реализую протокол в несколько строк. Но наши начинающие коллеги реально нуждаются в готовой библиотеке, т.к. без неё боятся. Это тоже нормально.

bwn
Offline
Зарегистрирован: 25.08.2014

ЕвгенийП пишет:

bwn пишет:

Так плюсов от нее не нашел в принципе, а минус начиная от лишних 2К и дальнейших извращений. OneWire делает все тоже самое, проще и быстрее. ИМХО.

Так оно ж понятно. Я в нормальных проектах на тиньках и OneWire не пользую, просто сам реализую протокол в несколько строк. Но наши начинающие коллеги реально нуждаются в готовой библиотеке, т.к. без неё боятся. Это тоже нормально.

Так я на этом датчике первый затык и получил, как раз и пробовал на DT, сломал моск, прочитал Чернова и больше к DT на выстрел не подхожу.))))

Logik
Offline
Зарегистрирован: 05.08.2014

Ага. 1Wire откровенно хреновый протокол. Была бы нормальная альтернатива ds18b20 я  бы тоже не подходил. Особенно при близком расположении датчиков к контролеру, где без разницы что 2, что 4 провода кидать. Но увы, куда не плюнь - везде термометр нужен, а i2c не тот габарит и цена.

///Я в нормальных проектах на тиньках и OneWire не пользую, просто сам реализую протокол в несколько строк.

Не надо ля-ля. Этот протокол в несколько строк без либы не реализуем. Один набор интервалов для него уже гарантирует большие неприятности 1мкс, 15мкс, 60мкс, 120мкс, 0,4мс, 0,8мс и 750мс. Его правильная реализация, без делеев с поиском девайсов на шине, конфигурировании датчика и пр. занимает как аналогичные для i2c, spi и uart вместе взятые. Одно в нем радует, местами он синхронный, и его там можна тормознуть и вписать весь бардак в процесс для лупа.

Показуйте свои "несколько строк" ;)

bwn
Offline
Зарегистрирован: 25.08.2014

Logik пишет:

Ага. 1Wire откровенно хреновый протокол. Была бы нормальная альтернатива ds18b20 я  бы тоже не подходил. Особенно при близком расположении датчиков к контролеру, где без разницы что 2, что 4 провода кидать. Но увы, куда не плюнь - везде термометр нужен, а i2c не тот габарит и цена.

Ну я то имел в виду конкретно DallasTemperature либу. А чем 1Wire так уж плох?
Под I2C - SHT1* хороши, цена правда не радует.((((

Logik
Offline
Зарегистрирован: 05.08.2014

Про эту либу вобще гадость, даже разгавору нет. Про 1Ware вроде - см. после цитированого, но то понятно еще цветочки, ягодки когда выясняется что конкретный датчик на линии хочет немножко другое время, например при ответе. 

SHT1* хороши, но кроме цены (она просто неадекват) еще и проблема габаритов. В виде трубки из нержавейки диаметром 6мм я их не встречал.

bwn
Offline
Зарегистрирован: 25.08.2014

Если влагозащита не требуется, то вот (почти как DS18B20). В Китае конечно подешевле.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

Не надо ля-ля.

А чё такой дерзкий-то?

Logik пишет:

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

Оно мне нах не надо. Я его реализую в каждом проекте под конкретный датчик безо всякой универсальности. Так что ни поиска, ни паразитного питания, ни каких-то особых конфигураций. Ни хрена та нет.

Чё, правда хотите полюбоваться?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

куда не плюнь - везде термометр нужен

Я вот сам ни резу не юзал, но мне интересно, кто-нибудь пользуеь измерение температуры, имеющееся в самой атмеге 328? Она ж умеет и температуру мерять. Кто-нибудь пользует?

ssss
Offline
Зарегистрирован: 01.07.2016

ЕвгенийП пишет:

А чё такой дерзкий-то?

А чё ты такой тупой и из последних сил усираешься? Типа в школе три класса учился? )))))))))))

Задолбал уже своим задротным "неблокирующим", если по сути один хрен оно блокирующее. Чтобы было "неблокирующее" нужно чтобы что-то было вытесняющим, а в меге такого нет и в помине. Ну или через ЮАРТ, разве что.

Logik
Offline
Зарегистрирован: 05.08.2014

ЕвгенийП пишет:

Чё, правда хотите полюбоваться?

Конечно!. Код в студию. Иначе "просто сам реализую протокол в несколько строк" пустой треп выходит.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Logik пишет:

Показуйте свои "несколько строк" ;)

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

Логик! Что с Вами? 1-wire простейший протокол, а Вы всегда были поклонником ногодрыга.

Я всего часа два его для тиньки писал и отлаживал, там делать - вообще нечего. Нужно просто ВНИМАТЕЛЬНО читать даташит на 18B20 в часи схемы таймингов.

-------------------

тот код писался ради И2с, но и Даллас там тоже есть.

Logik
Offline
Зарегистрирован: 05.08.2014

wdrakula пишет:

Логик! Что с Вами? 1-wire простейший протокол, а Вы всегда были поклонником ногодрыга.

 

И остаюсь им.

Но я лютый не поклонник wdelay_us(500); А там на каждом шагу его много.  Да еще и внутри циклов.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Дык wdelay там же и определена. См.выше. Это просто цикл нопов.

Logik
Offline
Зарегистрирован: 05.08.2014

Ага. Блокирующий.  А про прерывания при формировании интервалов Вы вобще не вспоминрали. А что будет если оно будет? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

ЕвгенийП пишет:

Чё, правда хотите полюбоваться?

Конечно!. Код в студию. Иначе "просто сам реализую протокол в несколько строк" пустой треп выходит.

Я шо, был замечен в пустом трёпе? Обижаешь, начальник!

Вот, любуйтесь. Термостат для травления плат персульфатом. Второй год уж служит верой и правдой.

#ifndef	DS18B20_H
#define	DS18B20_H

class DS18B20 {
public:
	enum ERROR_CODE { FAILED = -500 };

	DS18B20(void);
	int ReadTemperature(void);
private:
	void writeByte(const byte b);
	void writeBit(uint8_t b);
	uint8_t readByte(void);
	uint8_t readBit(void);
	bool sendReset(void);
	static uint8_t crc(const uint8_t *, uint8_t);
};

extern DS18B20 ds;

#endif	//	DS18B20_H

.



#include "DS18B20.h"
#include <DigitalPins.h>

//template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

#define	DALLAS_SENSOR_PIN	3

// OneWire commands
#define SKIPROM			0xCCu
#define STARTCONV			0x44u
#define READSCRATCHPAD	0xBEu

DS18B20::DS18B20(void) {
	_pinMode(DALLAS_SENSOR_PIN, OUTPUT);
}

int DS18B20::ReadTemperature(void) {
	//Serial << "Entered\n";
	if (!sendReset()) return FAILED;
	//Serial << "Connection established\n";
	writeByte(SKIPROM);
	writeByte(STARTCONV);
	unsigned long startMillis = millis();
	while (!readBit()) { delay(1); if ((millis() - startMillis) > 1000) return FAILED; }
	delay(1);
	//Serial << "Temperature stored successfully\n";
	union {
		uint16_t int16;
		uint8_t scratchpad[9];
	} dsData;
	bool sucessFlag;
	sendReset();
	writeByte(SKIPROM);
	writeByte(READSCRATCHPAD);
	for (int i = 0; i<9; dsData.scratchpad[i++] = readByte());
	sucessFlag = crc(dsData.scratchpad, 8) == dsData.scratchpad[8];
	//Serial << "Read tmp: " << ((const int)(((unsigned long)dsData.int16 * 625 + 500) / 1000)) << '\n';
	//Serial << "ScratchPad read\n";
	return (sucessFlag) ? (const int)(((unsigned long)dsData.int16 * 625 + 500) / 1000) : FAILED;
}


void DS18B20::writeByte(const byte b) {
	for (uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) writeBit(bitMask & b);
	_pinMode(DALLAS_SENSOR_PIN, INPUT);
	_digitalWrite(DALLAS_SENSOR_PIN, LOW);
}

void DS18B20::writeBit(uint8_t b) {
	noInterrupts();
	_digitalWrite(DALLAS_SENSOR_PIN, LOW);
	_pinMode(DALLAS_SENSOR_PIN, OUTPUT);
	delayMicroseconds((b) ? 10 : 65);
	_digitalWrite(DALLAS_SENSOR_PIN, HIGH);
	interrupts();
	delayMicroseconds((b) ? 55 : 5);
}

uint8_t DS18B20::readByte(void) {
	uint8_t result = 0;
	for (uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) if (readBit()) result |= bitMask;
	return result;
}

uint8_t DS18B20::readBit(void) {
	uint8_t result;
	noInterrupts();
	_pinMode(DALLAS_SENSOR_PIN, OUTPUT);
	_digitalWrite(DALLAS_SENSOR_PIN, LOW);
	delayMicroseconds(3);
	_pinMode(DALLAS_SENSOR_PIN, INPUT);
	delayMicroseconds(10);
	result = _digitalRead(DALLAS_SENSOR_PIN);
	interrupts();
	delayMicroseconds(53);
	return result;
}


bool DS18B20::sendReset(void) {
	_pinMode(DALLAS_SENSOR_PIN, INPUT);
	delayMicroseconds(10);
	_digitalWrite(DALLAS_SENSOR_PIN, LOW);
	_pinMode(DALLAS_SENSOR_PIN, OUTPUT);
	delayMicroseconds(480);
	noInterrupts();
	_pinMode(DALLAS_SENSOR_PIN, INPUT);
	delayMicroseconds(70);
	const bool r = !_digitalRead(DALLAS_SENSOR_PIN);
	interrupts();
	delayMicroseconds(410);
	return r;
}

//
// Dallas Semiconductor 8-бит	CRC
//
uint8_t DS18B20::crc(const uint8_t *addr, uint8_t len) {
	uint8_t crc = 0;
	while (len--) {
		uint8_t inbyte = *addr++;
		for (uint8_t i = 8; i; i--) {
			uint8_t mix = (crc ^ inbyte) & 0x01;
			crc >>= 1;
			if (mix) crc ^= 0x8C;
			inbyte >>= 1;
		}
	}
	return crc;
}

DS18B20 ds;

 

Logik
Offline
Зарегистрирован: 05.08.2014

Теперь смотрим время. За сколько вычитываются температура (т.е. 2 байта нужной инфы)  из указаного датчика по 1ware? Ну так под 10мс вроде. Поправте если не так. Как быть с прерываниями? И луп уже не такой быстрый.

 А по i2c недавно обговаривали - дето 30мкс на удобных 800КГц. Прерывания на нем вобще не мешают.

В общем какой протокол хороший, а какой не очень думаю ясно.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Logik пишет:

Ага. Блокирующий.  А про прерывания при формировании интервалов Вы вобще не вспоминрали. А что будет если оно будет? 

Логик! Вы "Бабу-Ягу" включили, которая всегда против? ;) Не обижайтесь.

1. Мне показалось, что Вы не заметили, что 500 - это микро секунды ;), то есть вообще не имеют значения. И такая задержка только в инициализации - это "ресет" протокола. Не "в цикле" ;).

2. Протокол устойчив к увеличению задержек, то есть на прерывания от таймера - насрать. Я же написал - читать даташит ВНИМАТЕЛЬНО!

3. Это обкатанный код, он вообще никогда не сбоил. У меня. Я открыт к инфлрмации о сбоях. ;). Каждому доказательно предъявившему сбой - от меня пиво.

----------------------

Вот сейчас Вы напомнили Архата, который своих ошибок не признает. Ошиблись - признайте, только больше уважение вызывать станете.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

В общем какой протокол хороший, а какой не очень думаю ясно.

Дык оно ж смотря для чего. Вот смотрите, в том термостате, о котором я говорил, он чего делает-то: читает температуру, включает/выключает/не трогает печку и ... ложится спать на полсекунды, а там снова читает ...

Ну так при таком применении есть хоть какая-то разница будет там протокол работать миллисекунды или микросекунды? Никакой ведь!

Т.е. как всегда - всё от задачи зависит.

По сравнению с I2C в этом протоколе на пин меньше и привязки к конкретным пинам нет - тоже ведь плюсы имеются.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

Вот, любуйтесь. Термостат для травления плат персульфатом. Второй год уж служит верой и правдой.

мой - проще  ;) Если желаете - можно его в объект обернуть.

Хотя, если к "вмещению" в тиньку не стремиться, то и так нормально.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

мой - проще  ;) 

Больше решений, хороших и разных!

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

Термостат для травления плат персульфатом. Второй год уж служит верой и правдой.

ОФФТОП.

Евгений! Хочу себе и не хочу велосипед изобретать.

Не могли бы Вы в соотв. ветке привести фото и описание? Я вот нагреватель никак выбрать не могу и не могу решить, делать ли ванну верикальной и прозрачной, как у многих в сети, или это излишнее украшательство.

Logik
Offline
Зарегистрирован: 05.08.2014

ЕвгенийП пишет:

Я шо, был замечен в пустом трёпе? Обижаешь, начальник!

Вот, любуйтесь. 

Так чем любоватся? Больше сотни строк, что очевидно никак  "реализую протокол в несколько строк". Это даже не несколько десятков как у i2c или spi. там реально так. 

И остальные проблемы, теже что и у wdrakula.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

А если не устраивает 1-wire то есть решение: берем LM335 за 30р  аналоговый, цепляем к тиньке 13 за 20р. + печатка + пара резисторов и конденсатор.

Соединение стандартное - питание и и2с., 4 провода. Можно специальной эпоксидкой все залить и получить водостойкость.

;) ;) ;) В тиньке хватит не только на поддержку И2с слейв, но и на плюшки останется, какие нить  пороги, прервания, термостаирование, вочдоги и энерго экономия.

Сам понимаешь, что по размеру примерно с фильтр от сигареты выйдет. если тиньку под SMD взять.

Logik
Offline
Зарегистрирован: 05.08.2014

wdrakula пишет:

Logik пишет:

Ага. Блокирующий.  А про прерывания при формировании интервалов Вы вобще не вспоминрали. А что будет если оно будет? 

Логик! Вы "Бабу-Ягу" включили, которая всегда против? ;) Не обижайтесь.

1. Мне показалось, что Вы не заметили, что 500 - это микро секунды ;), то есть вообще не имеют значения. И такая задержка только в инициализации - это "ресет" протокола. Не "в цикле" ;).

Заметил я все заметил, там воще 400 можна. А значение имеет итог: принять 2 байта порядка 10мсек блокирующего кода. Согласны?

wdrakula пишет:

2. Протокол устойчив к увеличению задержек, то есть на прерывания от таймера - насрать. Я же написал - читать даташит ВНИМАТЕЛЬНО!

Не буду я его читать. Я его за 4 варианта реализации чутьли не выучил :(

То что Вы показали - это у меня было давно. Два варианта назад, и где он "устойчив к увеличению задержек" - можна секономить, я об этом в сегодня выше писал, но к сожалению цитирую даташит стр.16 "60μs < TX “0” < 120μs" Так что ниче он не "устойчив к увеличению задержек". И чтение, сказано проверить линию в 15мкс ((

 

wdrakula пишет:

Это обкатанный код, он вообще никогда не сбоил. У меня. Я открыт к инфлрмации о сбоях. ;). Каждому доказательно предъявившему сбой - от меня пиво.

Заинтригован. 

А коньяк? ;)