Browse Source

Навёл чёть порядка. Добавил фильтров.

Vladimir N. Shilov 8 năm trước cách đây
mục cha
commit
74470e3726
3 tập tin đã thay đổi với 371 bổ sung0 xóa
  1. 27 0
      adc/median_filter.c
  2. 92 0
      adc/фнч.txt
  3. 252 0
      printf/printf.h

+ 27 - 0
adc/median_filter.c

@@ -0,0 +1,27 @@
+/*
+  http://electronix.ru/forum/index.php?showtopic=114436&view=findpost&p=1180944
+  Алгоритм основан на последовательной проверке точек массива на их "медианность".
+  Проверка состоит в сравнении точки со всеми остальными - подсчетом двух сумм (s1 и s2) - количества точек, которые оказались больше данной, и количества тех, которые оказались меньше нее.
+  Превышение показания хотя бы одного из счетчиков свыше половины длины массива (slit) бракует данную точку ДОСРОЧНО и переходит к проверке следующей (переход на nexti).
+  До полного перебора всех точек обычно не доходит, т.к. подходящая точка находится раньше (где-то в середине массива), т.е. тоже ДОСРОЧНО.
+*/
+
+datatype median( datatype array, int length)  // массив и его длина
+{
+    int  slit = length/2;
+
+    for( int i=0; i < length; i++) {
+        int s1=0, s2=0;
+        datatype val = array[i];
+        for( int j=0; j < length; j++) {
+            if( array[j] < val) {
+                if( ++s1 > slit) break;
+            } else if( array[j] > val) {
+                if( ++s2 > slit) break;
+            }
+        }
+        return val;
+    }
+
+    return 0;  // чистая формальность, досюда исполнение никогда не доходит
+}

+ 92 - 0
adc/фнч.txt

@@ -0,0 +1,92 @@
+http://we.easyelectronics.ru/Theory/chestno-prostoy-cifrovoy-filtr.html
+
+LN(1/5%)  = 2,996
+LN(1/0,1%) = 6,908
+Ntau = 2,996...6,908
+
+N = Тпп / Т
+
+Alfa < EXP(-Ntau / N)
+Beta = 1 - Alfa
+
+Ntau = 6.908 (7?)
+Tpp = 100 ms
+T = 1.5625 ms
+A = -1,306122448979591836734693877551 / 58982 / 3686
+B =  2,306122448979591836734693877551 / 5554  / 410
+
+Y(n) = (Na*Y(n-1) + Nb*X(n)) >> 8
+or
+Y(n) = Y(n-1) + [Nb*(X(n) — Y(n-1)) >> 8]
+
+uint filter(u16 x){
+  static u16 y = 0;
+  static u16 z = 0;
+
+  if (x >= y) {
+    z += (x - y);
+  } else {
+    z += (y - x);
+  }
+  return y = (u16)((u32)(5554 * z) >> 16);
+};
+
+//
+#define Na 15
+#define Nb 1
+#define k 4
+
+int filter(int x){
+  static int y = 0;
+  return y1 = (Na * y + Nb * x) >> k;
+};
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+http://electronix.ru/forum/lofiversion/index.php/t12237.html
+Самый простой способ, аналогичный ФНЧ, т.е. для условий, что сигнал
+низкочастотый и сетевая частота в нём присутствует в виде наводки как
+единственный высокочастоный сигнал:
+Частота дискретизации 1000 Гц;
+Подавляемая частота 50 Гц;
+На одном периоде подавляемой частоты получается 20 отсчетов.
+Для синуса при данных условиях получается, что если брать сумму выборок
+X(n-10)+X(n), то в результате должен получаться ноль.
+Но кроме синуса, какую-то часть веса выборки составляет полезный сигнал и
+простое суммирование приведёт к удвоению его среднего значения. Тогда делаем
+так: (X(n-10)+X(n))/2.
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+http://chipenable.ru/index.php/programming-avr/item/162-prostoy-cifrovoy-filtr.html
+
+По сути, программа этого цифрового фильтра состоит всего из двух строчек на Си.:
+	Dacc = Dacc + Din - Dout
+	Dout = Dacc/K
+где Dout - выходное значение фильтра, Din - входное значение фильтра, K -
+постоянный коэффициент, который рассчитывается по формуле:
+	K = T x SPS
+где T - это постоянная времени фильтра, SPS - частота дискретизации АЦП.
+
+Dacc и Dout должны сохранять свои значения, после выполнения алгоритма. Если
+алгоритм реализовать в виде функции, то эти переменные можно просто сделать
+статическими.
+
+Для 8-ми разрядных входных данных алгоритм цифрового фильтра в Си коде может выглядеть так:
+
+#define SPS 9600UL
+#define Trc 0.001f
+#define K (SPS*Trc)
+
+uint8_t Filtr(uint8_t data)
+{
+   static uint16_t Dacc = 0;
+   static uint8_t Dout = 0;
+   uint8_t Din = data;
+
+   Dacc = Dacc + Din - Dout;
+   Dout = Dacc/(uint16_t)K;
+
+   return Dout;
+}
+
+---
+Моё: я думаю, что SPS нужно брать не частоту АЦП, а частоту выборок.

