Подредактировать скетч
- Войдите на сайт для отправки комментариев
Чт, 19/04/2012 - 12:28
Дорый всем день!
Имеется скетч
// подключаем библиотеки
// ... они должны лежать в папке libraries с установленной ардионо-иде
#include <LiquidCrystalRus.h> // для общения с LCD по русски
#include <OneWire.h> // для обмена по 1-wire
#include <EEPROM.h> // для работы с EEPROM
byte butPin = 0; // пин входа кнопок
int val; // знач. АЦП при нажатой кнопке
byte butPush = 0; // код нажатой кнопки
boolean butRel=1; // отпущена ли сейчас кнопка
int butval[8]={0,1023,817,602,407,203,0,0}; // АЦП кнопок
// ... просьба не обращать внимание на то, что массив объявлен на
// ... восемь переменных, это просто пережиток прошлого
// ... также значения не обязательны такие, можно просто вбить нули
// ... впоследствии в этот массив мы считаем данные из памяти
byte butsens=20; // чувствительность кнопок
byte buzzer = 5; // выход динамика
byte menu=0; // переменная хранящая номер текущего экрана
byte i; // просто счетчик
byte n; // просто счетчик
byte m=0; // просто счетчик
byte t=0; // просто счетчик
float T[]={0,0,0,0}; // переменная для хранения температуры
float Tp[]={0,0,0,0}; // переменная для хранения температуры с прошлого замера
// ... нужно для устранения некоторых ошибок
byte data[9]; // массив для хранения данных принятых от датчика
byte TotalDS=0; // число найденых датчиков на линии
byte addr[4][8] = { // двумерный массив адресов датчиков
{0,0,0,0,0,0,0,0}, // 4 адреса по 8 байт
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
};
OneWire ds(31); // на этот пин подключена линия DQ 1-wire
LiquidCrystalRus lcd(8,9,4,5,6,7); //инициализация LCD
// ... соответственно на эти пины ардуины он и подключен
void setup()
{
lcd.begin(2, 16); // включаем дисплей
Serial.begin(9600); // последовательный порт для отладки
if (analogRead(butPin) > 100) { // если в момент загрузки значение АЦП
// ... клавиатуры больше 100 (нажата какая-то кнопка) то запускаем процедуру калибровки
lcd.print("Kaлибpoвкa"); // На дисплей выводим слово "Калибровка"
lcd.setCursor(0,1); // устанавливаем курсор во вторую строку
delay(3000); // пауза 3 сек, за это время надо отпустить кнопку
for ( i = 1; i < 6; i++) { // цикл от 1 до 5
lcd.clear(); // очищаем дисплей
lcd.print("Haжмитe "); // выводим слово "Нажмите" с пробелом в конце в первую строку
lcd.print(i, DEC); // выводим номер кнопки, теперь на экране написано "Нажмите 1"
while (analogRead(butPin) < 100) {}; //ничего не делаем (пустой цикл) пока не нажата кнопка
button (); // процедура опроса кнопки, по окончанию в val будет значение АЦП
butval[i]=val; // записываем это значение в массив
lcd.clear(); // очищаем дисплей
lcd.setCursor(0,1); // и во вторую строку ...
lcd.print(i, DEC); // ... выводим номер кнопки ...
lcd.print(" "); // ... и через пробел...
lcd.print(butval[i], DEC); // значение АЦРП ей соответствующее
EEPROM.write(224+i*2,butval[i]/4); // записиваем в EEPROM по 2 байта на значение начиная с адреса 224
// в первый адрес старшие 8 бит
EEPROM.write(225+i*2,butval[i]%4); // во второй - остаток. (всего у нас было 10 бит)
delay(1000); // пауза 1 сек (просто так... чтоб сильно не шокировать)
}
} // конец калибровки
else { // читаем АЦП кнопок // если условие запуска калибровки не выполнилось читаем то, что было записано ранее
for ( i = 0; i < 8; i++) { // цикл на 8 байт. опять же пережиток
butval[i] = EEPROM.read(224+i*2)*4+EEPROM.read(225+i*2); //процедура обратная записию берем старшие 8 бит,
// ... сдвигаем на 2 разряда (умножаем на 4) и прибавляем младшие биты.
} // конец цикла
} // конец if
read_DS(); //считываем адреса датчиков из памяти, подпрограмма ниже
} // конец setup
void loop() // главный цикл. Когда программа доходит до конца, выполнение переходит к этой строке
{
ds.reset(); // самое интересное - опрос датчиков. Начинается со сброса линии
ds.write(0xCC,1); // пропуск ROM - этим мы говорим "Внимание всем!" Следующую команду
// ... выполняют все устройства (если конечно их тип это позволяет)
ds.write(0x44,1); // запускаем конвертацию температуры
for( n = 1; n < 90; n++) { //ждем 900 мс... (время необходимое датчикам чтобы преобразовать температуру)
delay(10);
if (analogRead(butPin) > 100 && butRel) { Menu(button ()); } // ... периодически проверяя не нажата ли кнопка
// и если нажата - выполнить подпрограмму "Menu" (показываем меню)
if (analogRead(butPin) < 100) {butRel=1;}
}
for( n = 0; n < 4; n++) { // Цикл от 0 до 3 - по числу датчиков (4 шт)
ds.reset(); // начинаем считывать температуры, обмен начинается со сброса
ds.select(addr[n]); // выбираем нужный (по порядку) адрес датчика, после этой команды до след. сброса
// ... отвечать нам будет только выбранный датчик
ds.write(0xBE); // команда на считывание ОЗУ датчика
for ( i = 0; i < 9; i++) {data[i] = ds.read();} // читаем с линии 9 байт
Tp[n] = float((data[1] << 8) + data[0])/16; // значение температуры в первых 2-х байтах. Высчитываем температуру
// ... команда float приводит тип byte (полученный от датчика) к типу с плавающей точкой
if (Tp[n] == 85) {} else {T[n]=Tp[n];} // это для того, чтобы при глюке датчика (обычно при переключениях
// ... выдача температуры 85 град не приводила к переходу на другой шаг программы. Мы просто возьмем предыдущее значение
// ... (вот для чего мы его и хранили, ну впрочем можно еще дельту посчитать, вполне можно найти применение)
}
// Ну вот, температуру прочитали
// Тут может быть Ваша рекл... тьфу, Ваш код. Например сравнение температур с уставками и реализация каких-то действий
Menu(0); // собственно больше делать нечего. показываем юзеру картинку (меню) (ниже)
}
int button () { // подпрограмма считывания кнопок
int exitMenu = 1; // если exitMenu истина то выходим из меню
butPush = 0; // код нажатой кнопки
delay(15); // задержка для устранения дребезга контактов
val = analogRead(butPin); // читаем АЦП порта кнопок (значение от 0 до 1023)
if (val > (butval[5]-butsens) && val < (butval[5]+butsens)) {butPush = 5;} // если считанное значение около (на величину butsens)
// значения соответствующего кнопке 5 то считаем что она и нажата
if (val > (butval[4]-butsens) && val < (butval[4]+butsens)) {butPush = 4;} // аналогично для остальных
if (val > (butval[3]-butsens) && val < (butval[3]+butsens)) {butPush = 3;}
if (val > (butval[2]-butsens) && val < (butval[2]+butsens)) {butPush = 2;}
if (val > (butval[1]-butsens)) {butPush = 1;}
// коды кнопок: 1 - вверх, 2 - влево, 3 - ок, 4 - вправо, 5 вниз
butRel=0; // эта переменная нужна для проверки в главной программе
return butPush; // возвращаем значение нажатой кнопки
}
byte write_DS() { // программа записывает адреса датчиков в память
for (i=0; i<8; i++) { // всего 8 байт. В переменной m - номер датчика который надо записать
if (m==0) {EEPROM.write(128+t*8+i,0);} // записывать будем начиная с адреса 128. Если номер датчика равен нулю - то значит он отсутствует.
else {EEPROM.write(128+t*8+i,addr[m-1][i]);}
}
return 0;
}
byte read_DS() { // программа считывает адреса датчиков из памяти
for (n=0; n<4; n++) { // у нас она "заточена" на 4 адреса, потому и цикл до 4
for (i=0; i<8; i++) { // в адресе 8 байт
addr[n][i] = EEPROM.read(128+n*8+i); // читаем байт со смещения 128 + 8 * номер датчика + номер байта
}
}
return 0;
}
void Menu(int butPush) { // самая мутная но и самая интересная часть. Фунцция показа меню
lcd.clear(); // очищаем дисплей
switch (menu) { // оператор switch переключает на нужную секцию в зависимости от значения menu
case 0: // показываем все температуры
lcd.print("1:"); // Печатаем "1:"
lcd.print(T[0]); // выводим температуру первого датчика
lcd.setCursor(8,0); // ставим курсор посередине первой строки
lcd.print("2:"); // Печатаем "2:"
lcd.print(T[1]); // выводим температуру второго датчика
lcd.setCursor(0,1); // далее аналогично
lcd.print("3:");
lcd.print(T[2]);
lcd.setCursor(8,1);
lcd.print("4:");
lcd.print(T[3]);
if (butPush == 1) {menu=1; Menu(0);} // обработка кнопок. Если нажата кнопка "вверх" то возвращаемся в конец подменю
if (butPush == 5) {menu++; Menu(0);} // если нажата кнопка вниз - идем к следующему экрану. Далее эти кнопки не комментирую
break;
case 1: // меню настроек
lcd.print("Настройки");
lcd.setCursor(0,1);
lcd.print("Haжмитe OK");
if (butPush == 1) {menu--; Menu(0);}
if (butPush == 3) {menu=40; Menu(0);} // если нажать "ОК" в этом экране то пойдем к меню номер 40
if (butPush == 5) {menu=0; Menu(0);}
break;
//////////////////////////////////////////////////////////////////////////////////////
case 40: // поиск датчиков
i = 0;
n=0;
while (i != 1 ) // ищем датчики
{
if ( ds.search(addr[n]) != 1) { // функция поиска специальным образом выискивает первый датчик и записывает его адрес
// возвращет 1 если он найден. в случае, если вернет что-то не равное 1 (см. пред. строку) то поиск останавливается
ds.reset_search();
i = 1; }
else { // если что-то найдено то...
n++; // увеличиваем счетчик и ...
TotalDS = n; // говорим, что всего у нас теперь n датчиков
}
}
lcd.print("Поиск датчиков"); // Заголовок в первой ...
lcd.setCursor(0,1); // а результат будем печатать во второй строке
lcd.print(n, DEC);
lcd.print(" найдено");
if (butPush == 1) {menu=0; Menu(0);} // нажатие "вверх", ...
if (butPush == 2) {menu=0; Menu(0);} // ... "влево" ...
if (butPush == 5) {menu=0; Menu(0);} // ... и "вниз" возвращает нас в главное меню
if (butPush == 3) {menu=100; Menu(0);} // нажатие " ОК" ...
if (butPush == 4) {menu=100; Menu(0);} // ... или "вправо" переносит в меню детальной настройки датчиков
break;
//////////////////////////////////////////////////////////////////////////////////////
case 100: // меню настроек датчиков DS1820
lcd.print("T"); // выводим "Т" и
lcd.print(t+1,DEC); // ... номер датчика
lcd.setCursor(0,1);
if (m==0) {lcd.print("Отсутствует");} // если номер равен 0 то считаем что датчик отсутствует
else {lcd.print(T[m-1],DEC);} // иначе показываем текущую температуру
if (butPush == 1) {if (t==0) {menu=101;} else {t--;} Menu(0);} // кнопки "вверх" и "вниз" меняют номер датчика. если дошли до конца, то переходим к меню 101
if (butPush == 2) {if (m==0) {} else {m--;} Menu(0);} // кнопки "вправо" и "влево" изменяют физический датчик сопоставленный данному номеру.
if (butPush == 3) {write_DS(); lcd.setCursor(0,1); lcd.print("Записано в EEPROM"); tone(buzzer, 1000); delay(1000); noTone(buzzer); menu=100; Menu(0);}
// нажатие "ОК" вызывает запись текущего датчика в память. Записать необходимо все датчики поочередно
// ПОСЛЕ ЭТОЙ ПРОЦЕДУРЫ НЕОБХОДИМО ПЕРЕЗАГРУЗИТЬ УСТРОЙСТВО
if (butPush == 4) {m++; if (m > TotalDS) { m = TotalDS;} Menu(0);}
if (butPush == 5) {if (t==3) {menu=101;} else {t++;} Menu(0);}
break;
case 101: // Выход из меню. Комментировать не буду - надоело.
lcd.print("Выйти из меню");
lcd.setCursor(0,1);
lcd.print("OK для выхода");
if (butPush == 1) {t=3; menu=100; Menu(0);}
if (butPush == 3) {menu=0; Menu(0);}
if (butPush == 5) {t=0; menu=100; Menu(0);}
break;
} // end switch
}
Скеч не мой. Я только учюсь.
Прога сама ищет температурные датчики и выводит на дисплей показания.
Имеется ЛЦД шильд 16х2 и мега2560 с 4мя датчиками.
Датчики не находит. Что и где править?
Вот схемка включения кнопок
А что за шилд? датчики куда подключаются? В вашем коде датчики должны быть подключены к 31 выводу, у вас на шилде также?
Датчики подключены(средние ноги) на вывод31 самой меги
А какой способ питания датчиков используете паразитный(2 провода) или обычный(3 провода)?
Попробуйте упростить схему. Отключите все кнопки, LCD.
Подключите только датчики. Возмите библиотеку dallastemperaturecontrol, отложите ваш скетч в сторону, возмите примеры идущие с библиотекой. Укажите адреса датчиков в явном виде. Убедитесь что они у вас вообще работают и подключены правильно.
Потом, раз есть желание детектить адреса автоматом, возмите пример из библиотеки OneWire, убедитесь что "поиск" тоже работает нормально.
И только после этого, когда будете уверены что с датчиками "все в порядке" - начинайте разбиратся с собственным комплексным примером. Имея уверенность что "с датчиками все хорошо".
P.S. Надеюсь вы обратили внимание, что ваш скетч при "просто включении" - датчики не обнаружит. Он попробует прочитать их адреса из EEROM, а там будут "нули или мусор". Нужно, через меню, запустить их "обнаружение", записать найденные адреса, через меню, в EEROM, и перегрузить контроллер.
Датчики по трём проводам.
leshak прав. Так и делал.
После долгих мучений(предварительно изменив скетч в нескольких местах) зашёл в меню, нашёл датчики и прописал в еепром.
Теперь хотелось бы управлять пару релюшками.
Поможите?
Алгоритм выложу на днях.
Не ну делать ваш проект за вас - никто не будет. Попробуйте, вначале, тут поискать как народ релюхами, моторами, насосами управляет (вверху есть поиск).
Да и гугл на вопрос "арудино управление нагрузкой" думаю не оставит вас в неведениии.
Все-таки задача совершенно не экзотика. Нужно просто потратить время и разобратся, почитать, посмотреть.
Ну хотя-бы вот тут
http://easyelectronics.ru/upravlenie-moshhnoj-nagruzkoj-postoyannogo-tok...
http://easyelectronics.ru/upravlenie-moshhnoj-nagruzkoj-postoyannogo-tok...
Там вообще куча "нубских вопросов" освещена. Советую потратить время и основательно изучить этот сайт.
Не ну делать свой проэкт буду сам.Спасибо.