Создание пользовательского класса

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Добрый всем вечер.

Проблема банальна: нужно вынести пользовательские функции в отдельные файлы или файл. Чем больше читаю о создании классов или библиотек, тем больше убеждаюсь что это либо слишком сложно для меня либо вообще неприемлемо.

Вся беда в том, что мне нужно производить некоторые действия с помощью элементов библиотеки UTFT. Создаю свой класс, но он не проходит компиляцию, потому что в нем используются элементы другого класса.

Так что, получается что эта затея обречена? Вот коды моих изысков:

1. Сам скетч:

#include <UTFT.h>

UTFT myGLCD(ILI9327, 38, 39, 40, 41);

extern uint8_t BigFont[];
extern uint8_t SmallFont[];
extern uint8_t Dingbats1_XL[];
extern uint8_t battery_24x48[];

//******************** SETUP ****************

void setup ()
{
  myGLCD.InitLCD();                         // запуск дисплея
  myGLCD.clrScr();                          // очистка дисплея
  myGLCD.setFont(SmallFont);
  
}

void loop() {};

2. Заголовок "user.h":

#ifndef user_h
#define user_h
#endif
class user
{
  public:
    void InitEMU();
};

3. Класс "user.cpp":

#include "user.h"
void user::InitEMU()
{
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 220);
  delay(210);
  myGLCD.print("                   ", 0, 220);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 210);
  myGLCD.print("Loading", 0, 220);
  delay(310);
  for (int i = 0; i <= 75; i = i + 9) {
    myGLCD.print(".", 75 + i, 220);
    delay(40);
  }
  myGLCD.print("                   ", 0, 220);
  myGLCD.print("Init start:", 0, 200);
  myGLCD.print("Loading  .......... Done!", 0, 210);
  delay(340);
  myGLCD.print("Init start:", 0, 190);
  myGLCD.print("                            ", 0, 210);
  myGLCD.print("Loading  .......... Done!", 0, 200);
  myGLCD.print("Init sensors: ", 0, 220);
  myGLCD.setFont(battery_24x48);
  delay(340);
  myGLCD.print(String(9), 110, 215);
  delay(340);
  myGLCD.print(String(8), 110, 215);
  delay(340);
  for (int i = 1; i <= 6; i++) {
    myGLCD.print(String(i), 110, 215);
    delay(200);
  }
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
}

Я хочу знать только одно: можно ли внутри своего класса использовать элементы другого?

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно. Но не всегда так, как вы желаете. 

Пока вас,  по старой русской традиции,  не начали учить ухватом - сбегайте в гугл и почитайте про наследование классов, например. Или, хотя бы, сделайте myGLCD членом своего класса.

P.S. #endif ставят в конце защищаемого .h, иначе смысла в этой конструкции никакого нет.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buzzer2010, а почему класс, который Вы хотите использовать из своего класса, описан снаружи класса?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

andriano пишет:

Buzzer2010, а почему класс, который Вы хотите использовать из своего класса, описан снаружи класса?

Потому что я еще не умею правильно описывать классы. Это прежде всего. Покажите 1 раз как правильно пожалуста.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

sadman41 пишет:

Можно. Но не всегда так, как вы желаете. 

Пока вас,  по старой русской традиции,  не начали учить ухватом - сбегайте в гугл и почитайте про наследование классов, например. Или, хотя бы, сделайте myGLCD членом своего класса.

P.S. #endif ставят в конце защищаемого .h, иначе смысла в этой конструкции никакого нет.

Спасибо. Признаться я просто скопировал структуру класса из какого-то примера, не вникая в смысл происходящего.

Значит тогда вот так?:

#ifndef user_h
#define user_h

class user
{
  public:
    void InitEMU();
};
#endif
1  

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, переменная myGLCD в файле user.cpp используется? А описывать её за Вас Трамп будет? Опишите её и всего делов.

Вставьте в начало файла что-нибудь типа

#include <UTFT.h>

extern UTFT myGLCD;

Только вот знаете чего я никак не пойму? Вот нахрена Вам класс? Почему не использовать просто вункцию во внешнем файле? Какой кайф Вы планируете извлечь и того, что у Вас там именно класс?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:

Ну, переменная myGLCD в файле user.cpp используется? А описывать её за Вас Трамп будет? Опишите её и всего делов.

Вставьте в начало файла что-нибудь тпа

#include <UTFT.h>

extern UTFT myGLCD;

Только вот знаете чего я никак не пойму? Вот нахрена Вам класс? Почему не использовать просто вункцию во внешнем файле? Какой кайф Вы планируете извлечь и того, что у Вас там именно класс?

Вот спасибо что и Вы тоже откликнулись. Нахрена мне класс? Читал про библиотеки и классы и было высказано мнение что использование классов более желательно чем библиотеки. С точки зрения оптимизации. Кроме того, я хочу собрать все свои уже отлаженные и далее не редактируемые функции в один файл. А насколько я понял так сделано в "UTFT.cpp", которую я тут изучаю...

Сделал так как Вы подсказали:

user.cpp:2: error: 'UTFT' does not name a type

 extern UTFT myGLCD;

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

было высказано мнение что использование классов более желательно чем библиотеки. С точки зрения оптимизации. 

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

Отдельные функции делаются также. Есть заголовочный файл и файл кода. например, мне нужны две функции void kaka(const int) и long mumu(void). окей, делаю файл mylib.h примерно такой

#ifndef MYLIB_H
#define  MYLIB_H

extern void kaka(const int);
extern long mumu(void);

#endif  //  MYLIB_H

и файл кода mylib.cpp

#include "mylib.h"

void kaka(const int n) {
    // тело функции
    .........
}


