Типы данных в ардуино

Язык программирования устройств Ардуино основан на C/C++. Он прост в освоении, и на данный момент Arduino — это, пожалуй, самый удобный способ программирования устройств на микроконтроллерах.

Базовые и полезные знания, необходимые для успешного программирования под платформу Arduino:

  • Начало работы с Arduino в Windows
  • Работа с Arduino Mini
  • Цифровые выводы
  • Аналоговые входы
  • Широтно-импульсная модуляция
  • Память в Arduino
  • Использование аппаратных прерываний в Arduino
  • Перепрошивка контроллера Atmega8U2 для Arduino Uno и Mega2560
  • Переменные
  • Функции
  • Создание библиотек для Arduino
  • Использование сдвигового регистра 74HC595 для увеличения количества выходов
  • Прямое управления выходами через регистры микроконтроллера Atmega

Справочник языка Ардуино

Язык Arduino можно разделить на три раздела:

Операторы

Управляющие операторы
Синтаксис
  • ; (semicolon)
  • <> (curly braces)
  • // (single line comment)
  • /* */ (multi-line comment)
Арифметические операторы
  • = (assignment)
  • + (addition)
  • — (subtraction)
  • * (multiplication)
  • / (division)
  • % (modulo)
Операторы сравнения
  • == (equal to)
  • != (not equal to)
  • <(less than)
  • > (greater than)
  • <=(less than or equal to)
  • >= (greater than or equal to)
Логические операторы
Унарные операторы
  • ++ (increment)
  • — (decrement)
  • += (compound addition)
  • -= (compound subtraction)
  • *= (compound multiplication)
  • /= (compound division)

Пожалуй самый частоиспользуемый тип для хранения целых чисел со знаком — integer (целое число). Занимает 2 байта и может хранить цисла от -32768 до 32767.

На платформе Arduino также присутствует тип , который ничем не отличается от типа int .

int y = 10;

unsigned int

Беззнаковое целое число, занимает так же, как и int , 2 байта. Диапазон значений — от 0 до 65535.

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

Типы данных

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

НазваниеАльт. названиеВесДиапазонОсобенность
booleanbool1 байт *0 или 1, true или falseЛогический тип
char1 байт-128… 127 (AVR), 0.. 255 (esp)Символ (код символа) из таблицы ASCII
int8_t1 байт-128… 127Целые числа
byteuint8_t1 байт0… 255Целые числа
int **int16_t , short2 байта-32 768… 32 767Целые числа. На ESP8266/ESP32 – 4 байта! См. ниже
unsigned int **uint16_t , word2 байта0… 65 535Целые числа. На ESP8266/ESP32 – 4 байта! См. ниже
longint32_t4 байта-2 147 483 648… 2 147 483 647Целые числа
unsigned longuint32_t4 байта0… 4 294 967 295Целые числа
float4 байта-3.4E+38… 3.4E+38Числа с плавающей точкой, точность: 6-7 знаков
double4/8 байт-1.7E+308.. 1.7E+308Для AVR то же самое, что float .
  • (*) – да, bool занимает 1 байт (8 бит), так как это минимальная адресуемая ячейка памяти. Есть способы запаковать логические переменные в 1 бит, о них поговорим в другом уроке.
  • (**) – на ESP8266/ESP32 int и unsigned int занимает 4 байта, то есть является аналогами типов long и unsigned long !
  • (***) – Компилятор также поддерживает 64 битные числа. Стандартные Arduino-библиотеки с переменными этого типа не работают, поэтому можно использовать только в своём коде.

Целочисленные типы

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

  • Проще ориентироваться в максимальных значениях
  • Легче запомнить
  • Название более короткое
  • Проще изменить один тип на другой
  • Размер переменной задан жёстко и не зависит от платформы (например int на AVR это 2 байта, а на esp8266 – 4 байта)

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

  • UINT8_MAX – 255
  • INT8_MAX – 127
  • UINT16_MAX – 65 535
  • INT16_MAX – 32 767
  • UINT32_MAX – 4 294 967 295
  • INT32_MAX – 2 147 483 647
  • UINT64_MAX – 18 446 744 073 709 551 615
  • INT64_MAX – ‭9 223 372 036 854 775 807

Логический тип

bool – логический, он же булевый (придуман Джорджем Булем) тип данных, принимает значения 0 и 1 или false и true – ложь и правда. Используется для хранения состояний, например включено/выключено, а также для работы в условных конструкциях.

Также переменная типа bool принимает значение true , если присвоить ей любое отличное от нуля число.

bool a = 0; // false bool b = 1; // true bool c = 25; // true

Символьный тип

char – тип данных для хранения символов, символ указывается в одинарных кавычках: char var = ‘a’; . По факту это целочисленный тип данных, а переменная хранит номер (код) символа в таблице ASCII:

blank

