Как объявить функцию глобально, но после выполнения setup?

Тема в разделе "Arduino & Shields", создана пользователем user999, 6 апр 2017.

  1. user999

    user999 Гик

    Добрый день!
    Есть необходимость получать по сети информацию о пинах, на которые подключены датчики. Для этого в setupe обращаюсь с помощью запроса к серверу.

    После получения данных нужно объявить функцию OneWire ds(Номер полученного пина).
    Обычно это делается до setup. Как это сделать до setup, что бы в loope можно было использовать эту функцию?
     
  2. Onkel

    Onkel Гуру

    так ведь (Номер полученного пина может быть и переменной, в чем проблема?
     
  3. rkit

    rkit Гуру

    Это не функция, а переменная. Объявляете OneWire ds, в сетапе пишете ds = OneWire(pin)
     
  4. rkit

    rkit Гуру

    Ну и вообще, для OneWire нужен специфический подтягивающий резистор, так что
    чего там по сети не передавай, а совместимые линии от этого не изменятся. Нецелесообразно.
     
  5. user999

    user999 Гик

    Так если в setup переменную объявить она не будет видна в loop. Или библиотека OneWire.h уже объявила ее при подключении?
    Про резистор я помню.
     
  6. mcureenab

    mcureenab Гуру

    Глобально:
    OneWire *ds;

    В setup
    ds = new OneWire(pin);

    В loop
    ds->....
     
    user999 нравится это.
  7. user999

    user999 Гик

    У меня еще вопрос: как сравнить имя переменной с неким параметром?
    Пришло на ум использовать структуру. Но со стринг не компилируется, зависает и все.
    Так работает:
    Код (C++):
    typedef struct {
      int var;
      word id;
    } State;
    State lightVar[1] = {};

    int namevar = 5;

    void setup() {
      pinMode(13, OUTPUT);
      lightVar[0].var = 5;
    }

    void loop() {
      if (namevar == lightVar[0].var) {
        digitalWrite(13, HIGH);
        delay (1000);
        digitalWrite(13, LOW);
      }
      delay (1000);
    }
    А так нет
    Код (C++):
    typedef struct {
      String var;
      word id;
    } State;
    State lightVar[1] = {};

    String namevar = "5";

    void setup() {
      pinMode(13, OUTPUT);
      lightVar[0].var = "5";
    }

    void loop() {
      if (namevar == lightVar[0].var) {
        digitalWrite(13, HIGH);
        delay (1000);
        digitalWrite(13, LOW);
      }
      delay (1000);
    }
     
  8. Faberge

    Faberge Administrator Администратор

    А так да:

    Код (C++):
    typedef struct {
      String var;
      word id;
    } State;
    State lightVar = {};

    String namevar = "5";

    void setup() {
      pinMode(13, OUTPUT);
      lightVar.var = "5";
    }

    void loop() {
      if (namevar == lightVar.var) {
        digitalWrite(13, HIGH);
        delay (1000);
        digitalWrite(13, LOW);
      }
      delay (1000);
    }
     
  9. user999

    user999 Гик

    Так действительно да. Но предполагается, что lightVar.var будет не одна, а несколько
    Код (C++):
    lightVar[0].var;
    lightVar[1].var;
    lightVar[2].var;
     
  10. qwone

    qwone Гик

    Так замените структуру на класс. У класса есть конструктор. И создавать объект используя указатель на класс. Можно организовать массив указателей на класс. Или вообще список указателей на вновь созданых объектов.
     
  11. Faberge

    Faberge Administrator Администратор

    И это тоже не проблема.

    Код (C++):
    typedef struct {
      String var;
      word id;
    } State;
    // Создаем массив из 10 структур с индексами от 0 до 9 включительно
    State lightVar[10];

    // Строки с несколькими именами задач
    String namevar = "name_new";
    String taskvar = "task_new";

    void setup() {
      pinMode(9, OUTPUT);
      pinMode(13, OUTPUT);
      // Инициализируем поля структур в массиве
      lightVar[0].var = "name_new";
      lightVar[9].var = "task_new";
    }

    void loop() {
      // Сравниваем
      if (namevar == lightVar[0].var) {
        digitalWrite(13, HIGH);
        delay (1000);
        digitalWrite(13, LOW);
      }

      if (taskvar == lightVar[9].var) {
        digitalWrite(9, HIGH);
        delay (1000);
        digitalWrite(9, LOW);
      }
      delay (1000);
    }
     
    Последнее редактирование: 7 апр 2017
    user999 нравится это.
  12. mcureenab

    mcureenab Гуру

    Структура это класс у которого по умолчанию члены public.
     
  13. qwone

    qwone Гик

    И что? Главное что у класса есть конструктор. Структуру надо не только создать, но и загрузить. Если создание стуктуры находится за пределами setup и loop,то для загрузки структуры нужна дополнительная функция. А вот в классе уже есть встроеная такая функция - конструктор.
     
  14. mcureenab

    mcureenab Гуру

    То что структура это тоже класс. И у нее тоже может быть конструктор.
     
  15. user999

    user999 Гик

    В общем надо было вместо
    Код (C++):
    State lightVar[1] = {};
    Писать
    Код (C++):
    State lightVar[1];
    или
    Код (C++):
    State lightVar[] = {};
    А как лучше: указать размер массива с запасом, например, 10 (если точно не знаешь сколько будет) или не определять размер?
     
  16. mcureenab

    mcureenab Гуру

    Так с запасом, или размер в прнципе не известен на этапе компиляции?

    К стати какой смысл объявлять пустой массив? В него же ничего нельзя записать, даже если компилятор не ругается.
     
  17. user999

    user999 Гик

    Почему? У меня этот код работает
    Код (C++):
    typedef struct {
      String var;
      word id;
    } State;
    State lightVar[] = {};

    String namevar = "5";

    void setup() {
      pinMode(13, OUTPUT);
      lightVar[0].var = "5";
    }

    void loop() {
      if (namevar == lightVar[0].var) {
        digitalWrite(13, HIGH);
        delay (1000);
        digitalWrite(13, LOW);
      }
      delay (1000);
    }
     
  18. mcureenab

    mcureenab Гуру

    Такой код может случайно заработать. Я точно не знаю как компилятор память распределяет. Думаю за массивом {} нет никаких критичных данных.
    А lightVar это указатель на массив {}.
     
  19. mcureenab

    mcureenab Гуру

    Вероятно lightVar[0].var и namevar используют одну и ту же область памяти.
     
    user999 нравится это.
  20. Faberge

    Faberge Administrator Администратор

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

    Самый простой вариант, указать размер массива с запасом, он же и самый надежный. Динамическое выделение памяти в случае с микроконтроллерами - вариант требующий аккуратности и должного внимания при реализации. Во-первых, памяти у вас не так много (в Uno - 2Кб) и возможен случай, когда запрос на выделение новой памяти просто не будет удовлетворен. Во-вторых, когда дополнительная память программе уже не требуется, её желательно вернуть и в полном объеме, иначе возникнут утечки памяти.

    Если вам все-таки очень хочется связываться с динамическими данными, попробуйте реализовать их на основе контейнеров STL, например векторах. Стандартная библиотека возьмет на себя большую часть забот по размещению данных в памяти и, главное, это точно будет корректно. Ну или сделайте с помощью классов и операции new.
     
    user999 нравится это.