long mumu(void) {
    // тело функции
    .........
}

И все дела.

Кстати, необходимость описывать все используемые переменные (о чм я выше писал) это не отменяет. Трам - зараза за Вас не опишет :)

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

Сделал так как Вы подсказали:

user.cpp:2: error: 'UTFT' does not name a type

 extern UTFT myGLCD;

Про #include не забыли точно? Он точно такой же как и в основном скетче? И всё с этим файлом в порядке? Так не бывает, ищите какую-то фигню.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:

Buzzer2010 пишет:

было высказано мнение что использование классов более желательно чем библиотеки. С точки зрения оптимизации. 

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

Отдельные функции делаются также. Есть заголовочный файл и файл кода. например, мне нужны две функции void kaka(const int) и long mumu(void). окей, делаю файл mylib.h примерно такой

#ifndef MYLIB_H
#define  MYLIB_H

extern void kaka(const int);
extern long mumu(void);

#endif  //  MYLIB_H

и файл кода mylib.cpp

#include "mylib.h"

void kaka(const int n) {
    // тело функции
    .........
}


long mumu(void) {
    // тело функции
    .........
}

И все дела.

Кстати, необходимость описывать все используемые переменные (о чм я выше писал) это не отменяет. Трам - зараза за Вас не опишет :)

Трамп - он такой, да. Действует по принципу: "Обещать - не значит жениться"

А скажите - можно все свои функции собрать в одном файле или для каждой надо писать отдельно хедэр и .cpp?

Описывать перменные мне не трудно. Да только  - как? extern не прокатило, к сожалению (((((

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:
Про #include не забыли точно? Он точно такой же как и в основном скетче? И всё с этим файлом в порядке? Так не бывает, ищите какую-то фигню.

Вот как дело было:

#include "user.h"
#include <UTFT.h>
extern UTFT myGLCD;
void user::InitEMU()
{
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 220);
  delay(210);
  myGLCD.print("                   ", 0, 220);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 210);
  myGLCD.print("Loading", 0, 220);
  delay(310);
  for (int i = 0; i <= 75; i = i + 9) {
    myGLCD.print(".", 75 + i, 220);
    delay(40);
  }
  myGLCD.print("                   ", 0, 220);
  myGLCD.print("Init start:", 0, 200);
  myGLCD.print("Loading  .......... Done!", 0, 210);
  delay(340);
  myGLCD.print("Init start:", 0, 190);
  myGLCD.print("                            ", 0, 210);
  myGLCD.print("Loading  .......... Done!", 0, 200);
  myGLCD.print("Init sensors: ", 0, 220);
  myGLCD.setFont(battery_24x48);
  delay(340);
  myGLCD.print(String(9), 110, 215);
  delay(340);
  myGLCD.print(String(8), 110, 215);
  delay(340);
  for (int i = 1; i <= 6; i++) {
    myGLCD.print(String(i), 110, 215);
    delay(200);
  }
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);

}

Теперь орёт на "  myGLCD.setFont(SmallFont);" :

user.cpp:7: error: 'SmallFont' was not declared in this scope

Шрифты тоже тут объявлять нужно?

-----------------------

Вот так  - совсем не орал:

#include "user.h"
#include <UTFT.h>
extern UTFT myGLCD;
extern uint8_t SmallFont[];
extern uint8_t battery_24x48[];
void user::InitEMU()
{
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 220);
  delay(210);
  myGLCD.print("                   ", 0, 220);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 210);
  myGLCD.print("Loading", 0, 220);
  delay(310);
  for (int i = 0; i <= 75; i = i + 9) {
    myGLCD.print(".", 75 + i, 220);
    delay(40);
  }
  myGLCD.print("                   ", 0, 220);
  myGLCD.print("Init start:", 0, 200);
  myGLCD.print("Loading  .......... Done!", 0, 210);
  delay(340);
  myGLCD.print("Init start:", 0, 190);
  myGLCD.print("                            ", 0, 210);
  myGLCD.print("Loading  .......... Done!", 0, 200);
  myGLCD.print("Init sensors: ", 0, 220);
  myGLCD.setFont(battery_24x48);
  delay(340);
  myGLCD.print(String(9), 110, 215);
  delay(340);
  myGLCD.print(String(8), 110, 215);
  delay(340);
  for (int i = 1; i <= 6; i++) {
    myGLCD.print(String(i), 110, 215);
    delay(200);
  }
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);

}

А теперь же можно тут и другие функции свои поописывать и хэдер подправить?

Кстати: в какие скобки брать этот user.h  в #include  в самом скетче: в кавычки или в такие: <> ??? и какая в них разница ?

sadman41
Offline
Зарегистрирован: 19.10.2016

Смотрите на каждый файл с точки зрения компилятора: возможно ли использовать неизвестный объект?  Вот вы, к примеру, можете процитировать стихотворение малоизвестного автора, если я вам сообщу его название? Вот и компилятор тоже...

Только копировать не нужно во все файлы одно и то же. #include придумали, чтобы такой ерундой не страдать.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

sadman41 пишет:
Смотрите на каждый файл с точки зрения компилятора: возможно ли использовать неизвестный объект?  Вот вы, к примеру, можете процитировать стихотворение малоизвестного автора, если я вам сообщу его название? Вот и компилятор тоже...Только копировать не нужно во все файлы одно и то же. #include придумали, чтобы такой ерундой не страдать.

Это еще нужно разобраться... Пока что: "многабукаф" ))))))) Но - спасибо. Любой совет мотаю на ус...

Ой. А как теперь из скетча вызвать эту функцию или элемент класса? Пишет вот что:

DUE_LOAD_EMU:20: error: expected unqualified-id before '.' token

   user.InitEMU();

       ^

