Подключение нескольких DS18b20 на одну шину и на разные выводы
- Войдите на сайт для отправки комментариев
Втр, 15/09/2015 - 20:53
Всем доброго времени суток.
Выручайте, мужики. Весь мозг себе сломал.
Есть вроде бы простая задача подключить несколько датчиков DS18b20 на одну шину и на разные выводы, а конкретно 3 датчика подключить на пин 8 и по одному датчику на пины 5, 6, 7. Примеров в интернете море, НО
1)Многие примеры создатели "гавно-сайтов" просто копипастят не понимая смысла и потому код нерабочий.
Например, описывают подключение нескольких DS18b20 на шину, а в коде объявляют переменные только для одного датчика :
byte data[12];
byte addr[8];
2)Есть примеры, в которых ID (ROM) каждого DS18b20 надо определять отдельно и прописывать в коде. По-моему это как мерседес заводить ручкой ("кривым стартером")
3)Рабочие примеры для нескольких датчиков DS18b20 даны с использованием библиотеки DallasTemperature.h. Но в ней прописана задержка 750мсек, что для моего проекта не подходит.
Вот список страниц, на которых в какой-то степени есть решение моего вопроса:
http://playground.arduino.cc/Learning/OneWire Dallas Semiconductor's 1-Wire Protocol
http://research.andbas.com/2012/02/1-wire-ds18s20.html Измерение температуры или освоение 1-wire протокола на примере DS18S20
http://robocraft.ru/blog/187.html вопрос по DS18B20
http://habrahabr.ru/post/242377/ Читаем все датчики в автоматическом режиме
http://mk90.blogspot.com.by/2013/05/web.html Web-термометр
http://geektimes.ru/post/257256/ Zyxel Keenetic 4G, arduino и датчики температуры ds18b20
http://arduino.ru/forum/programmirovanie/3-datchika-ds18b20arduino 3 датчика DS18B20+Arduino
http://arduino.ru/forum/programmirovanie/pomogite-optimizirovat-kod-i-pa... Помогите оптимизировать код и пару вопросов по 1-Ware
Решения на приведенных страницах я не нашел.
Что хочу я?
1)Решить вопрос с использованием библиотеки OneWire.h средствами ардуино
2)Понимать используемый код, т.е. какие переменные используются и как они изменяются
3)Подключенные датчики DS18B20 автоматически определяются в SETUP, что бы в LOOP использовать без потери времени.
Вот часть моего кода в части DS18B20
01 | #include <OneWire.h>//для работы с DS18b20(датчик температуры) |
02 | //****************** Создаем объекты библиотечных классов ********************************** |
03 | //Если на 1-шине сидит один датчик, то его ID знать не требуется! |
04 | OneWire ds5(5); // создаем объект ds класса OneWire с единственным параметром номер пина шины OneWire |
05 | OneWire ds6(6); |
06 | OneWire ds7(7); |
07 |
08 | OneWire ds(8); //!!!! на этой шине будет несколько датчиков |
09 |
10 | const byte kol_DS = 3; //количество датчиков на 1-wire шине |
11 | byte addr[kol_DS][8]; //Создал массив: строки-кол-во датчиков по 8 байт в каждой для хранения адреса(ROM, ID) датчика |
12 | byte present = 0; |
13 | byte data[kol_DS][12]; //Создал массив: строки-ном датчика по 12 байт с температурой |
14 | byte type_s; |
15 |
16 |
17 | void setup ( void ) |
18 | { |
19 | Serial .begin(9600); |
20 | Serial .println( "Find" ); //Find DS18хх |
21 | Find_DS18b20(); //вызов подпрограммы |
22 | } |
23 |
24 | void loop ( void ) |
25 | { |
26 | //Когда данные датчиков будут в массиве, тогда понятно как получать температуру |
27 | } |
28 |
29 | void Find_DS18b20() |
30 | { |
31 | //Пример кода, когда датчиков 2шт: <a href="http://playground.arduino.cc/Learning/OneWire" title="http://playground.arduino.cc/Learning/OneWire" rel="nofollow">http://playground.arduino.cc/Learning/OneWire</a> |
32 |
33 | // 1) Сначала проверим, а есть ли хоть какой датчик на шине |
34 | for ( byte i = 0; i < kol_DS; i++) //начало цикла (0,1,2) определения адресов датчиков |
35 | { |
36 | Serial .println(i); |
37 | if ( !ds.search(addr[i])) //тогда нет. addr - у меня двумерный массив байтов, в котором будет храниться номер п.п. и адрес |
38 | { |
39 | Serial .println( "NoDS" ); //No DS18" |
40 | //delay(50); |
41 | //break; |
42 | ds.reset_search(); // если не нашли, сбрасываем поиск в начало |
43 | return ; // и возвращаемся в самое начало главного цикла void loop(void) |
44 |
45 | } //КонецIF |
46 | else // что-то на шине есть |
47 | { |
48 | //*********для отладки****** |
49 | for ( int g = 0; g < 8; g++) |
50 | { |
51 | Serial .write( ' ' ); |
52 | Serial .print(addr[i][g], HEX); |
53 | } |
54 | Serial .println(); |
55 | //******конец для отладки*************** |
56 | |
57 | // ds.reset_search();//addr[k] Если разремировать, то определяется только один датчик)!!!!!!!!!!!!!!! |
58 | // { |
59 | // switch (addr[i][0]) //n_ds18xx - номер п/п датчика, 0- 1-й байт содержит тип датчика |
60 | // { |
61 | // case 0x10://Find_Chip: DS18S20 |
62 | // type_s = 1; |
63 | // break; |
64 | // case 0x28: |
65 | // //Serial.println("Find_Chip: DS18B20"); |
66 | // type_s = 0; |
67 | // break; |
68 | // case 0x22://Find_Chip: DS1822 |
69 | // type_s = 0; |
70 | // break; |
71 | // //default: |
72 | // //Serial.println("Device is not a DS18x20 family device."); |
73 | // // return; |
74 | // }//КонецSwitch |
75 | // } |
76 | } |
77 | } |
78 | } |
Вот что программа выдает при этом коде
Find
0
28 51 2 45 6 0 0 34
1
28 69 F6 44 6 0 0 4E
2
28 D5 AC 2 5 0 0 11
Но мне нужен весь код. Если я разремирую,
01 | #include <OneWire.h>//для работы с DS18b20(датчик температуры) |
02 | //****************** Создаем объекты библиотечных классов ********************************** |
03 | //Если на 1-шине сидит один датчик, то его ID знать не требуется! |
04 | OneWire ds5(5); // создаем объект ds класса OneWire с единственным параметром номер пина шины OneWire |
05 | OneWire ds6(6); |
06 | OneWire ds7(7); |
07 |
08 | OneWire ds(8); //на этой шине будет несколько датчиков |
09 | const byte kol_DS = 3; //количество датчиков на 1-wire шине |
10 | byte addr[kol_DS][8]; //Создал массив: строки-кол-во датчиков по 8 байт в каждой для хранения адреса(ROM, ID) датчика |
11 | byte present = 0; |
12 | byte data[kol_DS][12]; //Создал массив: строки-ном датчика по 12 байт с температурой |
13 | byte type_s; |
14 | byte Gl_buffer_save[16]; //Буфер (0-16) сбора информации |
15 |
16 | void setup ( void ) |
17 | { |
18 | Serial .begin(9600); |
19 | Serial .println( "Find" ); //Find DS18хх |
20 | Find_DS18b20(); //вызов подпрограммы |
21 | } |
22 |
23 | void loop ( void ) |
24 | { |
25 | //Когда данные датчиков будут в массиве, тогда понятно как получать температуру |
26 | //start_termo();//начать измерение температуры |
27 | //delay(1000); |
28 | //get_termo(); |
29 | //Send_UART_SD();//отправка данных в UART |
30 | } |
31 |
32 | void Find_DS18b20() |
33 | { |
34 | //Пример кода, когда датчиков 2шт: <a href="http://playground.arduino.cc/Learning/OneWire" title="http://playground.arduino.cc/Learning/OneWire" rel="nofollow">http://playground.arduino.cc/Learning/OneWire</a> |
35 |
36 | // 1) Сначала проверим, а есть ли хоть какой датчик на шине |
37 | for ( byte i = 0; i < kol_DS; i++) //начало цикла (0,1,2) определения адресов датчиков |
38 | { |
39 | Serial .println(i); |
40 | if ( !ds.search(addr[i])) //тогда нет. addr - у меня двумерный массив байтов, в котором будет храниться номер п.п. и адрес |
41 | { |
42 | Serial .println( "NoDS" ); //No DS18" |
43 | //delay(50); |
44 | //break; |
45 | ds.reset_search(); // если не нашли, сбрасываем поиск в начало |
46 | return ; // и возвращаемся в самое начало главного цикла void loop(void) |
47 |
48 | } //КонецIF |
49 | else // что-то на шине есть |
50 | { |
51 | //*********для отладки****** |
52 | for ( int g = 0; g < 8; g++) |
53 | { |
54 | Serial .write( ' ' ); |
55 | Serial .print(addr[i][g], HEX); |
56 | } |
57 | Serial .println(); |
58 | //******конец для отладки*************** |
59 | |
60 | ds.reset_search(); //addr[k] Если разремировать, то определяется только один датчик)!!!!!!!!!!!!!!! |
61 | { |
62 | switch (addr[i][0]) //n_ds18xx - номер п/п датчика, 0- 1-й байт содержит тип датчика |
63 | { |
64 | case 0x10: //Find_Chip: DS18S20 |
65 | type_s = 1; |
66 | break ; |
67 | case 0x28: |
68 | //Serial.println("Find_Chip: DS18B20"); |
69 | type_s = 0; |
70 | break ; |
71 | case 0x22: //Find_Chip: DS1822 |
72 | type_s = 0; |
73 | break ; |
74 | //default: |
75 | //Serial.println("Device is not a DS18x20 family device."); |
76 | // return; |
77 | } //КонецSwitch |
78 | } |
79 | } |
80 | } |
81 | } |
то получу :
Find
0
28 51 2 45 6 0 0 34
1
28 51 2 45 6 0 0 34
2
28 51 2 45 6 0 0 34
Т.е. программа видит только один датчик.
Также хотелось бы от умных людей услышать описание "на пальцах" приведенных ниже команд.
Вот как понимаю их я:
ds.search(addr[i])
Арудино пытается определить есть ли хоть какое-нибуть устройство на 1-wire. Если есть, то записывает
"засветившийся" ROM (8байт) в строку i массива addr. Это понятно для одного датчика. Но если датчиков много, то при каждом обращении к шине подается сигнал сброса (здесь не видно) и первым откликнувшимся опять является "шустрый" DS18x20, что собственно и видно из второго примера.
Допустим, библиоткека сама определяет, что такой ROM она уже сохранила и продолжает "пинговать" шину, пока не словит нововый ROM. Т.е. я подсовываю команде ds.search()только место для сохранения ROM, а она сама все делает.
Но тогда непонятен смысл команды ds.reset_search(). Что я ей должен скормить? Она что-то куда-то запишет?
P.S. Кода решится вопрос с несколькми датчиками, я думаю, что сам разберусь с датчиками на отдельных пинах.
P.S.S Толковый учитель по вопросам ученика видит его больше, чем по ответам. И только даун при любом вопросе видит дауна.
Очень надеюсь на помощь.
Почитайте , там весьма подробно описаны все команды и алгоритмы.
VCC на 3,3 В
GND на GND
Все DATA на нужный пин
Между пином DATA и VCC подключаешь резистор на 4,7 кОм.
У каждого датчика есть свой уникальный адрес типа MAC на сетевой карте. В примере из DallasTemperature для двух датчиков есть кусок для получения адремсов всех датчков на пине.
Если у тебя датчики привязаны к конкретному месту уставноки, то храни адреса в EEPROM (один адрес - 8 байт), считывай их при запуске контроллера и используй в программе.
Команду на начала измерений можно пулять без задания адреса, тогда её получат все датчики на шине и начнут замер.
Почитайте , там весьма подробно описаны все команды и алгоритмы.
Спасибо, но Яндекс говорит, что такой страницы нет (404)
VCC на 3,3 В
GND на GND
Все DATA на нужный пин
Между пином DATA и VCC подключаешь резистор на 4,7 кОм.
У каждого датчика есть свой уникальный адрес типа MAC на сетевой карте. В примере из DallasTemperature для двух датчиков есть кусок для получения адремсов всех датчков на пине.
Если у тебя датчики привязаны к конкретному месту уставноки, то храни адреса в EEPROM (один адрес - 8 байт), считывай их при запуске контроллера и используй в программе.
Команду на начала измерений можно пулять без задания адреса, тогда её получат все датчики на шине и начнут замер.
Похоже у Вас между мозгом и глазами стоит стена. Я не спрашиваю как мне ОБОЙТИ проблему, я спрашиваю как её РЕШИТЬ в конкретных условиях. Чувствуете разницу?
Утро вечера мудреннее. Вот рабочий скетч для поиска и использования НЕСКОЛЬКИХ (2, 3, 4, 5, 6 ...) датчиков (указывается в настройках #define kol_DS 3 ) DS18b20 на одной шине с использованием библиотеки OneWire.h
компилировал под IDE 1.6.5. Библиотеку OneWire скачивал, так как в "коробке 1.6.5" не было. http://www.pjrc.com/teensy/td_libs_OneWire.html Version 2.1:
001
#include <OneWire.h>//для работы с DS18b20(датчик температуры)
002
//****************** Создаем объекты библиотечных классов **********************************
003
//Если на 1-шине сидит один датчик, то его ID знать не требуется!
004
005
OneWire ds(8);
//на этой шине будет несколько датчиков
006
#define kol_DS 3
007
//const byte kol_DS = 3; //количество датчиков на 1-wire шине
008
byte
addr[kol_DS][8];
//Создал массив: строки-кол-во датчиков по 8 байт в каждой для хранения адреса(ROM, ID) датчика
009
byte
present = 0;
010
byte
data[kol_DS][12];
//Создал массив: строки-ном датчика по 12 байт с температурой
011
byte
type_s;
012
byte
Gl_buffer_save[16];
//Буфер (0-16) сбора информации
013
014
015
void
setup
(
void
)
016
{
017
Serial
.begin(9600);
018
Serial
.println(
"Find"
);
//Find DS18хх
019
Find_DS18b20();
//вызов подпрограммы
020
}
021
022
void
loop
(
void
)
023
{
024
//Когда данные датчиков будут в массиве, тогда понятно как получать температуру
025
start_termo();
//начать измерение температуры
026
delay(1000);
//подождать пока DS18b20 закончит пересчитывать температуру в цифровой код
027
get_termo();
//прочитать температуру из всех датчиков DS18b20
028
Send_UART_SD();
//отправить данные в UART
029
}
030
031
void
Find_DS18b20()
032
{
033
for
(
int
i = 0; i < kol_DS; i++)
034
{
035
// Serial.println("Initialising DS18B20...");
036
if
(!ds.search(addr[i]))
037
{
038
Serial
.println(
"ErrInit1w"
);
//инициализация не выполнена:DS18B20 не найдены
039
return
;
040
}
041
else
//датчики найдены
042
{
043
//**********вывести номер датчика и его ROM ******
044
// Serial.print("Temp. Sensor ");
045
// Serial.print(i);
046
// Serial.print(": ");
047
// for (int j = 0; j < 8; j++)
048
// {
049
// Serial.print(addr[i][j], HEX);
050
// Serial.print(addr[i][j], HEX);
051
// }
052
//**************вывел ROM**********
053
}
//конец else
054
// Serial.println("...done!");
055
if
(OneWire::crc8(addr[i], 7) != addr[i][7])
056
{
057
Serial
.println(
"ErrCRC"
);
//CRC Failed!
058
return
;
059
}
060
if
(addr[i][0] != 0x28)
061
{
062
Serial
.println(
"notDS18B20"
);
//"OW Device is not DS18B20!"
063
}
064
}
//КонецЦикла
065
}
066
067
//начало измер температуры***********************************************************************************************
068
void
start_termo()
069
{
070
071
//для отладки
072
//Serial.println("1000_start_termo()");
073
// Serial.println(n_ds18xx);
074
//Запускаем преобразователи во всех датчиках, найденных на этапе SETUP
075
for
(
byte
i = 0; i < 3; i++)
076
{
077
ds.reset();
078
ds.select(addr[i]);
079
ds.write(0x44, 1);
// start conversion, with parasite power on at the end
080
/*После окончания преобразования данные сохраняются в 2-байтовом температурном регистре в
081
оперативной памяти, а DS18B20 возвращается в неактивное состояние с низким
082
энергопотреблением*/
083
}
084
085
//установить разрешение DS18b20
086
//00011111 -9bit 0x1F
087
//00111111 -10bit
088
//01011111 -11bit
089
//01111111 -12bit 0x7F
090
//byte conf=0x7F;//
091
//НЕ РАБОТАЕТ
092
// ds.reset();
093
// ds.skip(); // skip ROM, что бы обратиться ко всем устройствам на шине одновременно
094
// ds.write(0x4E); // write scratchpad Для записи данных в байты 2, 3, и 4 ОЗУ
095
// ds.write(0); // Th
096
// ds.write(0); // Tl
097
// ds.write(conf); // configuration
098
099
}
100
101
//получение температуры*************************************************
102
void
get_termo()
103
{
104
//для отладки <a href="http://usbsergdev.narod.ru/DOC/DS18B20_RU.pdf" rel="nofollow">http://usbsergdev.narod.ru/DOC/DS18B20_RU.pdf</a>
105
// Serial.println("1016_get_termo()");
106
//Serial.println(n_ds18xx);
107
108
for
(
byte
n_ds18xx = 0; n_ds18xx < kol_DS; n_ds18xx++)
//начало цикла (0,1,2) определения адресов датчиков
109
{
110
present = ds.reset();
//работа с датчиком всегда должна начинаться с сигнала ресета
111
ds.select(addr[n_ds18xx]);
//выбирается адрес (ROM ) датчика
112
//Чтобы проверить корректность записи данных, необходимо выполнить чтение (используя команду чтения
113
//Read Scratchpad [BEh]) после того, как данные (какие) будут записаны(куда).
114
ds.write(0xBE);
115
/*(0xBE = 190)/читать содержание ПАМЯТИ. Передача данных начинается с наименьшего значащего бита байта 0 и продолжается до 9-ого байта (байт 8
116
- циклический контроль избыточности). */
117
for
(
byte
i = 0; i < 9; i++)
118
{
119
data[n_ds18xx][i] = ds.read();
//сохраняем температуру(9 байт) в массиве соответствующего датчика
120
}
121
//проверка контрольной суммы:Старишие 8бит из 64 ROM, а не температуры!! содержат crc
122
if
( OneWire::crc8( addr[n_ds18xx], 7) != addr[n_ds18xx][7])
123
{
124
Serial
.println(
"ErrCRC"
);
125
//если контрольная сумма не совпала с тем, что мы приняли – работать с такими данными нельзя.
126
//Поэтому запишем в массив с результатом такие значения, которых в нормальных условиях мы получить не сможем
127
//return;
128
Gl_buffer_save[n_ds18xx + 5] = 131;
//придумать получше вариант
129
}
130
else
131
{
132
int16_t raw = (data[n_ds18xx][1] << 8) | data[n_ds18xx][0];
//Тип 16-разрядных целых
133
byte
cfg = (data[n_ds18xx][4] & 0x60);
134
if
(cfg == 0x00) raw = raw & ~7;
// 9 bit resolution, 93.75 ms
135
else
if
(cfg == 0x20) raw = raw & ~3;
// 10 bit res, 187.5 ms
136
else
if
(cfg == 0x40) raw = raw & ~1;
// 11 bit res, 375 ms
137
138
byte
celsius = (
float
)raw / 16.0;
//16.0 будет 2 знака после запятой. Мне надо целое
139
//byte s = 0;
140
Gl_buffer_save[n_ds18xx + 5] = celsius;
141
//для отладки
142
// Serial.print("1051 t=");
143
// Serial.print(Gl_buffer_save[n_ds18xx + 5]);
144
// Serial.println(" ");
145
}
146
}
147
}
148
//******Конец Функция void get_termo() измерения температуры
149
150
151
152
void
Send_UART_SD()
153
{
154
//Serial.println("793_Send_UART_SD()");
155
156
String dataString =
""
;
157
byte
tt = 0;
158
for
(
byte
s = 0; s < 17; s++)
// перебираем(0,1,2...) индексы массива Gl_buffer_save[ ]
159
{
160
tt = Gl_buffer_save[s];
161
162
if
(((s == 5) or (s == 6) or (s == 7)) and (tt > 127))
//больше 127- значит температура отрицательная
163
{
164
tt = 256 - tt;
165
Serial
.print(
'-'
);
166
dataString +=
'-'
;
//наполняем строку (выводимой в UART) информацией для записи на SD карты
167
}
168
Serial
.print(tt);
//name[7] = i%10 + '0';
169
dataString += String(tt);
//наполняем строку (выводимой в UART) информацией для записи на SD карты
170
Serial
.print(
" ; "
);
171
dataString +=
";"
;
//наполняем строку (выводимой в UART) информацией для записи на SD карты
172
}
173
Serial
.println();
174
175
}
//Конец Send_UART_SD()
Пользуйтесь на здоровье! И забудьте про этот дебилизм загонять ID датчиков в прошивку
Обратите внимание на одну тонкость: для хранения темпрературы я выделил байт. Т.е. можно записать число от 0 до 255, но тепература может быть отрицательной . Положительная температура будет записана числом от 0 до 127, а отрицательная от 128 (старший бит =1) до 255. Поэтому ставим знак минус перед числом. а модуль температуры получаем как (256-число)
> указывается в настройках #define kol_DS 3
Взоржал с тебя.
Не путай flash и eeprom, засмеют.
И вопрос со звездочкой. Как датчик успеет измерить температуру, если у тебя не предполагаются задерки?
А код бибилиотеки всё же изучи. Много полезного про нее узнаешь.
Тогда наберите "DS18B20 описание на русском" Чернов Геннадий.
На тему загоняния адресов в прошивку или EEPROM, готов сильно поспорить. После сбоя питания, откуда программа узнает местонахождение всех датчиков? Ваша попытка повесить их на отдельные пины, подозреваю связана именно с этим.
Похоже у Вас между мозгом и глазами стоит стена. Я не спрашиваю как мне ОБОЙТИ проблему, я спрашиваю как её РЕШИТЬ в конкретных условиях. Чувствуете разницу?
Вот бы Пухлявому так ответил)))))))
> указывается в настройках #define kol_DS 3
Взоржал с тебя.
1)Смех продлевает жизнь, а ржачь делает из человека животное.
Не путай flash и eeprom, засмеют.
2) Меня это не смущает. Есть пословица: Умный промолчит, дурак не заметит. Засмеивающие, мне кажется, ближе ко второй категории. Не стоит обращать на них внимания. За информацию спасибо. Гляну. Но код от этого не перестанет работать
И вопрос со звездочкой. Как датчик успеет измерить температуру, если у тебя не предполагаются задерки?
Открываем канал между глазами и мозгами и смотрим функцию LOOP
Я сделаю и забуду про этот проект. Некогда вникать во все библиотеки.
И все таки, как прога определяет местонахождение датчика? Могу предположить: датчики отсортированы по адресам и расположены последовательно. Что делать если датчик сдох? Перемещать все датчики, у которых адрес выше? Объясните, в чем преимущество вашего метода? Крику много, но не понятно.
1)И все таки, как прога определяет местонахождение датчика? 2)Могу предположить: датчики отсортированы по адресам и расположены последовательно. 3)Что делать если датчик сдох? 4)Перемещать все датчики, у которых адрес выше? 5)Объясните, в чем преимущество вашего метода? 6)Крику много, но не понятно.
Извините, но внес в цитаты цифры, что бы проще было отвечать.
1)датчики, подключенные к отдельным пинам будут установлены на определенные физические объекты и под это будет заточена программа. "Гирлянда" будет крепиться по обстоятельствам. Как узнать местонашождения датчика с гирлянды? Погреть и записать на бумажку, если угодно.
2)Ничего не сортировал. Ответ в п1
3)Если датчик сдох на отдельном пине, то об этом сообщит программа. Заменю, перезагружу программу и забуду. Если на "гирлянде" - тоже самое.
4)Наши абстракции не пересекаются. Не понимаю, о чем Вы.
5)Я не знаю, что Вы подразумеваете под "моим методом".
6)Странно, я вообще-то не кричал.
Видимо Ваши вопросы от потери контекста моего вопроса. Кратко повтою. Интесовал код для работы несколькими датчиками DS18b20 в определенных программных условиях. Другие моменты неактуальны, например, точность температуры.
1)Извини чувак, я хрустальный шар вчера разбил, хотя будущее он всё равно хреново показывал.
2)А хамить не надо, хамить я и сам умею. А таких шибкоумных велосипедостроителей тут в неделю по 5 штук бывает.
3)И вот тут я ловлю тебя на слове.
4)Ты сначала говришь про неприемлимость делаев и вот уже правишь пост с delay(1000). Либо крестик сними, либо трусы надень.
А устройство с двумя датчиками и адресами в EEPROM у меня сейчас на подоконнике лежит и температуру показывает.
> И все таки, как прога определяет местонахождение датчика?
5)Да никак. Я уже имел дело с таким говнокодером. Сренькнул и в кусты.
1)Думаю моё прощение Вам не поможет.
2)При обвинениях приводят цитаты. Но "чуваки" об этом не знают.
3)Опять бы цитата не помешала.
4)Т.е. моя фраза "Вот часть моего кода в части DS18B20" Вам ничего не говорит. Ладно скажу по другому. Так как проект очень большой и нет смысла его весь выкладывать, я выложил только часть кода, которая показывает суть проблемы. А что бы этот демо-код работал я добавил задержку в 1 сек там где надо.
5)Вообще-то я сам решил свой вопрос и выложил решение в общий доступ. Но у Вас, очевидно, к таким поспупкам свое специфическое отношение. Поэтому более с Вами объясняться не желаю.
Мальчики не сортесь по пустякам! 123ksn Ты вобще чего хотел то?! смотри стр.57
// ds.reset_search();
заремлен. В цикле нашли 1 датчик, потом 2 и третий. Разремилds.reset_search();
и нашли 1 датчик сбросили контекст поиска снованашли первый датчик.. Уберds.reset_search();
на...Да, еще как с тремя датчиками на одном выводе буш работать, то конвертацию запускай по очереди, иначе питания может нехватать, если сильно надо одновременно, то надо подпитку приличную. Но токо вот зачем оно может быть надо одновременно, не термоядерный реактор мониторить же, температура меняется не быстро. Можна и все датчики на один вывод поцепить.
А с сканированием датчиков кажется класно, типа новый датчик подключил, он автоматом обнаружился, но в реале неудобняк - ну нашли допустим ваши 3 датчика (а что если 2, или 4 обнаружилось?), а какой из них какую температуру меряет? Нужна табличка соответствия, с сохранением адресов датчиков в энергонезависимой памяти данных ;) Это загрузка, и/или редактирование. Невесело получается. Подключил новый датчик - пропиши его, заменил старый - правь табличку. Если же есть табличка - нафига сканировать каждый раз?!
А с сканированием датчиков кажется класно, типа новый датчик подключил, он автоматом обнаружился, но в реале неудобняк - ну нашли допустим ваши 3 датчика (а что если 2, или 4 обнаружилось?), а какой из них какую температуру меряет? Нужна табличка соответствия, с сохранением адресов датчиков в энергонезависимой памяти данных ;) Это загрузка, и/или редактирование. Невесело получается. Подключил новый датчик - пропиши его, заменил старый - правь табличку. Если же есть табличка - нафига сканировать каждый раз?!
Не, ну это мелочи, пришел такой крутой чувак, рассказал всем, что можно адреса в массив считать. Потом для его удобства и нежелания подумать, вместо одного шлейфа использовать три. Открыл истину, как хранить отрицательные числа в байте. В итоге получил высокотехнологичную х-ню на дорогом цифровом датчике, с которой вполне может справиться любой p-n переход.
1) Да, еще как с тремя датчиками на одном выводе буш работать, то конвертацию запускай по очереди, иначе питания может нехватать, если сильно надо одновременно, то надо подпитку приличную. Но токо вот зачем оно может быть надо одновременно, не термоядерный реактор мониторить же, температура меняется не быстро. Можна и все датчики на один вывод поцепить.
2)А с сканированием датчиков кажется класно, типа новый датчик подключил, он автоматом обнаружился, но в реале неудобняк - ну нашли допустим ваши 3 датчика (а что если 2, или 4 обнаружилось?), а какой из них какую температуру меряет? Нужна табличка соответствия, с сохранением адресов датчиков в энергонезависимой памяти данных ;) Это загрузка, и/или редактирование. Невесело получается. Подключил новый датчик - пропиши его, заменил старый - правь табличку. Если же есть табличка - нафига сканировать каждый раз?!
1)Я датчики DS18b20 давно использую и с тонкостями знаком. Вот на ардуине впервый раз. Но спасибо за добрый совет.
2)Logik, не придумывайте сложности. Пусть каждый делает как ему лучше, а я буду делать как мне лучше. Как говорится на вкус и цвет... DS18b20 можно подключить квазизвездой. Пользователь может даже не знать, что перед ним не звезда. Переключил вилку в нужную розетку и готово (Я использую провода и коннекторы от телефона)
Да, извините, строку 57 нет смысла обсуждать, так как я опубликовал пример рабочего кода
Кароч вывод простой : каждый точит как хочет :)
Ваши углы заточки возможно оптимальны для Вашего проекта, который остался вне обсуждения. Для понимания большинства присутствующих проЭктантов обоснованы другие углы заточки. К ним отношу себя и я. Работаю с этими датчиками не один год. Ваш подход понял, резоны нет.
Спасибо.
PS. Когда помещаете код, не забывайте пожалуйста ставить крыжык в закладке дополнительно, пункт сворачивать.
1)Кароч вывод простой : каждый точит как хочет :)
Ваши углы заточки возможно оптимальны для Вашего проекта, который остался вне обсуждения. Для понимания большинства присутствующих проЭктантов обоснованы другие углы заточки. К ним отношу себя и я. Работаю с этими датчиками не один год. Ваш подход понял, резоны нет.
2)Спасибо.
3) PS. Когда помещаете код, не забывайте пожалуйста ставить крыжык в закладке дополнительно, пункт сворачивать.
1) Конечно, сколько людей столько и мнений.
2)Не знаю за что спасибо, но скажу пожалуйста.
3)Спасибо. Не знал о такой возможности.
Добавьте впереди незначащие нули и вписывайте после х, только то, что вам написал экран, точно не DS18B20. Его ID начинается с 28.
спасибо разобрался
В чем причина при использовании кода периодически теряется связь с датчиками выводит на дисплей как о("sensor error") испытываю в протеусе
В чем причина при использовании кода периодически теряется связь с датчиками выводит на дисплей как о("sensor error") испытываю в протеусе
Ошибка - error.
Потыкай датчики по индексу вместо адреса.
И еще http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukomment...
Ошибка - error.
Потыкай датчики по индексу вместо адреса.
И еще http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukomment...
по индексу изначально не известно где какой датчик
Если по индексу все датчики отвечают, то проверяй адреса. Если не отвечают, то смотри соединение. Логика работает или где?
Если по индексу все датчики отвечают, то проверяй адреса. Если не отвечают, то смотри соединение. Логика работает или где?
может протеус глючит)?
При проверке в метале код работает получается протеус не всегда есть хорошо
При проверке в метале код работает получается протеус не всегда есть хорошо
Что то вроде резиновой женщины. ИМХО.
Помогите пожалуйста -начальство уже мозг проело, не могу прописать 6 датчиков ds18b20 на sd накопитель. Пишет только один датчик на флешку,остальные не удается. Микроконтлллер Atmega 328p. Ардуино писал Си плюс иде.Помогите как прописать поавильно чтобы писались все датчики на sd карту. Выручите мужики!
Код и схему в студию. Без кода в "Ищу исполнителя".
А за каким ..... их писать на SD? Вы базу адресов наличных датчиков создаете? Родного EEPROMа 328 штук на 100 датчиков хватит. Или у вас их больше?
01
двумя руками поддерживаю
"123ksn"
!!!
02
вот моя мини-переписка с другого сайта:
03
04
>>>>>>>>>>>>>>>>>>>>>>
05
valiktom
06
кто-нибудь может разобраться со скетчем ?
07
1.что делает
"12"
в
byte
data[12]; ,если собираем значения до девяти
08
"for ( i = 0; i < 9; i++) { // нам необходимо 9 байт"
?
09
2.что делает параметр
"present"
в
"present = ds.reset();"
и почему без него нельзя как выше
"ds.reset();"
?
10
3.как берутся и меняются значения в
"addr[8];"
для
"if ( !ds.search(addr)) {"
?
11
4.какие значения сбрасывает
"ds.reset_search();"
?
12
5.для чего нужен
"delay(250);"
?
13
заранее спасибо...
14
15
Е. > valiktom
16
1. мне тоже не понятно. У меня с data[9] всё как надо работает.
17
2. без present тоже всё работает прекрасно. А present - видимо, можно использовать, например, для вывода сообщения об ошибке:
if
(!present) {....}
18
3. Что касается ds.reset_search(), вот кусок из OneWire.cpp:
19
// You need to use this function to start a search again from the beginning.
20
// You do not need to do it for the first search, though you could.
21
//
22
void
OneWire::reset_search()
23
{
24
// reset the search state
25
LastDiscrepancy = 0;
26
LastDeviceFlag = FALSE;
27
LastFamilyDiscrepancy = 0;
28
for
(
int
i = 7; ; i--) {
29
ROM_NO[i] = 0;
30
if
( i == 0)
break
;
31
}
32
33
valiktom > Е.
34
по поводу
"addr[8];"
для
"if ( !ds.search(addr)) {"
поставлю вопрос по-другому:
35
36
...если ds.search(addr) прочёсывает все адреса от минимального до максимального,
37
натыкается на существующий, выдаёт единицу и дальше по коду,
38
то почему он до этого не ушёл в
"No more addresses."
и
"loop"
...
39
...а если код библиотеки (может я не разобрался) не даёт выйти из прочёсывания адресов,
40
то как мы видим два и больше сенсора за раз цикла...
41
..а если это разные циклы,
42
то откуда известно с какого адреса продолжать, ведь он объявляется по-новому каждый цикл
43
и нигде не запоминается...
44
где собака зарыта?
45
<<<<<<<<<<<<<<<<<<<<<<<<
46
47
в конечном счёте всё сводится к тому,<strong>что</strong> происходит в цикле?
48
while
(ds.search(addr) == 1) {
49
Serial
.println(addr);
50
}
51
52
виден аналогичный взгляд на вещи...
вот тоже понадобилось на три датчика на три входа повесить, без привязки к внутренним номерам датчиков.
для развития темы, притащил код из интернета:
01
/ подключение нескольких датчиков на разніе пині ардуино.
02
/*
03
Стандартная библиотека DallasTemperature несколько модернизирована и позволяет подключить несколько датчиков к одному пину Ардуино
04
и обращаться к ним по уникальным адресам, что удобно, если надо провести датчики температуры на большие расстояния от Ардуино к
05
местам измерения температур, так как количество проводов уменьшается до трёх или даже двух с паразитным подключением, и толщина
06
проводов может передать сигнал напряжением в 5 вольт на большие расстояния. Но что делать, если датчик испортился, например из-за
07
перегрева, при замене цифрового датчика на шине с другими датчиками нужно заново прописывать в программе новый уникальный номер
08
датчика DS18b20 и заново прошивать Ардуино.
09
Одно из решений подключить цифровые датчики, как аналоговые каждый на свой вывод и считывать температуру с привязкой к
10
выводу, а не к уникальному адресу или к номеру в последовательности определения на шине.
11
Если требуется подключить несколько цифровых датчиков DS18b20 на разные выводы по шине onewire воспользуётесь примером скетча:
12
* два цифровых датчика DS18B20 на отдельные пины для быстрой замены с разрешениями для быстроты срабатывания (менее 2 секунд) и проверкой на отсутствие
13
*/
14
#include <OneWire.h>
15
#include <DallasTemperature.h>
16
// пин 10 датчик температуры 1
17
OneWire oW_podacha(10);
18
// пин 11 датчик температуры 2
19
OneWire oW_Obratka(11);
20
DallasTemperature podacha(&oW_podacha);
21
DallasTemperature Obratka(&oW_Obratka);
22
DeviceAddress podachaAddress, ObratkaAddress;
23
int
Obrat;
24
int
podach;
25
int
raznost;
26
// float floatObrat;
27
// float floatpodach;
28
void
setup
(
void
)
29
{
30
Serial
.begin(9600);
31
podacha.begin();
32
Obratka.begin();
33
podacha.setResolution(11);
34
Obratka.setResolution(11);
35
<p>
// при максимальной точности время срабатывания 2 секунды если не указана точность
36
// 12 точность 0.06
37
// 11 точность 0.12
38
// 10 точность 0.25
39
// 9 точность 0.5
40
// 6 точность 0.5
41
}
42
void
loop
(
void
)
43
{
44
Serial
.println(
"Datchiki temperaturi:"
);
45
Obratka.requestTemperatures();
46
delay(40);
47
podacha.requestTemperatures();
48
delay(40);
49
Serial
.print(
"Podacha:"
);
50
Serial
.println(podacha.getTempCByIndex(0));
51
Serial
.print(
"Obratka:"
);
52
Serial
.println(Obratka.getTempCByIndex(0));
53
int
Obrat = Obratka.getTempCByIndex(0);
54
int
podach = podacha.getTempCByIndex(0);
55
int
raznost = podach - Obrat;
56
Serial
.print(
"RaZnost:"
);
57
Serial
.println(raznost);
58
delay(100);
59
oW_podacha.reset_search();
60
oW_Obratka.reset_search();
61
if
( !podacha.getAddress(podachaAddress, 0) ) {
Serial
.print(
"datchika Podachi net"
);}
62
if
( !Obratka.getAddress(ObratkaAddress, 0) ) {
Serial
.print(
"datchika Obratki net"
);}
63
}
64
//Также часто требуется проверка на наличие датчика в случае плохого контакта.
65
//Для ускорения работы цифровых датчиков следует установить разрешение (точность ) снятия измерений, если не указывать разрешение ,
66
//по умолчанию оно будет максимальным, а значит процесс замера температуры займёт 2 секунды.
http://arduino.ru/forum/programmirovanie/arduino-i-termodatchiki-ds18b20...
Тогда наберите "DS18B20 описание на русском" Чернов Геннадий.
Для развития темы скажу, что пробовал его библиотеку под контроллер PIC. После танцев с бубном все заработало. Обработка датчиков через прерывания сделана грамотно. Но код не просто перенести на другой микроконтроллер. Мне пришлось два вечера потратить на сверку регистров таймера моего микроконтроллера с тем, который использовал Геннадий, переделку кода и вылавливание ошибок. И там используется устаревший метод работы с EEPROM из-за чего библиотека занимает много места в памяти микроконтроллера. Т. е. все операции чтения/записи в EEPROM там расписаны вручную. В современных компиляторах для PIC этого не нужно, компилятор все делает сам, достаточно указать префикс eeprom при описании переменной.
А в целом именно так должа выглядеть нормальная библиотека для работы с датчиками температуры: до 16 датчиков на один провод, автоматический опрос датчиков, сохранение кодов датчиков в EEPROM, автоматическая замена кодов датчиков в EEPROM при смене датчика, работа через прерывания, что исключает задержки на ожидание ответа от датчика. В идеале ещё переделать её под ООП, чтобы можно было одновременно запускать несколько датчиков по нескольким пинам.
AlexeySh, даже и не знал про его библиотеки, именно перевод-описание работы с DS18B20 понравилось.
AlexeySh, даже и не знал про его библиотеки, именно перевод-описание работы с DS18B20 понравилось.
Добавлю ложку дегтя. Его же библиотеку для работы с LCD дисплеями на HD44780 запустить так и не удалось. Хотя она вообще не использует прерывания, только временные задержки. После пары дней развлечений с её отладкой нашел в Инете другую библиотеку, на которой сейчас и работает моё устройство на PIC16F648A.
001
#include <EEPROM.h>
002
#include <OneWire.h>
003
// OneWire DS18B20 only
004
//Скетч использует 10 574 байт (32%) памяти устройства. Всего доступно 32 256 байт.
005
//Глобальные переменные используют 455 байт (22%) динамической памяти,
006
//оставляя 1 593 байт для локальных переменных. Максимум: 2 048 байт.
007
/* UNO:
008
32 кБ флэш памяти
009
2 кБ ОЗУ (SRAM)
010
1 Кб EEPROM
011
14 цифровых выводов
012
Последовательная шина: 0 (RX) и 1 (TX)
013
Внешнее прерывание: 2 и 3
014
ШИМ: 3, 5, 6, 9, 10, 11
015
SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK).
016
LED: 13
017
I2C: 4 (SDA) и 5 (SCL).
018
6 аналоговых входов (обозначенных как A0 .. A5)/14..19 в качестве цифровых выводов
019
7, 8 - только для цифровых выводов
020
*/
021
022
#define NumGroup 18 //количество задействованных пинов для датчиков
023
#define MaxNumberSensor 113 //максимальное число датчиков, ограниченное объёмом EEPROM
024
//113x9=1017<1024 byte max EEPROM
025
unsigned
long
timeSens;
//время события
026
int
diftime = 0;
//разница времени между двумя событиями
027
//список номеров задействованных пинов:
028
byte
numPin[NumGroup] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
//for UNO: A0..A5=>14..19
029
int
Sensor[MaxNumberSensor];
//значения измерянной температуры
030
boolean ReadSens =
false
;
//признак чтения\записи датчика
031
boolean boot =
false
;
//признак завершения полного первого цикла записи\чтения всех датчиков
032
byte
present;
//признак готовности датчика к ответу
033
//без паразитного питания - если датчик готов к ответу =1,иначе =0. для паразитного питания - читайте документацию
034
035
void
setup
() {
036
Serial
.begin(9600);
037
timeSens = millis();
// 4,294,967,295 max
038
Serial
.println(F(
"If you Need to Run the Automatic Scanning T* Sensors DS18B20 - Send Any Value\r\nWaiting for Answer 10sec..."
));
039
//ждём ответа пользователя 10 секунд
040
while
(
Serial
.read() == -1 && diftime < 100) {
041
diftime =
int
(millis() - timeSens) / 100;
042
}
043
if
(diftime < 100) {
//если согласились на автоматическое сканирование датчиков
044
Serial
.println(F(
"Runing..."
));
045
//проверяем присутствие уже записаных в EEPROM датчиков по их номерам:
046
//каждый 9-й адрес(включая нулевой) в EEPROM соответствует порядковому номеру датчика,
047
//по нему и может обращаться программа контроля температуры;
048
//его значение совпадает с номером пина, к которому подключён датчик.
049
//MaxNumberSensor * 9 - число задействованных адресов в EEPROM(макс. 113x9 для UNO)
050
for
(
int
eAddrSens = 0; eAddrSens < MaxNumberSensor * 9; eAddrSens = eAddrSens + 9) {
051
byte
Pin = EEPROM.read(eAddrSens);
//читаем номер пина в EEPROM
052
if
(Pin != 255) {
//значит - записан в EEPROM
053
byte
n = 0;
054
byte
ID[8];
//собираем его ID
055
for
(
byte
i = eAddrSens + 1; i < eAddrSens + 9; i++) {
056
ID[n] = EEPROM.read(i);
057
n++;
058
}
059
OneWire ds(Pin);
//активизируем общение по записанному пину
060
n = 0;
//количество возможных повторов опроса датчика
061
while
(n < 3) {
062
present = ds.reset();
//если датчик готов к ответу present=1.
063
//полезно только для общего случая:
064
//если на пине больше одного датчика, то пользы мало - ответят все,
065
//но "ds.reset();" обязан быть до начала общения с датчиком.
066
ds.select(ID);
//выбираем датчик по записанному ID
067
//без преобразования - значение не важно, важно наличие верного ответа
068
ds.write(0xBE);
//Чтение памяти(+85*С после сброса питания или предыдущее значение измерения без сброса)
069
byte
data[9];
//( - если датчик отсутсвует)
070
Serial
.println();
071
//смотрим ответ датчика - для индикации
072
for
(
byte
d = 0; d < 9; d++) {
//собираем его ответ
073
data[d] = ds.read();
//читаем по-байтово
074
Serial
.print(data[d], HEX);
075
Serial
.print(
' '
);
076
}
077
Serial
.print(
"CRC="
);
078
byte
CRC = OneWire::crc8(data, 8);
079
Serial
.println(CRC, HEX);
080
int
T = (data[1] << 8) | data[0];
//может быть и отрицательным
081
T = (T + 8) >> 4;
//целые *C с округлением
082
Serial
.print(F(
"Temp = "
));
083
Serial
.print(T);
//0*C - если датчик отсутсвует
084
Serial
.println(F(
"*C"
));
085
//проверяем ответ датчика. если датчик отсутсвует:
086
//1.если датчик на дигитальном пине:
087
//-если резистор подключён к пину, то data = {FF FF FF FF FF FF FF FF FF},а CRC=C9 и != FF(data[8])
088
//-если пин висит в воздухе, то data = {0 0 0 0 0 0 0 0 0},а CRC=0 и == 0(data[8])
089
//2.если датчик на аналоговом пине:
090
//-если резистор подключён к пину, то data = {FF FF FF FF FF FF FF FF FF},а CRC=C9 и != FF(data[8])
091
//-если пин висит в воздухе, то в зависимости от наводок сработает один из двух вариантов
092
// дигитального пина или 'CRC' общего случая, если наводки прыгают на грани срабатывания
093
//по-этому:
094
if
(CRC != data[8] || present == 0 || CRC == 0) {
//датчик отсутсвует или мусор
095
n++;
096
delay(100);
//повторяем опрос датчика
097
}
098
else
{
//опрос успешный
099
break
;
100
}
101
}
102
//обобщаем данные
103
Serial
.print(F(
"Sensor #"
));
104
Serial
.print(eAddrSens / 9 + 1);
105
Serial
.print(F(
" ID from EEPROM # "
));
106
for
(
byte
d = 0; d < 8; d++) {
107
Serial
.print(ID[d], HEX);
108
Serial
.write(
' '
);
109
}
110
Serial
.print(F(
"on Pin #"
));
111
Serial
.print(Pin);
112
if
(n == 3) {
//если датчик отсутсвует
113
Serial
.println(F(
" not Responds.\r\nWaiting for Answer: Delete = 'd', Skip = 's'..."
));
114
char
answer;
115
do
{
//ждём ответа пользователя
116
answer =
Serial
.read();
117
if
(answer ==
'd'
) {
//удаляем датчик из EEPROM
118
for
(
int
i = eAddrSens; i < eAddrSens + 9; i++) {
119
EEPROM.write(i, 255);
120
}
121
Serial
.println(F(
"Deleted."
));
122
}
123
else
if
(answer ==
's'
) {
//пропускаем до выяснения потом
124
Serial
.println(F(
"Skipped."
));
125
}
126
else
if
(answer >= 0) {
//что-то ответили, но не то
127
Serial
.println(F(
"Waiting for the Correct Answer..."
));
128
answer =
'\0'
;
//ждём в цикле верный ответ
129
}
130
else
{
//ничего не ответили//answer == -1(int)
131
answer =
'\0'
;
//ждём в цикле ответ
132
}
133
}
134
while
(answer ==
'\0'
);
135
}
136
else
{
//всё впорядке
137
Serial
.println(F(
" is Exists and Responds."
));
138
}
139
}
140
}
141
SearchSensor();
142
}
143
else
{
144
Serial
.println(F(
"Skipping..."
));
145
}
146
Serial
.println(F(
"\r\nEnd Setup.\r\nIf you Need to Run the Automatic Scanning during program execution - Send Value 's'.\r\n"
));
147
}
148
//======================================================================
149
void
loop
() {
150
//надо помнить, что исполнение основной программы управления и выходы
151
//зависают в том положении, в котором мы остановились в момент начала поиска датчиков
152
if
(
Serial
.read() ==
's'
) {
//если хотим проверить датчики без перезагрузки
153
SearchSensor();
154
ReadSens =
false
;
155
boot =
false
;
156
}
157
else
{
//в програмном режиме
158
if
(timeSens > millis()) {
159
diftime =
int
(4294967295 - timeSens + millis());
160
}
161
else
{
162
diftime =
int
(millis() - timeSens);
163
}
164
if
(ReadSens ==
false
) {
165
for
(
byte
i = 0; i < NumGroup; i++) {
166
OneWire ds(numPin[i]);
167
// обращение ко всем датчикам шины сразу:
168
ds.reset();
//сброс шины
169
ds.write(0xCC);
//Игнорировать адрес
170
if
(boot ==
false
) {
//имеет смысл при первом запуске или замене\добавлении датчиков
171
ds.write(0x4E);
//разрешение записать конфиг //write scratchpad (starts at byte 2)
172
//задаём аварийные температуры(верхняя\нижняя) - изменить, если пользуетесь
173
ds.write(0x4B);
//default value of TH reg (user byte 1) - верхняя
174
ds.write(0x46);
//default value of TL reg (user byte 2) - нижняя
175
//задаём точность измерения датчика(от неё зависит время преобразованя)= 0,125гр
176
ds.write(0x5F);
//default value of Config = 0x7F (user byte 3)
177
//точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F - подставить нужное\учесть время преобразования
178
ds.write(0x48);
// копируем три байта в EEPROM DS18B20, чтобы сохранить постоянно
179
}
180
ds.write(0x44);
//начать преобразование температуры(без паразитного питания)
181
}
182
ReadSens =
true
;
183
timeSens = millis();
184
}
185
else
if
(ReadSens ==
true
&& diftime >= 500) {
//500ms(с запасом)-т.к. время преобразования 375ms для (0x5F)
186
for
(
byte
NumSens = 0; NumSens < MaxNumberSensor; NumSens++) {
187
int
AddrSensor = NumSens * 9;
188
byte
Pin = EEPROM.read(AddrSensor);
189
if
(Pin != 255) {
190
OneWire ds(Pin);
191
byte
m = 0;
192
byte
ID[8];
193
Serial
.print(F(
"Sensor ID #"
));
194
for
(
int
id = AddrSensor + 1; id < AddrSensor + 9; id++) {
195
ID[m] = EEPROM.read(id);
196
Serial
.print(ID[m], HEX);
197
Serial
.write(
' '
);
198
m++;
199
}
200
Serial
.println();
201
byte
crc = 0;
//индекс числа повторов опроса датчика
202
while
(crc < 3) {
203
present = ds.reset();
//коментарии в "void setup()"
204
ds.select(ID);
205
ds.write(0xBE);
//Чтение памяти
206
byte
data[9];
207
for
(
byte
i = 0; i < 9; i++) {
208
data[i] = ds.read();
209
}
210
//проверяем ответ датчика
211
byte
CRC = OneWire::crc8(data, 8);
//коментарии в "void setup()"
212
if
(CRC == data[8] && present == 1 && CRC != 0) {
//ответ корректный
213
Sensor[NumSens] = (data[1] << 8) | data[0];
214
Sensor[NumSens] = (Sensor[NumSens] * 10) >> 4;
//целое в десятых *C (214=>21,4*C)//(t*10)>>4 == (t*10)/16
215
break
;
216
}
217
else
{
//датчик отсутсвует или мусор
218
crc++;
219
Serial
.print(F(
"Error "
));
220
Serial
.println(crc);
221
delay(100);
222
}
223
}
224
Serial
.print(F(
"Sensor #"
));
225
Serial
.print(NumSens + 1);
226
if
(crc == 3) {
227
Serial
.println(F(
" Error.\r\n"
));
228
}
229
else
{
230
Serial
.print(F(
" Temp: "
));
231
Serial
.print(Sensor[NumSens] / 10);
232
Serial
.write(
','
);
233
Serial
.print(Sensor[NumSens] % 10);
//если в десятых *C
234
Serial
.println(F(
"*C.\r\n"
));
235
}
236
}
237
else
if
(boot ==
false
) {
238
Serial
.print(F(
"Sensor #"
));
239
Serial
.print(NumSens + 1);
240
Serial
.println(F(
" is Blank.\r\n"
));
241
}
242
}
243
boot =
true
;
244
ReadSens =
false
;
245
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
246
//место основной программы для Sensor[Sensor Number],
247
//т.к. в другом месте значения не меняются
248
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
249
}
250
}
251
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
252
//место другой основной программы
253
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
254
}
255
//=========================================================================================
256
void
SearchSensor()
257
{
258
//задавая номер обнаруженного нового датчика мы можем/хотим перезаписать уже существующий в EEPROM.
259
//по-этому после записи нового датчика в EEPROM мы должны заново проверить датчики на пине заменяемого старого датчика,
260
//а затем вернуться на предыдущий пин нового и продолжить поиск с того-же места,где прервали поиск.
261
//это позволяет добавлять/заменять/тасовать датчики по номерам,не меняя основную программу.
262
//в общем случае пины могут и совпадать, а поиск может и дублироваться повтором.
263
//эти значения заведомо больше, чем NumGroup, например:
264
byte
ReplaceNumPin = NumGroup + 1;
//номер группы(привязаной к пину) датчика на замену по номеру(остановка в непрерывном поиске)
265
byte
OldNumPin = NumGroup + 1;
//номер группы(привязаной к пину) старого датчика с тем-же номером
266
//делаем поиск датчиков перебирая пины
267
for
(
byte
Group = 0; Group < NumGroup; Group++) {
268
//т.к. ds.search(addr) не останавливается сам в поиске датчиков и идёт по-кругу, нам надо создать
269
//список их ID, и если ID повторяется - значит мы пошли на следующий круг...тут и выходим из него.
270
//в общем случае всё максимальное число датчиков может быть и на одном пине...поэтому:
271
byte
ID[MaxNumberSensor][9];
//список всех найденых на пине ID датчиков:ID[s][1_8] с их програмными номерами датчиков в EEPROM:ID[s][0].
272
//если ID[s][0]=0,то датчик не записан в EEPROM и по-этому он без номера.
273
for
(
byte
n = 0; n < MaxNumberSensor; n++) {
//обнуляем значения
274
for
(
byte
x = 0; x < 9; x++) {
275
ID[n][x] = 0;
276
}
277
}
278
//если хотим заменить датчик:
279
if
(OldNumPin != NumGroup + 1) {
280
Group = OldNumPin;
//проверяем группу заменяемого датчика
281
OldNumPin = NumGroup + 1;
//отменяем повтор на следующий цикл
282
}
283
else
if
(ReplaceNumPin != NumGroup + 1) {
284
Group = ReplaceNumPin;
//проверяем группу нового датчика на замену
285
ReplaceNumPin = NumGroup + 1;
//отменяем повтор на следующий цикл
286
}
287
OneWire ds(numPin[Group]);
//активизируем общение по очередному пину
288
Serial
.print(F(
"\r\nStart Search Pin #"
));
289
Serial
.println(numPin[Group]);
290
byte
addr[8];
//прочитанный ID датчика
291
byte
end_search = 0;
//число совершённых поисков датчиков на пине
292
byte
s = 0;
//порядковый номер в списке ID
293
byte
crc = 0;
//индекс числа повторов поиска датчиков при ошибке чтения "crc"
294
while
(end_search < 2) {
//ищем существующий ID датчика на пине
295
timeSens = millis();
// 4,294,967,295 max
296
//запускаем поиск датчиков на ограниченное время,
297
//в нашем случае = 2сек(с запасом)- т.к. возможно идентифицировать до 75 ROM в секунду
298
while
(ds.search(addr) != 1 && diftime < 200) {
//2sec
299
diftime =
int
(millis() - timeSens) / 10;
300
}
301
if
(diftime < 200) {
//если нашли датчик за это время, то проверяем CRC для его ID
302
if
(OneWire::crc8(addr, 7) != addr[7]) {
//если мусор
303
Serial
.println(F(
"Detected New Sensor but CRC is not valid!"
));
304
if
(crc == 0) {
//сброс и повтор поиска сначала
305
Serial
.println(F(
"Repeat Search..."
));
306
crc++;
307
ds.reset_search();
308
delay(250);
309
}
310
else
{
//уже повторяли поиск
311
Serial
.println(F(
"Skipping..."
));
312
}
313
}
314
else
{
//если корректный ID
315
//проверяем есть ли такой ID в списке
316
for
(
byte
n = 0; n < MaxNumberSensor; n++) {
317
if
(ID[n][8] == 0) {
//если попали на пустой ID ,то прекращаем поиск
318
break
;
319
}
320
byte
m = 0;
//иначе сравниваем побайтово значения записи с обнаруженым ID
321
for
(
byte
x = 0; x < 8; x++) {
322
if
(ID[n][x + 1] == addr[x]) {
323
m++;
324
}
325
else
{
//не совпадает
326
break
;
//идём к следующей записи
327
}
328
//"break" не даёт обойти "goto", по-этому - условие:
329
if
(m == 8) {
//если есть в списке, значит мы прошли полный цикл поиска с момента его сброса
330
Serial
.println(F(
"Checked All Possible IDs. Found Sensor IDs:"
));
331
goto
EndSearchPin;
//уходим на следующий пин
332
}
333
}
334
}
335
//если дошли сюда, то нашли новый ID и заносим его в список
336
for
(
byte
i = 0; i < 8; i++) {
337
ID[s][i + 1] = addr[i];
338
}
339
//проверяем, записан ли найденый датчик в EEPROM
340
byte
same = 0;
//индекс соответствия в поиске
341
for
(
int
eAddrSens = 0; eAddrSens < MaxNumberSensor * 9; eAddrSens = eAddrSens + 9) {
342
byte
Pin = EEPROM.read(eAddrSens);
343
if
(Pin == numPin[Group]) {
344
for
(
byte
n = eAddrSens + 1; n < eAddrSens + 9; n++) {
345
if
(addr[same] == EEPROM.read(n)) {
346
same++;
347
}
348
else
{
349
break
;
350
}
351
}
352
if
(same == 8) {
//если найден в EEPROM
353
Serial
.print(F(
"Sensor #"
));
354
Serial
.print(eAddrSens / 9 + 1);
355
Serial
.print(F(
" ID # "
));
356
for
(
byte
d = 0; d < 8; d++) {
357
Serial
.print(addr[d], HEX);
358
Serial
.write(
' '
);
359
}
360
Serial
.print(F(
"on Pin #"
));
361
Serial
.print(numPin[Group]);
362
Serial
.println(F(
" Already Recorded on EEPROM."
));
363
ID[s][0] = eAddrSens / 9 + 1;
//записываем номер датчика
364
break
;
365
}
366
else
{
367
same = 0;
368
}
369
}
370
}
371
if
(same == 0) {
//если нет в EEPROM, то датчик новый
372
Serial
.print(F(
"Detected New Sensor ID # "
));
373
for
(
byte
d = 0; d < 8; d++) {
374
Serial
.print(addr[d], HEX);
375
Serial
.write(
' '
);
376
}
377
Serial
.print(F(
"on Pin #"
));
378
Serial
.println(numPin[Group]);
379
Serial
.print(F(
"You Want to Add to EEPROM?\r\nWaiting for Answer:Sensor Number=(0<'?'<"
));
380
Serial
.print(MaxNumberSensor + 1);
381
Serial
.println(F(
")/NO='n'..."
));
382
String answer;
383
do
{
//ждём ответа пользователя
384
answer =
Serial
.readString();
385
byte
numSens = answer.toInt();
//теоретически тут можно начудить с ответом,
386
//по-этому дальше попросим подтверждения ответа
387
if
(answer ==
"n"
) {
//не хотим вносить в EEPROM
388
Serial
.println(F(
"Continue without Changes..."
));
389
//ID[s][0] = 0;//обнуляем номер датчика-он и был нулём
390
goto
ContSearchPin;
391
}
392
else
if
(numSens > 0) {
//если задали номер датчика,то смотрим его
393
Serial
.print(F(
"Sensor #"
));
394
Serial
.print(numSens);
395
numSens--;
//приводим к програмному значению
396
if
(numSens < MaxNumberSensor) {
//если в рамках допустимого
397
int
eAddrSens = numSens * 9;
//вычисляем начальный адрес ID датчика в EEPROM
398
if
(EEPROM.read(eAddrSens) == 255) {
//если он свободен(пустой)
399
Serial
.println(F(
"\r\nAre You Sure?\r\nWaiting for Answer:YES='y'/NO='n'..."
));
400
char
ans;
//просим подтверждения ответа
401
do
{
//ждём ответа пользователя
402
ans =
Serial
.read();
403
if
(ans ==
'n'
) {
//если ошиблись или передумали, то возвращаемся к предыдущему вопросу
404
Serial
.print(F(
"Waiting for Answer:Add to EEPROM Sensor Number=(0<'?'<"
));
405
Serial
.print(MaxNumberSensor + 1);
406
Serial
.println(F(
")/NO='n'..."
));
407
answer =
""
;
408
}
409
else
if
(ans ==
'y'
) {
//если согласны, то:(same==0)
410
EEPROM.write(eAddrSens, numPin[Group]);
//записываем номер пина в EEPROM
411
for
(
int
y = eAddrSens + 1; y < eAddrSens + 9; y++) {
// записываем ID датчика в EEPROM
412
EEPROM.write(y, addr[same]);
413
same++;
414
}
415
ID[s][0] = numSens + 1;
//записываем номер датчика в список
416
Serial
.println(F(
"Added."
));
417
}
418
else
if
(ans >= 0) {
//что-то ответили, но не то
419
Serial
.println(F(
"Waiting for the Correct Answer..."
));
420
ans =
'\0'
;
//ждём в цикле верный ответ
421
}
422
else
{
//ничего не ответили//ans == -1(int)
423
ans =
'\0'
;
//ждём в цикле ответ
424
}
425
}
426
while
(ans ==
'\0'
);
427
}
428
else
{
//если он не занят старой записью
429
Serial
.println(F(
" is Exists on EEPROM.You Want to Replace?\r\nWaiting for Answer:YES='y'/NO='n'/Change Number='c'..."
));
430
char
ans;
431
do
{
//ждём ответа пользователя
432
ans =
Serial
.read();
433
if
(ans ==
'n'
) {
//не хотим заменяь датчик в EEPROM
434
Serial
.println(F(
"Continue without Changes..."
));
435
//ID[s][0] = 0;//обнуляем номер датчика-он и был нулём
436
goto
ContSearchPin;
437
}
438
else
if
(ans ==
'c'
) {
//хотим поменяь номер датчика
439
Serial
.print(F(
"Waiting for Answer:Add Sensor Number=(0<'?'<"
));
440
Serial
.print(MaxNumberSensor + 1);
441
Serial
.println(F(
")/NO='n'..."
));
442
answer =
""
;
//ждём в цикле ответ
443
}
444
else
if
(ans ==
'y'
) {
//если согласны заменить датчик
445
ReplaceNumPin = Group;
//запоминаем номер группы найденого нового датчика
446
OldNumPin = EEPROM.read(eAddrSens);
//читаем\запоминаем номер пина старого датчика
447
for
(
byte
i = 0; i < NumGroup; i++) {
//переводим номер пина старого датчика в номер его группы
448
if
(numPin[i] == OldNumPin) {
449
OldNumPin = i;
//запоминаем номер группы старого датчика
450
break
;
451
}
452
}
453
//проверяем, есть ли старый ID в списке
454
for
(
byte
n = 0; n < MaxNumberSensor; n++) {
455
if
(ID[n][8] == 0) {
//если попали на пустой ID ,то прекращаем поиск
456
break
;
457
}
458
byte
m = 0;
//иначе
459
for
(
byte
x = 1; x < 9; x++) {
//сравниваем побайтово записи
460
if
(ID[n][x] == EEPROM.read(eAddrSens + x)) {
461
m++;
462
}
463
else
{
//если не соответствует, то переходим к следующей записи
464
break
;
465
}
466
//если дошли сюда, значит ID есть в списке с порядковым номером "n".
467
if
(n == MaxNumberSensor - 1) {
//если запись последняя, то просто обнуляем её
468
for
(
byte
i = 0; i < 9; i++) {
469
ID[n][i] = 0;
470
}
471
}
472
else
{
//иначе, затираем её,сдвигая все записи
473
for
(
byte
z = n; z < MaxNumberSensor; z++) {
474
if
(ID[z][8] == 0) {
//если попали на пустой ID,
475
break
;
//то прекращаем перезапись
476
}
477
for
(
byte
i = 0; i < 9; i++) {
478
ID[z][i] = ID[z + 1][i];
479
}
480
}
481
}
482
s--;
//уменьшаем количество записей на одну
483
}
484
if
(m == 8) {
//если уже нашли старый ID в списке, то прекращаем поиск
485
break
;
486
}
487
}
488
489
EEPROM.write(eAddrSens, numPin[Group]);
//записываем номер пина в EEPROM(same==0)
490
for
(
int
y = eAddrSens + 1; y < eAddrSens + 9; y++) {
// записываем ID датчика в EEPROM
491
EEPROM.write(y, addr[same]);
492
same++;
493
}
494
ID[s][0] = numSens + 1;
//записываем номер датчика в список
495
Serial
.println(F(
"Replaced."
));
496
ds.reset_search();
497
delay(250);
498
}
499
else
if
(ans >= 0) {
500
Serial
.println(F(
"Waiting for the Correct Answer..."
));
501
ans =
'\0'
;
502
}
503
else
{
504
ans =
'\0'
;
505
}
506
}
507
while
(ans ==
'\0'
);
508
}
509
}
510
else
{
511
Serial
.print(numSens + 1);
512
Serial
.println(F(
" is greater than the maximum number of sensors = "
));
513
Serial
.print(MaxNumberSensor);
514
answer =
""
;
515
}
516
}
517
else
if
(answer ==
""
) {
518
//answer = "";
519
}
520
else
{
521
Serial
.println(F(
"Waiting for the Correct Answer..."
));
522
answer =
""
;
523
}
524
}
525
while
(answer ==
""
);
526
}
527
}
528
}
529
else
{
530
Serial
.print(F(
"Sensors not Found."
));
531
if
(end_search == 0) {
532
Serial
.println(F(
"Repeat Search..."
));
533
ds.reset_search();
534
delay(250);
535
}
536
else
{
537
Serial
.println(F(
"Skipping..."
));
538
}
539
end_search++;
540
}
541
ContSearchPin:
542
s++;
543
if
(s == MaxNumberSensor) {
544
Serial
.print(F(
"Found maximum number of sensors = "
));
545
Serial
.println(MaxNumberSensor);
546
break
;
//выходим из поиска на пине
547
}
548
diftime = 0;
549
}
550
EndSearchPin:
551
for
(
byte
n = 0; n < s; n++) {
// значения по порядку нахождения ID
552
if
(ID[n][8] != 0) {
553
Serial
.print(F(
"Sensor #"
));
554
for
(
byte
x = 0; x < 9; x++) {
555
Serial
.print(ID[n][x], HEX);
556
Serial
.write(
' '
);
557
}
558
if
(ID[n][0] == 0) {
559
Serial
.print(F(
"Not writed to EEPROM."
));
560
}
561
Serial
.println();
562
}
563
}
564
Serial
.print(F(
"End Search Pin #"
));
565
Serial
.println(numPin[Group]);
566
}
567
}
написал тут программу поиска\замены датчиков...
думаю будет полезно для новичков, каким я и являюсь,
для понимания их работы.
> goto EndSearchPin
По рукам линейкой за такое.
профееееессор... и грубиян.
Прочитай про функции и отучайся от подобного говнокодерства.
ну я же говорю - грубиян.
Да, Си-шники не любят оператор goto. А мне вот, после ассемблера, тоже очень трудно без него обходиться. Хотя стараюсь.
001
#include <EEPROM.h>
002
#include <OneWire.h>
003
// OneWire DS18B20 only
004
//Скетч использует 11 550 байт (35%) памяти устройства. Всего доступно 32 256 байт.
005
//Глобальные переменные используют 455 байт (22%) динамической памяти,
006
//оставляя 1 593 байт для локальных переменных. Максимум: 2 048 байт.
007
/* UNO:
008
32 кБ флэш памяти
009
2 кБ ОЗУ (SRAM)
010
1 Кб EEPROM
011
14 цифровых выводов
012
Последовательная шина: 0 (RX) и 1 (TX)
013
Внешнее прерывание: 2 и 3
014
ШИМ: 3, 5, 6, 9, 10, 11
015
SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK).
016
LED: 13
017
I2C: 4 (SDA) и 5 (SCL).
018
6 аналоговых входов (обозначенных как A0 .. A5)/14..19 в качестве цифровых выводов
019
7, 8 - только для цифровых выводов
020
*/
021
022
#define NumGroup 18 //количество задействованных пинов для датчиков
023
#define MaxNumberSensor 113 //максимальное число датчиков, ограниченное объёмом EEPROM
024
//113x9=1017<1024 byte max EEPROM
025
unsigned
long
timeSens;
//время события
026
int
diftime = 0;
//разница времени между двумя событиями
027
//список номеров задействованных пинов:
028
byte
numPin[NumGroup] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
//for UNO: A0..A5=>14..19
029
int
Sensor[MaxNumberSensor];
//значения измерянной температуры
030
boolean ReadSens =
false
;
//признак чтения\записи датчика
031
boolean boot =
false
;
//признак завершения полного первого цикла записи\чтения всех датчиков
032
byte
present;
//признак готовности датчика к ответу
033
//без паразитного питания - если датчик готов к ответу =1,иначе =0. для паразитного питания - читайте документацию
034
035
void
setup
() {
036
Serial
.begin(9600);
037
timeSens = millis();
// 4,294,967,295 max
038
Serial
.println(F(
"If you Need to Run the Automatic Scanning T* Sensors DS18B20 - Send Any Value\r\nWaiting for Answer 10sec..."
));
039
//ждём ответа пользователя 10 секунд
040
while
(
Serial
.read() == -1 && diftime < 100) {
041
diftime =
int
(millis() - timeSens) / 100;
042
}
043
if
(diftime < 100) {
//если согласились на автоматическое сканирование датчиков
044
Serial
.println(F(
"Runing..."
));
045
//проверяем присутствие уже записаных в EEPROM датчиков по их номерам:
046
//каждый 9-й адрес(включая нулевой) в EEPROM соответствует порядковому номеру датчика,
047
//по нему и может обращаться программа контроля температуры;
048
//его значение совпадает с номером пина, к которому подключён датчик.
049
//MaxNumberSensor * 9 - число задействованных адресов в EEPROM(макс. 113x9 для UNO)
050
for
(
int
eAddrSens = 0; eAddrSens < MaxNumberSensor * 9; eAddrSens = eAddrSens + 9) {
051
byte
Pin = EEPROM.read(eAddrSens);
//читаем номер пина в EEPROM
052
if
(Pin != 255) {
//значит - записан в EEPROM
053
byte
n = 0;
054
byte
ID[8];
//собираем его ID
055
for
(
int
i = eAddrSens + 1; i < eAddrSens + 9; i++) {
056
ID[n] = EEPROM.read(i);
057
n++;
058
}
059
OneWire ds(Pin);
//активизируем общение по записанному пину
060
n = 0;
//количество возможных повторов опроса датчика
061
while
(n < 3) {
062
present = ds.reset();
//если датчик готов к ответу present=1.
063
//полезно только для общего случая:
064
//если на пине больше одного датчика, то пользы мало - ответят все,
065
//но "ds.reset();" обязан быть до начала общения с датчиком.
066
ds.select(ID);
//выбираем датчик по записанному ID
067
//без преобразования - значение не важно, важно наличие верного ответа
068
ds.write(0xBE);
//Чтение памяти(+85*С после сброса питания или предыдущее значение измерения без сброса)
069
byte
data[9];
070
Serial
.println();
071
//смотрим ответ датчика - для индикации
072
for
(
byte
d = 0; d < 9; d++) {
//собираем его ответ
073
data[d] = ds.read();
//читаем по-байтово
074
Serial
.print(data[d], HEX);
075
Serial
.print(
' '
);
076
}
077
Serial
.print(
"CRC="
);
078
byte
CRC = OneWire::crc8(data, 8);
079
Serial
.println(CRC, HEX);
080
int
T = (data[1] << 8) | data[0];
//может быть и отрицательным
081
T = (T + 8) >> 4;
//целые *C с округлением
082
Serial
.print(F(
"Temp = "
));
083
Serial
.print(T);
//0*C - если датчик отсутсвует
084
Serial
.println(F(
"*C"
));
085
//проверяем ответ датчика. если датчик отсутсвует:
086
//1.если датчик на дигитальном пине:
087
//-если резистор подключён к пину, то data = {FF FF FF FF FF FF FF FF FF},а CRC=C9 и != FF(data[8])
088
//-если пин висит в воздухе, то data = {0 0 0 0 0 0 0 0 0},а CRC=0 и == 0(data[8])
089
//2.если датчик на аналоговом пине:
090
//-если резистор подключён к пину, то data = {FF FF FF FF FF FF FF FF FF},а CRC=C9 и != FF(data[8])
091
//-если пин висит в воздухе, то в зависимости от наводок сработает один из двух вариантов
092
// дигитального пина или 'CRC' общего случая, если наводки прыгают на грани срабатывания
093
//по-этому:
094
if
(CRC != data[8] || present == 0 || CRC == 0) {
//датчик отсутсвует или мусор
095
n++;
096
delay(100);
//повторяем опрос датчика
097
}
098
else
{
//опрос успешный
099
break
;
100
}
101
}
102
//обобщаем данные
103
Serial
.print(F(
"Sensor #"
));
104
Serial
.print(eAddrSens / 9 + 1);
105
Serial
.print(F(
" ID from EEPROM # "
));
106
for
(
byte
d = 0; d < 8; d++) {
107
Serial
.print(ID[d], HEX);
108
Serial
.write(
' '
);
109
}
110
Serial
.print(F(
"on Pin #"
));
111
Serial
.print(Pin);
112
if
(n == 3) {
//если датчик отсутсвует
113
Serial
.println(F(
" not Responds.\r\nWaiting for Answer: Delete = 'd', Skip = 's'..."
));
114
char
answer;
115
do
{
//ждём ответа пользователя
116
answer =
Serial
.read();
117
if
(answer ==
'd'
) {
//удаляем датчик из EEPROM
118
for
(
int
i = eAddrSens; i < eAddrSens + 9; i++) {
119
EEPROM.write(i, 255);
120
}
121
Serial
.println(F(
"Deleted."
));
122
}
123
else
if
(answer ==
's'
) {
//пропускаем до выяснения потом
124
Serial
.println(F(
"Skipped."
));
125
}
126
else
if
(answer >= 0) {
//что-то ответили, но не то
127
Serial
.println(F(
"Waiting for the Correct Answer..."
));
128
answer =
'\0'
;
//ждём в цикле верный ответ
129
}
130
else
{
//ничего не ответили//answer == -1(int)
131
answer =
'\0'
;
//ждём в цикле ответ
132
}
133
}
134
while
(answer ==
'\0'
);
135
}
136
else
{
//всё впорядке
137
Serial
.println(F(
" is Exists and Responds."
));
138
}
139
}
140
}
141
SearchSensor();
142
}
143
else
{
144
Serial
.println(F(
"Skipping..."
));
145
}
146
Serial
.println(F(
"\r\nEnd Setup.\r\nIf you Need to Run the Automatic Scanning during program execution - Send Value 's'.\r\n"
));
147
}
148
//======================================================================
149
void
loop
() {
150
//надо помнить, что исполнение основной программы управления и выходы
151
//зависают в том положении, в котором мы остановились в момент начала поиска\удаления датчиков
152
if
(
Serial
.read() ==
's'
) {
//если хотим проверить датчики без перезагрузки
153
SearchSensor();
154
ReadSens =
false
;
155
boot =
false
;
156
}
157
else
if
(
Serial
.read() ==
'd'
) {
//если хотим удалить датчик без перезагрузки
158
Serial
.print(F(
"\r\nWaiting for Answer: Delete Sensor Number=(0<'?'<"
));
159
Serial
.print(MaxNumberSensor + 1);
160
Serial
.println(F(
")/NO='n'..."
));
161
String answer;
162
do
{
//ждём ответа пользователя
163
answer =
Serial
.readString();
164
byte
numSens = answer.toInt();
//теоретически тут можно начудить с ответом,
165
//по-этому дальше попросим подтверждения ответа
166
if
(answer ==
"n"
) {
//не хотим удалять из EEPROM
167
Serial
.println(F(
"Continue without Changes..."
));
168
//продожаем исполнение основной программы
169
}
170
else
if
(numSens > 0) {
//если задали номер датчика,то смотрим его
171
Serial
.print(F(
"Sensor Number = "
));
172
Serial
.print(numSens);
173
Serial
.println(F(
"\r\nAre You Sure?\r\nWaiting for Answer:YES='y'/NO='n'..."
));
174
char
ans;
//просим подтверждения ответа
175
do
{
//ждём ответа пользователя
176
ans =
Serial
.read();
177
if
(ans ==
'n'
) {
//если ошиблись или передумали, то возвращаемся к предыдущему вопросу
178
Serial
.print(F(
"Waiting for Answer:Delete Sensor Number=(0<'?'<"
));
179
Serial
.print(MaxNumberSensor + 1);
180
Serial
.println(F(
")/NO='n'..."
));
181
answer =
""
;
182
}
183
else
if
(ans ==
'y'
) {
//если согласны, то:
184
int
eAddrSens = (numSens - 1) * 9;
//вычисляем начальный адрес ID датчика в EEPROM
185
for
(
int
y = eAddrSens; y < eAddrSens + 9; y++) {
//стираем датчик из EEPROM
186
EEPROM.write(y, 255);
187
}
188
Serial
.println(F(
"Deleted."
));
189
//продожаем исполнение основной программы
190
}
191
else
if
(ans >= 0) {
//что-то ответили, но не то
192
Serial
.println(F(
"Waiting for the Correct Answer..."
));
193
ans =
'\0'
;
//ждём в цикле верный ответ
194
}
195
else
{
//ничего не ответили//ans == -1(int)
196
ans =
'\0'
;
//ждём в цикле ответ
197
}
198
}
199
while
(ans ==
'\0'
);
200
}
201
}
202
while
(answer ==
""
);
203
ReadSens =
false
;
204
boot =
false
;
205
}
206
else
{
//в програмном режиме
207
if
(timeSens > millis()) {
208
diftime =
int
(4294967295 - timeSens + millis());
209
}
210
else
{
211
diftime =
int
(millis() - timeSens);
212
}
213
if
(ReadSens ==
false
) {
214
for
(
byte
i = 0; i < NumGroup; i++) {
215
OneWire ds(numPin[i]);
216
// обращение ко всем датчикам шины сразу:
217
ds.reset();
//сброс шины
218
ds.write(0xCC);
//Игнорировать адрес
219
if
(boot ==
false
) {
//имеет смысл при первом запуске или замене\добавлении датчиков
220
ds.write(0x4E);
//разрешение записать конфиг //write scratchpad (starts at byte 2)
221
//задаём аварийные температуры(верхняя\нижняя) - изменить, если пользуетесь
222
ds.write(0x4B);
//default value of TH reg (user byte 1) - верхняя
223
ds.write(0x46);
//default value of TL reg (user byte 2) - нижняя
224
//задаём точность измерения датчика(от неё зависит время преобразованя)= 0,125гр
225
ds.write(0x5F);
//default value of Config = 0x7F (user byte 3)
226
//точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F - подставить нужное\учесть время преобразования
227
ds.write(0x48);
// копируем три байта в EEPROM DS18B20, чтобы сохранить постоянно
228
}
229
ds.write(0x44);
//начать преобразование температуры(без паразитного питания)
230
}
231
ReadSens =
true
;
232
timeSens = millis();
233
}
234
else
if
(ReadSens ==
true
&& diftime >= 500) {
//500ms(с запасом)-т.к. время преобразования 375ms для (0x5F)
235
for
(
byte
NumSens = 0; NumSens < MaxNumberSensor; NumSens++) {
236
int
AddrSensor = NumSens * 9;
237
byte
Pin = EEPROM.read(AddrSensor);
238
if
(Pin != 255) {
239
OneWire ds(Pin);
240
byte
m = 0;
241
byte
ID[8];
242
Serial
.print(F(
"Sensor ID #"
));
243
for
(
int
id = AddrSensor + 1; id < AddrSensor + 9; id++) {
244
ID[m] = EEPROM.read(id);
245
Serial
.print(ID[m], HEX);
246
Serial
.write(
' '
);
247
m++;
248
}
249
Serial
.println();
250
byte
crc = 0;
//индекс числа повторов опроса датчика
251
while
(crc < 3) {
252
present = ds.reset();
//коментарии в "void setup()"
253
ds.select(ID);
254
ds.write(0xBE);
//Чтение памяти
255
byte
data[9];
256
for
(
byte
i = 0; i < 9; i++) {
257
data[i] = ds.read();
258
}
259
//проверяем ответ датчика
260
byte
CRC = OneWire::crc8(data, 8);
//коментарии в "void setup()"
261
if
(CRC == data[8] && present == 1 && CRC != 0) {
//ответ корректный
262
Sensor[NumSens] = (data[1] << 8) | data[0];
263
Sensor[NumSens] = (Sensor[NumSens] * 10) >> 4;
//целое в десятых *C (214=>21,4*C)//(t*10)>>4 == (t*10)/16
264
break
;
265
}
266
else
{
//датчик отсутсвует или мусор
267
crc++;
268
Serial
.print(F(
"Sensor Error "
));
269
Serial
.println(crc);
270
delay(100);
271
}
272
}
273
Serial
.print(F(
"Sensor #"
));
274
Serial
.print(NumSens + 1);
275
if
(crc == 3) {
276
Serial
.println(F(
" Error.\r\n"
));
277
}
278
else
{
279
Serial
.print(F(
" Temp: "
));
280
Serial
.print(Sensor[NumSens] / 10);
281
Serial
.write(
','
);
282
Serial
.print(Sensor[NumSens] % 10);
//если в десятых *C
283
Serial
.println(F(
"*C.\r\n"
));
284
}
285
}
286
else
if
(boot ==
false
) {
287
Serial
.print(F(
"Sensor #"
));
288
Serial
.print(NumSens + 1);
289
Serial
.println(F(
" is Blank.\r\n"
));
290
}
291
}
292
boot =
true
;
293
ReadSens =
false
;
294
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
295
//место основной программы для Sensor[Sensor Number],
296
//т.к. в другом месте значения не меняются
297
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
298
}
299
}
300
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
301
//место другой основной программы
302
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
303
}
304
//=========================================================================================
305
void
SearchSensor()
306
{
307
//задавая номер обнаруженного нового датчика мы можем/хотим перезаписать уже существующий в EEPROM.
308
//по-этому после записи нового датчика в EEPROM мы должны заново проверить датчики на пине заменяемого старого датчика,
309
//а затем вернуться на предыдущий пин нового и продолжить поиск с того-же места,где прервали поиск.
310
//это позволяет добавлять/заменять/тасовать датчики по номерам,не меняя основную программу.
311
//в общем случае пины могут и совпадать, а поиск может и дублироваться повтором.
312
//эти значения заведомо больше, чем NumGroup, например:
313
byte
ReplaceNumPin = NumGroup + 1;
//номер группы(привязаной к пину) датчика на замену по номеру(остановка в непрерывном поиске)
314
byte
OldNumPin = NumGroup + 1;
//номер группы(привязаной к пину) старого датчика с тем-же номером
315
//делаем поиск датчиков перебирая пины
316
for
(
byte
Group = 0; Group < NumGroup; Group++) {
317
//т.к. ds.search(addr) не останавливается сам в поиске датчиков и идёт по-кругу, нам надо создать
318
//список их ID, и если ID повторяется - значит мы пошли на следующий круг...тут и выходим из него.
319
//в общем случае всё максимальное число датчиков может быть и на одном пине...поэтому:
320
byte
ID[MaxNumberSensor][9];
//список всех найденых на пине ID датчиков:ID[s][1_8] с их програмными номерами датчиков в EEPROM:ID[s][0].
321
//если ID[s][0]=0,то датчик не записан в EEPROM и по-этому он без номера.
322
for
(
byte
n = 0; n < MaxNumberSensor; n++) {
//обнуляем значения
323
for
(
byte
x = 0; x < 9; x++) {
324
ID[n][x] = 0;
325
}
326
}
327
Serial
.println();
328
//если хотим заменить датчик:
329
if
(OldNumPin != NumGroup + 1) {
330
Group = OldNumPin;
//проверяем группу заменяемого датчика
331
OldNumPin = NumGroup + 1;
//отменяем повтор на следующий цикл
332
Serial
.print(F(
"Re"
));
333
}
334
else
if
(ReplaceNumPin != NumGroup + 1) {
335
Group = ReplaceNumPin;
//проверяем группу нового датчика на замену
336
ReplaceNumPin = NumGroup + 1;
//отменяем повтор на следующий цикл
337
Serial
.print(F(
"Re"
));
338
}
339
OneWire ds(numPin[Group]);
//активизируем общение по очередному пину
340
Serial
.print(F(
"Start Search Pin #"
));
341
Serial
.println(numPin[Group]);
342
byte
addr[8];
//прочитанный ID датчика
343
byte
end_search = 0;
//число совершённых поисков датчиков на пине
344
byte
s = 0;
//порядковый номер в списке ID
345
byte
crc = 0;
//индекс числа повторов поиска датчиков при ошибке чтения "crc"
346
while
(end_search < 2) {
//ищем существующий ID датчика на пине
347
timeSens = millis();
// 4,294,967,295 max
348
//запускаем поиск датчиков на ограниченное время,
349
//в нашем случае = 2сек(с запасом)- т.к. возможно идентифицировать до 75 ROM в секунду
350
while
(ds.search(addr) != 1 && diftime < 200) {
//2sec
351
diftime =
int
(millis() - timeSens) / 10;
352
}
353
byte
m = 0;
//индекс нахождения записи в списке ID
354
if
(diftime < 200) {
//если нашли датчик за это время, то проверяем CRC для его ID
355
if
(OneWire::crc8(addr, 7) != addr[7]) {
//если мусор
356
Serial
.println(F(
"Detected New Sensor but CRC is not valid!"
));
357
if
(crc == 0) {
//сброс и повтор поиска сначала
358
Serial
.println(F(
"Repeat Search..."
));
359
crc++;
360
ds.reset_search();
361
delay(250);
362
}
363
else
{
//уже повторяли поиск
364
Serial
.println(F(
"Skipping..."
));
365
}
366
}
367
else
{
//если корректный ID
368
//проверяем есть ли такой ID в списке
369
for
(
byte
n = 0; n < MaxNumberSensor; n++) {
370
if
(ID[n][8] == 0) {
//если попали на пустой ID ,то прекращаем поиск
371
break
;
372
}
373
//иначе сравниваем побайтово значения записи с обнаруженым ID
374
for
(
byte
x = 0; x < 8; x++) {
375
if
(ID[n][x + 1] == addr[x]) {
376
m++;
377
}
378
else
{
//не совпадает
379
break
;
//идём к следующей записи
380
}
381
if
(m == 8) {
//запись обнаружена
382
break
;
383
}
384
}
385
if
(m == 8) {
//запись уже обнаружена
386
break
;
387
}
388
m = 0;
389
}
390
if
(m == 8) {
//если есть в списке, значит мы прошли полный цикл поиска с момента его сброса
391
Serial
.println(F(
"Checked All Possible IDs. Found Sensor IDs:"
));
392
break
;
//выходим из поиска на пине
393
}
394
else
{
//если нет, то нашли новый ID и заносим его в список
395
for
(
byte
i = 0; i < 8; i++) {
396
ID[s][i + 1] = addr[i];
397
}
398
//проверяем, записан ли найденый датчик в EEPROM
399
byte
same = 0;
//индекс соответствия в поиске
400
for
(
int
eAddrSens = 0; eAddrSens < MaxNumberSensor * 9; eAddrSens = eAddrSens + 9) {
401
byte
Pin = EEPROM.read(eAddrSens);
402
if
(Pin == numPin[Group]) {
403
for
(
int
n = eAddrSens + 1; n < eAddrSens + 9; n++) {
404
if
(addr[same] == EEPROM.read(n)) {
405
same++;
406
}
407
else
{
408
break
;
409
}
410
}
411
if
(same == 8) {
//если найден в EEPROM
412
Serial
.print(F(
"Sensor #"
));
413
Serial
.print(eAddrSens / 9 + 1);
414
Serial
.print(F(
" ID # "
));
415
for
(
byte
d = 0; d < 8; d++) {
416
Serial
.print(addr[d], HEX);
417
Serial
.write(
' '
);
418
}
419
Serial
.print(F(
"on Pin #"
));
420
Serial
.print(numPin[Group]);
421
Serial
.println(F(
" Already Recorded on EEPROM."
));
422
ID[s][0] = eAddrSens / 9 + 1;
//записываем номер датчика
423
break
;
424
}
425
else
{
426
same = 0;
427
}
428
}
429
}
430
if
(same == 0) {
//если нет в EEPROM, то датчик новый
431
Serial
.print(F(
"Detected New Sensor ID # "
));
432
for
(
byte
d = 0; d < 8; d++) {
433
Serial
.print(addr[d], HEX);
434
Serial
.write(
' '
);
435
}
436
Serial
.print(F(
"on Pin #"
));
437
Serial
.println(numPin[Group]);
438
Serial
.print(F(
"You Want to Add to EEPROM?\r\nWaiting for Answer:Sensor Number=(0<'?'<"
));
439
Serial
.print(MaxNumberSensor + 1);
440
Serial
.println(F(
")/NO='n'..."
));
441
String answer;
442
do
{
//ждём ответа пользователя
443
answer =
Serial
.readString();
444
byte
numSens = answer.toInt();
//теоретически тут можно начудить с ответом,
445
//по-этому дальше попросим подтверждения ответа
446
if
(answer ==
"n"
) {
//не хотим вносить в EEPROM
447
Serial
.println(F(
"Continue without Changes..."
));
448
//ID[s][0] = 0;//обнуляем номер датчика-он и был нулём
449
break
;
//продожаем поиск датчиков на пине
450
}
451
else
if
(numSens > 0) {
//если задали номер датчика,то смотрим его
452
Serial
.print(F(
"Sensor Number = "
));
453
Serial
.print(numSens);
454
numSens--;
//приводим к програмному значению
455
if
(numSens < MaxNumberSensor) {
//если в рамках допустимого
456
int
eAddrSens = numSens * 9;
//вычисляем начальный адрес ID датчика в EEPROM
457
if
(EEPROM.read(eAddrSens) == 255) {
//если он свободен(пустой)
458
Serial
.println(F(
"\r\nAre You Sure?\r\nWaiting for Answer:YES='y'/NO='n'..."
));
459
char
ans;
//просим подтверждения ответа
460
do
{
//ждём ответа пользователя
461
ans =
Serial
.read();
462
if
(ans ==
'n'
) {
//если ошиблись или передумали, то возвращаемся к предыдущему вопросу
463
Serial
.print(F(
"Waiting for Answer:Add to EEPROM Sensor Number=(0<'?'<"
));
464
Serial
.print(MaxNumberSensor + 1);
465
Serial
.println(F(
")/NO='n'..."
));
466
answer =
""
;
467
}
468
else
if
(ans ==
'y'
) {
//если согласны, то:(same==0)
469
EEPROM.write(eAddrSens, numPin[Group]);
//записываем номер пина в EEPROM
470
for
(
int
y = eAddrSens + 1; y < eAddrSens + 9; y++) {
// записываем ID датчика в EEPROM
471
EEPROM.write(y, addr[same]);
472
same++;
473
}
474
ID[s][0] = numSens + 1;
//записываем номер датчика в список
475
Serial
.println(F(
"Added."
));
476
}
477
else
if
(ans >= 0) {
//что-то ответили, но не то
478
Serial
.println(F(
"Waiting for the Correct Answer..."
));
479
ans =
'\0'
;
//ждём в цикле верный ответ
480
}
481
else
{
//ничего не ответили//ans == -1(int)
482
ans =
'\0'
;
//ждём в цикле ответ
483
}
484
}
485
while
(ans ==
'\0'
);
486
}
487
else
{
//если он занят старой записью
488
Serial
.println(F(
" is Exists on EEPROM.You Want to Replace?\r\nWaiting for Answer:YES='y'/NO='n'/Change Number='c'..."
));
489
char
ans;
490
do
{
//ждём ответа пользователя
491
ans =
Serial
.read();
492
if
(ans ==
'n'
) {
//не хотим заменяь датчик в EEPROM
493
Serial
.println(F(
"Continue without Changes..."
));
494
//ID[s][0] = 0;//обнуляем номер датчика-он и был нулём
495
break
;
//продожаем поиск датчиков на пине
496
}
497
else
if
(ans ==
'c'
) {
//хотим поменяь номер датчика
498
Serial
.print(F(
"Waiting for Answer:Add Sensor Number=(0<'?'<"
));
499
Serial
.print(MaxNumberSensor + 1);
500
Serial
.println(F(
")/NO='n'..."
));
501
answer =
""
;
//ждём в цикле ответ
502
}
503
else
if
(ans ==
'y'
) {
//если согласны заменить датчик
504
ReplaceNumPin = Group;
//запоминаем номер группы найденого нового датчика
505
OldNumPin = EEPROM.read(eAddrSens);
//читаем\запоминаем номер пина старого датчика
506
for
(
byte
i = 0; i < NumGroup; i++) {
//переводим номер пина старого датчика в номер его группы
507
if
(numPin[i] == OldNumPin) {
508
OldNumPin = i;
//запоминаем номер группы старого датчика
509
break
;
510
}
511
}
512
//проверяем, есть ли старый ID в списке
513
for
(
byte
n = 0; n < MaxNumberSensor; n++) {
514
if
(ID[n][8] == 0) {
//если попали на пустой ID ,то прекращаем поиск
515
break
;
516
}
517
//иначе
518
byte
y = 0;
//индекс нахождения ID в списке
519
for
(
byte
x = 1; x < 9; x++) {
//сравниваем побайтово записи
520
if
(ID[n][x] == EEPROM.read(eAddrSens + x)) {
521
y++;
522
}
523
else
{
//если не соответствует, то переходим к следующей записи
524
break
;
525
}
526
if
(y == 8) {
//если дошли сюда, значит ID есть в списке с порядковым номером "n".
527
if
(n == MaxNumberSensor - 1) {
//если запись последняя, то просто обнуляем её
528
for
(
byte
i = 0; i < 9; i++) {
529
ID[n][i] = 0;
530
}
531
}
532
else
{
//иначе, затираем её,сдвигая все записи
533
for
(
byte
z = n; z < MaxNumberSensor; z++) {
534
if
(ID[z][8] == 0) {
//если попали на пустой ID,
535
break
;
//то прекращаем перезапись
536
}
537
for
(
byte
i = 0; i < 9; i++) {
538
ID[z][i] = ID[z + 1][i];
539
}
540
}
541
}
542
s--;
//уменьшаем количество записей на одну
543
break
;
//если нашли старый ID в списке, то прекращаем сравнение
544
}
545
}
546
if
(y == 8) {
//если уже нашли старый ID в списке, то прекращаем поиск
547
break
;
548
}
549
}
550
EEPROM.write(eAddrSens, numPin[Group]);
//записываем номер пина в EEPROM(same==0)
551
for
(
int
y = eAddrSens + 1; y < eAddrSens + 9; y++) {
// записываем ID датчика в EEPROM
552
EEPROM.write(y, addr[same]);
553
same++;
554
}
555
ID[s][0] = numSens + 1;
//записываем номер датчика в список
556
Serial
.println(F(
"Replaced."
));
557
ds.reset_search();
558
delay(250);
559
}
560
else
if
(ans >= 0) {
561
Serial
.println(F(
"Waiting for the Correct Answer..."
));
562
ans =
'\0'
;
563
}
564
else
{
565
ans =
'\0'
;
566
}
567
}
568
while
(ans ==
'\0'
);
569
}
570
}
571
else
{
572
Serial
.print(F(
" is greater than the maximum number of sensors = "
));
573
Serial
.println(MaxNumberSensor);
574
Serial
.println(F(
"Waiting for the Correct Number..."
));
575
answer =
""
;
576
}
577
}
578
else
if
(answer ==
""
) {
579
//answer = "";
580
}
581
else
{
582
Serial
.println(F(
"Waiting for the Correct Answer..."
));
583
answer =
""
;
584
}
585
}
586
while
(answer ==
""
);
587
}
588
}
589
}
590
s++;
591
}
592
else
{
593
Serial
.print(F(
"Sensors not Found."
));
594
if
(end_search == 0) {
595
Serial
.println(F(
"Repeat Search..."
));
596
ds.reset_search();
597
delay(250);
598
}
599
else
{
600
Serial
.println(F(
"Skipping..."
));
601
}
602
end_search++;
603
}
604
if
(s == MaxNumberSensor) {
605
Serial
.print(F(
"Found maximum number of sensors = "
));
606
Serial
.println(MaxNumberSensor);
607
break
;
//выходим из поиска на пине
608
}
609
diftime = 0;
610
}
611
for
(
byte
n = 0; n < s; n++) {
// значения по порядку нахождения ID
612
Serial
.print(F(
"Sensor #"
));
613
Serial
.print(ID[n][0]);
614
Serial
.print(F(
" ID # "
));
615
for
(
byte
x = 1; x < 9; x++) {
616
Serial
.print(ID[n][x], HEX);
617
Serial
.write(
' '
);
618
}
619
if
(ID[n][0] == 0) {
620
Serial
.print(F(
"Not writed to EEPROM."
));
621
}
622
Serial
.println();
623
}
624
Serial
.print(F(
"End Search Pin #"
));
625
Serial
.println(numPin[Group]);
626
}
627
}
по просьбе отдельных професоров ушёл от "goto",
заодно дополнив кое-что и исправив неколько описок\багов и коментариев...
вроде работает...
1
<span style=
"font-family:Verdana, Geneva, Arial, sans-serif;font-size:12px;line-height:1.5em;"
>по просьбе отдельных професоров ушёл от
"goto"
,</span>
вроде работает...
1) Не обращайте внимание на "профессоров". Главное, что бы работало.
2)А вот "вроде работает" опускает Вас значительно ниже чем чем "goto".
Успехов!
1
<span style=
"line-height:1.5em;font-family:Verdana, Geneva, Arial, sans-serif;font-size:12px;"
>по просьбе отдельных професоров ушёл от
"goto"
,</span>
вроде работает...
1) Не обращайте внимание на "профессоров". Главное, что бы работало.
2)А вот "вроде работает" опускает Вас значительно ниже чем чем "goto".
Успехов!
какую не прогнозируюмую реакцию может вызвать попытка выражения скромности...
но это недостаток всех форумов: больше воды, чем обсуждения по сути...
а суть в данном случае, по-моему, в следуещем:
я попытался показать способ исправления недостатка библиотеки в поиске датчиков
(на мой взгляд, если я её правильно понял; - тоже не факт)
применительно к желанию пользователей(и моему тоже) автоматически зафиксировать их
(удалять\добавлять\тасовать\заменять) путём создания временного списка их ID,
что-бы остановить в нужном месте поиск, иначе он годится только для ручного вбивания
адресов в программу(и почему это "просто" не сделано в библеотеке?).
плюс общеизвестный способ хранения ID в EEPROM,
плюс упорядочение и так доступной информации по датчикам для новичков...
а код... он зависит от времени пребывания в нём... никто не идеален,
иначе нафиг нужны форумы? для взаимного выяснения IQ?
какую не прогнозируюмую реакцию может вызвать попытка выражения скромности...
.....
иначе нафиг нужны форумы? для взаимного выяснения IQ?
Извините. Просто отделяю "мух от котлет". Думал, что и Вы такой-же. Ошибся. Еще раз извините.
не извиняйтесь... такой-же... про IQ - это не к вам...а вообще к форумам...
по просьбе отдельных професоров ушёл от "goto",
заодно дополнив кое-что и исправив неколько описок\багов и коментариев...
вроде работает...
Респект и уважуха за проделанную работу.
Теперь можно разбираться и ставить эксперементы как НАЙТИ, ПРОНУМЕРОВАТЬ и использовать несколько датчиков на одной шине.
Код я буду писать заново под свои нужды. :-) Главное с принципом работы разобрались!
В качестве замечания по форме - старайтесь объявлять переменные в начале функции, а не в процессе их применения. Так потом легче разобраться если косяк с типом переменной и вообще откуда она взялась.
И для перфекционистов (да и простым смертным помогает) - первые 1-2 символа от типа переменной, а потом имя. (int iX; char chText[10]; byte bAdress)
А в целом текст программы очень хорошо читается - спасибо! Особенно за развернутые коменты.
Всем привет, "чукча не читатель, чукча писатель" прочитал по диагонали, нужного не нашел.
ЗАДАЧА: сверить показания нескольких датчиков или вывести показания группы датчиков по одной шине с известными адресами датчиков.
СХЕМА: все датчики в параллель, подтяжка шины данных 2,2к , подключение с питанием - без паразитки.
БИБЛИАТЕКА ЭТА:
OneWire.h
001
#ifndef OneWire_h
002
#define OneWire_h
003
004
#include <inttypes.h>
005
006
// you can exclude onewire_search by defining that to 0
007
#ifndef ONEWIRE_SEARCH
008
#define ONEWIRE_SEARCH 1
009
#endif
010
011
// You can exclude CRC checks altogether by defining this to 0
012
#ifndef ONEWIRE_CRC
013
#define ONEWIRE_CRC 1
014
#endif
015
016
// Select the table-lookup method of computing the 8-bit CRC by setting this to 1
017
#ifndef ONEWIRE_CRC8_TABLE
018
#define ONEWIRE_CRC8_TABLE 0
019
#endif
020
021
// You can allow 16-bit CRC checks by defining this to 1
022
// (Note that ONEWIRE_CRC must also be 1.)
023
#ifndef ONEWIRE_CRC16
024
#define ONEWIRE_CRC16 0
025
#endif
026
027
class
OneWire
028
{
029
private
:
030
#if ONEWIRE_SEARCH
031
uint8_t address[8];
032
char
searchJunction;
033
uint8_t searchExhausted;
034
#endif
035
uint8_t pin;
036
uint8_t port;
037
uint8_t bitmask;
038
volatile uint8_t *outputReg;
039
volatile uint8_t *inputReg;
040
volatile uint8_t *modeReg;
041
042
public
:
043
OneWire( uint8_t pin);
044
045
// Perform a 1-Wire reset cycle. Returns 1 if a device responds
046
// with a presence pulse. Returns 0 if there is no device or the
047
// bus is shorted or otherwise held low for more than 250uS
048
uint8_t reset();
049
050
// Issue a 1-Wire rom select command, you do the reset first.
051
void
select( uint8_t rom[8]);
052
053
// Issue a 1-Wire rom skip command, to address all on bus.
054
void
skip();
055
056
// Write a byte. If 'power' is one then the wire is held high at
057
// the end for parasitically powered devices. You are responsible
058
// for eventually depowering it by calling depower() or doing
059
// another read or write.
060
void
write( uint8_t v, uint8_t power = 0);
061
062
// Read a byte.
063
uint8_t read();
064
065
// Write a bit. The bus is always left powered at the end, see
066
// note in write() about that.
067
void
write_bit( uint8_t v);
068
069
// Read a bit.
070
uint8_t read_bit();
071
072
// Stop forcing power onto the bus. You only need to do this if
073
// you used the 'power' flag to write() or used a write_bit() call
074
// and aren't about to do another read or write. You would rather
075
// not leave this powered if you don't have to, just in case
076
// someone shorts your bus.
077
void
depower();
078
079
#if ONEWIRE_SEARCH
080
// Clear the search state so that if will start from the beginning again.
081
void
reset_search();
082
083
// Look for the next device. Returns 1 if a new address has been
084
// returned. A zero might mean that the bus is shorted, there are
085
// no devices, or you have already retrieved all of them. It
086
// might be a good idea to check the CRC to make sure you didn't
087
// get garbage. The order is deterministic. You will always get
088
// the same devices in the same order.
089
uint8_t search(uint8_t *newAddr);
090
#endif
091
092
#if ONEWIRE_CRC
093
// Compute a Dallas Semiconductor 8 bit CRC, these are used in the
094
// ROM and scratchpad registers.
095
static
uint8_t crc8( uint8_t *addr, uint8_t len);
096
097
#if ONEWIRE_CRC16
098
// Compute a Dallas Semiconductor 16 bit CRC. Maybe. I don't have
099
// any devices that use this so this might be wrong. I just copied
100
// it from their sample code.
101
static
unsigned
short
crc16(unsigned
short
*data, unsigned
short
len);
102
#endif
103
#endif
104
};
105
106
#endif
OneWire.cpp
001
/*
002
Copyright (c) 2007, Jim Studt
003
004
Updated to work with arduino-0008 and to include skip() as of
005
2007/07/06. --RJL20
006
007
Modified to calculate the 8-bit CRC directly, avoiding the need for
008
the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010
009
-- Tom Pollard, Jan 23, 2008
010
011
Permission is hereby granted, free of charge, to any person obtaining
012
a copy of this software and associated documentation files (the
013
"Software"), to deal in the Software without restriction, including
014
without limitation the rights to use, copy, modify, merge, publish,
015
distribute, sublicense, and/or sell copies of the Software, and to
016
permit persons to whom the Software is furnished to do so, subject to
017
the following conditions:
018
019
The above copyright notice and this permission notice shall be
020
included in all copies or substantial portions of the Software.
021
022
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
023
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
024
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
025
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
026
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
027
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
028
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
029
030
Much of the code was inspired by Derek Yerger's code, though I don't
031
think much of that remains. In any event that was..
032
(copyleft) 2006 by Derek Yerger - Free to distribute freely.
033
034
The CRC code was excerpted and inspired by the Dallas Semiconductor
035
sample code bearing this copyright.
036
//---------------------------------------------------------------------------
037
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
038
//
039
// Permission is hereby granted, free of charge, to any person obtaining a
040
// copy of this software and associated documentation files (the "Software"),
041
// to deal in the Software without restriction, including without limitation
042
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
043
// and/or sell copies of the Software, and to permit persons to whom the
044
// Software is furnished to do so, subject to the following conditions:
045
//
046
// The above copyright notice and this permission notice shall be included
047
// in all copies or substantial portions of the Software.
048
//
049
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
050
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
051
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
052
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
053
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
054
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
055
// OTHER DEALINGS IN THE SOFTWARE.
056
//
057
// Except as contained in this notice, the name of Dallas Semiconductor
058
// shall not be used except as stated in the Dallas Semiconductor
059
// Branding Policy.
060
//--------------------------------------------------------------------------
061
*/
062
063
#include "OneWire.h"
064
065
#if defined(ARDUINO) && ARDUINO >= 100
066
#include "Arduino.h"
067
#else
068
#include "WProgram.h"
069
#include "pins_arduino.h"
070
#endif
071
072
extern
"C"
{
073
#include <avr/io.h>
074
}
075
076
OneWire::OneWire( uint8_t pinArg)
077
{
078
pin = pinArg;
079
port = digitalPinToPort(pin);
080
bitmask = digitalPinToBitMask(pin);
081
outputReg = portOutputRegister(port);
082
inputReg = portInputRegister(port);
083
modeReg = portModeRegister(port);
084
#if ONEWIRE_SEARCH
085
reset_search();
086
#endif
087
}
088
089
//
090
// Perform the onewire reset function. We will wait up to 250uS for
091
// the bus to come high, if it doesn't then it is broken or shorted
092
// and we return a 0;
093
//
094
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
095
//
096
uint8_t OneWire::reset() {
097
uint8_t r;
098
uint8_t retries = 125;
099
100
// wait until the wire is high... just in case
101
pinMode(pin,INPUT);
102
do
{
103
if
( retries-- == 0)
return
0;
104
delayMicroseconds(2);
105
}
while
( !digitalRead( pin));
106
107
digitalWrite(pin,0);
// pull low for 500uS
108
pinMode(pin,OUTPUT);
109
delayMicroseconds(500);
110
pinMode(pin,INPUT);
111
delayMicroseconds(65);
112
r = !digitalRead(pin);
113
delayMicroseconds(490);
114
return
r;
115
}
116
117
//
118
// Write a bit. Port and bit is used to cut lookup time and provide
119
// more certain timing.
120
//
121
void
OneWire::write_bit(uint8_t v) {
122
static
uint8_t lowTime[] = { 55, 5 };
123
static
uint8_t highTime[] = { 5, 55};
124
125
v = (v&1);
126
*modeReg |= bitmask;
// make pin an output, do first since we
127
// expect to be at 1
128
*outputReg &= ~bitmask;
// zero
129
delayMicroseconds(lowTime[v]);
130
*outputReg |= bitmask;
// one, push pin up - important for
131
// parasites, they might start in here
132
delayMicroseconds(highTime[v]);
133
}
134
135
//
136
// Read a bit. Port and bit is used to cut lookup time and provide
137
// more certain timing.
138
//
139
uint8_t OneWire::read_bit() {
140
uint8_t r;
141
142
*modeReg |= bitmask;
// make pin an output, do first since we expect to be at 1
143
*outputReg &= ~bitmask;
// zero
144
delayMicroseconds(1);
145
*modeReg &= ~bitmask;
// let pin float, pull up will raise
146
delayMicroseconds(5);
// A "read slot" is when 1mcs > t > 2mcs
147
r = ( *inputReg & bitmask) ? 1 : 0;
// check the bit
148
delayMicroseconds(50);
// whole bit slot is 60-120uS, need to give some time
149
150
return
r;
151
}
152
153
//
154
// Write a byte. The writing code uses the active drivers to raise the
155
// pin high, if you need power after the write (e.g. DS18S20 in
156
// parasite power mode) then set 'power' to 1, otherwise the pin will
157
// go tri-state at the end of the write to avoid heating in a short or
158
// other mishap.
159
//
160
void
OneWire::write(uint8_t v, uint8_t power) {
161
uint8_t bitMask;
162
163
for
(bitMask = 0x01; bitMask; bitMask <<= 1) {
164
OneWire::write_bit( (bitMask & v)?1:0);
165
}
166
if
( !power) {
167
pinMode(pin,INPUT);
168
digitalWrite(pin,0);
169
}
170
}
171
172
//
173
// Read a byte
174
//
175
uint8_t OneWire::read() {
176
uint8_t bitMask;
177
uint8_t r = 0;
178
179
for
(bitMask = 0x01; bitMask; bitMask <<= 1) {
180
if
( OneWire::read_bit()) r |= bitMask;
181
}
182
return
r;
183
}
184
185
//
186
// Do a ROM select
187
//
188
void
OneWire::select( uint8_t rom[8])
189
{
190
int
i;
191
192
write(0x55,0);
// Choose ROM
193
194
for
( i = 0; i < 8; i++) write(rom[i],0);
195
}
196
197
//
198
// Do a ROM skip
199
//
200
void
OneWire::skip()
201
{
202
write(0xCC,0);
// Skip ROM
203
}
204
205
void
OneWire::depower()
206
{
207
pinMode(pin,INPUT);
208
}
209
210
#if ONEWIRE_SEARCH
211
212
//
213
// You need to use this function to start a search again from the beginning.
214
// You do not need to do it for the first search, though you could.
215
//
216
void
OneWire::reset_search()
217
{
218
uint8_t i;
219
220
searchJunction = -1;
221
searchExhausted = 0;
222
for
( i = 7; ; i--) {
223
address[i] = 0;
224
if
( i == 0)
break
;
225
}
226
}
227
228
//
229
// Perform a search. If this function returns a '1' then it has
230
// enumerated the next device and you may retrieve the ROM from the
231
// OneWire::address variable. If there are no devices, no further
232
// devices, or something horrible happens in the middle of the
233
// enumeration then a 0 is returned. If a new device is found then
234
// its address is copied to newAddr. Use OneWire::reset_search() to
235
// start over.
236
//
237
uint8_t OneWire::search(uint8_t *newAddr)
238
{
239
uint8_t i;
240
char
lastJunction = -1;
241
uint8_t done = 1;
242
243
if
( searchExhausted)
return
0;
244
245
if
( !reset())
return
0;
246
write( 0xf0, 0);
247
248
for
( i = 0; i < 64; i++) {
249
uint8_t a = read_bit( );
250
uint8_t nota = read_bit( );
251
uint8_t ibyte = i/8;
252
uint8_t ibit = 1<<(i&7);
253
254
if
( a && nota)
return
0;
// I don't think this should happen, this means nothing responded, but maybe if
255
// something vanishes during the search it will come up.
256
if
( !a && !nota) {
257
if
( i == searchJunction) {
// this is our time to decide differently, we went zero last time, go one.
258
a = 1;
259
searchJunction = lastJunction;
260
}
else
if
( i < searchJunction) {
// take whatever we took last time, look in address
261
if
( address[ ibyte]&ibit) a = 1;
262
else
{
// Only 0s count as pending junctions, we've already exhasuted the 0 side of 1s
263
a = 0;
264
done = 0;
265
lastJunction = i;
266
}
267
}
else
{
// we are blazing new tree, take the 0
268
a = 0;
269
searchJunction = i;
270
done = 0;
271
}
272
lastJunction = i;
273
}
274
if
( a) address[ ibyte] |= ibit;
275
else
address[ ibyte] &= ~ibit;
276
277
write_bit( a);
278
}
279
if
( done) searchExhausted = 1;
280
for
( i = 0; i < 8; i++) newAddr[i] = address[i];
281
return
1;
282
}
283
#endif
284
285
#if ONEWIRE_CRC
286
// The 1-Wire CRC scheme is described in Maxim Application Note 27:
287
// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
288
//
289
290
#if ONEWIRE_CRC8_TABLE
291
// This table comes from Dallas sample code where it is freely reusable,
292
// though Copyright (C) 2000 Dallas Semiconductor Corporation
293
static
uint8_t dscrc_table[] = {
294
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
295
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
296
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
297
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
298
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
299
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
300
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
301
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
302
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
303
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
304
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
305
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
306
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
307
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
308
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
309
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
310
311
//
312
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
313
// and the registers. (note: this might better be done without to
314
// table, it would probably be smaller and certainly fast enough
315
// compared to all those delayMicrosecond() calls. But I got
316
// confused, so I use this table from the examples.)
317
//
318
uint8_t OneWire::crc8( uint8_t *addr, uint8_t len)
319
{
320
uint8_t i;
321
uint8_t crc = 0;
322
323
for
( i = 0; i < len; i++) {
324
crc = dscrc_table[ crc ^ addr[i] ];
325
}
326
return
crc;
327
}
328
#else
329
//
330
// Compute a Dallas Semiconductor 8 bit CRC directly.
331
//
332
uint8_t OneWire::crc8( uint8_t *addr, uint8_t len)
333
{
334
uint8_t i, j;
335
uint8_t crc = 0;
336
337
for
(i = 0; i < len; i++) {
338
uint8_t inbyte = addr[i];
339
for
(j = 0; j < 8; j++) {
340
uint8_t mix = (crc ^ inbyte) & 0x01;
341
crc >>= 1;
342
if
(mix) crc ^= 0x8C;
343
inbyte >>= 1;
344
}
345
}
346
return
crc;
347
}
348
#endif
349
350
#if ONEWIRE_CRC16
351
static
short
oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
352
353
//
354
// Compute a Dallas Semiconductor 16 bit CRC. I have never seen one of
355
// these, but here it is.
356
//
357
unsigned
short
OneWire::crc16(unsigned
short
*data, unsigned
short
len)
358
{
359
unsigned
short
i;
360
unsigned
short
crc = 0;
361
362
for
( i = 0; i < len; i++) {
363
unsigned
short
cdata = data[len];
364
365
cdata = (cdata ^ (crc & 0xff)) & 0xff;
366
crc >>= 8;
367
368
if
(oddparity[cdata & 0xf] ^ oddparity[cdata >> 4]) crc ^= 0xc001;
369
370
cdata <<= 6;
371
crc ^= cdata;
372
cdata <<= 1;
373
crc ^= cdata;
374
}
375
return
crc;
376
}
377
#endif
378
379
#endif
КОД РАБОЧИЙ ЭТОТ:
001
//100% рабочий алгоритм
002
003
#include <OneWire.h>
004
OneWire ds(A2);
// линия 1-Wire будет на этом пине
005
006
byte
ndT = 9;
// сколько датчиков подключили
007
008
// список адресов моих датчиков для теста
009
byte
DeviceAddres[9][8]={
// ...а датчиков у мня 7 штук в наличии
010
{0x28, 0xB2, 0x29, 0xD7, 0x8, 0x0, 0x0, 0xDE},
// датчик с нулевым адресом, 1й
011
{0x28, 0x96, 0x66, 0xFA, 0x8, 0x0, 0x0, 0xDF},
// адрес 1, 2й второй по порядку
012
{0x28, 0x3F, 0x43, 0xD6, 0x8, 0x0, 0x0, 0x5D},
// 3й
013
{0x28, 0xD, 0xFD, 0xD7, 0x8, 0x0, 0x0, 0xBC},
// 4й
014
{0x28, 0x28, 0x88, 0xD6, 0x8, 0x0, 0x0, 0xD1},
// 5й
015
{0x28, 0xF1, 0xD0, 0xFA, 0x8, 0x0, 0x0, 0xD7},
// 6й - нет такого у меня, просто для теста кода
016
{0x28, 0x2B, 0xB7, 0xF7, 0x8, 0x0, 0x0, 0x9C},
// 7й
017
{0x28, 0xF1, 0xD0, 0xF7, 0x8, 0x0, 0x0, 0xD7},
// 8й
018
{0x28, 0xF1, 0xF1, 0xF1, 0x8, 0x0, 0x0, 0xD7},
// 9й - нет такого у меня, просто для теста кода
019
};
020
021
byte
CheckDevicePresent[9]= {0, 0, 0, 0, 0, 0, 0, 0, 0};
// заняли место в памяти под проверку датчиков и переменные
022
byte
data[12];
// переменная для данных из датчика
023
int
SignBit;
// знак температуры
024
int
Tc_100;
// умножено на 100 целочисленное значение температуры, т.е. запятая "подвинута >>" на 2 знака
025
026
void
setup
(
void
)
027
{
028
Serial
.begin(9600);
029
}
030
031
032
void
loop
()
033
{
034
035
for
(
byte
i = 0; i < ndT; i++)
// чИпЯтаем шапку таблЫцЫ
036
{
037
Serial
.print(
"Device №"
);
038
Serial
.print( i );
039
Serial
.print(
" "
);
040
}
041
042
for
(
byte
i = 0; i < ndT; i++)
// проверяем все датчикии, запускаем АЦП
043
{
044
start_conversion_T (i);
045
}
046
047
Serial
.println(
" "
);
048
Serial
.print(
" "
);
049
for
(
byte
i = 0; i < ndT; i++)
// пичатаем для самоконтроля
050
{
051
Serial
.print( CheckDevicePresent[i] , DEC );
052
Serial
.print(
" "
);
053
}
054
Serial
.println(
" "
);
055
delay (1000);
// задержка на конвертацию
056
057
058
059
for
(
byte
i = 0; i < ndT; i++)
// получаем и печатаем результаты
060
{
061
GETTEMP (i);
// получаем температуру
062
063
064
if
(CheckDevicePresent[i] != 0)
//если датчик не нашли
065
{
Serial
.print(
" NC "
);}
066
else
067
{
068
if
(SignBit) {
Serial
.print(
" -"
);}
069
else
{
Serial
.print(
" "
);}
070
Serial
.print( Tc_100 );
071
Serial
.print(
" "
);
072
}
073
}
074
075
076
Serial
.println(
" "
);
077
Serial
.println(
" "
);
078
Serial
.println(
" "
);
079
delay (30000);
// задержка на конвертацию !!!!!! :))))))))))))))
080
081
}
// конй loop
082
083
084
085
086
void
start_conversion_T (
byte
No)
087
{
088
089
ds.reset();
090
ds.select(DeviceAddres[No]);
091
ds.write(0xBE);
// Считываем ОЗУ датчика
092
093
for
(
byte
i = 0; i < 9; i++)
// читаем в байты, 9 байт ОЗУ датчика
094
{ data[i] = ds.read(); }
095
096
if
(data[4] == 255)
// проверяем CRC 8 или CONFIG 4 если его нет, нет датчика = 255 (0xFF)
097
// в конфиге бит 1 всегда 0, а CRC может быть 255
098
{
099
CheckDevicePresent[No]= 1;
// пишем, что датчика нет
100
return
;
101
}
102
103
CheckDevicePresent[No]= 0;
// датчик есть
104
ds.reset();
105
ds.select(DeviceAddres[No]);
106
ds.write(0x44, 1);
// Запускаем конвертацию (получение температуры)
107
}
108
109
110
void
GETTEMP (
byte
No)
111
{
112
113
if
(CheckDevicePresent[No] != 0)
// если датчика нет, пропускаем
114
{
return
; }
115
116
ds.reset();
117
ds.select(DeviceAddres[No]);
118
ds.write(0xBE);
// Считываем ОЗУ датчика
119
120
for
(
byte
i = 0; i < 9; i++)
// Обрабатываем 9 байт
121
{ data[i] = ds.read(); }
122
123
// Высчитываем температуру :)
124
125
int
TReading;
126
TReading = (data[1] << 8) + data[0];
// собираем в кучку оба байта
127
128
SignBit = TReading & 0x8000;
// Проверяем дубак там или нет
129
if
(SignBit)
// Если на улице дубак :)
130
{ TReading = (TReading ^ 0xffff) + 1; }
131
132
// Tc_100 - это температура из датчика формата int со сдвинутой запятой на 2 знака
133
Tc_100 = (6 * TReading) + TReading / 4;
// Умножаем на (100 * 0.0625) или 6.25
134
// т.е. убираем 4 лишних бита
135
}
ПРОБЛЕМА: не могу избавиться от чтения 9 байт ОЗУ при поиске датчиков. Строки 89 - 96.
перечитал даташит - идеи не появились, может я чего не понял :( .
UP