Arduino введение и дополнительные ресурсы1 нуну пе

3.7 Математические функции
В этом разделе будут описаны функции, используемые для выполнения математических операций с программными переменными. Как будет описано ниже, мы можем использовать функцию min() (Подраздел 3.7.1) для сравнения двух значений и возврата наименьшего из них, используется функция max() (подраздел 3.7.2) для сравнения двух значений и возврата наибольшего, функция abs() (подраздел 3.7.3), которая может использоваться для возврата модуля определенного числа, функция constrain() (Подраздел 3.7.4), который может использоваться для возврата значения, ограниченного определенным пользователем диапазоном, функция map() (Подраздел 3.7.5), который может быть использован для выполнения сопоставления между наборами диапазонов, функция pow() (подраздел 3.7.6), которая может быть использована для получения степени числа, и функция sqrt() (подраздел 3.7.7), которая может быть использована для извлечения квадратного корня из числа.
43
3.7.1 мининимум min
Используя функцию min(), можно сравнить два значения и вычислить наименьшее из них, как описано в примере 3.46.

Smaller_variable = min(значение 1, значение 2).;
Пример 3.46: Минимум min(value1\значение, value2) - Описание.
Пример использования функции min() можно увидеть в примере 3.47. Как указано, эта функция сравнивает два значения и возвращает наименьшее из них.

int S = min(5,9); //Значение, присвоенное "S", равно "5"
Пример 3.47: минимальное значение(значение1, значение2) - Пример.
3.7.2 максимальное значение min
Используя функцию max(), можно сравнить два значения и вычислить наибольшее из них, как описано в примере 3.48.

Highest_variable = max(значение 1, значение 2).;
Пример 3.48: Максимум max(value1, value2) - Описание.
Пример использования функции max() можно увидеть в примере 3.49. Как указано, эта функция сравнивает два значения и возвращает наибольшее из них.

int H = max(5,9); //Значение, присвоенное "H", равно "9"
Пример 3.49: max(value1, value2) - Пример.
3.7.3 abs
Используя функцию abs(), можно рассчитать модуль упругости заданного числа,
как описано в примере 3.50.
44

Module = abs(значение);
//"Модуль" равен "значению", если "значение" больше или равно нулю
//"Модуль" равен -1 x "значение", если "значение" меньше нуля
Пример 3.50: abs(значение) - Описание.
Пример использования функции abs() можно увидеть в примере 3.51. Как указывалось
ранее, эта функция возвращает модуль заданного числа для обработки.
int Module = 0; //Целочисленная переменная "Module" инициализируется значением "0"
Module = abs(-5); //Значение, присвоенное "Module", равно "5"
Пример 3.51: abs(значение) - Пример.
3.7.4 ограничение contrain
Используя функцию constrain(), вы можете сравнить значение с диапазоном, определенным пользователем, как описано в примере 3.52.

val = ограничение(значение, значение1, значение2).;
val = ограничение (тестовое значение, нижнее значение диапазона, верхнее значение диапазона);
//"val" = "значение", если "значение" находится внутри ["значение1","значение2"]
//"val" = "value1", если "value" меньше "value1"
//"val" = "value2", если "value" больше "value2"
Пример 3.52: ограничение(значение, value1, value2) - Описание.
Пример использования функции constrain() можно увидеть в примере 3.53. Как как описано ранее, эта функция возвращает значение, ограниченное заданным пользователем диапазоном, что может быть полезно для определения определенного интервала между переменными при обработке данных.

int val = 0; //Целочисленная переменная "val" инициализируется значением "0"
val = ограничение(5,2,10); //Значение, присвоенное "val", равно "5".
Пример 3.53: ограничение(значение, value1, value2) - Пример.
45
3.7.5 Карта\отображение map

Используя функцию map(), мы можем изменить диапазон значений, ожидаемых от данных.
приложение (пример 3.54). Эта функция позволяет настроить используемую шкалу, которая может быть полезен, например, для генерации ШИМ-сигналов в диапазоне от 0 до 255 из аналоговых входных сигналов в диапазоне от 0 до 1023.

new_interval_value = map(значение, значение1, значение2, значение 3, значение 4);
//"value" - отображаемое значение
//"value1" - нижний предел текущего диапазона
//"value2" - верхний предел текущего диапазона
//"value3" - нижний предел нового диапазона, который следует учитывать
//"значение 4" - это верхний предел нового диапазона, который необходимо учитывать
Пример 3.54: Карта (значение, значение1, значение2, значение 3, значение 4) — Описание.

Пример использования функции map() можно увидеть в примере 3.55. Как упоминалось ранее, эта функция может помочь установить связь между двумя различными диапазонами значений.

int val; //Инициализация целочисленной переменной "val".
int f[10]; //Инициализация целочисленного массива с 11 позициями в памяти
(.....) //Инициализация глобальных переменных
void setup(){
pinMode(3,INPUT); //Позволяет задать вывод 3 в качестве "входных данных"
(.....) //Программный код
}
void loop()
_BOS_ для(int i=0;i<=10;i++) _BOS_ //Выполняется до тех пор, пока значение "i" не станет меньше или равно 10
, val=analogRead(3); //Значению аналогового выхода 3 присваивается значение "val".
сопоставить(val,0,1023,0,500); // Преобразовать переменную "val" в диапазон [0,500]
f[i]=val; //Присвоить значение "val" массиву "f" в позиции "i".
}
(.....) //Программный код
}
Пример 3.55: сопоставление(значение, значение1, значение2, значение 3, значение 4) — Пример.

46
3.7.6 степень pow
Используя функцию pow(), вы можете вычислить степень заданного числа, как описано в примере 3.56.

Результирующее значение = pow(значение, показатель степени);
Пример 3.56: pow(значение, показатель степени) — Описание.

Пример использования функции pow() можно увидеть в примере 3.57. Как упоминалось ранее, эта функция вычисляет степень числа в соответствии с определенным показателем.

int val = 0; //Целочисленная переменная "val" инициализируется значением "0"
, val = pow(2,2); //Значение, присвоенное "val", равно "4".
Пример 3.57: степень pow(значение, экспонента) - пример.
3.7.7 корень sqrt
Используя функцию sqrt(), вы можете вычислить квадратный корень из заданного
числа, как описано в примере 3.58.

Получено значение = sqrt(значение);
Пример 3.58: sqrt(значение) - Описание.
Пример использования функции sqrt() можно увидеть в примере 3.59. Как упоминалось
ранее, эта функция вычисляет квадратный корень из числа.

int val = 0; //Целочисленная переменная "val" инициализирована значением "0"
, val = sqrt(9); //Значение, присвоенное "val", равно "3"
Пример 3.59: корень sqrt(значение) - Пример.
47
3.8 Тригонометрические функции
В этом разделе будут описаны функции, используемые для выполнения тригонометрических операций с программными переменными. Как описано ниже, мы можем использовать функцию sen() (Подраздел 3.8.1) для вычисления синуса заданного значения в радианах. Функция cos() (Подраздел 3.8.2) используется для вычисления косинуса заданного значения в радианах, а функция tan() (подраздел 3.8.3) используется для вычисления касательной к заданному значению в радианах.
3.8.1 синус sen
Используя функцию sen(), вы можете вычислить синус заданного значения в радианах, как описано в примере 3.60.

Результат = sen(угол); //"угол" указан в радианах
Пример 3.60: синус sen(значение) - Описание.
3.8.2 косинус cos
Используя функцию cos(), вы можете вычислить косинус заданного значения в
радианах, как описано в примере 3.61.

Результат = cos(угол); //"угол" указывается в радианах
Пример 3.61: cos(значение) - Описание.
3.8.3 тангенс tan
Используя функцию tan(), вы можете рассчитать касательную к заданному значению в
радианах, как описано в примере 3.62.

Результат = tan(угол); //"угол" указывается в радианах
Пример 3.62: tan(значение) - Описание.
48
3.9 Случайные числа

В этом разделе будут описаны функции, используемые для генерации случайных чисел. Как будет описано ниже, мы можем использовать функцию randomSeed() (подраздел 3.9.1), которая может быть использована для изменения места запуска алгоритма случайной последовательности, и функцию random() (подраздел 3.9.2), которая может быть использована для генерации случайного числа.
3.9.1 случайный запуск randomSeed
Используя функцию randomSeed(), можно изменить точку (начальное значение), в которой запускается алгоритм псевдослучайной последовательности (пример 3.63). Изменяя это значение, мы можем уменьшить вероятность повторения определенной последовательности.

randomSeed(значение); //"значение" - это десятичное число
Пример 3.63: случайный запуск randomSeed(значение) - Описание.
Пример использования функции randomSeed() можно увидеть в примере 3.64.  Изменяя это значение, мы можем добавить случайности в полученную последовательность чисел.