exit status 1
expected unqualified-id before '.' token

Вызываю вот так:

#include <UTFT.h>
#include "user.h"
UTFT myGLCD(ILI9327, 38, 39, 40, 41);

extern uint8_t BigFont[];
extern uint8_t SmallFont[];
//extern uint8_t SevenSegNumFontPlusPlus[];
extern uint8_t Dingbats1_XL[];
extern uint8_t battery_24x48[];
//extern unsigned short Life[0xFB40];


//******************** SETUP ****************

void setup ()
{
  myGLCD.InitLCD();                         // запуск дисплея
  myGLCD.clrScr();                          // очистка дисплея
  myGLCD.setFont(SmallFont);
  user.InitEMU();
}

void loop() {};

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

user.cpp:7: error: 'SmallFont' was not declared in this scope

Так правильно. Описывать нужно все переменные.  myGLCD Вы описали, а шрифты чем хуже?

Другое дело, если вы эти описания шрифтов (всех) поемстите в user.h, то Вам их не нужно будет описывать ни в основном скетче, ни в user.cpp - они будут в одном месте и это правильно.

Buzzer2010 пишет:

А теперь же можно тут и другие функции свои поописывать и хэдер подправить?

Ну я же приводил Вам пример для двух функций. В хеадере описываете все прототипы (хоть сто функций), а исполняеммо файле пишете сами функции.

Buzzer2010 пишет:

Кстати: в какие скобки брать этот user.h  в #include  в самом скетче: в кавычки или в такие: <> ??? и какая в них разница ?

Это к сожалению ещё один "тот самый" момент в который разработчики IDE полазали грязными руками и сделали правки за Вас.

Общее правило таково: <> используется в том случае, когда .h файл находится в всистемных папках для включаемых файлов, а "" - в том случае, когда файл в той же папке, что и скетч. Но, повторяю, разработчики IDE тут немного пошустрили. Более того, это зависит от версии IDE. Как они сделали описано в какой-то их документации, я видел, но не помню где. Как таковой проблемы у меня не возникало, потому плотно и не разбирался.

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

Ой. А как теперь из скетча вызвать эту функцию или элемент класса? Пишет вот что:

Вам бы всё-таки книжку почитать. Потому, что ответ на большинство Ваших вопросов (и на этот) примерно такой "есть 100500 способов, а как Вам надо?"

Ну, вот смотрите. Вы описали класс (тип данных) с именем user. Запомните, класс это тип данных. Теперь, чтобы им пользоваться, необхожимо описать хотя бы одну переменную этого типа (называется "экземпляр класса"). Например:

user kaka;

а потом уже вызывать метод "в контексте экземпляра"

kaka.InitEMU();

Но при том классе, что у Вас, как таковой экземпляр Вам не нужен, т.к. у него свойств нет, поэтому метод InitEMU можно сделать статическим (добавить слово static в его описание в .h файле) и тогда его можно вызывать по имени класса без экземпляра, но не через точку, а через :: Пример так

// в .h файл
.....
static void InitEMU();
.....

// тогда вызов выглядит так:
user::InitEMU();

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Так. Спасибо за разъяснения. Сейчас буду постигать.

Со скобками: я думал, примерно, тоже самое, но хотел услышать мнение специалиста.

УРРА! Заработало!!!! Вот спасибо Вам большое !!!! Будет чем на работе заняться: перенесу все свои отлаженные процедурки в один .cpp !!!!

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:
Ну, вот смотрите. Вы описали класс (тип данных) с именем user. Запомните, класс это тип данных. Теперь, чтобы им пользоваться, необхожимо описать хотя бы одну переменную этого типа (называется "экземпляр класса"). Например:

user kaka;

а потом уже вызывать метод "в контексте экземпляра"

kaka.InitEMU();

Но при том классе, что у Вас, как таковой экземпляр Вам не нужен, т.к. у него свойств нет, поэтому метод InitEMU можно сделать статическим (добавить слово static в его описание в .h файле) и тогда его можно вызывать по имени класса без экземпляра, но не через точку, а через :: Пример так

// в .h файл
.....
static void InitEMU();
.....

// тогда вызов выглядит так:
user::InitEMU();

Да, я уже заметил что-то неладное с UTFT и с созданием элемента класса "myGLCD" в строке:

UTFT myGLCD(ILI9327, 38, 39, 40, 41);