Отдельный символьный тип данных нужен для удобства работы, чтобы программа могла понять разницу между числом и символом, например для вывода на дисплей (чтобы вывести именно букву A, а не число 65). Из символов можно составлять строки, об этом более подробно поговорим в уроках про символьные строки и String-строки.

Символы и числа

Несмотря на то, что в языке Си символ это по сути целое число, значения например ‘3’ и 3 не равны между собой, потому что символ ‘3’ с точки зрения программы является числом 51 . На практике иногда бывает нужно конвертировать символы чисел в соответствующие им целые числа и наоборот (при работе со строками и буферами вручную), для этого распространены следующие алгоритмы:

  • Из символа в число – взять младший ниббл (4 бита): symbol v = 123456.654321; // 123456.656250 v = 0.0123456789; // 0.0123456788 v = 0.0000123456789; // 0.0000123456788 v = 123456789; // 123456792.0

    Другие особенности float чисел и работу с ними мы рассмотрим в уроках про математические операции и условия.

    Объявление и инициализация

    • Объявление переменной – резервирование ячейки памяти указанного типа на имя: тип_данных имя;
    • Присваивание – задание переменной значения при помощи оператора = (равно): имя = значение;
    • Инициализация переменной – объявление и присваивание начального значения: тип_данных имя = значение;

    Можно объявить и инициализировать несколько переменных через запятую:

    byte myVal; int sensorRead = 10; byte val1, val2, val3 = 10;

    • Переменная должна быть объявлена до использования, буквально выше по коду. Иначе вы получите ошибку Not declared in this scope – переменная не объявлена.
    • Нельзя объявить две и более переменных с одинаковым именем в одной области определения.

    Локальные и глобальные переменные Ардуино

    Плавное включение и выключение светодиода

    Глобальные и локальные переменные имеют разную видимость (время жизни). Локальная переменная в Arduino живет только внутри функции в которой ее инициализировали, если вы попытаетесь получить доступ к локальной переменной вне функции, вы получите ошибку. Например, в программе с мигающим светодиодом переменная объявляется внутри цикла for и, поэтому переменная не может быть использована вне цикла for.

    Объявление локальной переменной Ардуино

    #define LED 10 void setup() < Serial.begin(9600); pinMode(LED, OUTPUT); >void loop() < for(int i = 0; i for(int i = 255; i >= 0; i—) < analogWrite(LED, i); Serial.println(i); delay(10); >>

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

    Дробные числа (float)

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

    Тип записи Пример Чему равно
    Десятичная дробь20.520.5
    Научный2.34E52.34*10^5 или 234000
    Инженерный67e-1267*10^-12 или 0.000000000067

    Выше в таблице есть пометка “точность: 6-7 знаков” – это означает, что в этом типе можно хранить числа, размер которых не больше 6-7 цифр, остальные цифры будут утеряны! Причём целой части отдаётся приоритет.

    #

    Важный момент: если имя локальной переменной совпадает с одной из глобальных, то приоритет обращения отдаётся локальной переменной

    #

    Преобразования между типами данных

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

    функции преобразования данных

    Диапазон переменных

    Arduino IDE базируется на языке C/C++. Из него же позаимствован способ обработки переменных. При написании программы можно использовать как глобальные переменные, так и локальные переменные.

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

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

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

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

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

    Следующий код иллюстрирует место и способ декларации глобальных и локальных переменных:

    [slh lang=»php»]char tablica[10]; // глобальный массив доступный из любого места программы
    void setup()
    int a; // локальная переменная «a» доступна из функции setup()
    >
    int x; // глобальная переменная доступна из любого места программы
    void loop()
    int a; // локальная переменная «a» доступна из функции loop()
    char b; // локальная переменная «b» доступна из функции loop()
    > [/slh]

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

    Переменная «а» в функции setup () — это совершенно другая переменная, чем «а» в функции loop().

    Давайте рассмотрим другой код.

    Следующий код можно скомпилировать и запустить, а результат работы программы наблюдать с помощью монитора последовательного порта, доступного в Arduino IDE (функции Serial.begin и Serial.print предназначены для отправки данных через последовательный порт)

    [slh lang=»php»] void setup()
    Serial.begin(9600); //инициализация последовательного порта
    >
    int a=10; //глобальная переменная «а» со значением 10
    void loop()
    Serial.print(a); //вывод переменной «а», 10
    Serial.print(» «);
    int a=1; //локальная переменная «a» со значением 1
    Serial.println(a); //вывод переменной «а», 1
    >[/slh]

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

    В начале функции loop() локальная переменная еще не объявлена. Обращаясь к переменной «а», мы обращаемся к глобальной переменной, значение которой составляет 10. После объявления локальной переменной «а» внутри функции loop (), обращаемся к ней и получаем значение 1. Функция loop() вызывается в системе циклически, поэтому с помощью монитора последовательного порта, мы можем наблюдать чередование появление чисел 10 и 1.

    Изменим немного код:

    [slh lang=»php»] void setup()
    Serial.begin(9600); //инициализация последовательного порта
    >
    int a=10; //глобальная переменная «а» со значением 10
    void loop()
    Serial.print(a); //вывод переменной «а», 10
    Serial.print(» «);
    int a=1; //локальная переменная «a» со значением 1
    a++; //увеличить значение переменной «а» на единицу
    Serial.println(a); //вывод переменной «а»
    >
    [/slh]

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

    Инструкция по программированию Arduino

    Инструкция по программированию Arduino

    Друзья, на связи снова специалист Giant 4 Алексей! Мы продолжаем наш небольшой курс статей, по использованию платы Arduino Nano и так называемой адресной лентой, на основе светодиодов ws 2812 b . На сегодня это уже четвертая статья. В прошлый раз мы написали первую программу для управления лентой. Но все-таки нужно иметь хотя бы небольшое представление о языке программирования, которым мы пользовались. Иначе говорить о чем-то дальше будет просто бессмысленно. И так, перед Вами C / C ++ подобный язык. Конечно же, мы не будем изучать его полностью, но я постараюсь затронуть основные моменты. Основные функции Конечно же, это функции setup () и loop () и они нам уже знакомы. Функция setup () вызывается автоматически, при старте программы. Она выполняется один раз и ничего не возвращает, поэтому мы обозначаем данную функцию типом void . В дальнейшем мы разберем, что это значит. Функция loop () начинает выполняться после завершения функции setup (), данная функция тоже ничего не возвращает и выполняется по кругу бесконечное количество раз. И loop (), и setup () являются необходимым минимумом программы. Эти функции должны всегда присутствовать, иначе компилятор выдаст ошибку. Как правило, в setup () происходит инициализация объектов. А в loop () выполняется основная программа и вызываются другие функции. 4_01.PNGvoid setup() < >void loop() < >Типы данных Конечно же, когда речь идет о программировании, то приходится использовать данные разного типа. Типов достаточно много, но мы разберем лишь некоторые из них. — Boolean – это логический тип данных, переменные такого типа могут принимать лишь два значения true или false . Где true – это истина, а false – это ложь. Без этого типа было бы невозможно организовать логику программы. Для того, чтобы объявить переменную такого типа, необходимо записать « boolean a ;». И тогда нам будет доступна переменная с именем «а» типа boolean . А для того, чтобы присвоить данной переменной значение, нужно сделать такую запись – « a = true ;». Хотя можно присвоить значение сразу, при объявлении переменной «boolean a = true;». А чтобы в дальнейшем изменить значение переменной, достаточно просто присвоить ей новое значение. Кстати, да, знак равенства – это операция присваивания. Записи с такой операцией принято читать справа налево. « a = true ;» — Значение true присваивается переменно « a ». 4_02.PNGvoid setup() < >void loop() < boolean a = true; a = false; >Таким же образом, как мы объявляли переменные типа boolean , можно объявить переменную любого типа. — int – пожалуй, самый используемый и востребованный тип. В переменных такого типа хранятся целые числа от -32768 до 32767. Данные ограничения связанны с тем, что на переменную выделяется два байта памяти и больше записать просто не получится. Хотя, если понадобится, то можно воспользоваться другими типами, на которые выделено больше памяти, например, тип long (от -2 147 483 648 до 2 147 483 647). int i = 256; — String – строковый тип. В переменную такого типа можно записать строку или массив символов.
    4_03.PNGvoid setup() < >void loop() < String s = » Привет «; >Переменная Переменная – это имя, закреплённое за выделенной областью памяти. Переменная позволяет опустить потребность контроля, за расположением принадлежащей ей ячейки памяти. Достаточно записать значение в переменную, и значение попадет в выделенную для этого область памяти. При этом, пока существует переменная, присвоенное ей значение будет оставаться в целостности и не будет случайно стерто. Как мы уже могли понять, переменные могут быть разных типов и содержать в себе разные данные. Мало того, очень важно то, в каком месте объявлена переменная, так как объявление работает лишь в рамках тела, обособленного фигурными скобками. Как только тело заканчивается, переменная перестает существовать. В следующем примере при каждом повторе функции loop (), в начале работы, переменная инициализируется и ей присваивается значение, а в момент завершения, переменная перестает существовать. 4_04.PNGvoid setup() < >void loop() < String s = » Привет «; >С этим нужно быть аккуратным, так как на инициализацию переменной тратится немного вычислительного ресурса микроконтроллера. Теперь хочу еще раз обратить ваше внимание на то, что если мы объявим переменную в теле одной функции, и при этом попытаемся использовать в теле другой функции, то программа не сможет ее увидеть. Хорошо, что ошибка вылезет еще на этапе компиляции.

    4_05.PNG

Оцените статью
TutShema
Добавить комментарий