int seed=24; //Целочисленная переменная "seed" инициализируется значением "24".
(.....) //Инициализация глобальных переменных
void setup(){
randomSeed(начальное значение) //Изменение точки начала последовательности
(.....) //Программный код
}
пустой цикл(){
(.....) //Программный код
}
Пример 3.64: randomSeed(значение) - Пример.
49
3.9.2 случайный random
Используя функцию random(), можно генерировать случайные числа ( псевдослучайные числа), как описано в примере 3.65.

Результат = random(значение); //"значение" - это максимально возможное значение
Результат = случайный(v1, v2); //"v1" - минимальное значение, "v2" - максимальное
//Максимальное значение "v2" не входит в рассматриваемый интервал
//"Результат" относится к интервалу ["v1", ("v2"-1)]
Пример 3.65: случайный random() - Описание.
Пример использования функции random() можно увидеть в примере 3.66. Мы можем генерировать случайные числа в пределах определенного интервала, которые могут быть использованы в наших программах в соответствии с желаемым поведением встроенной системы.

int seed=24; //Целочисленная переменная "seed" инициализируется значением "24"
long random_value; //Беззнаковая длинная переменная "random_value"
(.....) //Инициализация глобальных переменных
void setup(){
randomSeed(начальное значение) //Изменение точки начала последовательности
(.....) //Программный код
}
void loop(){
случайное значение = random(10, 20); //"случайное значение" между "10" и "19"
(.....) //Программный код
}
Пример 3.66: random() - Пример.
3.10 Прерывания
В этом разделе будут описаны функции, которые можно использовать для выполнения прерываний. Прерывания могут изменять ход выполнения программы при возникновении определенного события
50
без проверки выполнения определенного условия (опроса ). Как будет описано ниже, мы можем использовать функцию attachInterrupt() (подраздел 3.10.1) для определения и управления внешними прерываниями, функцию detachInterrupt() (Подраздел 3.10.2) для отключения ранее определенного прерывания, функция interrupts() (подраздел 3.10.3) для разрешения использования прерываний и функция noInterrupts() (подраздел 3.10.4) для отключения использования прерываний.
3.10.1 Подключение прерывания attachInterupt
Используя функцию attachInterrupt(), можно определить работу внешнего прерывания (пример 3.67). Используя эту инструкцию, мы можем определить функцию, которая будет выполняться, вывод, на котором произойдет прерывание, и какое изменение сигнала будет учитываться.

attachInterrupt(прерывание, функция, режим);
//Arduino Uno Rev. 3
//прерывание == 0 соответствует цифровому выводу "2"
//прерывание == 1 соответствует цифровому выводу "3"
//Arduino Mega Rev. 3
//прерывание == 0 соответствует цифровому выводу "2"
//прерывание == 1 соответствует цифровому выводу "3"
//прерывание == 2 соответствует цифровому выводу "21"
//прерывание == 3 соответствует цифровому выводу "20"
//прерывание == 4 соответствует цифровому выводу "19"
//прерывание == 5 соответствует цифровому выводу "18"
//Примечания:
//Определенная "функция" должна быть из категории void
//"mode" определяет способ распознавания внешнего прерывания
Пример 3.67: подключение прерывания attachInterrupt(прерывание, функция, режим) - Описание.
Как описано в примере 3.67, определенная функция должна быть из типа void.  Параметр mode определяет способ распознавания внешнего прерывания, как описано в Таблице 3.2.
51
Таблица 3.2: Возможные условия идентификации функции attachInterrupt().
Низкий уровень Прерывание выполняется всякий раз, когда логическое значение на выводе равно 0 (0 В)
Изменение уровня Прерывание выполняется всякий раз, когда логическое значение на выводе изменяется
Повышение уровня Прерывание выполняется всякий раз, когда значение на выводе изменяется с 0 (0 В) на 1 (5 В)
Прерывание при падении Прерывание происходит всякий раз, когда напряжение на выводе меняется с 1 (5 В) на 0 (0 В).
3.10.2 Отсоединить  прерывание detachInterrupt
Используя функцию detachInterrupt() (пример 3.68), можно отключить ранее определенное прерывание с помощью функции attachInterupt(), как описано в Подразделе 3.10.1. Эта функция может быть использована в определенных условиях тестирования для контроля поведения системы с течением времени.

Отключите прерывание(interrupt);
//Arduino Uno Rev. 3
//прерывание == 0 соответствует цифровому выводу "2"
//прерывание == 1 соответствует цифровому выводу "3"
//Arduino Mega Rev. 3
//прерывание == 0 соответствует цифровому выводу "2"
//прерывание == 1 соответствует цифровому выводу "3"
//прерывание == 2 соответствует цифровому выводу "21"
//прерывание == 3 соответствует цифровому выводу "20"
//прерывание == 4 соответствует цифровому выводу "19"
//прерывание == 5 соответствует цифровому выводу "18"
Пример 3.68: отсоединение прерывания detachInterrupt(прерывание) - Описание.
3.10.3 прерывания interrupts
Используя функцию прерывания interrrupts() (пример 3.69), можно повторно активировать использование прерываний после того, как эта функция была отключена. Прерывания включены по умолчанию.
52

interrupts(); //Инструкция, позволяющая использовать прерывания
Пример 3.69: прерывания interrupts() - Описание.
Пример использования функции interrupts() можно увидеть в примере 3.70. Мы можем легко использовать его для включения прерываний во время выполнения программы.
процедура настройка(){
(.....) //Программный код
}
процедура цикл(){
noInterrupts(); //Инструкция, запрещающая использование прерываний
(.....) //Программный код
прерывания(); //Инструкция, позволяющая использовать прерывания
(.....) //Программный код
}
Пример 3.70: прерывания() - Пример.
3.10.4 Никаких прерываний  noInterrupts
Используя функцию noInterrupts() (пример 3.71), можно отключить использование прерываний. Прерывания включены по умолчанию.

noInterrupts(); //Инструкция, запрещающая использование прерываний
Пример 3.71: запрет прерываний noInterrupts() - Описание.
Пример использования функции noInterrupts() можно увидеть в примере 3.72.  С ее помощью мы можем легко отключить прерывания во время выполнения программы.
void setup(){
(.....) //Программный код
}
процедура цикл (){
noInterrupts(); //Инструкция, запрещающая использование прерываний
53

(.....) //
Прерывания программного кода(); //Инструкция, разрешающая использование прерываний
(.....) //Программный код
}
Пример 3.72: noInterrupts() - Пример.
3.11 Последовательный обмен данными \коммуникация
В этом разделе будут описаны функции управления последовательным обменом данными между устройствами. Как будет описано ниже, функция Serial.available() (Подраздел 3.11.1) может использоваться для получения количества полученных байт, функция Serial.begin() (подраздел 3.11.2) может использоваться для запуска последовательного для связи функция Serial.read() (подраздел 3.11.3) может использоваться для считывания данных с последовательного порта, функция Serial.flush() (подраздел 3.11.4) можно использовать для удаления всех существующих данных во входном буфере, функции Serial.print() и Serial.println() (подраздел 3.11.5) можно использовать для отправки десятичных, шестнадцатеричных и восьмеричных данных через последовательный порт и функцию Serial.write() (Подраздел 3.11.6) может использоваться для отправки двоичных данных через последовательный порт.
3.11.1 Серийный номер\последовательный .доступен Serial.available

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

int Number_bytes = Serial.available(); //Количество полученных байт
Пример 3.73: последовательный.доступен Serial.available() - Описание.
Пример использования функции Serial.available() можно увидеть в примере 3.74. Мы можем использовать эту функцию, чтобы проверить, получаем ли мы данные через последовательный порт, и выполнить какое-либо действие только после получения каких-либо данных.
54

int read=0; //Целочисленная переменная "read" инициализируется значением "0"
(.....) //Инициализация глобальных переменных
void setup(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
}
не пустой цикл(){
if(Serial.available()>0) //Проверяем, получаем ли мы данные
read=Serial.read(); //Если true, то значение сохраняется в "read".
(.....) //Программный код
}
Пример 3.74: последовательный.доступен Serial.available() - Пример.
3.11.2 Серийный номер.начать Serial.begin
Используя функцию Serial.begin() (пример 3.75), можно запустить последовательный обмен данными и определить используемую скорость передачи данных в бодах. Наиболее часто используемая скорость передачи данных в бодах скорости равны 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, и 115200. Однако могут быть определены и другие значения.

Serial.begin(скорость передачи данных в бодах); //Определение скорости передачи данных в бодах
Пример 3.75: Serial.begin() - Описание.
Пример использования функции Serial.begin() можно увидеть в примере 3.76. Определение
последовательной связи и скорости передачи данных в бодах выполняется внутри функции настройки.