Там явно создаётся еще одна переменная и только она потом вызывается через точку со всеми другими элементами UTFT. Я так делал - ничего не вышло почему-то ((( А почему?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buzzer2010 пишет:

Там явно создаётся еще одна переменная и только она потом вызывается через точку со всеми другими элементами UTFT. Я так делал - ничего не вышло почему-то ((( А почему?

Ответить на этот вопрос можно только при одновременном выполнении сразу двух условий:

1. В сообщении с вопросом присутствует полный скетч.

2. В сообщении с вопросом присутствует подробное описание, чего именно Вы хотите добиться, и чем то, что получается, отличается от желаемого.

sadman41
Offline
Зарегистрирован: 19.10.2016

Мне кажется, что ЕвгенийП прав - классы вам пока не нужны. Просто научитесь для начала разбивать код на разные файлы. Потом поработайте со структурами (struct), поймете что есть форма и что есть содержание, как крутить полями и почему там что-то "вызывается через точку". А затем уже до классов там рукой подать. 

Поверьте - редко кому удается с нуля взять и лупануть собственный класс, учтя все подводные камни. А вы еще и на достаточно сложном примере начали экспериментировать.

P.S. Для простых вещей (экспериментов) не стоит мучать сразу Arduino IDE с ее специфическими операторами. Я, к примеру, не завязанные на железе вещи, вообще в CodeLite сначала делаю. Там и дебаг есть и всё такое. А компилятор точно такой же, как в Arduino IDE. Так что при переносе возникает минимум проблем.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:
Ну, вот смотрите. Вы описали класс (тип данных) с именем user. Запомните, класс это тип данных. Теперь, чтобы им пользоваться, необхожимо описать хотя бы одну переменную этого типа (называется "экземпляр класса"). Например:

user kaka;

а потом уже вызывать метод "в контексте экземпляра"

kaka.InitEMU();

Но при том классе, что у Вас, как таковой экземпляр Вам не нужен, т.к. у него свойств нет, поэтому метод InitEMU можно сделать статическим (добавить слово static в его описание в .h файле) и тогда его можно вызывать по имени класса без экземпляра, но не через точку, а через :: Пример так

// в .h файл
.....
static void InitEMU();
.....

// тогда вызов выглядит так:
user::InitEMU();

Да, я уже заметил что-то неладное с UTFT и с созданием элемента класса "myGLCD" в строке:

UTFT myGLCD(ILI9327, 38, 39, 40, 41);

Там явно создаётся еще одна переменная и только она потом вызывается через точку со всеми другими элементами UTFT. Я так делал - ничего не вышло почему-то ((( А почему?

Начало темы, первый пост:

Добрый всем вечер.

Проблема банальна: нужно вынести пользовательские функции в отдельные файлы или файл. Чем больше читаю о создании классов или библиотек, тем больше убеждаюсь что это либо слишком сложно для меня либо вообще неприемлемо.

Вся беда в том, что мне нужно производить некоторые действия с помощью элементов библиотеки UTFT. Создаю свой класс, но он не проходит компиляцию, потому что в нем используются элементы другого класса.

Так что, получается что эта затея обречена? Вот коды моих изысков:

1. Сам скетч:

#include <UTFT.h>

UTFT myGLCD(ILI9327, 38, 39, 40, 41);

extern uint8_t BigFont[];
extern uint8_t SmallFont[];
extern uint8_t Dingbats1_XL[];
extern uint8_t battery_24x48[];

//******************** SETUP ****************

void setup ()
{
  myGLCD.InitLCD();                         // запуск дисплея
  myGLCD.clrScr();                          // очистка дисплея
  myGLCD.setFont(SmallFont);
  
}

void loop() {};

2. Заголовок "user.h":

#ifndef user_h
#define user_h
#endif
class user
{
  public:
    void InitEMU();
};

3. Класс "user.cpp":

#include "user.h"
void user::InitEMU()
{
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 220);
  delay(210);
  myGLCD.print("                   ", 0, 220);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 210);
  myGLCD.print("Loading", 0, 220);
  delay(310);
  for (int i = 0; i <= 75; i = i + 9) {
    myGLCD.print(".", 75 + i, 220);
    delay(40);
  }
  myGLCD.print("                   ", 0, 220);
  myGLCD.print("Init start:", 0, 200);
  myGLCD.print("Loading  .......... Done!", 0, 210);
  delay(340);
  myGLCD.print("Init start:", 0, 190);
  myGLCD.print("                            ", 0, 210);
  myGLCD.print("Loading  .......... Done!", 0, 200);
  myGLCD.print("Init sensors: ", 0, 220);
  myGLCD.setFont(battery_24x48);
  delay(340);
  myGLCD.print(String(9), 110, 215);
  delay(340);
  myGLCD.print(String(8), 110, 215);
  delay(340);
  for (int i = 1; i <= 6; i++) {
    myGLCD.print(String(i), 110, 215);
    delay(200);
  }
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
}

Я хочу знать только одно: можно ли внутри своего класса использовать элементы другого?

 

----------------------

Ну, собственно, часть ошибок уже исправлена, спасибо Евгению: объявлены переменные:

#include "user.h"
#include <UTFT.h>
extern UTFT myGLCD;
extern uint8_t SmallFont[];
extern uint8_t battery_24x48[];

Исправлен вызов:

// Было
user.InitEMU();

// Стало:
user::InitEMU();

На данном этапе мне и такого положения вещей хватит, но умные советы слушать готов всегда.

sadman41 пишет:
Мне кажется, что ЕвгенийП прав - классы вам пока не нужны. Просто научитесь для начала разбивать код на разные файлы. Потом поработайте со структурами (struct), поймете что есть форма и что есть содержание, как крутить полями и почему там что-то "вызывается через точку". А затем уже до классов там рукой подать. 

Поверьте - редко кому удается с нуля взять и лупануть собственный класс, учтя все подводные камни. А вы еще и на достаточно сложном примере начали экспериментировать.

P.S. Для простых вещей (экспериментов) не стоит мучать сразу Arduino IDE с ее специфическими операторами. Я, к примеру, не завязанные на железе вещи, вообще в CodeLite сначала делаю. Там и дебаг есть и всё такое. А компилятор точно такой же, как в Arduino IDE. Так что при переносе возникает минимум проблем.

Вот именно разбивать код - это то что мне нужно, что бы не листать метры скетча.

Со структурами - хотелось бы попробовать, но что это такое и нужно ли сейчас - надо почитать...

Сложность примера обуславливалась необходимостью выделить в отдельный файл несколько функций, которые используют в свою очередь класс "myGLCD". О том что это сложно я вчера еще не догадывался ))))

Дело в том, что для меня язык Си открывается только в виде Arduino IDE, где я с ним столкнулся первый раз в жизни. Так что мне пока что сравнивать не с чем )))))) Но все равно - спасибо за советы!

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Так, я буду собираться на работу. Если там комп не откинется - вечерком продолжим.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buzzer2010 пишет:

