Нелинейное сглаживание входящего сигнала: равномерное снятие показаний с аналогового датчика Arduino

Продолжение темы снятия данных непосредственно с фотодиода. В этом нет никаких сложностей за исключением прыгания снимаемых показаний при казалось-бы неизменных внешних условиях. И чем ближе к нулю, тем разброс больше.
Можно снимать несколько показаний и брать среднее — было рассмотрено в предыдущей теме. А можно произвести нелинейное сжатие входной шкалы. Минус: меньше точность. Плюс: скорость и стабильность выходных данных.
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);           // select the pins used on the LCD panel

//описание структуры входного интервала
typedef struct
{ short from, to, step, base;
} tLimit;

//описание всей шкалы, где
//0-1024 входной диапазон
//0,1,2...13 и далее - выход
//5,4,3,2,1 - дискретность/погрешность интервала
tLimit Limits[] =
{
 { 25, 40, 5, 0 },
 { 40, 52, 4, 3 }, 
 { 52, 61, 3, 6 }, 
 { 61, 69, 2, 9 }, 
 { 69, 1024, 1, 13 }
};

void setup(){
  lcd.begin(16, 2);               // start the library
}

//Собственно, алгоритм
int GetV()
{
 static int AhI = 0, Ah = Limits[0].from, R = Limits[0].base;
 int A = analogRead(A5), I = 0;
 
 if( A < 35 ) //устанавливаем нижнюю границу
  A = 35;
  
 do //определяем интервал в который попали входные данные
 { if( A >= Limits[I].from &&
       A <  Limits[I].to
     ) break;
   I ++;
 }while( true );
 
 //проверяем, преодолена ли погрешность по отношению к предыдущему значению
 if( abs( Ah - A ) > Limits[AhI].step )
 {
  Ah  = A;
  AhI = I;
  
  //вычисляем скорректированное значение
  R = Limits[I].base + (A - Limits[I].from)/Limits[I].step ;
 }
 
 return R;
}

void loop(){

   lcd.setCursor(0,1);
   //выводим скорректированное значение и входное (правда другое:)
   lcd.print( (String)GetV() +":"+ (String)analogRead(A5) + "       ");
   
   delay( 300 );
}

0 комментариев

Оставить комментарий