Запись и обработка номеров DS18b20 в его EEPROM
- Войдите на сайт для отправки комментариев
Пт, 24/03/2017 - 12:12
#include <OneWire.h>
#define NumPin 70 //колличество пинов на используемой плате ардуино (для примера - MEGA)(Uno=20)
#define NumConfigPin 69 //(A15)//выделенный пин для программирования номеров датчиков(Uno=19-(A5))
int NumSens;//колличество обнаруженых датчиков
boolean PinNumSens[NumPin - 3];//массив задействованных(true) или нет(false) пинов для датчиков(не включая пин 0 и 1 UART и выделенный пин)
unsigned long timeSens;//время события
int diftime = 0;//разница времени между двумя событиями
boolean ReadSens = false;//признак чтения\записи датчика
void setup() {
Serial.begin(9600);
Serial.println(F("Start Search for Sensors:"));
SearchNumSens();
}
void loop() {
if (Serial.available()) {
String SerialRead = Serial.readString();
if (SerialRead == "s") {//поиск числа датчиков и задействованных пинов
SearchNumSens();
}
else {//запись номера датчика в его EEPROM на выделенном пине NumConfigPin
int Num = SerialRead.toInt();
Serial.print(F("Sensors Number Recording: #"));
Serial.print(Num);
if (Num < 1) {
Serial.println(F(" Number Error"));
}
else if (NumConfigSens(Num)) {
Serial.println(F(" OK"));
}
else {
Serial.println(F(" Error"));
}
}
}
//что-бы не мешало переполнение millis
if (timeSens > millis()) {
diftime = int(4294967295 - timeSens + millis());
}
else {
diftime = int(millis() - timeSens);
}
if (ReadSens == false) {
for (byte i = 2; i < NumConfigPin; i++) {
if (PinNumSens[i - 2] == true) {
OneWire ds(i);
// обращение ко всем датчикам шины сразу:
ds.reset();//сброс шины
ds.write(0xCC);//Игнорировать адрес
ds.write(0x44);//начать преобразование температуры(без паразитного питания)
}
}
ReadSens = true;
timeSens = millis();
}
else if (ReadSens == true && diftime >= 1000) {//1000ms(с запасом)-т.к. время преобразования =750ms для
// default value of Config = 0x7F (user byte 3)
int Sensor[NumSens][3];//значения опроса датчиков
int N = 0;//число корректно ответивших датчиков
for (byte n = 2; n < NumConfigPin; n++) {
if (PinNumSens[n - 2] == true) {
OneWire ds(n);
byte addr[8];
while (N <= NumSens) {
if ( !ds.search(addr)) {
break;
}
for (byte c = 0; c < 2; c++) {
byte present = ds.reset();//признак готовности датчика к ответу
ds.select(addr);
ds.write(0xBE);//Чтение памяти
byte data[9];
for (byte d = 0; d < 9; d++) {
data[d] = ds.read();
}
byte CRC = OneWire::crc8(data, 8);
if (CRC == data[8] && present == 1 && CRC != 0) {//ответ корректный
if (N < NumSens) {
Sensor[N][0] = data[0];
Sensor[N][1] = data[1];
Sensor[N][2] = data[3] * 10 + data[2];//номер датчика
}
N++;
break;
}
else if (c == 0) {//датчик отсутсвует или мусор
Serial.println(F("CRC!"));
delay(100);
}
else {
Serial.println(F("Sensors CRC Error"));
}
}
}
if (N > NumSens) {
break;
}
}
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// просто пример обработки показаний датчиков,
// если их нумерация непрерывная с первого номера,
// хотя не обязательно - тогда каждый отдельно,
// а номера должны быть любые неповторяющиеся
for (int SensorN = 1; SensorN <= NumSens; SensorN++) {
int16_t DataT = DataSens(SensorN, Sensor);
if (DataT == -1000) {
Serial.print(F("Error"));
}
else {
double SensT = (double)DataT / 16.0;//для библиотеки PID например
Serial.print(SensT);
Serial.print(F("*C"));
}
Serial.print(F(" Sensor #"));
Serial.println(SensorN);
}
Serial.println();
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if (N > NumSens) {
Serial.println(F("Find New Sensor. Start Search:"));
SearchNumSens();
}
ReadSens = false;
}
}
//=========================================================
//поиск нужного значения температуры в массиве по номеру датчика
int16_t DataSens(int SensorN, int Sensor[][3]) {
int16_t rawData = -1000;//любое нереальное значение
for (byte i = 0; i < NumSens; i++) {
if (Sensor[i][2] == SensorN) {
rawData = (Sensor[i][1] << 8) | Sensor[i][0];
break;
}
}
return rawData;
}
//=========================================================
//запись номера датчика в его EEPROM
boolean NumConfigSens(int NumConfig) {
byte v1 = NumConfig % 10;
byte v2 = (NumConfig - v1) / 10;
OneWire ds(NumConfigPin);
ds.reset();//сброс шины
ds.write(0xCC);//Игнорировать адрес
ds.write(0x4E);//разрешение записать конфиг //write scratchpad (starts at byte 2)
ds.write(v1);//value of user byte 1
ds.write(v2);//value of user byte 2
ds.write(0x7F);//default value of Config = 0x7F (user byte 3)//точность преобразования
ds.reset();//сброс шины - обязательно до задания следующей комманды копирования в EEPROM
ds.write(0xCC);//Игнорировать адрес
ds.write(0x48);// копируем три байта в EEPROM DS18B20, чтобы сохранить постоянно
delay(20);//ждём, пока закончит запись
ds.reset();//сброс шины - обязательно до задания следующей комманды копирования в ОЗУ
ds.write(0xCC);//Игнорировать адрес
ds.write(0xB8);//Данные перезагружены из EEPROM в ОЗУ
ds.reset();//сброс шины - обязательно до задания следующей комманды чтения из ОЗУ
ds.write(0xCC);//Игнорировать адрес
ds.write(0xBE);//Чтение памяти - нам нужны только байт 2,3
ds.read();//нам не нужен(0)
ds.read();//нам не нужен(1)
if (ds.read() == v1 && ds.read() == v2) {
return true;
}
else {
return false;
}
}
//=========================================================
//поиск числа датчиков и задействованных пинов
void SearchNumSens() {
NumSens = 0;
byte addr[8];
for (byte n = 2; n < NumConfigPin; n++) {
PinNumSens[n - 2] = false;
OneWire ds(n);
while (true) {
if ( !ds.search(addr)) {
break;
}
Serial.print(F("Pin #"));
Serial.print(n);
Serial.print(F(":\r\nROM = "));
for (byte i = 0; i < 8; i++) {
Serial.print(addr[i], HEX);
Serial.print(' ');
}
if (OneWire::crc8(addr, 7) == addr[7]) {
ds.reset();//сброс шины - обязательно до задания следующей комманды чтения из ОЗУ
ds.select(addr);
ds.write(0xBE);//Чтение памяти - нам нужны только байт 2,3
ds.read();//нам не нужен(0)
ds.read();//нам не нужен(1)
Serial.print(F("Sensor #"));
Serial.println(ds.read() + ds.read() * 10);
NumSens++;
PinNumSens[n - 2] = true;
}
else {
Serial.println(F("Sensors ID Error!"));
}
}
}
Serial.print(F("\r\nNumber of Sensors = "));
Serial.println(NumSens);
Serial.println();
}
думаю хорошей идеей будет записать в Eeprom датчика его номер
и уже по нему обрабатывать его показания:
1.подключаем датчик к выделенному пину
2.программой записываем в датчик нужный номер
3.помечаем биркой его номер
4.забываем про ID датчиков
пользуемся любым колличеством, на любом пине, в любом порядке...
что вы думаете по этому поводу?
начинайте критиковать...
А это что за плод сумрачных мыслей?
Зачем искать пины, к которым подключены ds18b20? Вы забыли куда их подключали - дак посмотрите. По хорошему, должна быть схема, где это видно невооруженным глазом,
А чего спросить то хотели?
У датчика уже есть "врожденный" номер. Его адрес, зачем второй в него писать?
ПС. стр39-45 Это чё нафиг такое? Опять переполнение миллиса?! Да сколько ж можна то...
поеееехали..
представте себе наладчика.который подготовил датчики(ну сто, например) по номерам,
программу обработки, кабели на проэкте , воткнув их в любой пин...
что осталось? : подключить физически датчики по списку номеров совместив их с местом на проекте...
а поменять датчик? : вписал номер и всё...
а поменять местами, если ошибся?...
или по ID сверять?
а для дома с парой датчиков и городить нечего: записал на бумажке и в прорамму ID и всё...
а по поводу миллиса моооожно поподробней? только без обычных грубостей...
Опять переполнение миллиса?! Да сколько ж можна то...
А вдруг переполнится? Ужасть-же!
или по ID сверять?
А чем Ваш номер в епроме лучше его родного номера/адреса? Вот просто - какие выгоды Вы от этого получаете?
Вы собрались приклеивать бирки с номерами, так что мешает приклеивать бирки с адресами?
а по поводу миллиса моооожно поподробней? только без обычных грубостей...
Дак без грубостей первую полсотню раз было ))) Не помогает, поищите по форуму, оно пару раз в месяц всплывает с завидной регулярностью.
Опять переполнение миллиса?! Да сколько ж можна то...
А вдруг переполнится? Ужасть-же!
да просто раз в 50 дней будет сбой верности чтения датчика, или я что-то не так понимаю?
а если не критично ,то можно и упростить...
да просто раз в 50 дней будет сбой верности чтения датчика, или я что-то не так понимаю?
Что-то не так понимаете.
или по ID сверять?
А чем Ваш номер в епроме лучше его родного номера/адреса? Вот просто - какие выгоды Вы от этого получаете?
Вы собрались приклеивать бирки с номерами, так что мешает приклеивать бирки с адресами?
можно теоретически и в бинарном виде номер дома обозначать, только почту перестанете получать...
номер как-то человечней для наладчика...
а по поводу миллиса моооожно поподробней? только без обычных грубостей...
Дак без грубостей первую полсотню раз было ))) Не помогает, поищите по форуму, оно пару раз в месяц всплывает с завидной регулярностью.
учту,пороюсь...
номер как-то человечней для наладчика...
А адрес (число от 8 до 127) как-то бесчеловечно? :) Понял.
Предлагаю ещё более человечный вариант: футбольные карточки: на одном датчике Пеле, на другом Кака, на третьем Ахахауи. Ну, или, если наладчики - мужики, то можно фото порнозвёзд использовать. Всяко лучше, чем безликое число :))))
Да. Колода порнокарт - просто идеально и картон крепкий и идентификаторы какие хочеш, хоть чирва девятка, хоть блондинка в раскаряку.
номер как-то человечней для наладчика...
А адрес (число от 8 до 127) как-то бесчеловечно? :) Понял.
Предлагаю ещё более человечный вариант: футбольные карточки: на одном датчике Пеле, на другом Кака, на третьем Ахахауи. Ну, или, если наладчики - мужики, то можно фото порнозвёзд использовать. Всяко лучше, чем безликое число :))))
а число действительно безликое. т,к ID произвольный, а номер - контролируемый...
и заодно сходите на проект...
и попросите наладчика найти датчик по ID...да даже в списке.
куда он пошлёт?
Неважно куда пощлет, важно куда пойдет. Выдете ему датчик с порнокартой "блондинка в раскаряку" а в коде, лучше в отдельном файле ашнике, пишете
с реальным адресом этого датчика.
Когда вернется - скажет куда дел датчик, "на трубе весит" снова прямо в код.
#define BLONDINKA_IN_RASCARYAKA_POSITION "На трубе"
Потом все такие дефайники собираете в массив структур из которого всегда можна узнать адрес датчика на трубе. Если надо то и идентификатор бирки, можна хранить. А можна и в код глянуть когда надо узнать соответствие между биркой расположением и адресом.
вот нашёл объяснение:
UPD1:
Раз в коментариях возник вопрос, попробую объяснить "почему тут не будет переполнения".
Оно будет. Но будет "два раза". После того как millis() перепрыгнет границу и начнет опять отсчет с нуля можно заподозрить что выражение if(millis()-lastDoTime>inteval) больше никогда не сработает. Так как разница (millis()-lastDoTime) - будет отрицательной (пока millis() опять не станет боьлше lastDoTime). И соответственно всегда меньше любого интервала.
Но.... это в математике. А тут нам нужно еще помнить про типы. И то что время мы храним в unsigned long. Следовательно отрицательных чисел - у нас просто не бывает. Попытка сохранить отрицательное числов в беззнаковую переменную, опять вызовет переполнение-переход. Только "в обратную сторону". И интервал (millis()-lastDoTime) - все-таки будет правильным. Несмотря на переполнение.
исправлюсь...
а насчёт трубы...
а вы соберите макет на несколько датчиков, потасуйте, поменяйте ,
увидите как удобно, само всё находится автоматически,
наладчику надо минимум навыков(не нужен програмист) - в этом и была цель.
Я делал такое 2-я приложениями одно чисто для такой процедуры и сохраняет в EEPROM, а второе основное рабочее просто использует готовіе данные. Так размер основного приложения сокращается.