Страница 1 из 1

Контроль усвоенного материала.

Добавлено: 25 янв 2018, 14:23
Виктор
Здравствуйте.
Нахожусь в стадии изучения Ардуино и в связи с этим прошу совета опытных пользователей.
Если есть возможность, проконтролируйте мой код, мне просто хотелось бы понять,
где нужно пойти другим путем, как оптимизировать, ну в общем что бы при дальнейшем
обучении не тащить за собой изначально не правильное понимание. На данный момент
вопросы по созданию глобальных, локальных переменных, возвращение типов результатов функций (как
из функции вернуть текстовое сообщение), и работа с указателями.

Логика программки следующая:
- Есть трехразрядный семисегментный Led индикатор и я пытаюсь на нем реализовать
ввод нескольких параметров.
1. при включении устройства по индикаторам пробегает змейка (взято из урока)
2. далее индикаторы гасятся.
3. при нажатии на кнопку (меню) активируются на всех разрядах G - сегмент (черточка)
4. далее плюсом или минусом выбираем номер параметра (левый разряд отвечает за номер параметра)
(при этом на среднем и правом разрядах отображается значение параметра под данным номером)
5. При нажатии на кнопку (меню) заходим в редактирование данного параметра (в левом разряде при этом загорается
точка, указывает что мы находимся в редактировании)
6. плюсом или минусом редактируем параметр
7. при нажатии на меню записываем параметр в память и выходим в начало меню.
(при бездействии 10 сек выходим в начало и гасим индикаторы)
Библиотека управления индикатором и кнопками взята у Эдуарда (сам пока не осилил), но пользовался только отображением сегментов.

Код: Выделить всё

#include <FlexiTimer2.h>
#include <Led4Digits.h>
#include <Button.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(2, 4,3,2,255, 6,7,8,9,10,11,12,13);
//-------------------------------------------------------------------------------

Button buttonMinus(16, 10);  // кнопка МИНУС, вывод 16 (A2)
Button buttonMenu(17, 10);   // кнопка МЕНЮ,  вывод 17 (A3)
Button buttonPlus(18, 10);   // кнопка ПЛЮС,  вывод 18 (A4)

#define MENU_TIME 5000  // время цикла тамера отображения меню ( * 2 = 1 сек)
unsigned int countIdleTime = 0; // счетчик времени отображения меню в бездействии
byte statMenu = 0;      // режим, 0 - не активно, 1 - активно, 2 - ввод параметра, 3 - запись параметра в память и переход в начало меню
byte numberParam = 0;   // номер параметра

struct Menu {
  byte itemNom;   // выбранный номер меню
  byte parameter; // значение выбраного по номеру параметра
};
// пока не знаю как читать из памяти, присвою начальные параметры тут
Menu paramValue[3] = {{1, 21}, {2, 5}, {3, 10}};
//---------------

void setup() {
 FlexiTimer2::set(2, timerInterrupt); // прерывания по таймеру 2 мс
 FlexiTimer2::start();               // разрешение прерывания
 // чтение переменных из памяти
 
 // 1. - температура в комнате
 // 2. - время между измерениями
 // 3. - пока не знаю
 //----------
 // скопировано из урока
  for (int i = 0; i < 32; i++) {
    if ( i == 0) disp.digit[0]= 1;
    else if ( i == 8)  disp.digit[1]= 1;
    else if ( i == 16) disp.digit[2]= 1;
    else if ( i == 24) disp.digit[3]= 1;
    else {
      disp.digit[0] = disp.digit[0] << 1;
      disp.digit[1] = disp.digit[1] << 1;
      disp.digit[2] = disp.digit[2] << 1;
      disp.digit[3] = disp.digit[3] << 1;     
    }
    delay(100);   
  } 
}

void loop() {

static byte valueIndikator[4]= {0,0,0,0};

 //----нажатие кнопки МЕНЮ ----
 if ( buttonMenu.flagClick == true ) {
    buttonMenu.flagClick = false; // сброс признака
    countIdleTime = 0;     // сброс счетчика
    if ((statMenu == 0 && numberParam == 0) || (statMenu > 0 && statMenu < 4 && numberParam > 0)) {
      statMenu ++; // выходим в режим выбора меню
    }
  }
  // ----фиксация в памяти введенного параметра----
 if (statMenu == 3) {
   // записываем параметр в память
   //пока не знаю как-
   //---------   
   statMenu = 1; numberParam = 0;
 }
 // ---- выбираем номер меню (кнопка плюс)----
 if ( buttonPlus.flagClick == true ) {
    buttonPlus.flagClick = false; // сброс признака
    countIdleTime = 0;     // сброс счетчика
    if (statMenu == 1 && numberParam < 3) numberParam ++;  // повышаем номер меню
    else if (statMenu == 2) {
      paramValue[numberParam-1].parameter ++; // повышаем значение параметра
    }
  }
 // ---- выбираем номер меню (кнопка минус)----
 if ( buttonMinus.flagClick == true ) {
    buttonMinus.flagClick = false; // сброс признака
    countIdleTime = 0;     // сброс счетчика
    if(statMenu == 1 && numberParam > 0) numberParam --; // понижаем номер меню
    else if (statMenu == 2) {
      paramValue[numberParam-1].parameter --; // понижаем значение параметра
    }
 }
  // ---- отображение меню на индикаторах----
  // делим значение параметра на десятки и единицы и выводим на 2 и 3 разрядах, на 1 разряде отображаем номер параметра.
  // При редактировании параметра отображаем на первом разряде точку.
 byte var1 = paramValue[numberParam-1].parameter / 10;
 byte var2 = paramValue[numberParam-1].parameter % 10;
 if (statMenu == 0) {
  // гасим индикаторы
   valueIndikator[0] = 88; 
   valueIndikator[1] = 88; 
   valueIndikator[2] = 88; 
   valueIndikator[3] = 0;
   }
 else if (statMenu == 1 && numberParam == 0) {
   // выподим тире (режим ожидания)
   valueIndikator[0] = 99; 
   valueIndikator[1] = 99; 
   valueIndikator[2] = 99; 
   valueIndikator[3] = 0;
   }
 else if (statMenu == 1 && numberParam > 0 ) {
   valueIndikator[0] = numberParam; // выводим показания параметров (номер параметра)
   valueIndikator[1] = var1; // выводим показания параметров (значение десятков параметра)
   valueIndikator[2] = var2; // выводим показания параметров (значение едениц параметра)
   valueIndikator[3] = 0;    // выводим показания параметров (отображение точки)
   }
 else if (statMenu == 2) {
   valueIndikator[0] = numberParam; // выводим показания параметров (номер параметра)
   valueIndikator[1] = var1; // выводим показания параметров (значение десятков параметра)
   valueIndikator[2] = var2; // выводим показания параметров (значение едениц параметра)
   valueIndikator[3] = 1;    // выводим показания параметров (отображение точки)
   }
 for (byte i=0; i<=2 ;i++) {
   if (valueIndikator[i] == 88) disp.digit[2-i]= B00000000;        // (i разряд) гасим
   else if (valueIndikator[i] == 99) disp.digit[2-i]= B01000000;   // (i разряд) знак (- ожидание выбра номера параметра)
   else if (2-i==2 && valueIndikator[3]==1)  {
      byte tempNumber = getNumberInd(valueIndikator[i]);
      disp.digit[2-i] = bitSet(tempNumber,7); //включаем бит точки на индикаторе и выводим значение номера параметра и значение самого параметра
      }
   else disp.digit[2-i] = getNumberInd(valueIndikator[i]); //выводим значение номера параметра и значение самого параметра
   }
 }

// --------- конвертация десятичного числа в двоичное 
int getNumberInd(byte indCifra) {
 byte indByte = B00000000;
 if      (indCifra == 1) indByte = B00000110;
 else if (indCifra == 2) indByte = B01011011;
 else if (indCifra == 3) indByte = B01001111;
 else if (indCifra == 4) indByte = B01100110;
 else if (indCifra == 5) indByte = B01101101;
 else if (indCifra == 6) indByte = B01111101;
 else if (indCifra == 7) indByte = B00000111;
 else if (indCifra == 8) indByte = B01111111;
 else if (indCifra == 9) indByte = B01101111;
 else if (indCifra == 0) indByte = B00111111;
 return indByte;
 }


