Объявление глобальной переменной
- Войдите на сайт для отправки комментариев
Сб, 14/10/2017 - 12:53
Добрый день, уважаемые форумчане!
У меня есть класс Engine, который содержит только один конструктор с агументами типа int. Есть класс Movement, который содержит конструктор с аргментуами типа Engine.
В setup() у меня такая запись:
Engine left_en(PIN_A_LEFT, PIN_B_LEFT, PIN_C_LEFT, PIN_D_LEFT); Engine right_en(PIN_A_RIGHT, PIN_B_RIGHT, PIN_C_RIGHT, PIN_D_RIGHT); Movement movement(left_en, right_en);
Необходимо переменные left_en, right_en и movement сделать глобальными. Если в самом начале программы делаю объявление(аналогично Java)
Movement movement;
, то комплиятор говорит, что не знает такой тип данных.
Подскажите пожалуйста, каким образом правильно объявить глобальную переменную собственного типа?
Что то мутноват у меня хрустальный шар или я не вижу в этой теме ваш скетч.
ПС: я бы написал так.
В setup() у меня такая запись:
Необходимо переменные left_en, right_en и movement сделать глобальными.
А что, просто вынести их из setup на глобальный уровень нельзя? Там какие-то нетривиальные конструкторы?
qwone, ЕвгенийП, спасибо большое за помощь! Шутка про зеркальный шар заставила улыбнуться. ))
Я хотел зарезервировать переменные на глобальном уровне, а потом присовоить им ссылку на новый созданный объект в другом месте. Так сделать не получилось.
Решил присвоить этим переменным ссылку на инициализированный объект с нужными мне значениями аргументов в конструкторе, но опять не получилось. Оказалось, что проблема была в том, что я инициализировал их ДО описания используемого класса, а не ПОСЛЕ. Привые писать на Java, то такое разрешается.
Сейчас проблема решена.
Можно задам вопрос в этой теме, чтобы не плодить лишний раз? Тем более, наверной, мой вопрос, как всегда, очень примитивный. Но я действительно не могу понять, почему так происходит.
Необходимо реализовать прием данные через Bluetooth и их обработку. Если значение входящих данных равно 48, то выполнить определенный код. Проблема в том, что у меня получается так:
- (ввожу '4')
- Я получил: 52
- (ввожу '2')
- Я получил: 50
- (ввожу '0')
- Я получил: 48
- (ввожу '7')
- Вхожу в условие 48
- Я получил: 48
Почему когда я ввожу '0'(48), происхдит печать результата только при вводе следующего значения?
Вам не когда не казалось странным когда пишете 1 подразумеваете что это одна палочка, а когда пишете 8 то почему то видите не восемь палочек а значек 8. А вот когда пишете 0, то должно быть пусто, а там значек 0. Вот так и по непонятной логике код числа '0' почему то 48 в десятичной. Ну и так далее. Так в Serial отправляется все числа и сообщения в коде ASC-2 .
qwone, спасибо за разъяснение. Я понимаю, что происходит обмен символами, которые описываются кодами ASCII.
Вопрос был в другом. Когда я ввожу символ '0', в Arduino поступает код "48". В этом случае должен выполниться код из этого блока:
20
if
(incomingByte == 48){
21
mySerial.print(
"\nВошли в условие 48"
);
22
}
Но печать происходит только при вводе следующего символа. С чем это может быть связано?
Ну наверно потому что вы написали print, а не println . Print помещает строку в буффер, а вот что бы отправить на консоль по каналу надо сделать перевод строки.
qwone, спасибо большое!!! Всё заработало.
Извинитие пожалуйста за глупые вопросы.
Происходит непонятное.. для меня. Объявляю перменную movemen на глобальном уровне. В методе setup() создаю объект класса Movement, произвожу его настройку и присваиваю переменной movemen ссылку на созданный объект.
У класса Movement есть метод void to_home(). Если я использую этот метод в setup(), то всё хорошо. Но если я использую void to_home() в методе loop(), то ничего не происходит. Подскажите пожалуйста, в чём может быть проблема?
Определил то, что метод в loop() не работает тем, что поочередно комментировал вызов метода в setup() и loop().
Twilkeris. у вас глобальной является только ссылка на обьект, а сам обьект локальной переменной функции setup(), потому снаружи ее и не работает. Строчку 4 переместите "наружу" из функции setup() - и все будет работать.
Почитал ваши посты выше - у вас, так сказать, глобальное непонимание глобальных переменных
Я хотел зарезервировать переменные на глобальном уровне, а потом присовоить им ссылку на новый созданный объект в другом месте. Так сделать не получилось.
Так делать нельзя. Создание указателя на обьект не создает самого обьекта. Этим вы ничего не "резервируете".
тоже самое
В обоих случаях проблема была вовсе не в этом, а в том, что вы обьект, созданый локально, пытались использовать как глобальный.
Обьекты ничем не отличаются от простых типов, например int. Если вы создаете переменную типа int внутри функции setup(), вы же, надеюсь, понимаете, что она в loop() видна не будет? - так почему для обьекта вы ждете другого?
b707, спасибо большое за помощь! Дело в том, что до этого программировал только на Java, поэтому непривычно работать отдельно с ссылками на объект и отдельно самим объектом. То, что Вы написали - понял, свою ошибку осознал.
Если я создаю глобальный объект класса Movement, то при обращении к методу to_home() ничего не происходит.
Если же инициализирую объект класса Movement внутри метода setup(), то всё на работает.
Может ли это быть связано как-то с тем, что метод to_home() использует значенения, полученные от концевых выключателей? pinMode() для них назначается в setup(). Просто больше других причин не вижу..
Twilkeris,поймите. Хотя Джава и Си похожи и вроде из одного корня, это совершенно разные языки. Считайте это как русский и польский. Вроде славянские и похожи, но многие похожие совершено похожие слова несут разный смысл. Так что знание Джавы вредно для написания программ на Си++. Разбиритесь с кучей и ссылками на вновь сознаваемые элементы в куче. Это славный плюс в Си, чего нет в Джаве явно.
Пс: http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov
почитайте это
У меня есть класс Engine, который содержит только один конструктор с агументами типа int. Есть класс Movement, который содержит конструктор с аргментуами типа Engine.
А у меня, как и у qwone некоторые проблемы с хрустальным шаром.
А тексты тех классов, что у Вас есть, Вы не приводите.
И как в такой ситуации быть?
Могу лишь высказать предположение, что либо классы написаны неправильно, либо Вы их неправильно используете.
Еще могу высказать некоторые соображения, которые либо будут Вам полезными, либо нет (в зависимости от того, сумел ли я воспользоваться хрустальным шаром).
Работа скетча для Ардуино и программы для ПК имеют некоторые различия. В частности, для обеспечения гибкости создатели Ардуино сделали так, что глобальные переменные инициализируются до того, как произойдет полная инициализация "железа". Соответственно, это накладывает некоторые ограничения на действия доступные конструктору, создающего глобальный объект. Чтобы обойти эти ограничения в Ардуино принято часть действий по инициализации и настройке оборудования, используемого объектом, производить не из конструктора, а из метода begin(), вызываемого из setup(), т.е. уже после того, как будет окончательно настроена вся системная периферия.
qwone, спасибо! Ещё летом натыкался на Вашу тему. Изучу подробнее.
andriano, очень сыдно приводить свой код целиком, потому что писался он для того, чтобы проверить работоспособность идеи. Заранее логика работы программы не продумывалась, поэтому код такой некрасивый. Совсем не думал, что может возникнуть проблема в работе с глобальными перменными.. И тем более не подумал про особенности работы с Arduino, про которые, конечно же, я не знаю.
Прикладываю файл со скетчем и код скетча в сообщении. Если нужно будет, то оставлю что-то одно из двух.
Ссылка на скетч
Конечно, жесть - передавать объекты классов по значению, когда можно (и даже нужно) по ссылке. Наверняка, ещё и в определении класса Movement объекты Engine объявлены по значению. Эээх, не экономим память, совсем... Короче, вот так - неправильно:
а вот так = расово вернее:
Ну - или так:
Ну и до кучи - определить оператор присваивания и конструктор копирования, как минимум. Норм загрузил, не? :) :) :)
Правка: писал сообщение, не видя кода всего скетча, с ТС практически в одно время разродились :) Но там всё равно - по значению в конструктор лезет экземпляр класса, непорядок. Потому оно и не взлетает, собсно.
DIYMan, спасибо за замечания, учту. Я понимаю, что в моем коде очень много изъянов. Наверное, правильно говорить, что он весь сплошной изъян. :))
Дело в том, что заранее логика программы не продумывалась. Да и не возможно её было продумать, потому что шел творческий процесс и постоянно что-то добавлялось в систему или убиралось из неё прочь, поэтому приходилось делать костыли. Многие конструкции очень кривые и некрасивые, но мне было важно, чтобы система просто заработала. Более того, в ходе написания программы приходилось в ускоренном темпе изучать крайне поверхностно новый язык программирования с целью реализовать то, что было необходимо в тот момент времени. Да и это был мой первый, относительно, серьезный опыт работы с Arduino.
Если сейчас разберусь с тем, как работать с объектом класса Movement из метода setup() в данных условиях, то большего от этого проекта мне ничего не потребуется. В свободное время можно будет сесть, собраться с мыслями и переписать его.
Если сейчас разберусь с тем, как работать с объектом класса Movement из метода setup() в данных условиях, то большего от этого проекта мне ничего не потребуется. В свободное время можно будет сесть, собраться с мыслями и переписать его.
Дык вы не поняли, не? Я вам написал, почему не работает - вы передаёте экземпляр класса по значению в конструктор другого класса. При этом объект КОПИРУЕТСЯ на стек, и вы сохраняете ссылку на ЛОКАЛЬНЫЙ на стеке объект в области видимости. Как только вы выпадете из области видимости (вышли из конструктора) - всё, приплыли, ваши указатели указывают на Марс, ориентировочно.
И то, что вы объявляете все объекты глобальными - не спасает от того, что при вызове конструктора класса Movement внутри него сохраняются ссылки на труху. Передавайте по ссылке, как я писал выше в примере.