int read=0; //Целочисленная переменная "read" инициализируется значением "0"
(.....) //Инициализация глобальных переменных
аннулирует setup(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
55

}
цикл аннулирования(){
(.....) //Программный код
}
Пример 3.76: последовательный.начать Serial.begin() - Пример.
3.11.3 Серийный номер.читать  Serial.read

Используя функцию Serial.read() (пример 3.77), можно считывать данные через последовательный порт. Эта функция вернет значение -1, если данные отсутствуют.

Received_data = Serial.read(); //Данные, полученные через последовательный порт
Пример 3.77: последовательный.чтение Serial.read() - Описание.
Пример использования функции Serial.read() можно увидеть в примере 3.78. Используя эту функцию, полученные данные могут быть сохранены и обработаны для использования информации, полученной через последовательный порт, для взаимодействия с разработанной системой.

int read=0; //Целочисленная переменная "read" инициализируется значением "0".
(.....) //Инициализация глобальных переменных
void setup(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
}
не пустой цикл(){
if(Serial.available()>0) //Проверяем, получаем ли мы данные
read=Serial.read(); //Если true, то значение сохраняется в "read"
(.....) //Программный код
}
Пример 3.78: последовательный.чтение Serial.read() - Пример.
56
3.11.4 последовательный.смыть Serial.flush
Используя функцию Serial.flush() (пример 3.79), можно очистить (стереть) все существующие данные во входном буфере. Объем входного буфера составляет 64 байта.

Serial.flush(); //Очистка (стирание) входного буфера
Пример 3.79: последовательный.смыть Serial.flush() - Описание.
Пример использования функции Serial.flush() можно увидеть в примере 3.80. Эта функция может гарантировать, что буфер не переполнится и что мы считываем и обрабатываем самые последние данные, полученные с помощью последовательного порта.

избежать настройка(){
(.....) //Программный код
}
не пустой цикл(){
Serial.flush(); //Удаляет содержимое входного буфера
(.....) //Программный код
}
Пример 3.80: последовательный.смыть Serial.flush() - Пример.
3.11.5 последовательный.печать Serial.print против последовательный.печать линии Serial.println
Используя функции последовательный.печать Serial.print() и последовательный.печать линия Serial.println() (пример 3.81), можно для отправки данных через последовательный порт. Основное различие между функциями заключается в том, что функция Serial.println() также отправляет вместе с данными символы возврата каретки и новой строки.

Serial.print(data);
//data == Может быть строкой
Serial.print(данные, формат);
//формат == "DEC" Десятичный, "HEX" шестнадцатеричный или "OCT" восьмеричный
Пример 3.81: последовательный.печать Serial.print() против последовательный.печать линия Serial.println() - Описание.
57
Пример использования функций Serial.print() и Serial.println() можно увидеть в Примере 3.82. Как описано в примере 3.81, мы можем отправить строку или данные с помощью десятичных, шестнадцатеричных и восьмеричных представлений.
процедура настройка(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
}
не пустой цикл(){
Serial.flush(); //Удаляет содержимое входного буфера
Serial.print("B"); //Отправляет строку "B"
Serial.println("B"); //Строка "B" + возврат каретки + новая строка
(.....) //Программный код
}
Пример 3.82: Serial.print() против Serial.println() - Пример.
3.11.6 Серийный номер\последовательный.запись Serial.write
Используя функцию Serial.write() (пример 3.83), можно отправлять двоичные данные через последовательный порт. Двоичные данные могут передаваться как в виде одного байта, так и в виде набора байтов.
Serial.write(значение);
//"значение" записывается в двоичном формате
Serial.write(строка);
//"строка" в виде набора байтов
Serial.write(вектор, размер);
//Определяем вектор, который будет отправлен, и его размер
Пример 3.83: последовательный.запись Serial.write() - Описание.
Переменная value, описанная в примере 3.83, определяет значение, которое будет отправлено в двоичном формате через последовательный порт. В качестве альтернативы, данные могут быть отправлены с использованием строки в виде набора байт или с определением вектора и его соответствующего размера.
58
4 ДОПОЛНИТЕЛЬНЫЕ\ПРОДВИНУТЫЕ РЕСУРСЫ
В этой главе мы рассмотрим расширенные ресурсы, необходимые для большинства приложений, которые упрощают проектирование систем и создание прототипов. Расширенные ресурсы, рассмотренные в этой главе, не являются исчерпывающим перечнем существующих, поскольку новые появляются практически ежедневно. В этой главе также будут описаны внешние библиотеки, которые упрощают реализацию. Эти библиотеки можно легко загрузить с помощью менеджера библиотек, если они недоступны непосредственно в среде Arduino IDE. Эта глава разделена на следующие разделы:
• Флэш-память (раздел 4.1) - В этом разделе описываются некоторые функции, которые может использоваться для чтения и записи непосредственно из флэш-памяти;
• Память EEPROM (раздел 4.2) - В этом разделе описаны некоторые функции, которые можно использовать для чтения и записи непосредственно из памяти EEPROM;
• Серводвигатель (раздел 4.3) - В этом разделе описывается интерфейс, который можно легко использовать для управления серводвигателями;
• Программная последовательная связь (раздел 4.4) - В этом разделе подробно описывается реализация программной последовательной связи, которая может быть использована для увеличения числа возможных одновременных подключений к внешним устройствам (преодоления аппаратных ограничений).;
59
• Введение в визуальный дизайн (раздел 4.5) - В этом разделе кратко описывается, как Arduino можно использовать для визуального дизайна, сочетая протокол firmata [50] с использованием некоторого стороннего программного обеспечения для обработки [51];
• Получение сигнала (раздел 4.6) - В этом разделе рассматриваются теоретические концепции получения сигнала и то, как Arduino это выполняет.
4.1 Флэш-память
В микроконтроллере (подраздел 2.1.2) объем доступной памяти SRAM обычно намного меньше, чем объем доступной флэш-памяти. Как описано в Подраздел 2.1.3, Arduino не является исключением, и доступная память легко это становится ограничением в программах, использующих большое количество переменных. Учитывая это, очевидным решением было бы использовать флэш-память для хранения некоторых переменных. Единственным ограничением в использовании флэш-памяти является то, что запись может выполняться только во время загрузки программы. Это означает, что мы должны использовать Flash только для хранения постоянных переменных, чтобы не занимать место в SRAM без необходимости. Для упрощения взаимодействия с флэш-памятью будет использоваться библиотека Flash [52], которая изначально не входит в состав программного обеспечения IDE, но может быть легко загружена с помощью Менеджера библиотек Arduino. Эта библиотека упрощает операции записи (подраздел 4.1.1) и чтения (подраздел 4.1.2), делая их простыми в выполнении.
4.1.1 Запись данных

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

FLASH_STRING(имя, данные); //"данные" - это строка
FLASH_ARRAY(тип, имя, данные); //"type" определяет тип "данных"
FLASH_TABLE(тип, имя, столбцы, данные); //"columns" определяет ширину таблицы
FLASH_STRING_ARRAY(имя, PSTR(данные), PSTR(столбец данных), ...); //Запись в формате PSTR
Пример 4.1: Запись в библиотеку Flash - описание.
60
Используемая библиотека напрямую не поддерживает создание вектора строк. Вместо, он создается в SRAM, векторе, содержащем адреса отдельных строк , сохраненных во Flash. Это приводит к тому, что эта инструкция занимает 2 байта для каждой сохраненной строки [52]. Процесс записи переменных во флэш-память описан в примере 4.2.

#включить <Flash.h> //Включить используемую библиотеку
FLASH_STRING(тест, "Песанья");
FLASH_ARRAY(int, тесты_1, 2,2,3,0,5);
FLASH_TABLE(int, teste_2, 2, {0x00, 0x00}, {0x24, 0x34});
процедура настройка(){
FLASH_STRING_ARRAY(тест_3, PSTR("N"), PSTR("P"));
//FLASH_STRING_ARRAY должен быть объявлен внутри функции - запись в формате PSTR
(.....) //Программный код
}
не пустой цикл(){
(.....) //Программный код
}
Пример 4.2: Создание Flash-библиотеки - Пример.
4.1.2 Считывание данных
Как описано в предыдущем подразделе, чтение данных также важно при разработке любого приложения, поскольку оно является основой рабочего процесса любой программы. При использовании этой библиотеки этот процесс становится простым, как описано в примере 4.3.

имя[index]; //"index" определяет позицию считываемого вектора
sizeof(name); //Возвращает значение размера переменной "name"
имя.length(); //Возвращает длину переменной "name".
name.rows(); //Возвращает количество строк переменной FLASH_TABLE "name"
name.cols(); //Возвращает переменную FLASH_TABLE "name" количество столбцов
name.copy(переменная, размер, смещение); //Копирует содержимое переменной "name"
name.print(последовательный); //Печатает переменную, используя последовательную связь
Пример 4.3: Чтение - описание библиотеки Flash.
61
Доступ к данным из Flash аналогичен простоте использования векторов, что является одной из сильных сторон этой библиотеки. При использовании этой библиотеки существует больше синтаксиса [52], но самый важный из них представлен здесь. Процесс считывания переменных из флэш-памяти описан в примере 4.4.