+ 252 - 0
printf/printf.h

@@ -0,0 +1,252 @@
+/** \file printf.c
+ * Simplified printf() and sprintf() implementation - prints formatted string to
+ * USART (or whereever). Most common % specifiers are supported. It costs you about
+ * 3k FLASH memory - without floating point support it uses only 1k ROM!
+ * \author Freddie Chopin, Martin Thomas, Marten Petschke and many others
+ * \date 16.2.2012
+ * Get from http://www.firefly-power.de/ARM/printf.html
+ */
+
+/******************************************************************************
+* chip: STM32F10x
+* compiler: arm-none-eabi-gcc 4.6.0
+*
+* global functions:
+* 	int printf_(const char *format, ...)
+* 	int sprintf_(char *buffer, const char *format, ...)
+*
+* STM32 specific functions:
+*         init_UART1(void)
+*	void putc_UART1 (char);                // blocking put char, used by printf()
+*
+* local functions:
+* 	int putc_strg(int character, printf_file_t *stream)
+* 	int vfprintf_(printf_file_t *stream, const char *format, va_list arg)
+* 	void long_itoa (long val, int radix, int len, vfprintf_stream *stream)
+*
+******************************************************************************/
+
+/*
++=============================================================================+
+| includes
++=============================================================================+
+*/
+
+#include <stdarg.h>     // (...) parameter handling
+
+/*
++=============================================================================+
+| options
++=============================================================================+
+*/
+//#define INCLUDE_FLOAT  // this enables float in printf() and costs you about 2kByte ROM
+
+/*
++=============================================================================+
+| global declarations
++=============================================================================+
+*/
+
+int sprintf_(char *buffer, const char *format, ...);
+
+/*
++=============================================================================+
+| local declarations
++=============================================================================+
+*/
+
+void putc_strg(char);          // the put() function for sprintf()
+char *SPRINTF_buffer;          //
+
+static int vfprintf_(void (*) (char), const char *format, va_list arg); //generic print
+void long_itoa (long, int, int, void (*) (char)); //heavily used by printf_()
+
+/*
++=============================================================================+
+| global functions
++=============================================================================+
+*/
+
+int sprintf_(char *buffer, const char *format, ...)
+{
+	va_list arg;
+
+	SPRINTF_buffer=buffer;	 //Pointer auf einen String in Speicherzelle abspeichern
+
+	va_start(arg, format);
+	vfprintf_((&putc_strg), format, arg);
+	va_end(arg);
+
+	*SPRINTF_buffer ='\0';             // append end of string
+
+	return 0;
+}
+
+/*
++=============================================================================+
+| local functions
++=============================================================================+
+*/
+// putc_strg() is the putc() function for sprintf_()
+void putc_strg(char character)
+{
+	*SPRINTF_buffer = (char)character;	// just add the character to buffer
+	 SPRINTF_buffer++;
+}
+
+/*--------------------------------------------------------------------------------+
+ * vfprintf_()
+ * Prints a string to stream. Supports %s, %c, %d, %ld %ul %02d %i %x  %lud  and %%
+ *     - partly supported: long long, float (%ll %f, %F, %2.2f)
+ *     - not supported: double float and exponent (%e %g %p %o \t)
+ *--------------------------------------------------------------------------------+
+*/
+static int vfprintf_(void (*putc)(char), const char* str,  va_list arp)
+{
+	int d, r, w, s, l;  //d=char, r = radix, w = width, s=zeros, l=long
+	char *c;            // for the while loop only
+
+#ifdef INCLUDE_FLOAT
+	float f;
+	long int m, mv, p, w2;
+#endif
+
+	while ((d = *str++) != 0) {
+		if (d != '%') {
+			(*putc)(d);
+			continue;
+		}
+		d = *str++;
+		w = r = s = l = 0;
+		if (d == '%') {
+			(*putc)(d);
+			d = *str++;
+		}
+		if (d == '0') {
+			d = *str++; s = 1;  //padd with zeros
+		}
+		while ((d >= '0')&&(d <= '9')) {
+			w += w * 10 + (d - '0');
+			d = *str++;
+		}
+		if (s) w = -w;      //padd with zeros if negative
+
+	#ifdef INCLUDE_FLOAT
+		w2 = 2;            //default decimal places=2
+		if (d == '.'){
+			d = *str++; w2 = 0; }
+		while ((d >= '0')&&(d <= '9')) {
+			w2 += w2 * 10 + (d - '0');
+			d = *str++;
+		}
+	#endif
+
+		if (d == 's') {
+			c = va_arg(arp, char*);
+			while (*c)
+				(*putc)(*(c++));
+			continue;
+		}
+		if (d == 'c') {
+			(*putc)((char)va_arg(arp, int));
+			continue;
+		}
+		if (d == 'u') {     // %ul
+			r = 10;
+			d = *str++;
+		}
+		if (d == 'l') {     // long =32bit
+			l = 1;
+			if (r==0) r = -10;
+			d = *str++;
+		}
+		if (d =='\0') break;    //avoid crashing if format string is buggy
+		if (d == 'u') r = 10;//     %lu,    %llu
+		else if (d == 'd' || d == 'i') {if (r==0) r = -10;}  //can be 16 or 32bit int
+		else if (d == 'X' || d == 'x') r = 16;               // 'x' added by mthomas
+		else if (d == 'b') r = 2;
+   #ifdef INCLUDE_FLOAT
+		else if (d == 'f' || d == 'F') {
+			f=va_arg(arp, double);
+			if (f >= 0.0) {
+				r = 10;
+            mv = f;
+            m = mv;
+			}
+			else {
+				r = -10;
+            mv = f;
+				f = -f;
+            m = f;              // f and m are always positive
+			}
+			long_itoa(mv, r, w, (putc));
+			if (w2!=0) {
+            putc('.');
+            f=f-m;
+            w=-w2; p=1;
+            while (w2--) p = p*10;
+            m=f*p;
+            long_itoa(m, 10, w, (putc));
+			}
+			l=3; //do not continue with long
+		}
+	#endif
+		else str--;                                         // normal character
+
+		if (r==0) continue;  //
+		if (l==0) {
+			if (r > 0){      //unsigned
+				long_itoa((unsigned long)va_arg(arp, int), r, w, (putc)); //needed for 16bit int, no harm to 32bit int
+			}
+			else            //signed
+				long_itoa((long)va_arg(arp, int), r, w, (putc));
+		} else if (l==1){  // long =32bit
+				long_itoa((long)va_arg(arp, long), r, w, (putc));        //no matter if signed or unsigned
+		}
+	}
+
+	return 0;
+}
+
+
+void long_itoa (long val, int radix, int len, void (*putc) (char))
+{
+	char c, sgn = 0, pad = ' ';
+	char s[20];
+	int  i = 0;
+
+
+	if (radix < 0) {
+		radix = -radix;
+		if (val < 0) {
+			val = -val;
+			sgn = '-';
+		}
+	}
+	if (len < 0) {
+		len = -len;
+		pad = '0';
+	}
+	if (len > 20) return;
+	do {
+		c = (char)((unsigned long)val % radix); //cast!
+		if (c >= 10) c += ('A'-10); //ABCDEF
+		else c += '0';            //0123456789
+		s[i++] = c;
+		val = (unsigned long)val /radix; //cast!
+	} while (val);
+
+	if ((sgn!=0) && (pad!='0')) s[i++] = sgn;
+	while (i < len)
+		s[i++] = pad;
+	if ((sgn!=0) && (pad=='0')) s[i++] = sgn;
+
+	do
+		(*putc)(s[--i]);
+	while (i);
+}
+
+
+/******************************************************************************
+* END OF FILE
+******************************************************************************/