Дело в том, что для меня язык Си открывается только в виде Arduino IDE, где я с ним столкнулся первый раз в жизни. Так что мне пока что сравнивать не с чем )))))) Но все равно - спасибо за советы!

А вот это очень напрасно.

По собственному опыту: для того, чтобы сделать что-то вменяемое на Ардуино, требуется гораздо больше кода написать для ПК.

В качестве примера скажу что для проекта: http://arduino.ru/forum/proekty/floppy-hdd-music

На ПК были написаны:

1. Рабор MIDI-файла.

2. Аранжировка разобранного в п.1. под особенности конкретного инструмента.

3. Таблицы перевода нот в коэффициенты деления.

В общем, из 9 используемых файлов 7 были сгенерены в автоматическом режиме на ПК.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Это всё чудесно и проект впечатляющий. Однако. Однако же это всё хорошо для тех, кто в свободно сях разбирается и может посты на форуме писать на С++. Но Вы же тоже с чего-то начинали? Не родились же Вы с компилятором в голове?

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

Buzzer2010 пишет:

Не родились же Вы с компилятором в голове?

я родился с if() {} в голове - следующий вопрос, пожалуйста.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

И как живётся с управляющим оператором в голове? Наверно все управляют кому не лень, ставят свои условия постоянно? Мне так больше по душе switch - case: сделал что полагается и пошли все остальные нафиг со своими условиями )))

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

Buzzer2010 пишет:

И как живётся с управляющим оператором в голове? Наверно все управляют кому не лень, ставят свои условия постоянно?

это называется управляющим оператором?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

Не родились же Вы с компилятором в голове?

Ко мне внук, постоянно бегал с простейшими проблемами, которые вполне мог бы решить сам. Каждый раз я специально тратил больше времени, чем было необходимо для объяснения его проблемы специально для того, чтобы показать ему ход рассуждений и проверок от того, что он знает к решению проблемы, показывая тем самым, что он мог бы и сам это решить. Но впечатления не производило. Потом я как-то случайно брякнул, "Блин, ну вот правда, странно слышать о таких проблемах от программиста в чётвёртом поколении!". И это подействовало! Он стал гораздо больше разбираться сам и намного реже приходить с простейшими вопросами. Уж не знаю, с чем он родился, но осознав свою "наследственность", резко изменил своё отношение и это тут же сказалось на результатах. Вот такая история.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buzzer2010 пишет:

Однако же это всё хорошо для тех, кто в свободно сях разбирается и может посты на форуме писать на С++. Но Вы же тоже с чего-то начинали?

Лично я начиналс Алгола-60. Потом был Фортран...

А специально для того, чтобы научить сына программировать, выучил Паскаль.

Это я к тому, что Си для меня язык не родной и программирую я на нем недавно.

 

PS. навеяно постом ЕП: Buzzer2010, будем надеяться, у Вашего правнука не будет проблем с программированием.

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

Он стал гораздо больше разбираться сам и намного реже приходить с простейшими вопросами. Уж не знаю, с чем он родился, но осознав свою "наследственность", резко изменил своё отношение и это тут же сказалось на результатах. Вот такая история.

Может нашёл более сговорчивого деда или подсел на футбол?

sadman41
Offline
Зарегистрирован: 19.10.2016

Buzzer2010 пишет:

Это всё чудесно и проект впечатляющий. Однако. Однако же это всё хорошо для тех, кто в свободно сях разбирается и может посты на форуме писать на С++. Но Вы же тоже с чего-то начинали? Не родились же Вы с компилятором в голове?

Есть такая штука, как скальпель (бритва) Оккама. Не знакомы? Советую. 

В конечном счете все эти ваши классы превратятся в линейный код для МК. А ООП тут - исключительно синтаксический сахар, а не жизненная необходимость. Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования. Я не думаю, что у вас на данный момент настолько сложный код, в котором позарез нужна функциональность классов. Но, если хочется понять, как это работает, то пожалуйста, конечно. Однако, повторюсь, что изучение принципов работы сложных структур языка без отладчика, с нуль-пространственным прыжком через все базовые вещи, является чистой воды мазохизмом. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Может нашёл более сговорчивого деда или подсел на футбол?

Второй дед у него, к сожаленю, уже умер. Из живых программистов у него прадед, я, моя жена и оба родителя (как раз он - в четвёртом поколении). Насчёт футбола - не думаю, телевизора у них в доме нет, а живые матчи в нашей деревне не проводятся.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

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

Избежать-то можно всегда. В конце концов, всё можно запрограммировать на брейнфаке машине Тьюринга. Но иногда, до чего ж удобно! Вот не так давно проектик был - ардуиновская классика: радиоприёмник, совмещённый с часами, погодной станцией, лабораторным блоком питания и мультиметром (усё в одном ящике). На всё про всё один 4" семисегментный дисплей на котором надо показывать то время, то частоту радиостанции, то прогноз температуры на завтра, то напряжение или ток для мультиметра, то установку таймера, то будильника, ... и до хрена чего ещё. Иерархия классов экрана со множетсвенным наследованием настолько упростила задачу отображения информации, что диву даёшься. Без наследования трахаться там и трахаться.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:

Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.

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

sadman41
Offline
Зарегистрирован: 19.10.2016

andriano пишет:

sadman41 пишет:

Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.

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

Вроде бы речь идет о пользовательском классе, а не "вообще". 

Так-то я, конечно, не извращенец, если вы это хотите выяснить - на асме не пишу, но порой приходится чужие библиотеки потрошить и секвестировать, проводя, так сказать, классовую борьбу )) И не нужно сразу считать меня оголтелым тупоконечником. Если человек умеет обращаться с инструментом - пусть использует. Если не умеет - изучает, а потом сам принимает решение по поводу инструмента для решения задачи забивания гвоздя в табуретку - микроскоп брать или молотком шибануть.

