int raw = analogRead(sensePin);
float volts = raw / 205.0;
float tempC = 100.0 * volts — 50;
Но в действительности температура в виде вещественного числа нужна только тогда, когда требуется отобразить ее на экране. Другие операции с температурой, такие как сравнение или усреднение при нескольких попытках чтения, вполне можно выполнять с непреобразованным значением типа int, и при этом они будут выполняться значительно быстрее.
Поиск против вычисления
Как вы уже поняли, в скетчах вещественных чисел лучше избегать. Но как быть, если понадобится сгенерировать на аналоговом выходе сигнал синусоидальной формы, для чего, как можно догадаться, потребуется вычислять и вывести на аналоговый выход значение синуса этого угла. На самом деле все немного сложнее, потому что синусоиду нужно привести к диапазону значений, которые можно вывести на аналоговый выход.
Следующий пример генерирует синусоиду, разбивая каждый цикл на 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: