Подредактировать скетч

Alex2x
Offline
Зарегистрирован: 15.01.2012

Дорый всем день!

Имеется скетч

 
// подключаем библиотеки
// ... они должны лежать в папке 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мя датчиками.

Датчики не находит. Что и где править?

 

Alex2x
Offline
Зарегистрирован: 15.01.2012

Вот схемка включения кнопок 

maksim
Offline
Зарегистрирован: 12.02.2012

А что за шилд? датчики куда подключаются? В вашем коде датчики должны быть подключены к 31 выводу, у вас на шилде также?

Alex2x
Offline
Зарегистрирован: 15.01.2012

 Датчики подключены(средние ноги) на вывод31 самой меги

maksim
Offline
Зарегистрирован: 12.02.2012

А какой способ питания датчиков используете паразитный(2 провода) или обычный(3 провода)?

leshak
Offline
Зарегистрирован: 29.09.2011

 Попробуйте упростить схему. Отключите все кнопки, LCD.

Подключите только датчики. Возмите библиотеку dallastemperaturecontrol, отложите ваш скетч в сторону, возмите примеры идущие с библиотекой. Укажите адреса датчиков в явном виде. Убедитесь что они у вас вообще работают и подключены правильно.

Потом, раз есть желание детектить адреса автоматом, возмите пример из библиотеки OneWire, убедитесь что "поиск" тоже работает нормально.

И только после этого, когда будете уверены что с датчиками "все в порядке" - начинайте разбиратся с собственным комплексным примером. Имея уверенность что "с датчиками все хорошо".

P.S. Надеюсь вы обратили внимание, что ваш скетч при "просто включении" - датчики не обнаружит. Он попробует прочитать их адреса из EEROM, а там будут "нули или мусор". Нужно, через меню, запустить их "обнаружение", записать найденные адреса, через меню,  в EEROM, и перегрузить контроллер.

Alex2x
Offline
Зарегистрирован: 15.01.2012

Датчики по трём проводам.

 leshak прав. Так и делал.

После долгих мучений(предварительно изменив скетч в нескольких местах) зашёл в меню, нашёл датчики и прописал в еепром.

Теперь хотелось бы управлять пару релюшками.

Поможите?

Алгоритм выложу на днях.

leshak
Offline
Зарегистрирован: 29.09.2011

 Не ну делать ваш проект за вас - никто не будет. Попробуйте, вначале, тут поискать как народ релюхами, моторами, насосами управляет (вверху есть поиск).

Да и гугл на вопрос "арудино управление нагрузкой" думаю не оставит вас в неведениии.

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

Ну хотя-бы вот тут

http://easyelectronics.ru/upravlenie-moshhnoj-nagruzkoj-postoyannogo-tok...

http://easyelectronics.ru/upravlenie-moshhnoj-nagruzkoj-postoyannogo-tok...

Там вообще куча "нубских вопросов" освещена. Советую потратить время и основательно изучить этот сайт.

 

 

Alex2x
Offline
Зарегистрирован: 15.01.2012

Не ну делать свой проэкт буду сам.Спасибо.