#включить <Flash.h> //Включить используемую флэш-библиотеку
FLASH_STRING(тест, "Песанья");
FLASH_ARRAY(int, тесты_1, 2,2,3,0,5);
FLASH_TABLE(int, teste_2, 2, {0x00, 0x00}, {0x24, 0x34});
недействительная настройка(){
Serial.begin(9600); //Инициализация последовательной связи - проверка скорости
передачи данных в бодах_2.print(Serial);
Serial.println(); //Отправка табличных данных
Serial.println(teste_2.rows()); //Отправить количество строк таблицы
Serial.println(teste_2.cols()); //Отправить количество столбцов таблицы
Serial.println(sizeof(teste_2)); //Отправить
символическую переменную размера таблицы[24] = {0}; // Скопировать целевую переменную
проверить.скопировать(извлечь, 1, 1); //Скопировать 1 символ со смещением 1
(.....) //Программный код
}
аннулировать цикл(){
(.....) //Программный код
}
Пример 4.4: Чтение из библиотеки Flash - Пример.
4.2 Память EEPROM
Как описано в подразделе 2.1.3, объем оперативной памяти Arduino Uno Rev 3 составляет 1 килобайт [12, 15], а Arduino Mega Rev 3 - 4 килобайта [13, 20]. Преимуществом этого типа памяти является то, что она сохраняет информацию даже после выключения или сброса, поскольку является энергонезависимой. Еще одним преимуществом является возможность сохранять информацию во время выполнения программы, чего не происходит с флэш-памятью
62
memory (раздел 4.1). Эта библиотека изначально включена в Arduino IDE без ее загрузки с помощью Arduino library manager. Эта библиотека упрощает запись (Подраздел 4.2.1) и операций чтения (подраздел 4.2.2), что упрощает их выполнение. Основным ограничением в использовании памяти EEPROM является ограничение циклов чтения/записи [15, 20].
4.2.1 Запись данных

Сохранение данных имеет важное значение при разработке любого приложения, поскольку оно является основой рабочего процесса любой программы. Используя эту библиотеку, этот процесс становится простым, как описано в Примере 4.5. Мы можем сохранить значение от 0 до 255 (28-1), соответствующее 1 байту в каждой позиции памяти.
EEPROM.write(адрес, данные); //"Адрес" - целое число, "данные" - байт.
EEPROM.read(адрес); //"Адрес" - это целое значение
Пример 4.5: Описание записи в библиотеку EEPROM.
Процесс записи переменных в память EEPROM представлен в примере 4.6. Как описано, запись в память EEPROM может производиться во время выполнения программы (функция цикла). Среднее время записи составляет около 3,3 миллисекунд, при ожидаемом жизненном цикле около 100 тысяч циклов записи [15, 20].

#включить<EEPROM.h> //Включить используемую библиотеку EEPROM
в void setup(){
EEPROM.write(1,1); //Записать значение 1 в позицию памяти 1
(.....) //Программный код
}
не пустой цикл(){
EEPROM.write(2,1); //Записать значение 1 в позицию памяти 2
(.....) //Программный код
}
Пример 4.6: Пример написания библиотекой EEPROM.
63
4.2.2 Считывание данных
Чтение данных имеет важное значение при разработке любого приложения, поскольку оно является основой рабочего процесса любой программы. Используя эту библиотеку, этот процесс становится простым, как описано в примере 4.7. Мы можем считывать значение от 0 до 255 (28-1), соответствующее 1 байту в каждой позиции памяти.

EEPROM.read(адрес); //"Адрес" - это целое значение
Пример 4.7: Чтение библиотеки EEPROM - Описание.
Процесс чтения переменных из памяти EEPROM описан в примере 4.8. Как описано выше, запись в память EEPROM может быть произведена во время выполнения нашей программы выполнение (функция цикла). Мы должны постоянно считывать содержимое EEPROM, чтобы учитывать самое последнее значение в памяти.

#включить<EEPROM.h> //Включить используемую библиотеку EEPROM
int r=0; //Целочисленная переменная "r", инициализируемая значением "0"
int r_2=0; //Целочисленная переменная "r", инициализируемая значением "0"
(.....) //Инициализация глобальных переменных
аннулирует установку(){
EEPROM.write(1,1); //Запишите значение 1 в позицию памяти 1
EEPROM.write(2,4); //Записать значение 4 в позицию памяти 2
(.....) //Программный код
}
не пустой цикл(){
EEPROM.write(2,1); //Записать значение 1 в позицию памяти 2
r = EEPROM.read(1); //Первая позиция памяти EEPROM сохраняется в "r"
EEPROM.write(2,24); //Значение 24 записывается в позицию памяти 2
r_2 = EEPROM.read(2); //Позиция 2 в памяти EEPROM сохраняется в "r_2"
(.....) //Программный код
}
Пример 4.8: Чтение библиотекой EEPROM - Пример.
64
4.3 Серводвигатель

Стандартный серводвигатель - это исполнительный механизм, который позволяет точно регулировать его положение, скорость и ускорение в соответствии с входным сигналом [53], как описано в Рис. 4.1. В зависимости от желаемого режима использования сервопривод будет сохранять свое положение, если этот сигнал остается постоянным. Серводвигатели широко используются, например, в робототехнике [54, 55, 56], и имеют множество возможных применений.

Рисунок 4.1: Серводвигатель - иллюстрация (слева) и упрощенная схема (справа).

Серводвигатель, как описано на рис. 4.1, имеет три входа: (i) источник питания (5 В для стандартных серводвигателей), (ii) заземления и (iii) входного сигнала. Входным сигналом будет ШИМ-сигнал, рабочий цикл которого пропорционален требуемому положению сервопривода (Подраздел 2.1.4). Существует множество серводвигателей с линейным и угловым перемещением, которые также могут быть рассчитаны на непрерывное вращение [53]. Как показано на рисунке 4.2, схема управления управляет двигателем постоянного тока на основе информации, полученной с помощью потенциометра, и входного сигнала. Потенциометр непосредственно соединен с осью вращения, что обеспечивает непрерывную обратную связь о положении оси.
Множество возможных применений серводвигателей делают эту тему незаменимой для любого любителя электроники. Для создания этого интерфейса будет использоваться внешняя библиотека, но также возможно управлять серводвигателем напрямую с помощью аналоговых контактов. Эта библиотека изначально включена в Arduino IDE без загрузки с помощью Arduino library manager. Она упрощает настройку серводвигателя (подраздел 4.3.1), управление (подраздел 4.3.2) и считывание угла наклона (Подраздел 4.3.3) -операции, упрощающие их выполнение.
65
шпонка вывода
приводящие шестеренки
серво коробка
цепь управления
потенциометр
мотор
Фигура 4.2: Серводвигатель - реальное представление.
4.3.1 Конфигурация
Чтобы начать настройку, вспомогательная угловая переменная должна быть назначена выводу Arduino для создания конфигурации серводвигателя. Как описано в примере 4.9, после создания переменной мы можем легко установить вывод для управления серводвигателем.

servo_name сервопривода; //Создание переменной servo_name серводвигателя
servo_name.attach(вывод) //Установка номера "вывода" серводвигателя
servo_name.attach(вывод, минимальный, максимальный) //Необязательно
//"минимальная" длительность импульса при минимальном угле - 0 градусов (микросекунды)
//"максимальная" длительность импульса при максимальном угле - 180 градусов (микросекунды)
servo_name.detach() //Отсоединить переменную серводвигателя от ее контакта
Пример 4.9: Описание конфигурации библиотеки серводвигателей.
66
Процесс создания переменных, присоединения и отсоединения описан в Примере 4.10. Использование этой библиотеки упрощает управление серводвигателем, поскольку требуется только настроить нужный управляющий контакт.

#включить<Servo.h> ////Включить используемую библиотеку сервоприводов
Пример сервопривода; //Переменная сервопривода "пример".
Пример сервопривода2; //Переменная сервопривода "пример2"
(.....) //Инициализация глобальных переменных
аннулирует настройку(){
пример.присоединение(10); //Устанавливает вывод серводвигателя на "10"
пример2.присоедините(9); //Устанавливает вывод серводвигателя на "9"
(.....) //Программный код
}
не пустой цикл(){
пример.отсоединить(); // Отсоединить переменную серводвигателя от контакта "10"
пример 2.отсоединить(); // Отсоединить переменную серводвигателя от контакта "9"
(.....) //Программный код
}
Пример 4.10: Конфигурация библиотеки серводвигателей - Пример.
4.3.2 Контроль
После выполнения настройки мы можем быстро переместить ось серводвигателя в нужное положение (пример 4.11). Стандартный сервопривод будет управляться с помощью желаемого угла ориентации вала (от 0 до 180 градусов). Непрерывное вращение сервопривод будет управляться с заданным направлением и скоростью (от 0 до 180 оборотов).