//----------- обработчик прерывания 2 мс
void  timerInterrupt()
 {
 disp.regen(); // регенерация индикатора
 buttonMinus.filterAvarage();  // сканирование кнопки МИНУС, метода фильтрации по среднему
 buttonMenu.filterAvarage();  // сканирование кнопки МЕНЮ, метода фильтрации по среднему
 buttonPlus.filterAvarage();  // сканирование кнопки ПЛЮС, метода фильтрации по среднему
 if (statMenu > 0) {
     countIdleTime++;  // + 1 к счетчику таймера отображения меню
 }
 if (countIdleTime >= MENU_TIME ) {
    countIdleTime = 0;     // сброс счетчика
    statMenu = 0;
    numberParam = 0;
    // код программы вызывается каждые 1000 мс   
  }   
}

Re: Контроль усвоенного материала.

Добавлено: 25 янв 2018, 14:43
Эдуард
Здравствуйте!
Я бы посоветовал немного изменить структуру. Выделить режимы в программные блоки, а в них уже производить анализ условий, действия. Получится боле стройная, понятная программа. Такая структура используется, например, в сигнализации на Ардуино (урок 17).

Код: Выделить всё

void loop() {

  if(statMenu == 0) {
    // не активно
   
  }

  else if(statMenu == 1) {
    // активно
   
  }

  else if(statMenu == 2) {
    // ввод параметра
   
  }

  else if(statMenu == 3) {
    // запись параметра в память
   
  }

  else statMenu=0;

}

Re: Контроль усвоенного материала.

Добавлено: 26 янв 2018, 13:01
Виктор
Добрый день.

Я переделал, работает, но кое что так и не могу понять, я там в коде в комментариях вопросительными знаками выделил что не получается и не понятно. Если у Вас будет возможность, не могли бы Вы подсказать что я не так понимаю?

Код: Выделить всё

#include <FlexiTimer2.h>
#include <Led4Digits.h>
#include <Button.h>

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(2, 4,3,2,255, 6,7,8,9,10,11,12,13);
//-------------------------------------------------------------------------------

Button buttonMinus(16, 10);  // кнопка МИНУС, вывод 16 (A2)
Button buttonMenu(17, 10);   // кнопка МЕНЮ,  вывод 17 (A3)
Button buttonPlus(18, 10);   // кнопка ПЛЮС,  вывод 18 (A4)

#define MENU_TIME 5000  // время цикла тамера отображения меню ( * 2 = 1 сек)
unsigned int countIdleTime = 0; // счетчик времени отображения меню в бездействии
byte statMenu = 0;      // режим, 0 - не активно, 1 - активно, 2 - ввод параметра, 3 - запись параметра в память и переход в начало меню
byte numberParam = 0;   // номер параметра

struct Menu {
  byte itemNom;   // выбранный номер меню
  byte parameter; // значение выбраного по номеру параметра
};

Menu paramValue[3] = {{1, 21}, {2, 5}, {3, 10}}; //пока временно присваиваю значения таким способом

void setup() {
 FlexiTimer2::set(2, timerInterrupt); // прерывания по таймеру 2 мс
 FlexiTimer2::start();               // разрешение прерывания
 // чтение переменных из памяти
 
 // 1. - температура в комнате
 // 2. - время между измерениями
 // 3. - пока не знаю
 //----------
 }

void loop() {

static byte valueIndikator[4]= {0,0,0,0};  // ??? ВОПРОС! Необходим ли данный код? (прочитал что данная конструкция
                  // отменяет постоянную инициализацию массива (видимо это должно влиять
                  // на время выполнения программы ??? или не обязательно так делать?
//----НАЖАТИЕ кнопки МЕНЮ ----
 if (buttonMenu.flagClick == true ) {
    buttonMenu.flagClick = false;    // сброс признака
    countIdleTime = 0;           // сброс счетчика
    if (statMenu >= 0 && statMenu <=3) statMenu ++; // ограничение на  нажатие кнопки меню
 }   
// -----МЕНЮ НЕ АКТИВНО-----
 if (statMenu == 0) {
   // гасим индикаторы
   valueIndikator[0] = 88; 
   valueIndikator[1] = 88; 
   valueIndikator[2] = 88; 
   valueIndikator[3] = 0;
 }
// -----МЕНЮ АКТИВНО-----
 else if (statMenu == 1) {
   // выводим тире на всех разрядах (режим ожидания если не выбран номер параметра)
   if (numberParam == 0) {
      valueIndikator[0] = 99; 
      valueIndikator[1] = 99; 
      valueIndikator[2] = 99; 
      valueIndikator[3] = 0;
   }
   // ----перемещаемся по номерам параметров----
   if (numberParam >= 0 && numberParam <= 3) {
 
  // ??????? Хотел попробовать через указатель но не получается так  (ниже код в комментариях) ???????
  //    ptrnumberParam = &numberParam;          ??? Пытался так передать адрес
  //    selectParameter(ptrnumberParam); 
  //                  или же вот так:
  //    selectParameter(&numberParam)
  //
  //    а в функции писал так: 
  //
  //   void selectParameter(byte *variable) {
  //  *variable ++;
  //  (numberParam) - это глобальная переменная, но я в одну и туже функцию
  // хотел в одном месте передавать номер выбора параметра (что бы кнопками +- менять его
  // а в другом месте менять через эту же функцию значение выбранного параметра
  // ????????
   
 selectParameter(numberParam);     // Это работает. Я так понимаю это передача параметра по ссылке. (читал что возможна только
                        // для базовых типов)
   if (numberParam>3) numberParam = 3;
               
               //------- или же нужно было присвоить значение глобальной переменной
               // какой то локальноый переменной, передать ее в функцию, там
               // произвести расчет, вернуть через return и присвоить значение обратно
               // глобальной numberParam ? пример:
               //  byte y = numberParam;
               //  numberParam = selectParameter(y);
               //  ???????????????????????????????????????
   }
  }
 // -----МЕНЮ ВВОД ПАРАМЕТРА-----
 else if (statMenu == 2) {
   if (paramValue[numberParam-1].parameter >=0 && paramValue[numberParam-1].parameter <100) {
      selectParameter(paramValue[numberParam-1].parameter); // редактируем значение параметра
   }
 }
 // -----МЕНЮ ЗАПИСЬ ПАРАМЕТРА-----
 else if (statMenu == 3) {
   if (numberParam > 0) { // && если значение в  EEPROM  отлично от текущего тогда
      // а так же дополнительные условия проверки значений на различные пункты параметров)
      // записываем значение (paramValue[numberParam-1].parameter)
      // номера параметра (numberParam)  память
      //(тут должен быть код записи параметров в память
      statMenu = 1; numberParam = 0;
   }
 }
 displayIndikators(valueIndikator);
}
 
//*****отображение меню на индикаторах*****
int displayIndikators(byte vInd[4]) {
 // делим значение параметра на десятки и единицы и выводим на 2 и 3 разрядах, на 1 разряде отображаем номер параметра.
 // При редактировании параметра отображаем на первом разряде точку.
 byte var1 = paramValue[numberParam-1].parameter / 10;
 byte var2 = paramValue[numberParam-1].parameter % 10;
 if (statMenu == 0) {
  // гасим индикаторы
   vInd[0] = 88; 
   vInd[1] = 88; 
   vInd[2] = 88; 
   vInd[3] = 0;
 }
 else if (statMenu == 1 && numberParam == 0) {
   // выводим тире (режим ожидания)
   vInd[0] = 99; 
   vInd[1] = 99; 
   vInd[2] = 99; 
   vInd[3] = 0;
 }
 else if (statMenu == 1 && numberParam > 0 ) {
   vInd[0] = numberParam; // выводим показания параметров (номер параметра)
   vInd[1] = var1; // выводим показания параметров (значение десятков параметра)
   vInd[2] = var2; // выводим показания параметров (значение едениц параметра)
   vInd[3] = 0;    // выводим показания параметров (отображение точки)
 }
 else if (statMenu == 2) {
   vInd[0] = numberParam; // выводим показания параметров (номер параметра)
   vInd[1] = var1; // выводим показания параметров (значение десятков параметра)
   vInd[2] = var2; // выводим показания параметров (значение едениц параметра)
   vInd[3] = 1;    // выводим показания параметров (отображение точки)
 }
 for (byte i=0; i<=2 ;i++) {
   if (vInd[i] == 88) disp.digit[2-i]= B00000000;        // (i разряд) гасим
   else if (vInd[i] == 99) disp.digit[2-i]= B01000000;   // (i разряд) знак (- ожидание выбра номера параметра)
   else if (2-i==2 && vInd[3]==1)  {
      byte tempNumber = getNumberInd(vInd[i]);
      disp.digit[2-i] = bitSet(tempNumber,7); //включаем бит точки на индикаторе и выводим значение номера параметра и значение самого параметра
      }
   else disp.digit[2-i] = getNumberInd(vInd[i]); //выводим значение номера параметра и значение самого параметра
   }
 }
 
// *****обработка кнопок плюс и минус*****   
 void selectParameter(byte &variable) {   //??? это передача по ссылке?  Или же можно не писать символ &
 // в данном коде? Как оптимальнее поступить?
 
 // -----НАЖАТИЕ КНОПКИ ПЛЮС-----
 if (buttonPlus.flagClick == true ) {
    buttonPlus.flagClick = false;    // сброс признака
    countIdleTime = 0;           // сброс счетчика
    variable ++;
   }
 // -----НАЖАТИЕ КНОПКИ МИНУС-----
 if (buttonMinus.flagClick == true ) {
    buttonMinus.flagClick = false;    // сброс признака
    countIdleTime = 0;           // сброс счетчика
    if (variable > 0) variable --;   
 }
 }

// *****конвертация десятичного числа в двоичное***** 
int getNumberInd(byte indCifra) {
 byte indByte = B00000000;
 if      (indCifra == 1) indByte = B00000110;
 else if (indCifra == 2) indByte = B01011011;
 else if (indCifra == 3) indByte = B01001111;
 else if (indCifra == 4) indByte = B01100110;
 else if (indCifra == 5) indByte = B01101101;
 else if (indCifra == 6) indByte = B01111101;
 else if (indCifra == 7) indByte = B00000111;
 else if (indCifra == 8) indByte = B01111111;
 else if (indCifra == 9) indByte = B01101111;
 else if (indCifra == 0) indByte = B00111111;
 return indByte;
 }


//*****обработчик прерывания 2 мс*****
void  timerInterrupt() {
 disp.regen(); // регенерация индикатора
 buttonMinus.filterAvarage();  // сканирование кнопки МИНУС, метода фильтрации по среднему
 buttonMenu.filterAvarage();  // сканирование кнопки МЕНЮ, метода фильтрации по среднему
 buttonPlus.filterAvarage();  // сканирование кнопки ПЛЮС, метода фильтрации по среднему
 if (statMenu > 0) {
     countIdleTime++;  // + 1 к счетчику таймера отображения меню
 }
 if (countIdleTime >= MENU_TIME ) {
    countIdleTime = 0;     // сброс счетчика
    statMenu = 0;
    numberParam = 0;
    // код программы вызывается каждые 1000 мс   
  }   
}

Re: Контроль усвоенного материала.

Добавлено: 26 янв 2018, 14:33
Эдуард
Здравствуйте!

Код: Выделить всё

static byte valueIndikator[4]= {0,0,0,0};  // ??? ВОПРОС! Необходим ли данный код? (прочитал что данная конструкция

Объявление static внутри функции означает, что после инициализации переменная остается в памяти постоянно, даже после выхода из функции. В функции loop это не имеет смысла. Логичнее объявить этот массив глобальным.

Вот пример из контроллера элемента Пельтье (урок 42) , как передается аргумент функции через указатель.

Код: Выделить всё

// -------------------------------- запись данного типа Float в EEPROM с контрольной суммой
void writeFloatToEeprom(int adress, float *value) {
 
  EEPROM.write(adress, *((byte*)value));
  EEPROM.write(adress+1, *(((byte*)value)+1));
  EEPROM.write(adress+2, *(((byte*)value)+2));
  EEPROM.write(adress+3, *(((byte*)value)+3));
  EEPROM.write(adress+4, (*((byte*)value) + *(((byte*)value)+1) + *(((byte*)value)+2) + *(((byte*)value)+3)) ^ 0xe5);     
}

Через указатель передается второй аргумент. Вызов функции происходит так:

Код: Выделить всё

writeFloatToEeprom(EEPROM_SET_TEMP_REF, & setTempRef);

Re: Контроль усвоенного материала.

Добавлено: 26 янв 2018, 19:04
Виктор
Я перечитал несколько раз урок 15 (про указатели), все вроде понятно написано. Через монитор порта вижу что значение переменной полученное через указатель соответствует значению глобальной переменной (на которую я брал указатель), но на сложение - вычитание не реагирует, нельзя делать со значением через указатель ничего?

Код: Выделить всё

byte parametr = 25;

void setup() {
}

void loop() {

byte* ptrw;
ptrw = (byte*)(& parametr); 
selectParameter(ptrw);
}