Вчера, к слову, немного читал avr-lib в оригинале - тоже классов не нашёл. Так что бессмысленный философский диспут о том, является ли какая-либо подключаемая библиотека носителем класса, можно считать открытым. Участвовать в нем, правда, не обещаю.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

микроскоп брать или молотком шибануть.

Не наши методы!

По-нашему - железка от молотка, планетарная передача, серво-мотор, ардуина, немного говна и палок и, опционально, потенциометр для регулировки частоты ударов - полгода траха со скетчем и имеем автоматический молоток! Во как! 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:

Вроде бы речь идет о пользовательском классе, а не "вообще". 

Что такое "класс Си++" я имею некоторое представление. А что такое "пользовательский класс"? И чем он отличается от "класса Си++"?

Цитата:

Так-то я, конечно, не извращенец, если вы это хотите выяснить - на асме не пишу,

Ни в коей мере не собирался переходить на личности. Вопрос сугубо "эхотажный" - о роли классов в концепции Ардуино.

Кстати, я иногда пишу на языке Ассемблера, это значит, что я - извращенец?

Цитата:

Вчера, к слову, немного читал avr-lib в оригинале - тоже классов не нашёл.

Ну, AVR - это одно, а Arduino - совершенно другое. И концепции у них совершенно различные, если не сказать, диаметрально противоположные.

В Ардуино любое периферийное устройство - объект. И это вполне осознанный и весьма целесообразный подход.

Цитата:

Так что бессмысленный философский диспут о том, является ли какая-либо подключаемая библиотека носителем класса, можно считать открытым. Участвовать в нем, правда, не обещаю.

Вопрос на самом деле не в классах, а в целесообразности применения ООП в том или ином случае. В той же Ардуино millis, digitalRead и т.п. являются простыми функциями, а не методами класса, но это никак не влияет на тот факт, что концепция Ардуино основана на ООП.

sadman41
Offline
Зарегистрирован: 19.10.2016

Наверное вам, как фаундеру платформы Arduino виднее насчет концепции. И, также возможно, что вам, как строгому последователю принципов Страуструпа, представляется что мы отговариваем человека писать на C++ без применения объектов. Однако хочу вас уверить, что это не так - пусть пишет так, как умеет. В данном случае с классами (именно классами C++, а то вдруг ещё какие с улицы притащит) он не умеет. Но я не совсем понимаю для чего затевать холивары на предмет Procedural vs Object-oriented в применении к Arduino. Как будто тут темы фонтанов и костылей не хватает для бессмысленного изведения траффика.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Ну народ. Я-таки обязан внести некоторую ясность. Классом свою задачу я называю только потому что этот термин используется в языке С++ и может быть в каких-то других еще, не знаю. А я и не подозревал на самом деле, что затеял такую сложную для себя головоломку. Спасибо Евгению за разъяснения и жаль что мне не довелось побыть его студентом.

Про бритву Оккама слышал в сериале Доктор Хаус. В данном контексте метод Оккама немного тернистый путь для изучения принципов грамотного программирования )))) Хотя, признаться, этим я сейчас и занимаюсь: отбразываю все неверные решения и ищу оставшиеся, которые и будут верными. Но слава Богу - есть этот форум с массой людей на порядок умнее и опытнее меня!

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:
Так правильно. Описывать нужно все переменные.  myGLCD Вы описали, а шрифты чем хуже?

Другое дело, если вы эти описания шрифтов (всех) поемстите в user.h, то Вам их не нужно будет описывать ни в основном скетче, ни в user.cpp - они будут в одном месте и это правильно.

Что-то не получается пока что. После описания всех используемых шрифтов в "user.h" компилятор пишет вот что:

In file included from sketch\user.cpp:1:0:

user.h:3: error: 'uint8_t' does not name a type

 extern uint8_t BigFont[];

 

И так на каждый шрифт.
Текущее состояние user.h : 
#ifndef user_h
#define user_h
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFontPlusPlus[];
extern uint8_t Dingbats1_XL[];
extern uint8_t battery_24x48[];
extern uint8_t SmallFont[];
extern uint8_t Various_Symbols_32x32[];

class user
{
  public:
    user();
    static void InitEMU();
    static void InitDraw();
};
#endif

 

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

А вот так - работает вроде:

#ifndef user_h
#define user_h
#include <UTFT.h>
extern UTFT myGLCD;
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFontPlusPlus[];
extern uint8_t Dingbats1_XL[];
extern uint8_t battery_24x48[];
extern uint8_t SmallFont[];
extern uint8_t Various_Symbols_32x32[];


class user
{
  public:
    user();
    static void InitEMU();
    static void InitDraw();
};
#endif

Кстати у меня есть сомнения насчёт строки №2  в "user.cpp"

#include "user.h"
user::user()
{}
void user::InitEMU()
{
  // myGLCD.drawBitmap (0, 0, 320, 201, Life, 1); // BitMap logo
  myGLCD.setFont(SmallFont);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 220);
  delay(210);
  myGLCD.print("                   ", 0, 220);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.print("Init start:", 0, 210);
  myGLCD.print("Loading", 0, 220);
  delay(310);
  for (int i = 0; i <= 75; i = i + 9) {
    myGLCD.print(".", 75 + i, 220);
    delay(40);
  }
  myGLCD.print("                   ", 0, 220);
  myGLCD.print("Init start:", 0, 200);
  myGLCD.print("Loading  .......... Done!", 0, 210);
  delay(340);
  myGLCD.print("Init start:", 0, 190);
  myGLCD.print("                            ", 0, 210);
  myGLCD.print("Loading  .......... Done!", 0, 200);
  myGLCD.print("Init sensors: ", 0, 220);
  myGLCD.setFont(battery_24x48);
  delay(340);
  myGLCD.print(String(9), 110, 215);
  delay(340);
  myGLCD.print(String(8), 110, 215);
  delay(340);
  for (int i = 1; i <= 6; i++) {
    myGLCD.print(String(i), 110, 215);
    delay(200);
  }
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
  delay(300);
  myGLCD.print("6", 110, 215);
  delay(300);
  myGLCD.print("7", 110, 215);
}

