Программист с++ – arduino+

Arduino

ВерсияПлатформаЯзыкРазмерФорматЗагрузка* скачайте бесплатно Arduino для Windows, файл проверен!
   Arduino 1.8.5 для Windows Windows Русский 94.8MB .exe
   Arduino 1.8.5 для Mac MAC Русский 157.7MB .zip

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

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

Среда разработки Arduino написана на Java. В неё входит простой редактор кода, обработчик компилятора и процедура обновления прошивки микроконтроллеров. IDE замечательно подойдёт начинающим программистам, владеющим С и С++. Новички, ранее не занимавшиеся программированием, также смогут освоить основы разработки и прошивки программного обеспечения с помощью подробной документации.

Возможности Arduino

Arduino IDE доступна на русском языке и позволяет получить возможность создавать текстовый код для основной программной платы Arduino. Текстовый код можно транслировать в язык программирования С. Написанный код переходит в компилятор, который преобразует команду в заключительный этап обработки, и затем передаётся микроконтроллеру.

Преимущества программы Arduino:

  • Кроссплатформенность – возможность работать со всеми системами: Windows, OS X и Linux.
  • • В панель инструментов входят все необходимые параметры для задания алгоритмов управления внешних устройств: сохранения, экспорта, отладки, поиска и замены, а закладки и файлы предоставляют возможность работать с несколькими документами.
  • • Имеет открытый исходный код.
  • • Программное обеспечение может использоваться с любой платой Arduino.

Плата Arduino – мобильная плата микроконтроллера, небольшой схема, содержащая целый компьютер в маленьком чипе. Этот контроллер может взаимодействовать с программным обеспечением, установленным на компьютере: Macromedia Flash, Pure Data, SuperCollider, Max/MSP и многим другим.

Первый выпуск Arduino состоялся в 2005 году. Программа активно развивается, актуальной версией на данный момент является Arduino 1.8.5.

В отличие от предыдущей редакции, в ней исправлена ошибка с отрицательным размером шрифта, добавлено обходное решение для ошибки видимости меню в Mac OS X 10.

13, а вкладка «Новый»/«Переименовать» теперь позволяет давать переменным имена, начинающимся с числа.

Источник: http://arduino.download-windows.org/

Команды языка программирования Arduino

Язык программирования Arduino основан на языке Си. В случае если Вы желаете посмотреть команды данного языка, выполните в среде программирования команду меню Справка / Содержание. Команды сгруппированы в три столбца:

· Structure: команды для написания структуры программы – циклы, ветвления, синтаксис, арифметические и логические операторы, операторы сравнения и работы с битами

· Variables: различные переменные. Аналогичны используемым в Си, для Arduino характерны только несколько:

o HIGH – высокий уровень, логическая 1, +5 Вольт на контакте Arduino

o LOW – низкий уровень, логический 0, 0 Вольт на контакте Arduino

o INPUT – прописывание контакта Arduino как входного (прием информации с внешних устройств)

o OUTPUT – прописывание контакта Arduino как выходного (передача информации на внешние устройства, управление силовыми блоками)

· Functions: функции, используемые в работе с Arduino, будут подробно рассмотрены на следующих занятиях

Примечание 1: структура и переменные аналогичны используемым в языке программирования Си, то есть если Вы знаете данный язык – легко освоите программирование Arduino и наоборот, освоение языка программирования Arduino поможет Вам в освоении языка Си и подобных ему.

Примечание 2: описания команд в приложенной в среде инструкции даются на английском языке, что может представлять затруднения. Перевод описаний на русский язык имеется на сайте Arduino.ru

Примечание 3: описание команды в программе можно получить, выделив эту команды и выполнив Справка / Найти в справке.

Синтаксис языка программирования Arduino

Аналогичен используемому в языке Си:

· ; – точка с запятой. Указывает на конец строки. Пример использования:

int led = 13;

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

· { } – круглые скобки. Открывающая скобка – начало блока, закрывающая – конец блока

void setup() {

pinMode(led, OUTPUT);

}

· // – комментарии. То, что написано в строке после данных символов, контроллер на воспринимает, это примечания для программиста

delay(1000); // ждем одну секунду (1000 миллисекунд)

· #include – подключение библиотеки – набора программ, к примеру, для управления ЖК индикатором:

#include

Примечание: точка с запятой после #include не требуется.

  • – Электронная часть – контроллер Arduino и совместимые с ним модули

    В качестве основы для обучения и проектов клуба используется контроллер Arduino. Выбор обусловлен низкой стоимостью при достаточно неплохих характеристиках (от 100-150 рублей за самый дешевый Arduino Pro Mini до 1200 рублей за Arduino Due – флагман основной линейки Arduino), большим количеством… [читать подробнее].

  • – Подключение Arduino к компьютеру

    Для загрузки написанной программы в Arduino, а также для питания его в процессе работы Arduino подключается к компьютеру через USB. Для этого используется кабель USB-mini USB, который должен быть достаточной длины для комфортной работы с контроллером. После подключения желательно… [читать подробнее].

  • Источник: http://referatwork.ru/category/programmirovanie/view/290475_komandy_yazyka_programmirovaniya_arduino

    AVR на C – просто?

    Материалы приведенные далее рассчитаны на пользователей знакомых с программированием в целом и языком C (не обязательно) в частности.

    В основном излагаемый материал описывает использование микроконтроллеров AVR, особое внимание на ATmega328. Для изучения материалов понадобится Arduino Uno или Arduino Nano 3.

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

    1. Подготовка к изучению

    Для изучения нам понадобятся:

    • Среда разработки;
    • Стандартные библиотеки C для микроконтроллеров AVR;
    • Программа для загрузки микропрограмм в микроконтроллер;
    • Микроконтроллер.

    1.1. Среда разработки

    При выборе среды разработки можно натолкнутся на «не пробиваемую стену» множества программных оболочек для программирования на разных языках программирования. Но учитывая направление на микроконтроллеры круг поиска сужается до сред разработки адаптированных под конкретный вид микроконтроллеров семейства AVR фирмы Atmel. Кроме того среда разработки язык программирования C.

    Из множества вариантов рассмотрим среду разработки СodeBlocks. Будем использовать оригинальную версию СodeBlocks с сайта разработчиков www.codeblocks.org последней версии, на момент написания это версия 16.01. Данная среда разработки интересна наличием версий под популярные операционные системы Linux, Windows и Mac OS.

    Вкратце рассмотрим установку под Windows. Скачав файл codeblocks-16.01-setup.exe запускаем его.

    Ознакомимся с лицензией и принимаем ее.

    Устанавливаем все компоненты без изменений

    Путь установки оставляем без изменений.

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

    Получаем установленную среду разработки Code::Blocks.

    1.2. Стандартные библиотеки C/C++ для микроконтроллеров AVR

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

    Скачиваем необходимое после простой регистрации по адресу: http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx

    Понадобится Atmel AVR 8-bit Toolchain так как использовать собираемся ATmega328 а он 8-bit. После скачивания запускаем полученный само распаковываемый архив и получаем папку (вида avr8-gnu-toolchain) со всем необходимым. Куда ее положить?

    Запускаем ранее установленный Code::Blocks идем в меню Settings >> Compiler переходим во вкладку Toolchain executables выбираем интересующий нас компилятор из списка Selected compiler это будет GNU GCC Compiler for AVR. Далее смотрим путь по умолчанию для размещения ранее скачанной и распакованной папки.

    Переименовываем нашу папку как в настройках Code::Blocks и перемещаем по указанному пути.

    1.3. Программа для загрузки микропрограмм в микроконтроллер

    Теперь все готово для программирования, но не хватает программы для облегчения прошивки микроконтроллера. Для изучения микроконтроллера ATmega328 будем использовать платформу Arduino UNO или Arduino Nano v3. Это дает возможность изучать микроконтроллер без паяльника и программатора.

    Для Arduino есть хорошая программа ArduinoBuilder и оболочка из проекта CodeBlocks Arduino IDE (среда разработки Code::Blocks с добавлением библиотек ардуино). Использовать микроконтроллер без ардуино гораздо интересней поэтому скачиваем только ArduinoBuilder. Его будем использовать для экспериментов с микроконтроллером на плате Arduino.

    Распаковываем архив, например в корень диска c: в папку ну скажем ArduinoBuilder, из нее делаем ссылку на рабочий стол и получаем два ярлыка:

    Все программное обеспечение готово. Приступим к «железным» вопросам

    1.4. Микроконтроллер

    В своих изысканиях будем рассматривать микроконтроллер ATmega328 программы будем писать именно для него. «Знатоки» сразу нас пошлют к DataSheet но это не для нас. Мы пойдем своим путем и будем изучать его анатомию практически — методом «Тыка» :).

    Первое что необходимо, это приобрести минимальное оборудование. Ограничимся для начала покупкой ардуины или аналога. Главное, чтобы на ней был установлен микроконтроллер ATmega328.

    Нас интересуют:

    Любой из перечисленных вариантов подойдет с теми или иными ограничениями или изменениями.

    Рассмотрим подробнее вариант Arduino Nano v3. Здесь установлен микроконтроллер ATmega328P, есть возможность подключать через USB, а также существует несколько клонов по приемлемой цене. Описания в интернете можно найти массу, поэтому рассмотрим только схематичное описание найденное на просторах интернет.

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

    Часть 2

    Источник: http://cxem.net/mc/mc410.php

    Записки программиста

    Тема программирования микроконтроллеров ранее многократно поднималась в этом блоге, но исключительно в контексте микроконтроллеров AVR и, соответственно, Arduino.

    Сегодня же речь пойдет о микроконтроллере STM32F103C8T6 на базе ядра ARM 32 Cortex-M3.

    Вы наверняка слышали об архитектуре ARM — она используется в большинстве современных телефонов и планшетов, а также Raspberry Pi, полетных контроллерах для квадрокоптеров, некоторых осциллографах, и много где еще.<\p>

    Список покупок

    Для повторения шагов из сей заметки вам понадобится следующие железки:

    К моменту, когда вы будете читать эти строки, ссылки могут устареть. Однако необходимые товары легко находятся по запросам «STM32F103C8T6 Development Board» и «ST-Link v2 Programmer» как на AliExpress, так и на eBay. Плата также известна под названием «STM32 Blue Pill».

    Важно! Заметьте, что USB-разъем на этих платах часто не слишком надежно припаян и может быстро оторваться. Первым делом после покупки рекомендуется его подпаять.

    О плате Blue Pill

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

    • Микроконтроллер 32-х битный;
    • Рабочая частота 72 МГц;
    • 64 Кб flash-памяти;
    • 20 Кб оперативной памяти;
    • Мне удалось насчитать 32 GPIO;
    • 12-и битный АЦП, 10 аналоговых пинов;
    • 16-и битный ШИМ, 15 ШИМ-пинов;
    • 3 UART канала, 2 I2C шины, 2 SPI шины;
    • Возможность отладки по SWD;
    • Плата питается от 3.3 В;

    Расположение пинов (кликабельно — GIF, 1082×759, 143 Кб, источник):

    Для сравнения, Arduino Nano стоит столько же и имеет похожий форм-фактор, но работает на 8-и битном микроконтроллере, имеет частоту 16 МГц, меньше пинов, лишь 32 КБ flash-памяти, 2 Кб оперативной памяти, 10-битный АЦП, 8-и битный ШИМ, по одному каналу UART, I2C и SPI, а про отладку он и вовсе слыхом не слыхивал. То есть, за те же деньги мы получаем куда более мощную железку.

    Настройка Arduino IDE

    Интересная особенность платы заключается в том, что под нее можно писать из Arduino IDE, используя знакомый набор процедур и классов, а также многие библиотеки, изначально написанные под Arduino. Это делает плату весьма привлекательной для начинающих.

    Для программирования под данную плату нам понадобится кросс-компилятор для ARM, отладчик, стандартная библиотека C и клиент к программатору. В Arch Linux соответствующие пакеты ставятся так:

    sudo pacman -S arm-none-eabi-gcc arm-none-eabi-gdb
      arm-none-eabi-newlib stlink

    Далее учим Arduino IDE работать с нашей платой:

    Читайте также:  Вольтметр на ардуино: создание устройства своими руками по шагам

    cd ~/opt/arduino/hardware
    git clone https://github.com/rogerclarkmelbourne/Arduino_STM32.git

    Мне дополнительно пришлось поправить Arduino_STM32/STM32F1/platform.txt:

    # compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/
    compiler.path=/usr/bin/

    … ибо сыпались ошибки про то, что Arduino IDE не может найти исполняемый файл arm-none-eabi-g++.

    После этого если открыть Arduino IDE, то в меню Tools → Board вы обнаружите большой выбор плат на базе микроконтроллеров STM32. Выбираем Generic STM32F103C. В Tools → Upload Method выбираем STLink.

    Четыре пина на плате с подписями 3.3V, IO, CLK и GND подключаем к пинам 3.3V, SWDIO, SWCLK и GND программатора соответственно. Проверяем джамперы на плате.

    Оба джампера (так называемые boot0 и boot1) должны стоять в положении 0.

    Fun fact! Чтобы постоянно не возиться с проводами при подключении программатора, выясняя, провод какого цвета к какому пину платы нужно подключить в этот раз, можно взять кусок макетки и спаять адаптер на базе разъема IDC-10. Адаптер подключается к плате через четыре угловых гнезда с шагом 2.54 мм, а затем адаптер подключается к программатору через соответствующий шлейф. Больше никакой путаницы!

    Пробуем скомпилировать и залить такой скетч:

    void setup() {
      pinMode(PC13, OUTPUT);
    }

    void loop() {

      digitalWrite(PC13, HIGH);
      delay(100);
      digitalWrite(PC13, LOW);
      delay(100);
    }

    Fun fact! В плате Blue Pill светодиод стоит между ногой PC13 и VCC (схема [PDF]), а не между ногой и землей, как можно было бы ожидать. Поэтому, подавая HIGH на PC13, мы гасим светодиод, а подавая LOW — зажигаем.

    Если при прошивке возникает ошибка:

    st-flash 1.3.1 INFO src/common.c: Loading device parameters….

    WARN src/common.c: unknown chip id! 0xe0042000

    … проверьте, не перепутали ли вы пины CLK и IO, а также попробуйте зажать кнопку Reset на плате.

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

    Поздравляю, среда разработки настроена!

    Более сложный пример

    Ниже приведен код посложнее, демонстрирующий использование ШИМ, аналоговых пинов, а также отладочный вывод по UART:

    const int LED1 = PB8;
    const int LED2 = PB9;
    const int PTNT = PA0;
    const int BTN = PB7;

    int selected_led = LED1;

    bool btn_was_high = false;

    void setup() {

      pinMode(LED1, PWM);
      pinMode(LED2, PWM);
      pwmWrite(LED1, 0);
      pwmWrite(LED2, 0);
      pinMode(BTN, INPUT);
      pinMode(PTNT, INPUT_ANALOG);

      Serial.begin(115200);

    }

    void loop() {

      delay(100);

      if(digitalRead(BTN) == HIGH) {

        btn_was_high = true;
      } else if(btn_was_high) {
        btn_was_high = false;
        if(selected_led == LED1) {
          selected_led = LED2;
          pwmWrite(LED1, 0);
        } else {
          selected_led = LED1;
          pwmWrite(LED2, 0);
        }
      }

      int ptnt = analogRead(PTNT);

      int ptnt_mapped = map(ptnt, 0, 4095, 0, 65535);

      Serial.println(String(“ptnt = “) + ptnt + “, ptnt_mapped = ” +

        ptnt_mapped);

      pwmWrite(selected_led, ptnt_mapped);

    }

    Соответствующая цепь, собранная на макетной плате:

    При нажатии на кнопку один светодиод гаснет, а второй загорается. Яркость свечения светодиода регулируется потенциометром. Как видите, код очень мало отличается от обычного кода для Arduino. Отличаются только названия пинов, а также диапазоны значений, с которыми работают процедуры analogRead и pwmWrite.

    Еще больше примеров можно найти в File → Examples → A_STM32_Examples.

    Сторонние библиотеки

    Многие библиотеки уже портированы под STM32 — Wire, Servo, LiquidCrystal, и другие. А что, если попытаться использовать стороннюю библиотеку с GitHub? Для эксперимента я решил попытаться воспользоваться библиотекой LiquidCrystal_I2C, уже знакомой нам по заметке Об использовании экранчиков 1602 с I2C-адаптером.

    Добавляем библиотеку в Arduino IDE:

    cd ~/Arduino/libraries
    git clone
     https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library.git
     ./LiquidCrystal_I2C

    Заливаем прошивку:

    #include

    LiquidCrystal_I2C lcd(0x3F, PB6, PB7);

    void setup() {

      lcd.begin();
      lcd.setCursor(0, 0);
      lcd.print(“Current time:”);
    }

    void loop() {

      delay(100);    

      lcd.setCursor(0, 1);

      unsigned long tstamp = millis();
      int h = tstamp / 1000 / 60 / 60;
      int m = (tstamp / 1000 / 60) % 60;
      int s = (tstamp / 1000) % 60;

      String line = String(h) + “h ” +

                    String(m) + “m ” +
                    String(s) + “s”;

      int len = line.length();

      while(len

    Источник: https://eax.me/stm32-arduino-ide/

    С++ (18+) для микроконтроллеров – разведка боем

    Published: Пн. 20 Март 2017By Oleg Mazko

    In Embedded.

    tags: msp430

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

    И если у Си всё так хорошо, зачем все ведущие производители микроконтроллеров (PIC32, MSP430, AVR) дружно подтянули в свои инструментарии для разработчиков C++ компиляторы ? В отличие от своего предшественника Си, C++ декларирует поддержку различных парадигм программирования — процедурное, объектно-ориентированное (ООП), обобщённое (шаблоны).

    Вместе с тем C++ не является серебряной пулей для решения проблем своего предшественника — ручное управление памятью по-прежнему на плечах программиста. C++ добавляет к Си объектно-ориентированные возможности — вводятся классы, которые обеспечивают три самых важных свойства ООП: инкапсуляцию, наследование и полиморфизм.

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

    Если отбросить религиозные пристрастия, то стоит признать, что на данный момент C++ это единственный нативный язык без GC (garbage collector), который позволяет легко переключаться от самого низкого уровня, близкого к аппаратуре, до очень высокого, вроде ООП и обобщенного программирования. При этом данный язык снабжен широким набором инструментария, книг и документации, различных интернет-ресурсов. Плюс огромное количество разработчиков во всем мире.

    Запускаться будем на микроконтроллерах MSP430, компилятор как обычно на сайте производителя. MSP430 — семейство 16-разрядных микроконтроллеров фирмы «Texas Instruments», которые имеют фон-Неймановскую архитектуру с единым адресным пространством для команд и данных (для сравнения у Microchip PIC и Atmel AVR Гарвардская архитектура).

    C++ в большинстве случаев обратно совместим со своим предшественником, так что поначалу всё выглядит как в старом добром Си и совсем нестрашно.

    Частота микроконтроллеров MSP430 задаётся программно и может меняться в процессе выполнения для снижения энергопотребления. Сетка частот встроенного тактового генератора описана в документации – регистры RSEL служат для грубой настройки, DCO для более точной.

    Микроконтроллер msp430f1611 имеет шесть восьмибитных портов ввода-вывода, а шесть делится на три и получаем 16 RGB светодиодов.

    elf | MSP430.js | исходники

    main.cpp

    /*
    reset && (export GCC_DIR=~/ti/msp430_gcc ;
    $GCC_DIR/bin/msp430-elf-c++
    -I $GCC_DIR/include -L $GCC_DIR/include
    -Werror -Wall -Weffc++ -mmcu=msp430f1611 -O2 *.cpp)
    */ #include
    #include “app.h” int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer // DCO = 3, RSEL = 0, f = 0.13 MHz DCOCTL = /* DCO2 + */ DCO1 + DCO0; BCSCTL1 = XT2OFF /* + RSEL1 + RSEL0 + RSEL2 */; constexpr auto O = 0; P1OUT = O; P2OUT = O; P3OUT = O; P4OUT = O; P5OUT = O; P6OUT = O; P1DIR = P2DIR = P3DIR = P4DIR = P5DIR = P6DIR = 0xFF; return app::run();
    }

    Тут в коде три интересных момента, касающихся С++:

    • constexpr – константа на этапе компиляции, в отличие от const не занимает физический адрес в памяти
    • auto – автоматическое выведение типа на этапе компиляции исходя из присваиваемого значения
    • app::run() – вызов метода из пространства имён app

    app.h

    namespace app { int run();
    }

    app.cpp

    #include
    #include “rgb.h” namespace app { int run() { // rgb_strip: default initialization rgb::RgbStripLayer rgb_strip; constexpr auto colors = { rgb_strip.RED, rgb_strip.GREEN, rgb_strip.BLUE, rgb_strip.YELLOW, rgb_strip.VIOLET, rgb_strip.CYAN, rgb_strip.WHITE, rgb_strip.BLACK }; for (;;) { for (const auto& c : colors) { for (auto& m : rgb_strip.mem) { m = c; rgb_strip.flush(); __delay_cycles(10000); } } } return 0; }
    }

    • функция run находится в пространстве имён namespace app – в пределах одного пространства имён идентификаторы (имена) должны быть уникальны, тогда как один и тот же идентификатор может быть определён в нескольких пространствах имён
    • для переменной rgb_strip отсутствует выражение инициализации и поэтому происходит инициализация по умолчанию – для классов, структур и объединений это инициализация с помощью конструктора по умолчанию (до классов мы ещё дойдём)
    • цикл по контейнеру for (const auto& c : colors) позволяет пройтись по всем элементам без явного указания индекса и стало быть без ошибок, связанных с неправильным индексом за пределами контейнера
    • С++ даёт возможность программисту избегать лишних звёздочек – доступ к переменным по ссылке auto& c обычно безопаснее и более строго проверяется компилятором чем через разыменовывание указателя *с в стиле Си

    hal.h

    #include “pin.h”
    #include
    #include namespace pin { // MSP430 aliases using msp430_port_t = decltype(P1OUT); using msp430_pin_t = Pin;
    }

    • using msp430_port_t = decltype(P1OUT); – псевдоним типа, в данном случае можно было бы спокойно заменить на Cи typedef decltype(P1OUT) msp430_port_t – это дело вкуса и стиля
    • decltype(P1OUT) – в большинстве случаев нам не нужно знать какой там именно у микроконтроллера порт – 8, 16 или 32 бит, но его тип нам понадобится т.к. проверку типов на этапе компиляции никто не отменял
    • Pin – псевдоним шаблона, кто это такой и зачем он нужен станет понятно чуть дальше

    non-copyable.h

    // C++ compile time check idiom: Non-Copyable Class
    // TODO: inheritance approach bloats the code size
    class NonCopyable {
    protected: NonCopyable(NonCopyable const&) = delete; NonCopyable& operator=(NonCopyable const&) = delete; NonCopyable() = default;
    };

    Конструктор копирования… В вежливой форме предлагаю его сразу отключать и забыть – для этого достаточно просто наследовать классы от класса NonCopyable. В таком случае кривой код, пытающийся создать побитовую копию объекта просто сломает компиляцию и это правильно.

    rgb.h

    #include “hal.h”
    #include namespace rgb { using namespace pin; class RgbStripLayer : NonCopyable { template struct MonoStrip; static MonoStrip red; static MonoStrip green; static MonoStrip blue; public: // mem: value initialization RgbStripLayer(): mem() {} static constexpr std::size_t STRIP_SZ = 2*8; struct RGB { bool r, g, b; }; std::array mem; static constexpr RGB RED = { 1, 0, 0 }, GREEN = { 0, 1, 0 }, BLUE = { 0, 0, 1 }, YELLOW = { 1, 1, 0 }, CYAN = { 0, 1, 1 }, VIOLET = { 1, 0, 1 }, WHITE = { 1, 1, 1 }, BLACK = { 0 }; void flush(); RgbStripLayer& operator += (const RgbStripLayer& layer); };
    }

    Итак ООП.

    • все поля и методы классов class (а также структур struct) имеют права доступа – по умолчанию все содержимое класса является доступным для чтения и записи только для него самого т.е. закрыто (private), а для структуры struct наоборот по умолчанию всё открыто для всех (public)
    • поля red, green, blue в классе RgbStripLayer (слой анимации) статические – все экземпляры этого класса используют одну и ту же копию этих полей и тем самым экономится память RAM
    • std::array – это контейнер для массива фиксированного размера, имеет ту же семантику, что и Cи массивы плюс знает собственный размер, поддерживает присваивание, итераторы и т.д.
    • методы, совпадающие с именем класса это конструкторы, RgbStripLayer(): mem() {} это конструктор по умолчанию т.к. не содержит аргументов, в нашем случае в конструкторе контейнер mem инициализируется нулями
    • слои анимаций RgbStripLayer можно смешивать между собой – для этого перегружен оператор +=

    rgb.cpp

    #include “rgb.h” namespace rgb { template struct RgbStripLayer::MonoStrip : NonCopyable { msp430_pin_t leds[STRIP_SZ] = { { p1, 0 }, { p1, 1 }, { p1, 2 }, { p1, 3 }, { p1, 4 }, { p1, 5 }, { p1, 6 }, { p1, 7 }, { p2, 0 }, { p2, 1 }, { p2, 2 }, { p2, 3 }, { p2, 4 }, { p2, 5 }, { p2, 6 }, { p2, 7 }, }; }; decltype(RgbStripLayer::red) RgbStripLayer::red; decltype(RgbStripLayer::green) RgbStripLayer::green; decltype(RgbStripLayer::blue) RgbStripLayer::blue; void RgbStripLayer::flush() { for (auto i = mem.size(); i–;) { red.leds[i].set(mem[i].r); green.leds[i].set(mem[i].g); blue.leds[i].set(mem[i].b); } } RgbStripLayer& RgbStripLayer::operator += (const RgbStripLayer& layer) { for (auto i = mem.size(); i–;) { mem[i].r |= layer.mem[i].r; mem[i].g |= layer.mem[i].g; mem[i].b |= layer.mem[i].b; } return *this; }
    }

    • объявление класса и реализация в отдельных файлах в С++ не является обязательной, однако позволяет при необходимости ускорить сборку проекта за счёт т.н. раздельной компиляции – также как и в Си собственно
    • шаблоны C++ позволяют задавать обобщённые алгоритмы без привязки к некоторым параметрам – в случае c MonoStrip это конкретные порты ввода вывода p1, p2 различные у каждого цвета, код шаблона сгенерируется на этапе компиляции и в этом они схожи с макросами Си
    • каждый класс в C++ использует свое пространство имен, если внутри класса записано только объявление, реализация должна быть определена в другом месте с помощью операции доступа к области видимости ::
    Читайте также:  Будущее человечества или наша жизнь в 2116 году - arduino+

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

    pin.h

    #include “non-copyable.h” namespace pin { template class Pin : NonCopyable { port_t& m_port; const port_t m_mask; public: Pin(port_t& port, const pos_t pos): m_port(port), m_mask(1

    Источник: http://proiot.ru/blog/posts/2017/03/20/s-18-dlia-mikrokontrollerov-razvedka-boem/

    Пишем прошивку для Arduino на С++ с REST управлением через последовательный порт и экранчиком

    4 декабря 2014 в 22:45 (МСК) | сохранено5 декабря 2014 в 22:45 (МСК)<\p>

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

    То есть, например, отправив в последовательный порт что-то типа

    /battery?act=statusполучим в ответ что-то типа{ “status”: “OK”, “minValue”: 600, “maxValue”: 900, “value”:750, “percent”: 50 }
    Для тех, кому лень читать статью, сразу ссылка на github и Яндекс-диск, у кого гитхаб залочен (спасибо MaximChistov). Итак, в какой-то момент я понял, что без ардуины мне никак не обойтись, достал из закромов Arduino Nano и купил к нему экранчик с I2C переходником. Как я пытался подключить экран, это отдельная песня с припевом, но в итоге оказалось, что у меня был перебитый земляной провод и I2C адрес экрана не соответствовал ни одному из описаний в инете. После успешного запуска HelloWorld из примеров я начал думать и что же мне со всем этим делать.

    Что имелось в начале

    На старте имелось следующее: Список задач:

    1. Управление по типу HTTP REST
    2. Отображение на экране сообщений, уведомлений (больше приоритет) и иконок по типу system tray
    3. Определение уровня заряда батарейки
    4. Управление питанием и выстрелом пушки

    Чуть-чуть про пушку и батарейку.

    Для определения уровня заряда я подключил плюс батарейки через делитель из 2х резисторов по 43КОм на вход A0. Осталось только откалибровать верхнее и нижнее значения. Пушка у меня включена не постоянно. При подаче единицы на цифровую ногу ардуины через полевой транзистор запитывается сервопривод наведения пушки и заодно лазерный прицел.

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

    Также сразу уточню, что посмотрев на объем RAM у ATMega328, который всего 2 килобайта, я испугался и не стал использовать динамическую память. Только стек, только хардкор.

    Базовый скелет для обработки REST запросов

    Поняв, что мне надо от ардуины и прогнав тестовые примеры, я радостно открыл Arduino IDE и завис. Мне явно было мало одного файла и хотелось нормального C++ с подсветкой и автокомплитом. Через некоторое время пришло озарение.

    Исходник оформляется в виде библиотеки, лежащей в sketchbook/libraries, а сам скетч создает единственный объект с методами Setup() и Loop() и соответственно их вызывает.

    На всякий случай, уточню, что у Arduino SDK есть две абстракции ввода-вывода.

    Это Print, на который можно как это ни странно выводить и Stream, который унаследован от Print.

    Базовые сущности получились такие:

    1. Команда. Создается из строки вида /commandName?arg1=value1&arg2=value2 и содержит простейший парсер аргументов.

      Интерфейсclass Command
      {
      public: Command( char* str ); inline const char* Name() const { return _name; } inline const char* Params() const { return _params; } const char* GetParam( const char* paramName ); bool GetIntParam( const char* paramName, int* out ); bool GetDoubleParam( const char* paramName, double* out ); bool GetStringParam( const char* paramName, const char** out ); private: char* _name; char* _params; size_t _paramsLen;
      };

    2. Обработчик команды. Обрабатывает команду и шлет ответ в виде JSON.
      Интерфейсclass CommandHandler
      {
      public: virtual void HandleCommand( Command& cmd, Print &output ); static void SendError( Print &output, const char* err ); static void SendOk( Print &output ); static void SendErrorFormat( Print &output, const char* fmt, … );
      };
    3. Обработчик запросов. Создает команду и маршрутизирует ее на соответствующий обработчик, если таковой есть.
      Интерфейсstruct HandlerInfo
      { const char* command; CommandHandler* handler; HandlerInfo(): command(0), handler(0) {} HandlerInfo(const char* c, CommandHandler* h): command(c), handler(h) {}
      }; class RequestHandler
      {
      public: RequestHandler(); void SetHandlers( HandlerInfo* handlers, size_t count ); void HandleRequest( char* request, Print& output ); private: HandlerInfo* _handlers; size_t _handlersCount;
      };

    Для обработки запросов с последовательного порта (или еще какого Stream'a) был написан

    StreamRequestHandlerclass StreamRequestHandler : public RequestHandler
    {
    public: static const size_t BufferSize = 128; StreamRequestHandler( Stream& stream ); void Proceed(); private: Stream& _stream; char _requestBuf[BufferSize]; size_t _requestLen;
    };Настало время все это протестировать. Для этого надо создать экземпляр StreamRequestHandler, передав ему в конструктор Serial (который на самом деле синглтон класса HardwareSerial), передать в SetHandlers массив обработчиков команд и дергать метод Proceed где-то внутри loop().

    Первым обработчиком стал

    PingHandlerclass PingHandler : public CommandHandler
    {
    public: virtual void HandleCommand( Command& cmd, Print &output ) { SendOk(output); }
    };

    Работа с экраном

    После успешного отклика на пинг захотелось прочитать что-нибудь на экранчике и там же увидеть заряд батарейки. Стандартный экран 16×2 имеет, как ни странно, две строки по 16 символов, а также позволяет переопределить изображения для первых восьми символов.

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

    Чтобы не городить связные списки на указателях, максимальное количество сообщений в очереди было ограничено до 8 обычных и 4 приоритетных, что позволило использовать для их хранения обычный кольцевой буфер. Иконками в system tray стали обычные символы с кодами от 0 до 7.

    Для показа иконки надо сначала ее зарезервировать, получив iconID (который просто код символа), после чего для iconID можно задать само изображение. Анимированную иконку можно получить постоянно меняя картинку. Экран такое издевательство выдерживает без проблем.

    Что в итоге получилосьclass DisplayController
    {
    public: static const uint8_t MaxIcons = 8; static const uint8_t Rows = 2; static const uint8_t Cols = 16; static const uint8_t IconsRow = 0; static const uint8_t IconsCol = 0; static const int MaxMessages = 8; static const unsigned MessageInterval = 150; static const uint8_t MessageRow = 1; static const uint8_t MessageCol = 0; static const uint8_t MessageLen = 16; static const int MaxAlerts = 4; static const unsigned AlertInterval = 1000; static const uint8_t AlertRow = 1; static const uint8_t AlertCol = 0; static const uint8_t AlertLen = 16; private: struct Message { const char* text; int length; int position; inline Message() { Clear(); } inline void Clear() { text = 0; length = 0; position = 0; } }; struct Alert { const char* text; int length; bool visible; inline Alert() { Clear(); } inline void Clear() { text = 0; length = 0; visible = false; } }; public: DisplayController( uint8_t displayAddr ); void Init(); int8_t AllocateIcon(); void ReleaseIcon(int8_t iconId); void ChangeIcon(int8_t iconId, uint8_t iconData[]); void UpdateIcons(); void Proceed(); bool PutMessage( const char* text ); bool PutAlert( const char* text ); inline bool HasMessages() { return _messages[_messageHead].text != 0; } inline bool HasAlerts() { return _alerts[_alertHead].text != 0; } void UpdateMessage(); void UpdateAlert(); private: LiquidCrystal_I2C _lcd; int _iconBusy; unsigned long _messageTick; Message _messages[MaxMessages]; int _messageHead; int _messageTail; unsigned long _alertTick; Alert _alerts[MaxAlerts]; int _alertHead; int _alertTail;
    };

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

    Собственно, все, спасибо за внимание. Надеюсь, что кому-нибудь мой опыт пригодится. Весь код, кроме скетча лежит на github'е или на Яндекс-диске, а сам скетч выглядит так:

    Скетч#include
    #include
    #include Tank tank(19200, 0x3F, A0, 4, 5, 6); void setup()
    { tank.Setup();
    } void loop()
    { tank.Loop();
    }

    Источник: https://sohabr.net/habr/post/245043/

    C++| ARDUINO IDE | ESP8266. Указатели (типы данных)

    03 02 2018      Петр       1 комментарийВ предыдущих главах переменные были объяснены как местоположения (ячейки) в памяти компьютера, к которым можно получить доступ по их идентификатору (их имени).

     Таким образом, программе не нужно заботиться о физическом адресе данных в памяти; он просто использует идентификатор всякий раз, когда ему нужно ссылаться на переменную.Для программы на C ++ память компьютера похожа на последовательность ячеек памяти, каждый побайтовый размер и каждый с уникальным адресом.

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

     Например, ячейка памяти с адресом 1776всегда следует сразу после ячейки с адресом1775и предшествует одному 1777, и составляет ровно одну тысячу ячеек после 776и ровно одну тысячу ячеек раньше 2776.Когда объявляется переменная, памяти, необходимой для сохранения ее значения, назначается определенное место в памяти (адрес памяти).

     Как правило, C ++-программы не принимают активного решения точные адреса памяти, где хранятся его переменные. К счастью, эта задача остается в среде, в которой запускается программа, – как правило, операционная система, которая решает конкретные ячейки памяти во время выполнения.

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

    Адрес переменной можно получить, указав имя переменной с символом амперсанда ( &), известным как адрес-оператора . Например:

    Это будет присваивать адрес переменной myvarк foo; предшествуя имени переменной myvarс адресом-operator ( &), мы больше не назначаем содержимое самой переменной foo, а ее адрес.

    Фактический адрес переменной в памяти не может быть известен до выполнения, но предположим, чтобы помочь прояснить некоторые концепции, которые myvarпомещаются во время выполнения в адрес памяти 1776.

    В этом случае рассмотрим следующий фрагмент кода:

    1 2 3 myvar = 25; foo = &myvar; bar = myvar;

    Значения , содержащиеся в каждой переменной после выполнения этого, показаны в следующей схеме: Во-

    первых, мы присвоили значение 25для myvar(переменной, адрес которой в памяти мы предположили , чтобы быть 1776).

    Второй оператор присваивает fooадрес myvar, который мы предположили 1776.

    И, наконец, третье утверждение, присваивает значение , содержащееся в myvarк bar. Это стандартная операция присваивания, как это уже делалось много раз в предыдущих главах.

    Основное отличие второго и третьего операторов – появление адреса-оператора ( &).

    Переменная, которая хранит адрес другой переменной (например,fooв предыдущем примере) – это то, что в C ++ называется указателем . Указатели – очень мощная функция языка, который имеет много применений в программировании более низкого уровня. Немного позже мы увидим, как объявлять и использовать указатели.

    Как видно, переменная, которая хранит адрес другой переменной, называется указателем . Указатели, как говорят, «указывают» на переменную, адрес которой они хранят.

    Интересным свойством указателей является то, что они могут использоваться для доступа к переменной, на которую они указывают напрямую. Это делается путем указания имени указателя с помощью оператора разыменования ( *). Сам оператор можно считать «значением, на которое указывает».

    Поэтому, следуя значениям предыдущего примера, следующий оператор:

    Это может быть истолковано как: « bazравно значению , адресуемый параметром foo», и заявление будет фактически присвоить значение 25для baz, так как fooесть 1776, а величина , на которую указывает 1776(после приведенного выше примера) будет 25.

    Важно четко различать, что fooотносится к значению 1776, в то время как *foo(со звездочкой, *предшествующей идентификатору) относится к значению, хранящемуся по адресу 1776, что в этом случае 25. Обратите внимание на разницу включения или отсутствия оператора разыменования (я добавил пояснительный комментарий о том, как можно прочитать каждое из этих двух выражений):

    1 2 baz = foo; // baz equal to foo (1776) baz = *foo; // baz equal to value pointed to by foo (25)

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

    • &является адресом оператора , и его можно просто читать как «адрес»,
    • *является оператором разыменования и может считаться «значением, на которое указывает« значение »,

    Таким образом, они имеют противоположные значения: Полученный адрес &может быть разыменован *.

    Ранее мы выполнили следующие две операции присваивания:

    1 2 myvar = 25; foo = &myvar;

    Сразу после этих двух утверждений все приведенные ниже выражения дали бы результат:

    1 2 3 4 myvar == 25 &myvar == 1776 foo == 1776 *foo == 25

    Первое выражение достаточно ясно, учитывая, что выполняемая операция присваивания myvarбыла myvar=25. Второй использует адрес-оператора ( &), который возвращает адрес myvar, который мы предположили, что он имеет значение 1776.

     Третий несколько очевидна, так как второе выражение верно и операция присваивания выполняется на fooбыло foo=&myvar.

     В четвертом выражении используется оператор разыменования ( *), который можно читать как «значение, на которое указывает», и значение, на которое указывает, fooдействительно 25.

    Итак, после всего этого вы также можете сделать вывод о том, что до тех пор, пока адрес, на который указывает, fooостается неизменным, будет также выполняться следующее выражение:

    Из-за способности указателя напрямую ссылаться на значение, на которое оно указывает, указатель имеет разные свойства, когда указывает на a, charчем когда он указывает на a intили a float. После разыменования тип должен быть известен. И для этого в декларации указателя должен быть указан тип данных, на который указывает указатель.

    Объявление указателей следует этому синтаксису:

    type * name;

    где typeтип данных, на который указывает указатель. Этот тип не является типом самого указателя, а типом данных, на которые указывает указатель. Например:

    1 2 3 int * number; char * character; double * decimals;

    Это три объявления указателей. Каждый из них предназначен для указания на другой тип данных, но на самом деле все они являются указателями, и все они, вероятно, будут занимать одинаковое пространство в памяти (размер в памяти указателя зависит от платформы где выполняется программа).

     Тем не менее, данные, на которые они указывают, не занимают одинаковое пространство и не имеют одного и того же типа: первый указывает на a int, второй на a charи последний на a double.

     Поэтому, хотя эти три переменные пример все из них указатели, они на самом деле имеют различные типы: int*, char*, и , double*соответственно, в зависимости от типа они указывают.

    Обратите внимание, что звездочка (*), используемый при объявлении указателя, означает только то, что он является указателем (он является частью спецификатора типа type), и его не следует путать с оператором разыменования, который был замечен раньше, но который также написан со звездочкой ( *). Это просто две разные вещи, представленные одним и тем же знаком.

    Давайте посмотрим пример на указатели:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // my first pointer #include using namespace std; int main () { int firstvalue, secondvalue; int * mypointer; mypointer = &firstvalue; *mypointer = 10; mypointer = &secondvalue; *mypointer = 20; cout

    Источник: https://mirrobo.ru/c-arduino-ide-esp8266-ukazateli-tipy-dannyx/

    Arduino — основы программирования

    После ознакомления с основными элементами Arduino, а также написания программы «Hello World!» пришло время для знакомства с языком программирования.

    Структура языка основана главным образом на C/C++, поэтому те, кто ранее программировал на этом языке, не будут испытывать затруднений при освоении программирования Arduino. Остальные должны освоить основную информацию о командах управления, типах данных и функциях.

    Большая часть информации, содержащейся здесь, будет совместима с любым курсом C/C++, с учетом различий в типах данных, а также несколько конкретных инструкций, касающихся программирования портов ввода/вывода.

    Внимание: Рекомендуется ознакомиться (хотя бы бегло) с курсом C++, а именно с системой счисления, алгоритмами, записи кода…

    Основы основ

    Несколько формальных вещей, то есть таких, о которых все знают, но иногда забывают…

    В Arduino IDE, как в C/C++, необходимо помнить о регистрах символов. Ключевые слова, такие как if, for всегда записываются в нижнем регистре. Каждая инструкция заканчивается на «;». Точка с запятой сообщает компилятору, какую часть интерпретировать как инструкцию.

    Скобки {..} используются для обозначения программных блоков. Мы используем их для ограничения тела функции (см. ниже), циклов и условных операторов.

    Хорошей практикой является добавление комментариев к содержимому программы, это помогает легко понять код. Однострочные комментарии начинаются с // (двойная косая черта). Многострочные комментарии начинаются с /* и заканчиваются на */

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

    #include // стандартная библиотека #include «svoya_biblioteka.h» // библиотека в каталоге проекта

    Функции в Arduino

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

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

    Объявление функции

    Схема объявления функции выглядит следующим образом:

    тип имя_функции(параметр) { // инструкции для выполнения (тело функции) return (/* возвращение значения*/); }

    тип — это имя любого доступного типа данных на данном языке программирования. Список типов, доступных при программировании Arduino приведем в отдельной статье.

    После исполнения, функция вернет значение объявленного типа. В случае, если функция не принимает никакого возвращаемого значения, то тип данных будет «void».

    имя_функции позволяет ее однозначно идентифицировать. Для того чтобы вызвать (запустить) функцию, мы даем ей имя.

    параметр — параметр вызова функции. Параметры не обязательны, но зачастую они бывают полезны. Если мы напишем функцию, у которой нет аргументов, мы оставляем круглые скобки пустыми.

    Внутри скобок «{…}» содержится собственно тело функции или инструкция, которые мы хотим выполнить. Описание конкретных инструкций укажем в отдельной статье.

    Все функции, возвращающие значение, заканчиваются оператором return, за которым следует возвращаемое значение. Только функции, объявленные нулевым указателем («void»), не содержат оператор return. Необходимо знать, что оператор return завершает выполнение функции независимо от местоположения.

    Ниже приведены некоторые примеры деклараций функций.

     void f1() { //тело функции } —————————————— int minus() { //тело функции return (0); } —————————————— int plus(int a, int b) { return (a+b); }

    Как вы можете видеть на примерах, объявление функции может принимать различные формы в зависимости от ваших потребностей.

    Настоятельно рекомендуем вам изучить и применять функции при написании собственных программ. Со временем, у каждого программиста набирается собственная библиотека функций «на все случаи жизни», которая позволяет облегчить и ускорить процесс написания новых программ.

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

    Вызов функции

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

    Объявив функцию, мы можем использовать ее в других функциях с соответствующим именем и любыми требуемыми параметрами. Ниже приведены примеры вызова функций, которые мы привели выше:

    f1(); plus(2,2); y=plus(1,5);

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

    Если функция f1() объявлена без параметров, то при ее вызове нельзя указывать никакие параметры, т.е. вызов функции f1(0) будет неверным.

    Функция plus(int a, int b) требует ровно двух параметров, поэтому вызов с одним или тремя параметрами невозможно.

    Вызов y=plus(1,5) приведет к выполнению функции «plus» с параметрами «1» и «5» и сохранить возвращаемое значение в переменную «y».

    Функции setup() и loop()

    Обладая знаниями об объявлении и вызове функций, мы можем перейти к системным функциям Arduino: setup() и loop(). Arduino IDE в обязательном порядке необходимо объявлять эти две функции.

    setup () — это функция, которая вызывается автоматически при включении питания или нажатии кнопки RESET.

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

    void setup () { // тело функции — инициализация системы }

    loop () — это функция, которая вызывается в бесконечном цикле. Данная функция также не возвращает значения и не вызывается с параметрами. Ниже показано правильное объявление функции loop():

    void loop () { // тело функции — программный код }

    Как вы видите, объявление функции loop () идентично объявлению функции setup (). Различие состоит в выполнении этих функций микроконтроллером.

    Теперь мы проанализируем следующий псевдокод:

    void setup () { on_led1 ();    //включаем светодиод led1 off_led1 ();    //выключаем светодиод led1 } void loop () { on_led2 ();    //включаем светодиод led2 off_led2 ();    //выключаем светодиод led2 }

    В функции setup () есть две инструкции: первая включает светодиод led1, подключенный к плате (например, контакт 13), а вторая выключает светодиод led1.

    Функция loop () имеет идентичные инструкции для включения и выключения светодиода led2, подключенного к плате (например, контакт 12).

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

    Нажатие кнопки RESET приведет к тому, что led1 снова мигнет один раз, а led2 снова начнет постоянно мигать.

    Подведем итог:

    • Функции setup () и loop () — это системные функции, которые должны быть определены в каждом проекте. Даже в ситуации, когда в одном из них мы не пропишем какой-либо код, мы все равно должны объявить эти две функции;
    • Функция setup () выполняется один раз, loop() выполняется непрерывно;
    • Мы создаем собственные функции в одном файле;
    • Мы можем вызвать свои функции как из setup () и loop (), так и из других функций;
    • Наши собственные функции можно вызывать с параметрами и возвращать значение;
    • Вызов функции должен быть совершен в соответствии с ее декларацией.

    Источник: http://www.joyta.ru/10709-arduino-osnovy-programmirovaniya/

    Ссылка на основную публикацию
    Adblock
    detector