// *****обработка кнопок плюс и минус*****   

 void selectParameter(byte *variable) {   
 // -----НАЖАТИЕ КНОПКИ ПЛЮС-----
 if (buttonPlus.flagClick == true ) {
    buttonPlus.flagClick = false;    // сброс признака
   
       *variable ++;      //??? не меняется значение глобальной переменной (parametr )
   }
 // -----НАЖАТИЕ КНОПКИ МИНУС-----
 if (buttonMinus.flagClick == true ) {
    buttonMinus.flagClick = false;    // сброс признака
   
   *variable --;    //??? не меняется значение глобальной переменной (parametr )
 }
 }

Re: Контроль усвоенного материала.

Добавлено: 26 янв 2018, 22:55
Эдуард
Проверьте этот вариант.

Код: Выделить всё

byte parametr;

void setup() {
  Serial.begin(9600);
}

void loop() {
  selectParameter(& parametr);
  Serial.println(parametr);
  delay(1000);
}

void selectParameter(byte *variable) {
 (* variable) ++;
}

Re: Контроль усвоенного материала.

Добавлено: 26 янв 2018, 23:59
Виктор
Да, Эдуарт, не хватало скобок!!! Я тоже нашел на просторах интернета пример и заодно нашел ошибку в своем коде и пока разбирался как исправить, не успел Вам ответить. Спасибо Вам за Ваше терпение и извините за бесталковые вопросы, но уж очень хочется разобраться, очень Вам благодарен! Если Вы не против, по ходу работы, еще буду задавать вопросы (скорей всего тоже для Вас наивные), но для меня очень важные, если против, Вы сразу скажите, я без обид. (признаюсь, несколько лет потратил на отопление дома для родителей, в итоге сам с отцом установили пиролизный котел с большим тепло - аккумулятором), но максимального эффекта без мозгов не достичь, так как клапаны бегать в котельную вручную крутить нет смысла, в итоге накопленное тепло форточками регулируют и все выдувается, так как с начало очень жарко, потом ночь и утром холодно). Понимаю что можно все готовое купить, но под нашу систему, мозги дороже котла и нашей работы стоят.. Да и раз уж все сами, то и решил и дальше сам двигаться. И черчение изучил и 3D принтер прикупил (с китая конечно, но сервопривод уже крутится), только его нужно научить куда и когда крутиться. Еще бы понять как вычислять температуру подачи в зависимости от комнатной.... наверно просто соберу статистику по факту, прикину коэффициент между комнатной и подачей да и все..). Вообщем, дело в том, что начиналось все, когда я еще в школе был, а теперь отец уже на пенсии и у меня дети, работа, времени очень мало теперь, но хочется что бы пожил более менее комфортно, поэтому и тороплюсь и обращаюсь к Вам...

Re: Контроль усвоенного материала.

Добавлено: 27 янв 2018, 00:38
Эдуард
Пишите, спрашивайте. Никаких проблем. Я раскручиваю форум естественным образом, и мне нужен новый контент. Если можно, не мешайте все в одну тему, а открывайте новые под каждую задачу.

Re: Контроль усвоенного материала.

Добавлено: 26 окт 2018, 09:38
Виктор
Здравствуйте.
Создал менюшку, все вроде работает, но хотелось сделать немножко по другому (через не определенный тип данных), но не могу правильно (а может это вообще не возможно) написать вызов параметра. Подскажите пожалуйста, пытался читать и примеры искал, пока только больше каши в голове.
Рабочий код:

Код: Выделить всё

// -------Параметры, выбираемые в меню  --------   
byte tComfSummer = 23;   // летняя температура комфорта в комнате
byte tComfWinter   = 24;   // зимняя температура комфорта в комнате
byte tInpStr          = 45;   // средняя температура подачи теплоносителя
byte timeQuer         = 15;   // Время опроса датчиков   
byte Pump               = 1 ;   // контроль циркуляционного насоса 1- вкл,  0 выкл
//-----------------------------------------------

typedef struct _procesBut {
    void(*on_click)(char);   
    byte &param;   //!!!!!!! ВОПРОС ПО ЭТОМУ ПАРАМЕТРУ при указании ссылки все получается НО тип параметра одинаковый должен
    String title;
    } ProcesBut;
   