Имя_серво сервопривода; //Создание переменной для серводвигателя "имя_серво"
имя_серво.запись (угол) //Стандартный - переход к "углу" (градусы)
servo_name.write(s) //Непрерывное вращение - "s" означает скорость вращения
Пример 4.11: Управление библиотекой серводвигателей - Описание.
67
Процесс управления серводвигателем описан в примере 4.12. Использование этой библиотеки упрощает управление серводвигателем, поскольку требуется только настроить нужный управляющий контакт.

#включить<Servo.h> ////Включить используемую библиотеку сервоприводов
Пример сервопривода; //Переменная сервопривода "пример"
Пример сервопривода_2; //Переменная сервопривода "пример_2"
(.....) //Инициализация глобальных переменных
аннулирует установку(){
пример.присоединить(10); //Устанавливает вывод серводвигателя на "10"
пример_2.присоединить(9); //Устанавливает вывод серводвигателя на "9"
(.....) //Программный код
}
цикл аннулирования(){
example.write(0); //Стандартный сервопривод - перемещает ось на "0" градусов
example_2.write(90); //Сервопривод непрерывного вращения - останавливает свое вращение
(.....) //Программный код
}
Пример 4.12: Управление библиотекой серводвигателей - Пример.
4.3.3 Угол считывания
Во время выполнения программы и в зависимости от желаемого применения, получение последней управляющей команды, используемой для управления серводвигателем, может быть важным, как описано в примере 4.13.

Servo имя_серво; //Создание переменной серводвигателя "имя_серво".
int angle = servo_name.read() //Возвращает последнее значение функции записи
Пример 4.13: Чтение - описание библиотеки серводвигателей.
Процесс получения последнего значения, переданного с помощью функции записи серводвигателя, описан в примере 4.14. Например, иногда, во время выполнения кода
68
и при использовании некоторых приращений или значения угла поворота оси серводвигателя, пропорционального в случае ввода последней команды разобраться в ней непросто. Эта функция упрощает получение этой информации.

#включить<Servo.h> ////Включить используемую библиотеку Servo
Пример сервопривода; //Переменная сервопривода "example"
int angle=0; //Целочисленная переменная "angle" инициализирована значением "0"
(.....) //Инициализация глобальных переменных
аннулирована setup(){
пример.присоедините(10); //Устанавливает вывод серводвигателя на "10"
(.....) //Программный код
}
аннулирует цикл(){
пример.запись(угол); //Стандартный сервопривод - Перемещение оси на угол "0"
градусов
угол = пример.чтение()+1; //Увеличение на один градус
(.....) //Программный код
}
Пример 4.14: Пример чтения библиотеки серводвигателей.
4.4 Последовательная связь\подача
При разработке системы возможно, что нам потребуется использовать другие контакты для последовательной связи, отличные от стандартных. Мы можем использовать дополнительную библиотеку для упрощения этой реализации, расширяя коммуникационные возможности платы Arduino за счет реализации последовательной связи на большем количестве контактов. Как описано в подразделе 2.1.2, стандартная последовательная связь является синхронной и реализуется с использованием USART, как показано на рисунке 4.3.
При реализации последовательной связи мы можем иметь синхронные (рис. 4.3) или асинхронные (рис. 4.4) операции с различными режимами работы. Синхронная связь основана на реализации ведущего и ведомого устройств,
69
мастер\ведущий
слуга\ведомый
чип отбор
данные
часы
Рисунок 4.3: Синхронная последовательная связь - иллюстрация.
при этом ведущий сервер определяет скорость передачи данных и синхронизирует поток данных с помощью тактового сигнала. Асинхронная связь основана на использовании отправителя и получателя (которые могут меняться со временем) без синхронизации скорости передачи данных.
Отправитель
получатель
данные
земля
Рисунок 4.4: Асинхронная последовательная связь - иллюстрация.
Можно программно имитировать асинхронную последовательную связь, используя дополнительную библиотеку. Поскольку мы не используем аппаратное обеспечение USART, у нас не будет входного буфера, что приведет к потере всей информации, которую мы не прочитали при ее получении. Эта библиотека изначально включена в Arduino IDE без ее загрузки с помощью Arduino library manager. Это упрощает последовательную настройку программного обеспечения (Подраздел 4.4.1), чтобы считывать (подраздел 4.4.2) и передавать (подраздел 4.4.3) данные, что упрощает их выполнение.
70
4.4.1 Конфигурация

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

SoftwareSerial name; //Имя созданной последовательной переменной программного обеспечения.
Имя программного обеспечения = SoftwareSerial(Pin_1, Pin_2);
//"Pin_1" - это pin-код приемника (Rx)
//"Pin_2" - это pin-код для передачи (Tx)
 имя.начало (скорость передачи); // Инициализация последовательной связи
Пример 4.15: Конфигурация библиотеки последовательного интерфейса программного обеспечения - Описание.
Процесс настройки последовательной связи программного обеспечения описан в Примере 4.16. При выполнении этой настройки также необходимо настроить скорость передачи данных в бодах, которая в идеале должна быть меньше или равна 9600 бод, и определить используемые контакты в качестве входных и выходных.

#включить<SoftwareSerial.h> ////Включить используемую библиотеку последовательных файлов
Пример SoftwareSerial = SoftwareSerial(4,5); //Rx - вывод 4 и Tx - вывод 5
(.....) //Инициализация глобальных переменных
void setup(){
pinMode(4,INPUT); //Позволяет установить вывод 4 в качестве "ВХОДНОГО".
pinMode(5,ВЫХОД); //Позволяет установить вывод 5 в качестве "ВЫХОДНОГО сигнала".
пример.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
}
не пустой цикл(){
(.....) //Программный код
}
Пример 4.16: Конфигурация последовательной библиотеки программного обеспечения - Пример.
71
4.4.2 Чтение данных
Чтение данных имеет важное значение при разработке любого приложения, поскольку оно является основой рабочего процесса любой программы. Используя эту библиотеку, этот процесс становится простым, как описано в примере 4.17. Перед получением данных важно настроить pin-коды, используемые для осуществления обмена данными.

Имя программного обеспечения = SoftwareSerial(Pin_1, Pin_2).;
//"Pin_1" - это pin-код приемника (Rx).
//"Pin_2" - это pin-код передачи (Tx)
char received //Инициализация переменной char "received"
received=name.read(); //Полученное значение сохраняется в "received".
Пример 4.17: Библиотека последовательного чтения программного обеспечения - Описание.

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

#включить<SoftwareSerial.h> ////Включить используемую библиотеку последовательных файлов
Пример SoftwareSerial = SoftwareSerial(4,5); //Rx - вывод 4 и Tx - вывод 5
получен символ; //Инициализация переменной типа char "получено"
(.....) //Инициализация глобальных переменных
void setup(){
pinMode(4,INPUT); //Позволяет установить вывод 4 в качестве "ВХОДНОГО".
pinMode(5,ВЫВОД); //Позволяет установить вывод 5 в качестве "ВЫВОДА"
example.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
}
void loop(){
received=example.read(); //Полученное значение сохраняется в "received".
(.....) //Программный код
}
Пример 4.18: Последовательная библиотека программного обеспечения считывает данные - Пример.
72
4.4.3 Передавать данные
Передача данных необходима при разработке любого приложения, поскольку она является основой рабочего процесса любой программы. Используя эту библиотеку, этот процесс становится простым, как описано в примере 4.19. Перед передачей данных важно настроить контакты, используемые для осуществления обмена данными.

Имя программного обеспечения = SoftwareSerial(Pin_1, Pin_2);
//"Pin_1" - это pin-код приемника (Rx)
//"Pin_2" - это имя pin-кода для передачи (Tx)
имя.print(данные); //Отправляет имя "data"
имя .println(данные); //Отправляет "data" + возврат каретки + новая строка
Пример 4.19: Последовательная библиотека программного обеспечения для передачи данных - Описание.
Процесс передачи данных с использованием программного последовательного соединения описан в примере 4.20. Поскольку программное обеспечение реализует эту передачу, рекомендуется, чтобы скорость передачи данных была меньше или равна 9600 бод во избежание ошибок.