void user::InitDraw()
{
  myGLCD.clrScr();
  myGLCD.fillScr(VGA_BLACK);
  myGLCD.setBackColor(VGA_TRANSPARENT);
  myGLCD.drawRoundRect(167, 1, 315, 25);        // Рамочка для отображения текущего режима
  // myGLCD.setFont(Various_Symbols_32x32);
  myGLCD.setFont(Dingbats1_XL);
  myGLCD.print("9", 290, 27);
  myGLCD.setFont(BigFont);
  //  myGLCD.drawRoundRect(147, 32, 295, 55);   // Рамочка для температуры
  //  myGLCD.print("t ", 155, 36);              // Знак температуры
  //  myGLCD.drawCircle(170, 40, 2);            // Кужочек обозначения температуры
  //  myGLCD.print("C", 280, 36);               // Знак Celsium
  //  myGLCD.drawCircle(278, 40, 3);            // Кужочек Celsium


}          // ************** END of InitDraw() **************************

Эту строку я собизъянничал в "UTFT.cpp" Прокомментируйте пожалуста.

=============================================================

У меня тут возникли некоторые вопросы.

Дилема №1. Если я помещу все свои подпрограммы в тело класса "user", то в основном скетче у меня останется только главный цикл, который будет перебирать элементы основного меню, а это всего несколько строк в структуре "switch-case". Другими словами - основная масса кода ляжет на плечи класса или классов (во избежании путаницы возможно придётся несколько иначе организовать деление на отдельные файлы и их может быть несколько). 

Сам вопрос: насколько это корректно и правильно с точки зрения оптимизации кода?

Дилема №2. Если все мои основные циклы будут крутиться в классе, то мне придётся из одного метода класса вызывать другой и отсюда второй вопрос на ту же тему: насколько это правильно и корректно?

Спасибо.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:

Наверное вам, как фаундеру платформы Arduino виднее насчет концепции.

Вы всерьез полагаете, что знать, в какой цвет выкрашен забор, может только человек, который его собственноручно красил?

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

sadman41 пишет:

Как будто тут темы фонтанов и костылей не хватает для бессмысленного изведения траффика.

[ушёл создавать биржу фьючерсного трафика флуда]

sadman41
Offline
Зарегистрирован: 19.10.2016

1.В файлах .c/.cpp для поддержки типов данных uint8_t, int64_t и т.п. требуется производить подключение системной библиотеки stdint.h, компиляция же .ino происходит по несколько иным правилам, тут разработчики IDE подложили свинью пользователям (или облегчили им жизнь. сложно сказать) - подключение части библиотек производится после того, как вы нажали кнопку "Скомпилировать", перед фактическим вызовом компилятора.

2. Никакой существенной оптимизации, подозреваю, класс вам не принесет, но вполне может вызвать головную боль. Вы можете представить себе класс, как оглавление книги. Он помогает пользователью более удобно сгруппировать имена переменных, подпрограмм (методов класса) и таскать их потом по всему проекту, передавая в функции и т.п. Специфические свойства класса(protected-члены, например), вы не используете. Так что, фактически, делаете обычные переменные и обычные функции (компилятор будет рассматривать их именно так), но пытаетесь запихнуть их в класс потому что считаете, что так круче. Однако, в switch() вы точно так же можете вызывать подпрограммы, просто вынесенные в другой файл. 

Поэтому, на самом деле, дилемма стоит перед нами - объяснять ли как собрать бензопилу для того, чтобы вы смогли из куста ивняка сделать одно удилище.  

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buzzer2010 пишет:

Кстати у меня есть сомнения насчёт строки №2  в "user.cpp"

#include "user.h"
user::user()
{}Эту строку я собизъянничал в "UTFT.cpp" Прокомментируйте пожалуста.

А тут нечего комментировать (как исполняемый, так и инициализирующий код отсутствуют)

Цитата:

=============================================================

У меня тут возникли некоторые вопросы.

Дилема №1. Если я помещу все свои подпрограммы в тело класса "user", то в основном скетче у меня останется только главный цикл, который будет перебирать элементы основного меню, а это всего несколько строк в структуре "switch-case". Другими словами - основная масса кода ляжет на плечи класса или классов (во избежании путаницы возможно придётся несколько иначе организовать деление на отдельные файлы и их может быть несколько). 

Сам вопрос: насколько это корректно и правильно с точки зрения оптимизации кода?

Оптимизации - по какому критерию?

Идея ООП - оптимизировать труд программиста:

- чтобы он не писал по много раз одни и те же конструкции в разных проектах,

- чтобы лучше обозначить структуру программы, сгруппировав функции, имеющие отношение к одной сущности, в одном классе.

Т.е. если в проекте есть несколько взаимодействующих устройств (например, датчик и дисплей), то все взаимодействие с каждым из них помещается в соответствующий класс, а в основной программе - только связь между ними, т.е. "взять число из датчика" и "вывести число на экран".

Цитата:

Дилема №2. Если все мои основные циклы будут крутиться в классе, то мне придётся из одного метода класса вызывать другой и отсюда второй вопрос на ту же тему: насколько это правильно и корректно?