ProcesBut procesButs[] = {
    {Edit_tPrmComfSummer, tComfSummer, "tLeto:          "}, // летняя температура комфорта в комнате
    {Edit_tPrmComfWinter, tComfWinter, "tSima:          "}, // зимняя температура комфорта в комнате
    {Edit_tInpStr, tInpStr, "tPod:           "},      // средняя температура подачи теплоносителя
    {Edit_tInpStr, timeQuer, "vrOpr:          "},      // время опроса (задействуем туже функцию что и в темп.подачи)
    {SettingPump, Pump, "Nasos:          "}      // контроль циркуляционного насоса
    };

// --------------------- функции обработки кнопок ------------------------------------
void Edit_tPrmComfSummer(char Concat) {
   tComfSummer = constrain((tComfSummer * 10 + Concat)/10, 15, 30);  // Изменяем с ограничением
}
void Edit_tPrmComfWinter(char Concat) {
   tComfWinter = constrain((tComfWinter * 10 + Concat)/10, 15, 30);  // Изменяем с ограничением
}   
//  ------------- ну и т.д.....

//  --- код всяческий и потом выводим на дисплей

   disp.setCursor(0, 0);
        disp.print("  <<< MENU >>>  ");
       disp.setCursor(0,1);
       disp.print(procesButs[NomParam].title);
       disp.setCursor(10,1);
       disp.print(procesButs[NomParam].param);
 // тут все понятно, все работает     


хотелось бы что бы переменные параметров были не все одного (byte) типа как вверху а как (далее)

Код: Выделить всё

// -------Параметры, выбираемые в меню  --------
   
float tComfSummer = 23.5;    // летняя температура комфорта в комнате   !!!!!!!!!!!!!!!
float tComfWinter   = 24.4;    // зимняя температура комфорта в комнате   !!!!!!!!!!!!!!
byte tInpStr          = 45;   // средняя температура подачи теплоносителя
byte timeQuer         = 15;   // Время опроса датчиков   
boolean Pump           = 1 ;   // контроль циркуляционного насоса 1- вкл,  0 выкл   !!!!!!!!!!!!!!
//-----------------------------------------------

typedef struct _procesBut {
    void(*on_click)(char);   
    void *param;   //!!!!!!!!!!!! ВОПРОС ПО ЭТОМУ ПАРАМЕТРУ заменил тип и сделал указателем
    String title;
    } ProcesBut;
   
ProcesBut procesButs[] = {
    {Edit_tPrmComfSummer, &tComfSummer, "tLeto:          "}, // летняя температура комфорта в комнате !!!!!!!!! указал ссылки на перемен
    {Edit_tPrmComfWinter, &tComfWinter, "tSima:          "}, // зимняя температура комфорта в комнате   !!!!!!!!! указал ссылки на перемен
    {Edit_tInpStr, &tInpStr, "tPod:           "},      // средняя температура подачи теплоносителя  !!!!!!!!! указал ссылки на перемен
    {Edit_tInpStr, &timeQuer, "vrOpr:          "},      // время опроса (задействуем туже функцию что и в темп.подачи)
    {SettingPump, &Pump, "Nasos:          "}      // контроль циркуляционного насоса  !!!!!!!!! указал ссылки на перемен
    };

// --------------------- функции обработки кнопок ------------------------------------
void Edit_tPrmComfSummer(char Concat) {
   tComfSummer = constrain((tComfSummer * 10 + Concat)/10, 15, 30);  // Изменяем с ограничением
}
void Edit_tPrmComfWinter(char Concat) {
   tComfWinter = constrain((tComfWinter * 10 + Concat)/10, 15, 30);  // Изменяем с ограничением
}   
//  ------------- ну и т.д.....

//  --- код всяческий и потом выводим на дисплей

   disp.setCursor(0, 0);
        disp.print("  <<< MENU >>>  ");
       disp.setCursor(0,1);
       disp.print(procesButs[NomParam].title);
       disp.setCursor(10,1);
       ///  !!!!!! тут начинаются проблемы
       //// Возможно ли получить параметр (param) и если да, то как правильно написать?
             
          //dtostrf(tInpStr, 2, 1, procesButs[NomParam].param);     /// ОШИБКА
          // disp.print(procesButs[NomParam].param);         ///ОШИБКА

   // ошибки при вызове procesButs[NomParam].param
   // видимо как то нужно указать тип данных, но не знаю как

p.s. прошу прощение если что то не правильно называю, переменные обзываю не по правилам, я учусь, стараюсь ))