#включить<SoftwareSerial.h> ////Включить используемую библиотеку последовательных файлов
Пример SoftwareSerial = SoftwareSerial(4,5); //Получен символ Rx - вывода 4 и Tx - вывода 5
; //Инициализация переменной char "получено"
(.....) //Инициализация глобальных переменных
void setup(){
pinMode(4,INPUT); //Позволяет установить вывод 4 в качестве "ВХОДНОГО".
pinMode(5,ВЫХОД); //Позволяет установить вывод 5 в качестве "ВЫХОДНОГО сигнала".
пример.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
(.....) //Программный код
}
void loop(){
received=example.read(); //Полученное значение сохраняется в "received".
пример.print(получено); //Передается значение "получено"
(.....) //Программный код
}
Пример 4.20: Передача данных последовательной библиотекой программного обеспечения - Пример.
73
4.5 Введение в визуальный дизайн
Основная цель этого раздела - кратко описать, как можно легко создать визуальный дизайн\проект. Протокол firmata [50] изначально был создан для реализации универсального протокол обмена данными между Arduino и сторонним программным обеспечением. Программное обеспечение может считывать и отправлять данные через последовательный порт для управления Arduino. При проектировании системы возможна адаптация библиотеки к каждому пользовательскому приложению, и такая гибкость является очевидным преимуществом библиотеки.
Интерфейс Arduino с программным обеспечением для обработки данных с открытым исходным кодом [51] — это реализация, которую обычно изучают художники и дизайнеры, интересующиеся электроникой. Это программное обеспечение позволяет осуществлять визуальное программирование, при котором графические объекты создаются с помощью инструкции по программированию. Эти графические объекты, такие как квадраты, круги или линии, могут быть простыми. Тем не менее, они также могут обладать высокой сложностью, что позволяет визуализировать сложные объекты и формы для создания произведений искусства. Бенджамин Фрай и Кейси Реас разработали это программное обеспечение во время учебы в 2001 году [51]. Это полезный программный инструмент с открытым исходным кодом [57], который может быть легко использован для визуального проектирования или реализован в других областях для обеспечения взаимодействия человека и машины.

Рисунок 4.5: Hello World - Обработка [51].

Рисунок 4.6: Пример графических объектов- обработки.
74
4.6 Получение сигнала
Получение сигналов - одна из наиболее важных тем, касающихся электроники, поскольку большинство интерфейсов и приложений основаны на глубоких знаниях в этой области. В этом разделе будут рассмотрены теоретические концепции получения сигналов (подраздел 4.6.1) и то, как Arduino выполняет это (подраздел 4.6.2).
4.6.1 Теоретические концепции

При выполнении обработки мы обычно рассматриваем непрерывный сигнал, дискретизированный с определенной частотой дискретизации. Чтобы выполнить дискретизацию аналогового сигнала, мы должны использовать аналого-цифровой преобразователь A/D, как описано на рисунке 4.7. Аналого-цифровой преобразователь A/D- это [58]: (i) устройство дискретизации или преобразования сигнала из непрерывного в дискретный (C/D), (ii) квантователь и (iii) кодировщик.
Непрерывный\дискретный
квантователь
кодировщик
Рисунок 4.7: Аналого-цифровой преобразователь - иллюстрация.
Сэмплер /пробник образцов (рис. 4.7) позволяет преобразовывать аналоговый сигнал xa (t) в дискретную последовательность x(n), которая создается путем сохранения значений xa (t) с постоянными интервалами времени Ts . Это соотношение может быть описано формулой:

Квантователь (рис. 4.7) присваивает дискретное значение амплитуды каждому из отсчетов, полученных с помощью дискретизатора. Дискретные амплитуды делятся на интервалы амплитуды ;, и амплитуда отсчетов x(n) описывается в соответствии с возможными значениями. Возможное количество интервалов зависит от количества битов, то есть большее число соответствует более высокой точности.
75
После квантования кодер (рис. 4.7) присваивает двоичную последовательность каждому выборочному и количественному значению, полученные соответствующие цифровые значения для аналоговой входной последовательности.
Выбор частоты дискретизации имеет важное значение, поскольку мы должны гарантировать, что с помощью аналого-цифрового преобразования А/D мы можем получить достоверное представление об исходном сигнале. Чтобы выбрать частоту дискретизации, мы должны рассмотреть теорему Найквиста (sampling theorem теорема образцов) представлено [58, 59, 60]:

При соблюдении теоремы о выборке (уравнение 4.2) исходный сигнал может быть восстановлен по его выборкам с помощью простого фильтра нижних частот без необходимости возникновения псевдонимов [58, 60]. Псевдонимы могут быть охарактеризованы как искажения при восстановлении сигнала из-за низкой частоты дискретизации [61]. На рисунке 4.8 представлен пример того, что происходит, когда теорема о выборке не соблюдается, поскольку входной сигнал (обозначенный красным цветом) отбирается с частотой дискретизации, меньшей минимальной частоты для восстановления исходного сигнала (уравнение 4.2). Результат аналого-цифрового преобразования A/D представлен синим цветом, где мы можем видеть наличие наложения псевдонимов, получая восстановленный сигнал, который не соответствует исходному.

Рисунок 4.8: Сглаживание - Иллюстрация.
4.6.2 Анализ Arduino
После краткого описания теоретических концепций, лежащих в основе сбора сигналов, важно изучить, как это выполняется микроконтроллером Arduino. Используемые
76
микроконтроллеры семейства Arduino имеют аналого-цифровые преобразователи A/D с разрешением 10 бит [1, 15, 20]. При использовании этого разрешения входное значение в диапазоне от 0 до 5 В будет соответствовать десятичным значениям в диапазоне от 0 до 1023 (210 -1) и разрешающей способности приблизительно 5 мВ. Первое аналого-цифровое преобразование занимает 25 тактов, поскольку для этого требуется для выполнения инициализации аналого-цифрового преобразователя, в то время как для следующих требуется 13 тактов [15, 20]. Если мы рассмотрим частоту 1 МГц и после инициализации аналого -цифрового преобразователя получим следующие:
Примеры /образцы\выборка

Если мы имеем частоту дискретизации 77 кГц и учитываем уравнение 4.2, то максимальная частота сигнала, которая может быть дискретизирована, должна быть меньше или равна 38,5 кГц, чтобы соблюсти теорему о дискретизации и избежать наложения псевдонимов. Системная частота Arduino составляет 16 МГц. Однако это не входные часы аналого-цифрового преобразователя A/D. Системные часы делится на коэффициент деления (прескалер), и это будет входной тактовый сигнал аналого-цифрового преобразователя A/D, как показано на рисунке 4.9.
a/d enum старт
такт
сброс
7 бит а\д прескалер
а\д источник такта

Рисунок 4.9: Прескалер аналого-цифрового преобразователя [15].
77
Коэффициент деления прескалера может быть определен путем изменения содержимого битов ADPS0, ADPS1 и ADPS2 из регистра ADCSRA, как описано на рисунке 4.10. Возможные комбинации разрядов приведены в таблице 4.1.

Рисунок 4.10: Регистр ADCSRA [15].

Таблица 4.1: Комбинации коэффициентов деления [15].
 ADPS2ADPS1ADPS0 Коэффициент деления (предварительный масштабатор\коэффициент)
000 2
001 2
010 4
011 8
100 16
101 32
110 64
111 128
Как описано выше, и с учетом определенного коэффициента деления, а/д источник синхронизации (рис. 4.9) будет дана:
А\д такт
Системные часы
Участник дивизиона\коэффициент деления
Используя уравнение 4.4, мы можем получить все возможные источники тактовых импульсов аналого-цифрового преобразователя А\D в  МГц, как описано в таблице 4.2. Анализируя таблицу 4.2, мы можем сделать вывод, что максимальная полученная частота дискретизации составляет приблизительно 8 МГц. Это означает, что максимальная частота входного сигнала составляет 4 МГц, чтобы избежать наложения. Однако значения, представленные в таблице 4.2, являются только теоретическими. Фактические значения соответствуют значениям значительно ниже, чем показано в таблице 4.3.
78

Таблица 4.2: Возможные значения тактовой частоты аналого-цифрового преобразователя.
Коэффициент деления А\д такт(МГц)
2 8
4 4
8 2
16 1
32 0.5
64 0.25
128 0.125
Синтаксис, который может изменить коэффициент деления, описан в примере 4.21. Этот синтаксис служит не только для изменения содержимого реестра ADCSRA, поскольку тот же синтаксис может изменить содержимое любого регистра микроконтроллера. Доступные регистры, а также их содержимое и функции указаны в техническом описании соответствующего микроконтроллера [15, 20].
//Определение функций — упрощение
#ifndef  если неопределен cbi
#определить cbi(sfr, бит) (_SFR_BYTE(sfr) &= ~_BV(бит))
#окончание
#ifndef sbi
#определить sbi(sfr, бит) (_SFR_BYTE(sfr) |= _BV(бит))
#endif конец если
sbi(Реестр,бит); //Установить "бит" в "реестре"
cbi(Реестр,бит); //Убрать "бит" в "реестре"
Пример 4.21: Коэффициент деления (прескалер) — Описание.

