Следующий пример генерирует синусоиду, разбивая каждый цикл на 64 шага, и выводит сигнал на аналоговый выход DAC0 платы Arduino Due. Имейте в виду, что для данного эксперимента годятся только платы Arduino с истинными аналоговыми выходами, такие как Due.
// sketch_-4_03_sin
void setup()
{
}
float angle = 0.0;
float angleStep = PI / 32.0;
void loop()
{
int x = (int)(sin(angle) * 127) + 127;
analogWrite(DAC0, x);
angle += angleStep;
if (angle > 2 * PI)
{
angle = 0.0;
}
}
Измерение на выходе показывает, что данный скетч действительно производит сигнал замечательной синусоидальной формы, но с частотой всего 310 Гц. Процессор на плате Arduino Due работает с тактовой частотой 80 МГц, поэтому можно было бы ожидать увидеть сигнал с большей частотой. Проблема в том, что здесь скетч снова и снова повторяет одни и те же вычисления. Но поскольку каждый раз получаются одни и те же результаты, почему бы просто не рассчитать их все сразу и не сохранить в массиве?
Следующий пример также генерирует синусоиду, разбивая цикл на 64 шага, но использует прием поиска по таблице заранее подготовленных значений, которые выводит непосредственно в цифроаналоговый преобразователь (ЦАП).
byte sin64[] = {127, 139, 151, 163, 175, 186, 197,
207, 216, 225, 232, 239, 244, 248, 251, 253, 254,
253, 251, 248, 244, 239, 232, 225, 216, 207, 197, 186,
175, 163, 151, 139, 126, 114, 102, 90, 78, 67, 56, 46,
37, 28, 21, 14, 9, 5, 2, 0, 0, 0, 2, 5, 9, 14, 21, 28,
37, 46, 56, 67, 78, 90, 102, 114, 126};
void setup()
{
}
void loop()
{
for (byte i = 0; i < 64; i++)
{
analogWrite(DAC0, sin64[i]);
}
}
Этот пример генерирует точно такой же сигнал в форме синусоиды, но уже с частотой 4,38 кГц, то есть работает более чем в 14 раз быстрее.
Таблицу синусов можно рассчитать разными способами. Можно сгенерировать числа по обычной формуле в электронной таблице или написать скетч, который будет выводить числа в монитор последовательного порта, откуда их можно скопировать и вставить в другой скетч. Далее приводится версия скетча sketch_04_03_sin, которая выводит значения один раз в монитор последовательного порта:
// sketch_-4_05_sin_print
float angle = 0.0;
float angleStep = PI / 32.0;
void setup()
{
Serial.begin(9600);
Serial.print("byte sin64[] = {");
while (angle < 2 * PI)
{
int x = (int)(sin(angle) * 127) + 127;
Serial.print(x);
angle += angleStep;
if (angle < 2 * PI)
{
Serial.print(", ");
}
}
Serial.println("};");
}
void loop()
{
}
Открыв окно монитора порта, вы увидите сгенерированную последовательность чисел (рис. 4.1).

Рис. 4.1.Использование скетча для получения массива чисел
Быстрый ввод/вывод
В этом разделе мы посмотрим, как увеличить скорость включения и выключения цифровых выходов. Мы увеличим максимальную частоту с 73 кГц почти до 4 МГц.
Простая оптимизация кода
Начнем с простого кода, включающего и выключающего цифровой выход с помощью digitalWrite:
// sketch_04_05_square
int outPin = 10;
int state = 0;
void setup()
{
pinMode(outPin, OUTPUT);
}
void loop()
{
digitalWrite(outPin, state);
state = ! state;
}
Если запустить этот скетч и подключить осциллограф или частотомер к цифровому контакту 10, вы получите частоту чуть выше 73 кГц (мой осциллограф показал 73,26 кГц).
Прежде чем сделать большой шаг в направлении непосредственного управления портом, можно попробовать немного оптимизировать программный код скетча. Прежде всего, ни одна из переменных не обязана иметь тип int, их вполне можно объявить с типом byte. Это изменение увеличит частоту до 77,17 кГц. Далее переменную с номером контакта можно сделать константой, добавив слово const перед объявлением переменной. Это изменение увеличит частоту до 77,92 кГц.
В главе 2 вы узнали, что функция loop — это не просто цикл while, так как дополнительно проверяет наличие входящих данных в последовательном порте. То есть следующим шагом в направлении увеличения производительности может стать отказ от функции loop и перенос кода в setup. Скетч, в котором выполнены все описанные изменения, приводится ниже:
// sketch_04_08_no_loop
const byte outPin = 10;
byte state = 0;
void setup()
{
pinMode(outPin, OUTPUT);
while (true)
{
digitalWrite(outPin, state);
state = ! state;
}
}
void loop()
{
}
В результате всего этого мы получили увеличение максимальной частоты до 86,39 кГц.
В табл. 4.2 перечислены все улучшения, которые можно выполнить для увеличения производительности простого программного кода, прежде чем сделать последний шаг и заменить digitalWrite чем-нибудь более быстрым.
Таблица 4.2.Увеличение производительности простого программного кода
Действие
Скетч
Читать дальше