d.styler ©:zcom ©:Параллельный опрос датчиков
В каком месте интересно? Датчики опрашиваются последовательно в коде. И да - опрашивать их паралельно не получится - читай 1-Wire протокол.
Рекомендую ознакомится. https://www.interfaceinnovations.org/on … ation.html
d.styler ©:Из коментариев - запрос на конверсию можно как раз параллельно всем послать - быстрее чем каждому по отдельности. Для этого - послать ресет, затем 0xСС (skip ROM), а затем 0x44. При этом конверсия будет произведена параллельно. При 2-х датчиках это не критично, а вот когда их 4-6 - тогда можно сэкономить.
Первое время делал именно так. Убил три часа времени - отладчика-то нет в Ардуине. Не работает. Датчики сигнал не воспринимают. Выдают непонятно что. Изучение импортных форумов (на наших все друг у друга перепечатывают или типовой пример правят) дало этот вариант решения. Это гарантировано работает, это раз, второе, для неиспользуемые датчики (enable = false) не напрягаются, третье, если есть еще устройства на OneWire, то они не получают "случайную" команду. А устройства я планирую добавлять.
d.styler ©:Конверсия в датчике занимает какое-то время - то есть можно конечно выставить 1мс между посылкой конверсии и чтением - но что мы читаем при этом?
Здесь ценность в том, что можно не ждать ответа от датчиков, а параллельно обрабатывать сигналы клавиатуры, управлять шаговыми двигателями, мощностью тэна и т.п. При использовании delay(1000), как во всех примерах, это невозможно. Здесь - легко. Даже на UNO.
Читаем после того, как датчики готовы. Кстати, здесь тоже подводный камень... Как оказалось. 
Сейчас, как раз, правлю код.
Иван ©:Я конечно спец аховый, но это вроде стандартный пример.. надо только либу подгрузить.
Это написано, практически, "с нуля" по спецификациям.
В пример поглядывал, но он реально однозадачный. А задача была - управление многими устройствами. Не только "умный градусник".
Иван ©:zcom ©:Куда данные выводить?
Вот это вопрос меня в тупик ставит... да куда нравится, хоть в SQL писать... это зависит от поставленной самому себе задачи.
zcom ©:В принципе, программировать на Ардуине легко. Так что заказы по доработке принимаются
Легко... наверное, когда куча готовых примеров и можно их изменить. Давай для начала в SQL в реальном времени... сможешь? Или на худой конец в CSV .
Готовые примеры - это прекрасно, но они же уровня "обучалки". Очень плохо дружат между собой - проще новый код написать. В реальном вывод в SQL? Здесь вообще не проблема на стороне Arduino. Он-то в порт льет, успевай ловить. Проблема в софте на стороне компа. Там нужен "резидент", который в реальном времени снимает данные с порта и размещает их через ODBC в любой SQL-базе. С этим сложнее.
Проще в CSV выгружать по команде. Сделаю.
Kreg1969 ©:А может логичнее температурный лог на флэшку или SD карту скидывать? В простом текстовом формате, например, номер (расположение) датчика, время и температура через запятую и следующий замер с новой строки.
Да, думал об этом. С реальным временем сложно - нужен его источник. В Ардуине своих часов нет. Но можно использовать момент времени с начала запуска контроллера. Формат CSV. Его легко импортировать хоть в Excell, хоть в СУБД.
Вот новый вариант скетча. Код стал более читаем, избавился от проблем, связанных с использованием "паразитного питания" (по 2-м проводам, вместо трех). Теперь скетч будет корректно работать и с такой формой подключения. Код функций setup() и loop() существенно упростился. Теперь легко можно добавлять код для управления другими устройствами.
В начале кода есть идентификаторы.
TS_PERIOD - период опроса датчиков. В начале периода идет команда на конвертацию значений (подготовка показаний для считывания), по завершению периода - считывание и размещение куда укажем.
RESOLUTION - разрядность определения температуры. Чем точнее, тем дольше (для 12 бит надо 750мс).
SENSORS - количество датчиков на линии. У меня пока подключено два, планирую шесть.
#include <OneWire.h>
#define PIN_CONNECT 10 // on pin 10 (a 4.7K resistor is necessary)
#define SERIAL_BAUD 115200 //
#define TS_PERIOD 1000 //
#define RESOLUTION 12 // 9, 10, 11, 12 bit
#define SENSORS 2 //
struct tsdata {
byte addr[8];
byte answer[9];
float tempC;
float tempF;
boolean enable = false;
boolean readable = false;
};
tsdata ts[SENSORS];
unsigned long count = 0;
OneWire ds(PIN_CONNECT);
void print_hex(byte data[], byte l = 8, boolean ns = true) {
byte i;
for( i=0; i<l; i++) {
if (data[i] < 16)
Serial.print("0");
Serial.print(data[i], HEX);
if (i != (l-1))
Serial.print(".");
}
if (ns)
Serial.println();
}
void ts_inin(void) {
byte i=0, j;
ds.reset_search();
while (ds.search(ts[i].addr)) {
if (ds.crc8(ts[i].addr, 7) == ts[i].addr[7]) {
if ((ts[i].addr[0] == 0x10) || (ts[i].addr[0] == 0x22) || (ts[i].addr[0] == 0x28)) {
ts[i].enable = true;
i++;
if (i > SENSORS)
break;
}
}
}
Serial.print("All sensor = ");
Serial.println(i);
for (i=0; i<SENSORS; i++) {
if (ts[i].enable) {
Serial.print("Device ");
Serial.print(i);
Serial.print(" = ");
print_hex(ts[i].addr, 8, true);
ds.reset();
ds.select(ts[i].addr);
ds.write(0x4E);
ds.write(0);
ds.write(0);
switch (RESOLUTION) {
case 9:
ds.write(0x1F);
case 10:
ds.write(0x3F);
case 11:
ds.write(0x5F);
default:
ds.write(0x7F);
}
ds.write(0x48);
}
}
}
void ts_conv(void) {
byte i;
for (i=0; i<SENSORS; i++) {
if (ts[i].enable) {
ts[i].readable = false;
ds.reset();
ds.select(ts[i].addr);
ds.write(0x44);
}
}
}
void ts_read(void) {
byte i, j;
int16_t test;
for (i=0; i<SENSORS; i++) {
if (ts[i].enable) {
ds.reset();
ds.select(ts[i].addr);
ds.write(0xBE);
for (j=0; j<9; j++) {
ts[i].answer[j] = ds.read();
}
ts[i].readable = (ds.crc8(ts[i].answer, 8) == ts[i].answer[8]);
test = ts[i].answer[1] * 256 + ts[i].answer[0];
if (ts[i].addr[0] == 0x10) {
test = test << 3;
if (ts[i].answer[7] == 0x10) {
test = (test & 0xFFF0) + 12 - ts[i].answer[6];
}
}
else {
switch (ts[i].answer[4] & 0x60) {
case 0x00:
test = test & ~7;
case 0x20:
test = test & ~3;
case 0x40:
test = test & ~1;
}
}
ts[i].tempC = (float)test / 16.0;
ts[i].tempF = ts[i].tempC * 1.8 + 32.0;
}
}
}
void ts_output_serial(void) {
byte i;
for (i=0; i<SENSORS; i++) {
if (ts[i].enable) {
Serial.print(i+1);
Serial.print(": ");
Serial.print(ts[i].tempC);
Serial.print("C, ");
Serial.print(ts[i].tempF);
Serial.println("F");
}
}
}
void setup(void) {
Serial.begin(SERIAL_BAUD);
ts_inin();
ts_conv();
count = millis();
}
void loop(void) {
if ((millis() - count) >= TS_PERIOD) {
count = millis();
ts_read();
ts_output_serial();
ts_conv();
}
}
Проблема "паразитного питания" для датчиков не позволяет сделать вариант считывания данные датчиков "по готовности". Требуется держать линию в активном состоянии, что не позволяет ее также использовать для работы других устройств. Неудобства.