Оверсэмплинг (oversampling) - методика повышения разрядности целочисленного цифрового сигнала, часто используется для повышения разрешения АЦП. Простыми словами - позволяет математически очень просто повысить точность измерений и добавить к ним несколько двоичных разрядов, т.е. условно из 10-бит сигнала (значения 0.. 1023) получить 12 бит (0.. 4095) и выше. Бывает реализовано аппаратно в некоторых АЦП.
Математика #
В основе метода лежит самое обыкновенное среднее арифметическое, а также предположение, что АЦП шумит гармонически и "взвешенно". Для оверсэмплинга нужно усреднить несколько значений с АЦП, прочитанных подряд без пауз, т.е. мы рассчитываем получить шум самого АЦП.
Например, если с АЦП получаются значения 300, 300, 300, 301, и 300, то можно предположить, что истинное значение будет 300.2
- как среднее арифметическое. Переход к дробным числам не всегда удобен, особенно во встраиваемой электронике - здесь и пригодится оверсэмплинг. Идея в том, что мы точно так же складываем несколько измерений, но не будем делить их на количество - вместо этого просто примем, что разрешение увеличилось и данные теперь находятся в другом диапазоне. В программировании всё привязано к степеням двойки, поэтому и переходить к новому диапазону удобнее в битах, чтобы оптимизировать вычисления и удобнее ориентироваться в значениях.
Для этого нужно сложить определённое количество измерений (сэмплов, samples) и разделить на коэффициент в зависимости от желаемого увеличения разрешения. В общем случае всё это описывается вот такими формулами:
Значение | Формула | +1 | +2 | +3 | +4 |
---|---|---|---|---|---|
Кол-во сэмплов | 4^GAIN |
4 |
16 |
64 |
256 |
Делитель суммы | 2^GAIN |
2 |
4 |
8 |
16 |
Новый максимум | 2^(CUR + GAIN) - 2^GAIN |
Где GAIN
- увеличение разрешения (на количество бит), а CUR
- текущее разрешение сигнала в битах.
Новый максимум будет слегка отличаться от ожидаемого - например мы повысили разрешение с 10 до 12 бит и ожидаем, что в новом диапазоне будет максимальное значение 2^12 - 1 = 4095
, например для перевода значения в Вольты. Но оверсэмплинг слегка уменьшает максимум - он будет равен 4092
по формуле выше. Это почти незначительно и можно пренебречь в расчётах, но если нужно максимально точное значение - лучше брать расчётный максимум.
Код #
Для максимальной производительности приведённые выше формулы можно оптимизировать до следующего вида, а деление - до сдвига:
// количество измерений, которое нужно сделать
constexpr uint16_t OVS_SAMPLES(uint8_t gain) {
return 1ul << (gain << 1);
}
// число, на которое нужно сдвинуть сумму
constexpr uint32_t OVS_SHIFT(uint8_t gain) {
return gain;
}
// максимальное значение при начальном разрешении
constexpr uint16_t OVS_MAX(uint8_t base, uint8_t gain) {
return (1ul << (gain + base)) - (1 << gain);
}
Пример - расчёт напряжения на АЦП при помощи оверсэмплинга с 10 бит (по умолч. analogRead
Arduino) до 12 бит:
uint32_t sum = 0;
for (uint16_t i = 0; i < OVS_SAMPLES(2); i++) {
sum += analogRead(0);
}
sum >>= OVS_SHIFT(2);
// теперь sum - 12 битное значение с АЦП
Библиотека #
У меня есть готовая библиотека OVS с этими функциями и классом-обёрткой.
Полезные страницы #
- Набор GyverKIT – наш большой стартовый набор Arduino, продаётся в России
- Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress
- Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])
- Поддержать автора за работу над уроками