Спасибо.

Это совершенно нормальная ситация. Более того, обычно среди методов класса встречаются private, т.е. те, которые вызываются только из других методов класса и не могут быть вызваны извне.

sadman41
Offline
Зарегистрирован: 19.10.2016

Я всерьез полагаю, что о принципе выбора краски (не только ее цвета, но и физико-химико-экономических свойств), которой выкрашен забор, может знать только тот, кто придумал его покрасить. Все остальные находятся в области высказывания догадок и построения на них собственных теорий, которые, безусловно, могут многократно превосходить первоначальный замысел. 

Хотя, если вы можете узнавать о концепции по одному только цвету краски - снимаю шляпу и причисляю к пантеону, который вы сами себе можете выбрать.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:

Я всерьез полагаю, что о принципе выбора краски (не только ее цвета, но и физико-химико-экономических свойств), которой выкрашен забор, может знать только тот, кто придумал его покрасить.

А я почему-то считал, что в первую очередь тот, кто разработал/произвел эту краску.

А тот, кто с кисточкой в руках, может вообще иметь весьма смутные представление о физике, химии и экономике.

Цитата:

Хотя, если вы можете узнавать о концепции по одному только цвету краски - снимаю шляпу и причисляю к пантеону, который вы сами себе можете выбрать.

Концепция - достаточно общее понятие. Поэтому с одной стороны - она не затрагивает тонкостей реализации (как то физико-химико-экономических свойства), а с другой стороны - должна быть легко понимаема не только авторами, но и широкими кругами общественности.

Другими словами: если мы видим покрашенную поверхность, то при некоторых условиях (достаточноая толщина покрытия, приемлемое освещение и отсутствие проблем со зрением) мы вполне адекватно можем судить о цвете этой краски.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Полемика это всё очень хорошо...

А вот andriano за пост #43 огромное и чисто человеческое спасибо!

Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче. Кстати такая мысль уже прозвучала здесь:

ЕвгенийП пишет:
... В вашем же случае использование класса проигрывает и по памяти и по времени.
sadman41 пишет:
Мне кажется, что ЕвгенийП прав - классы вам пока не нужны. Просто научитесь для начала разбивать код на разные файлы. Потом поработайте со структурами (struct), поймете что есть форма и что есть содержание, как крутить полями и почему там что-то "вызывается через точку". А затем уже до классов там рукой подать. 

Поверьте - редко кому удается с нуля взять и лупануть собственный класс, учтя все подводные камни. А вы еще и на достаточно сложном примере начали экспериментировать.

-----------------------

В конечном счете все эти ваши классы превратятся в линейный код для МК. А ООП тут - исключительно синтаксический сахар, а не жизненная необходимость. Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Buzzer2010 пишет:

Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче.

Основной критерий оптимизации это, как не странно , надежность и удобство использования другими людьми данной библиотеки. Если же после использования у вас в программе заведутся глюки или же даже вы через полгода не будете понимать как работает ваш скетч, то никто не будет пользоваться вашей библиотекой. Если нет покупателя, то и продавец и производитель работают даром. А на счет скорости и меньшей памяти, так она должна быть просто в разумных рамках. Если же ее всеже маговато, то мега и дуе вам в помощь. 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

qwone пишет:

Buzzer2010 пишет:

Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче.

Основной критерий оптимизации это, как не странно , надежность и удобство использования другими людьми данной библиотеки. Если же после использования у вас в программе заведутся глюки или же даже вы через полгода не будете понимать как работает ваш скетч, то никто не будет пользоваться вашей библиотекой. Если нет покупателя, то и продавец и производитель работают даром. А на счет скорости и меньшей памяти, так она должна быть просто в разумных рамках. Если же ее всеже маговато, то мега и дуе вам в помощь. 

Во первых - всем не угодишь. Во вторых - "надёжность и удобство" зависят от кривости рук тех, кто ее потом будет использовать. Я не могу запретить копать своё творение всем кому не попадя и потом еще выслушивать нелестные отзывы в свой адрес насчёт надёжности и удобства использования. В третих - человек не понимающий как работает его скетч, скорее всего, не является его автором. Так что это не обо мне. В четвертых: я не собираюсь торговать своими библиотеками потому что я только еще учусь программировать и врядли мне вообще такое придёт в голову. В пятых: мега и дуэ - не панацея и я уже не уверен что мне хватит 512к для того, что я задумал (((((((.....

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buzzer2010 пишет:

Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче.

Отнюдь.

Понятие как скорости, так и объема кода радикальным образом зависят от конкретной задачи.

Если, например, для управления каким-либо устройством требуется точность не хуже 0.1 секунды, а Ардуина в зависимости от реализации может обеспечить точность от 0.000050 с до 0.000005 с, то для устройства нет никакой разницы, который из методов реализации Вы выберете. А вот для Вас трудоемкость реализации во втором случае может оказаться больше в те самые 10 раз, а то и больше.

Аналогично с объемом: ксли выбор между 2к и 12к, то никакой разницы с этой точки зрения нет, т.к. "оставшуюся" память Вы все равно не сможете никак использовать.

Вообще же концепция Ардуино исходит из приоритета удобства пользователя перед эффективностью. Именно поэтому использование собственного кода вместо библиотечного в большинстве случаев способно существенно увеличить производительность. Весь вопрос в том, нужно ли это в конкретном проекте.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Конкретно в этом проекте - тут еще не совсем понятно, поскольку все ветви проекта еще не осуществлены. Та часть, которая концептуально уже готова особого быстродействия не требует, поскольку считывание показаний температуры с 18B20 происходит настолько медленно, что в цикле не надо даже delay() ставить.

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