Иллюстрацию конфигурации реестра ADCSRA можно увидеть в примере 4.22. В этом примере она также реализована в функции loop - наборе функций, которые могут измерять время, необходимое для выполнения аналого-цифрового преобразования. Полученный результат средняя частота дискретизации из 1000 отсчетов представлена в таблице 4.3, где мы можем видеть, что максимальная полученная экспериментально частота дискретизации составляет – 125 кГц.
79

#ifndef если не определен cbi
#определить cbi(sfr, бит) (_SFR_BYTE(sfr) &= ~_BV(бит))
#endif конец если
#ifndef воо
#определить sbi(sfr, бит) (_SFR_BYTE(sfr) |= _BV(бит))
#
настройка endif void(){
пример.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
sbi(ADCSRA, ADPS2); //Установить бит ADPS2 в реестре ADCSRA
cbi(ADCSRA, ADPS1); //Очистить бит ADPS1 в реестре ADCSRA
cbi(ADCSRA, ADPS0); //Очистить бит ADPS0 в реестре ADCSRA
(.....) //Программный код
}
цикл аннулирования(){
b = micros() //Время в микросекундах с момента запуска программы
a = analogRead(0); //Значение аналогового вывода 0 присвоено "a"
c = micros(); //Время в микросекундах с момента запуска программы
Serial.print(c-b); //Отправка значения "c-b" - Время выборки
(.....) //Программный код
}
Пример 4.22: Коэффициент деления (прескалер) — Пример.

Таблица 4.3: Экспериментальные результаты аналого-цифрового преобразования.
Частота дискретизации коэффициентов деления (кГц)
128–8
64–16
32–31
16–50
8–63
4–83
2–125
80
5 ВЫВОДЫ
Этот документ предназначен для того, чтобы открыть двери для более глубокого понимания Arduino и не собирается соответствовать всем существующим знаниям в этой области. Для повышения квалификации и приобретения дополнительных знаний необходимо гарантировать постоянные исследования и разработки. Кто бы мог подумать, что академический проект зайдет так далеко? Вероятно, никто бы не подумал. Этот реальный пример подчеркивает настойчивость и преданность делу, необходимые для того, чтобы этот проект стал успешным во всем мире. Чтобы добиться успеха, необходимо постоянно стремиться к знаниям, потому что знания не занимают много места в памяти.
Даже с течением лет и с учетом первоначального подтвержденного быстрого роста, платформа развивалась годами, но по-прежнему используется во многих приложениях. Она идеально подходит для обучения и энтузиастов электроники. Обширное сообщество Arduino,
которое растет с каждым днем, часто вносит свой вклад, предлагая простые руководства и реализации, которые могут быть полезны во время обучения.
Важно распространять знания, и в будущем будет разработано больше руководств по более сложным темам, которые будут доступны сообществу Arduino. Приветствуются любые материалы, обмен опытом и заметки.  Чтобы связаться со мной, используйте контактные данные, указанные на обложке.
Разум есть роскошь
81 БИБЛИОГРАФИЯ
[1] Arduino. Веб-сайт Arduino, 2022. URL: https://www.arduino.cc/.
[2] Нуну Песанья Сантос. Знакомство с Arduino и повторение приключений. Эскола
Военно-морской флот, 2009. doi:10.13140/RG.2.2.17609.08807.
[3] Фабио Нилветти и Марко Си Де Симоне. Испытательный стенд для приложений идентификации и контроля . В программе и материалах Международной конференции по
проблемам вибрации (ICOVP-2013), стр. 9-12, 2013.
[4] Угур Сари, Хусейн Мирач Пекташ, Омер Фарук Шен и Харун Челик.
Развитие алгоритмического мышления с помощью физических вычислений.
с помощью arduino в stem-образовании. Образование и информационные технологии,
страницы 1-21, 2022. doi:10.1007/s10639-022-10893-0.
[5] Йошихару Като. Splish: визуальная среда программирования для arduino , ускоряющая работу с физическими вычислениями.
В 2010 году состоялась Восьмая Международная
Конференция по созданию, подключению и совместной работе с помощью вычислений,
стр. 3-10. IEEE, 2010. doi:10.1109/C5.2010.20.
[6] Йоханнес Брауманн и Сигрид Брелл-Коккан. Цифровые и физические вычисления
для промышленных роботов в архитектуре. взаимодействие arduino с промышленными
82робота. По ту сторону кодов и пикселей: Материалы 17-й Международной
Конференция по компьютерному архитектурному проектированию в Азии, Гонконг
Конг, страницы 317-326, 2012.
[7] Ардуино. Форум Arduino, 2022. URL: https://forum.arduino.cc/.
[8] Пьер Э. Герцог и Артур Дж. Сварт. Arduino — программа, позволяющая студентам инженерных специальностей
добиваться успехов в учебе с помощью модуля, основанного на проектировании. В 2016 году IEEE Global
Конференция по инженерному образованию (EDUCON), стр. 66-73. IEEE, 2016. do
i:10.1109/EDUCON.2016.7474533.
[9] Педро Плаза, Элио Санкристобаль, Герман Карро, Мануэль Бласкес, Феликс Гарсия.-
Лоро, Серхио Мартин, Клара Перес и Мануэль Кастро.
Arduino как образовательный инструмент для внедрения робототехники. В 2018 году Международная конференция IEEE по преподаванию, оценке и обучению в инженерных целях (TALE), стр. 1-8.
IEEE, 2018. doi:10.1109/TALE.2018.8615143.
[10] Хари Кишан Кондавити, Нандиш Кумар Кумаравелу, Санни Даял
Ванамбатина, Судха Эллисон Мате и Сузила Ваппанги. Систематический
обзор литературы по созданию прототипов с помощью arduino: приложения, проблемы,
преимущества и ограничения.
Computer Science Review, 40: 100364, 2021.
doi:10.1016/j.cosrev.2021.100364.

[11] Ахмад Адаму Галадима.
Arduino - это инструмент обучения.
В 2014 году 11-Я Международная Конференция По Электронике, Вычислительной Технике И Компьютерным Технологиям
(ICECCO), страницы 1-4. IEEE, 2014. doi: 10.1109/ICECCO.2014.6997
577.
[12] Ардуино. Arduino One Rev3, 2022 год выпуска. URL: https://store.arduino.cc
/ товары/arduino-one-rev3?_гл.
[13] Ардуино. Arduino mega 2560 rev3, 2022 год выпуска. URL: https://store.ардуин
o.cc/products/arduino-mega-2560-rev3?_gl .
[14] Святой Дух. Введение в Arduino. Военно-морское училище, 2008 год. дои:
10.13140/РГ.2.2.16840.80649.
83 [15] Корпорация Atmel. ATMEGA328P-8-разрядный микроконтроллер avr с 32 тыс. байт
встроенная программируемая вспышка\флеш. Корпорация Atmel, 2015 год. URL: HTTPS://
ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-A
utomotive-Микроконтроллеры-Таблица данных atmega328p_.pdf.
[16] Р. J. Митчелл. Микропроцессорные системы: Введение. Издательство "Ред Глоб Пресс"
Лондон, Бостон, Массачусетс, 1995.
[17] Тяньхун Пан И И Чжу.
Проектируйте встраиваемые системы с помощью Arduino.
Спрингер, 2018.
[18] Димосфен и Боланакис. Обзор исследований в области обучения работе с микроконтроллерами.
Журнал Иберо-Американских Технологий IEEE, 14 (2): 50-57,
2019. doi: 10.1109/РИТА.2019.2922856.
[19] Стивен Ф. Барретт. Микроконтроллер Arduino: обработка данных для всех! Синтез
Чтение о Цифровых Схемах И Системах, 7(2):1-371, 2012. индекс полезности: 10.2200/
S00421ED1V01Y201205DCS038.
[20] Корпорация Atmel.
ATMEGA2560-8-разрядный микроконтроллер atmel и
встроенная программируемая вспышка емкостью 16/32/64 Кбайт. Корпорация Atmel, 2014 год. URL-адрес:
https://ww1.microchip.com/downloads/en/devicedoc/atm
el-2549-8-бит-avr-микроконтроллер-atmega640-1280-128
1-2560-2561_ таблица данных.pdf.
[21] Кэти Кокс и Клей Мерритт.
Схема генераторной установки микроконтроллера
соображения. Инструкция по применению Freescale Semiconductor AN1706, 1997.
[22] Роб Деккер, Фрэнкс Бинкер И Лок Тиссен.
Реалистичная модель неисправности
алгоритмы статического произвольного доступа и тестирования памяти. Транзакции IEEE
об автоматизированном Проектировании Интегральных Схем и Систем, 9 (6): 567-572,
1990. doi: 10.1109/43.55188.
[23] Сейити Аритомэ, Икуо Хатакеяма, Тецуо Эндо, Тецуя Ямагути,
Сусуму Шуто, Хирохиса Дзидзука, Тоору Маруяма, Хироси Ватанабе, Гертиан
84Хеминк, Кодзи Сакуи и др.
Передовая технология построения ячеек nand
для надежного подключения 3,3 В 64 Мб с возможностью электрического стирания и программирования только для чтения
воспоминания (eeproms). Японский журнал прикладной физики, 33 (1S): 524-1994.
doi:10.1143/jiap.33.524.
[24] Мин-Инь Хао, Хенсан Хван и Джек Си Ли. Влияние кремния-
имплантированные оксиды для электрически стираемой программируемой памяти, доступной только для чтения
приложения. Письма по прикладной физике, 62(13):1530-1532, 1993. doi: 10.106
3/1.108630.
[25] Пауло Каппеллетти, Карла Голла, Пьеро Оливо И Энрико Занони.
Вспышка
воспоминания. Springer Science & Business Media, 2013.
[26] Паоло Паван, Роберто Без, Пьеро Оливо И Энрико Занони. Флэш-память
ячейка - общий обзор. Материалы конференции IEEE, 85(8):1248-1271, 1997. дои:
10.1109/5.622505.
[27] Дживан С. Параб, Винод Г. Шелаке, Раджаниш Камат И Гуриш М. Наик.
Изучение возможностей встроенных ресурсов программирования для портов ввода-вывода,
прерывания и таймер/счетчик. Изучение языка Си для микроконтроллеров: Рука об руку
Подход, страницы 37-67, 2007. doi: 10.1007/978-1-4020-6067-0_4.
[28] У. J. Бьюкенен. RS-232, страницы 239-274. СПРИНГЕР, США, Бостон, Массачусетс, 2004. дои:
10.1007/978-1-4020-7870-5_11.
[29] Дауд Шенуда Дауд и Питер Дауд. 6-Последовательный периферийный интерфейс
(SPI), страницы 191-244. Издательство "Ривер Паблишерс", 2020 год.
[30] Питер Коркоран. Два срока и 30 лет: налоговое и вводное руководство по
двухпроводная шина I2C. Журнал IEEE по потребительской электронике, 2(3):30-36, 2013.
doi: 10.1109/MCE.2013.2257289.
[31] Роберт Х. Уолден. Обзор и анализ аналого-цифрового преобразователя. ИЭЭЭ
Журнал по избранным областям коммуникаций, 17(4):539-550, 1999. дои:
10.1109/49.761034.
85 [32] Марсель ИМ Пелгром.
Аналого-цифровое преобразование.
Аналого-цифровой
Перевод: страницы 325-418. Спрингер, 2013. doi: 10.1007/978-1-461
4-1371-4_8.
[33] МИСС Хефни и ее высочество Амер.
Разработка усовершенствованной схемы контроля
для систем на базе микроконтроллеров.
ICM’99. Производство. Одиннадцатый
Международная конференция По Микроэлектронике (IEEE Cat. Нет. 99EX388), страницы
165–168. IEEE, 1999. doi: 10.1109/ICM.2000.884831.
[34] Павел Боул и Алеш Воборник.
пикоспутник pilsencube.
Встроенная микроконтроллерная система для
В 2013 году состоялся 16-й Международный симпозиум IEEE по
Проектирование И Диагностика Электронных Схем И Систем (DDECS), страницы 131–
134. IEEE, 2013. doi: 10.1109/DDECS.2013.6549804.
[35] Дэвид Де Соуза и Николас Сезар Лавиния. Подключение к РИС. 16F877A:
передовые меры. Эрик, 2008 год.
[36] Майкл Барр. Широтно-импульсная модуляция. Встроенные системы программирования,
14(10):103–104, 2001.
[37] Святой Дух. Arduino И Проблема Со Сбором Данных
налоги Амстердама. Военно-морское училище, 2009 год. doi:10.13140/rg.2.2.2767
5.41761.
[38] Автор: Том Айго. Заставлять вещи говорить: Практические методы подключения физики
объекты. О'Рейли, Севастополь, США, 2007.
[39] Компания Future Technology Devices International Limited. Будущее технологических устройств
international limited - ftdi, 2022 год. URL: https://ftdichip.com/ /
[40] Натан Энсменгер. У блок-схемы несколько значений. Информация &
Культура, 51(3):321-351, 2016.
[41] Цун С. Жрачка. Разработка программного обеспечения моделируется с помощью машин для тестирования конечного состояния. ИЭЭЭ
труды по разработке программного обеспечения, страницы 178-187, 1978.
86 [42] Христос Ангелов, Кшиштоф Сиршецкий и Николас Мариан. Проектные модели для
многоразовые и реконфигурируемые конечные автоматы. Международная конференция по
Встроенные и повсеместные вычисления, страницы 152-163. Спрингер, 2005.
[43] Норман Данбар. Компиляция Arduino. Внутренние компоненты программного обеспечения Arduino, страницы
9–72. Спрингер, 2020 год. doi: 10.1007/978-1-4842-5790-6_2.
[44] Пшеница. Программное обеспечение Arduino. Внутренние устройства Arduino, страницы 89-97. Прыгун,
2011. doi: 10.1007/978-1-4302-3883-6_5.
[45] Т. Джамиль. Risc против cisc. Потенциал IEEE, 14(3):13-16, 1995. doi: 10.110
9/45.464688.

[46] Г. Арроз, Дж. К . Монтейру и А. Оливейра. Архитектура компьютеров, dos
Цифровые системы - это микропроцессоры aos. IST Press, Лиссабон, Португалия, 2007.
[47] Эмили Блем, Джайкришнан Менон и Картикеян Санкаралингам.
Борьба за власть: возвращение к дискуссии о risc и cisc в современных архитектурах arm и
x86.
В 2013 году состоялся 19-й Международный симпозиум IEEE по высоким-
Архитектура высокопроизводительных компьютеров (HPCA), страницы 1-12, 2013. doi:10.1
109/HPCA.2013.6522302.
[48] M. Tecnology. Расширенная спецификация RISC-вычислений, 1992. URL: http:
//www.bitsavers.org/pdf/mips/ARC_1.2_Specification_1
992.pdf.
[49] Сол Горн, Роберт У. Бемер и Джулиен Грин. Американский стандартный код для
обмена информацией. Коммуникации ACM, 6(8):422-426, 1963.
[50] Ханс-Кристоф Штайнер. Firmata: На пути к тому, чтобы микроконтроллеры стали
дополнением к компьютеру. В издании New Interfaces for Music Expression, 2009.
[51] Дэниел Шиффман. Обучающая обработка: руководство для начинающих по программированию
изображений, анимации и взаимодействию. Морган Кауфманн, 2009.
[52] Майкл Харт. Библиотека Flash Arduino, 2023. URL: https://github.com/sch
inken/Flash.
87[53] Риазолла Фирузян. Серводвигатели и теория промышленного управления. Springer,
2014.
[54] Фабио Руджеро, Мигель Анхель Трухильо, Рауль Кано, Х. Аскорбе, Антидио Вигурия,
К. Перес, Винченцо Липпьелло, Анибаль Оллеро и Бруно Сицилиано. Многослойное
управление для мультироторных беспилотных летательных аппаратов, оснащенных серво-манипулятором. В 2015
году международная конференция IEEE по робототехнике и автоматизации (ICRA), стр. 4014–
4020. IEEE, 2015.
[55] Миодраг Ракич. Многопалая роботизированная рука с возможностью самоадаптации. Робототехника и
Производство, интегрированное с компьютером, 5(2-3):269-276, 1989.
[56] Сай Киран Оруджанти и Аджит Хосла. 3d-печать и беспроводные
системы передачи энергии для приложений мягкой робототехники. Транзакции ECS, 98(13):55, 2020.
[57] Обработка. Добро пожаловать в processing!, 2023. URL: https://processing.o
rg/.
[58] Монсон Х. Хейс. Краткое изложение теории и проблем цифровой
обработки сигналов, написанное Шаумом. McGraw-Hill, 1999.
[59] П.П. Вайдьянатан. Обобщения теоремы о выборке: семь десятилетий
спустя после Найквиста.
Труды IEEE по схемам и системам I: Фундаментальные
Теория и приложения, 48(9):1094-1109, 2001.
[60] Х. Дж. Ландау. Выборка, передача данных и коэффициент Найквиста. Труды
IEEE, 55(10):1701-1706, 1967.
[61] Саид против Васеги. Усовершенствованная цифровая обработка сигналов и подавление шума. Джон
Уайли и сыновья, 2008.
88


Рецензии