Thursday 26 October 2017

Buffer Circular De Media Móvil


Introducción Una de las principales aplicaciones de la placa Arduino es la lectura y el registro de datos del sensor. Por ejemplo uno monitores de presión cada segundo del día. Como las tasas de muestra de alta frecuencia genera picos en los gráficos también se quiere tener un promedio de las mediciones. A medida que las mediciones no son estáticos en el tiempo lo que a menudo necesitamos es un medio de funcionamiento. Este es el promedio de un cierto período y muy valiosa cuando se hace el análisis de tendencias. forma más simple de un promedio móvil se puede hacer mediante un código que se basa en el promedio de ejecución anterior: Si uno No quiere utilizar aritmética de punto flotante -, esto toma la memoria y disminuye la velocidad - uno puede hacer lo mismo por completo en el dominio entero. La división por 256 en el código de ejemplo es un cambio a la derecha 8, que es más rápido que decir la división por ejemplo, 100. Esto es cierto para todas las potencias de 2 como divisor y uno sólo debe tener cuidado de la suma de los plomos es igual a la potencia de 2. Y, por supuesto, uno debe tener cuidado no hay desbordamiento intermedio (considere el uso de largo sin signo) Si necesita un medio de funcionamiento más preciso, en concreto de las 10 últimas mediciones, se necesita una matriz (o lista enlazada) para sostenerlos. Esta matriz actúa como un buffer circular y con cada nueva medición se elimina el más antiguo. El promedio de funcionamiento se calcula como la suma de todos los elementos dividido por el número de elementos en el array. El código para el promedio de funcionamiento será algo como esto: inconveniente de este código es que la matriz para contener todos los valores puede llegar a ser bastante grande. Si usted tiene una medición por segundo y quiere un promedio móvil por minuto se necesita un conjunto de 60 en promedio por hora necesitaría un conjunto de 3600. Eso no podía ser hecho de esta manera en un Arduino ya que sólo tiene 2 KB de memoria RAM. Sin embargo mediante la construcción de un promedio de 2 etapas que se puede abordar bastante bien (disclaimer: no para todas las mediciones). En pseudo código: A medida que se necesita una nueva matriz estática interno para cada función runningAverage, esta grita para ser implementado como una clase. biblioteca La biblioteca RunningAverage runningAverage hace una clase de la función anterior por lo que se puede utilizar varias veces en un bosquejo. Se desacopla el add () y el promedio () para ser un poco más flexible, por ejemplo, uno puede llamar a los medios varias veces sin añadir nada. Tenga en cuenta que cada instancia de la clase añade su propia matriz para contener las mediciones, y que esto se suma a la utilización de la memoria. La interfaz de la clase se mantiene lo más pequeña posible. Nota: con la versión 0.2 los nombres de los métodos son todos hechos más descriptivo. Uso Un pequeño boceto muestra cómo se puede utilizar. Un generador aleatorio se utiliza para imitar un sensor. En setup () el Myra se borra para que podamos empezar a añadir nuevos datos. En loop () primero se genera un número aleatorio y se convierte a un flotador que se añade a Mira. A continuación, el runningAverage se imprime en un puerto serie. También se podría mostrarlo en algunos LCD o enviar a través de Ethernet, etc. Cuando se añaden 300 artículos Myra se aclaró que empezar de nuevo. Notas Para utilizar la biblioteca, hacer una carpeta en sus SKETCHBOOKPATHlibaries con el nombre RunningAverage y poner el. hy. cpp allí. Opcionalmente hacer un subdirectorio de ejemplos para colocar la aplicación de ejemplo. 2011-01-30 Historia: versión inicial 2011-02-28: Se ha corregido falta destructor en el archivo. h 2011-02-28: eliminado constructor por defecto 2012--. trimValue () Yuval Naveh añadió trimValue (que se encuentra en la web) 21/11/2012: 2012-12-30 refactorizada: fillValue () reprogramado para la publicación 03/07/2014 añadido: Código de protección de memoria adicional - tamaño si matriz interna no puede ser asignado se convierte en 0. Esto es para resolver el problema descrito aquí - forum. arduino. cc/indextopic50473.msg1790086msg1790086 - Prueba de Todo ampliamente. Plantilla RunningAverage clase. h RunningAverage. cppThe Científico y Guía de Ingenieros de Procesamiento Digital de Señales Por Steven W. Smith, Ph. D. Capítulo 28: Digital Signal Processors Procesadores de señales digitales están diseñados para llevar a cabo rápidamente los filtros FIR y técnicas similares. Para entender el hardware. primero debemos entender los algoritmos. En esta sección vamos a hacer una lista detallada de los pasos necesarios para implementar un filtro FIR. En la siguiente sección veremos como DSP están diseñados para llevar a cabo estos pasos tan eficientemente como sea posible. Para empezar, hay que distinguir entre el procesamiento fuera de línea y procesamiento en tiempo real. En el procesamiento fuera de línea, toda la señal de entrada reside en la computadora al mismo tiempo. Por ejemplo, un geofísico podría utilizar un sismómetro para registrar el movimiento del suelo durante un terremoto. Después de que pase el temblor, la información puede leerse en un ordenador y se analiza de alguna manera. Otro ejemplo de procesamiento fuera de línea es de imágenes médicas, tales como la tomografía computarizada y la resonancia magnética. El conjunto de datos se adquiere mientras el paciente está dentro de la máquina, pero la reconstrucción de la imagen se puede retrasar hasta un momento posterior. El punto clave es que toda la información es al mismo tiempo a disposición del programa de procesamiento. Esto es común en la investigación científica y de ingeniería, pero no en los productos de consumo. Fuera de la línea de procesamiento es el reino de los ordenadores personales y ordenadores centrales. En el procesamiento en tiempo real, la señal de salida se produce al mismo tiempo que está siendo adquirido la señal de entrada. Por ejemplo, esto es necesario en la comunicación telefónica, audífonos, y el radar. Estas aplicaciones deben tener la información inmediatamente disponible, aunque puede ser retrasada por un corto periodo. Por ejemplo, un retardo de 10 milisegundos en una llamada telefónica no puede ser detectado por el orador u oyente. Del mismo modo, no hace ninguna diferencia si una señal de radar tiene un retraso de unos pocos segundos antes de ser mostrados al operador. En tiempo real de entrada de las aplicaciones de una muestra, realizar el algoritmo, y la salida de una muestra, sobre-y-over. Alternativamente, pueden entrada de un grupo de muestras, realizar el algoritmo, y la salida de un grupo de muestras. Este es el mundo de los procesadores de señal digital. Ahora mirar hacia atrás en la Fig. 28-2 e imaginar que se trata de un filtro FIR de ser implementado en tiempo real. Para calcular la muestra de salida, tenemos que tener acceso a un cierto número de las más recientes muestras de la entrada. Por ejemplo, supongamos que utilizamos ocho coeficientes de este filtro, un 0. un 1. hellip un 7. Esto significa que debemos conocer el valor de las ocho muestras más recientes de la señal de entrada, x n, x n-1, n hellip x -7. Estos ocho muestras deberán ser almacenadas en la memoria y continuamente actualizan a medida que se adquieren nuevas muestras. ¿Cuál es la mejor manera de manejar estas muestras almacenadas La respuesta se almacena en búfer circular. La figura 28-3 ilustra un buffer circular de ocho muestras. Hemos colocado este buffer circular en ocho posiciones de memoria consecutivas, 20041 a 20048. La figura (a) muestra cómo se pueden almacenar las ocho muestras de la entrada en un instante determinado en el tiempo, mientras que (b) muestra los cambios después de la muestra siguiente es adquirido. La idea de búfer circular es que el fin de esta disposición lineal está conectado a su posición de memoria a partir de 20041 es visto como estar al lado de 20048, al igual que 20044 es junto al 20045. Se hace un seguimiento de la matriz por un puntero (una variable cuyo valor es una dirección) que indica dónde reside la muestra más reciente. Por ejemplo, en (a) el puntero contiene la dirección de 20044, mientras que en (b) contiene 20045. Cuando se adquiere una nueva muestra, que sustituye la muestra más antigua de la matriz, y el puntero se mueve una dirección de delante. buffer circular son eficientes porque sólo un valor necesita ser cambiado cuando se adquiere una nueva muestra. Se necesitan cuatro parámetros para gestionar una memoria intermedia circular. En primer lugar, tiene que haber un puntero que indica el inicio de la memoria intermedia circular en la memoria (en este ejemplo, 20041). En segundo lugar, debe haber un puntero que indica el final de la matriz (por ejemplo, 20048), o una variable que contiene su longitud (por ejemplo 8). En tercer lugar, el tamaño de paso de la direccionamiento de memoria debe ser especificado. En la Fig. 28-3 el tamaño de paso es uno. Por ejemplo: Dirección 20043 contiene una muestra, dirección 20044 contiene la muestra siguiente, y así sucesivamente. Esto no ocurre con frecuencia. Por ejemplo, el direccionamiento puede referirse a bytes, y cada muestra puede requerir dos o cuatro bytes para mantener su valor. En estos casos, el tamaño de paso tendría que ser de dos o cuatro, respectivamente. Estos tres valores definen el tamaño y la configuración de la memoria intermedia circular, y no cambiarán durante el funcionamiento del programa. El cuarto valor, el puntero a la muestra más reciente, debe ser modificado a medida que cada nueva muestra se adquiere. En otras palabras, debe ser la lógica del programa que controla cómo se actualiza este cuarto valor basado en el valor de los tres primeros valores. Si bien esta lógica es bastante simple, tiene que ser muy rápido. Este es el punto central de esta discusión DSP debe ser optimizado en el manejo de buffer circular para conseguir la máxima velocidad de ejecución posible. Como acotación al margen, el almacenamiento en búfer circular también es útil en el procesamiento fuera de línea. Considere un programa en el que tanto las señales de entrada y de salida están completamente contenidos en la memoria. Circular isnt de amortiguación necesaria para un cálculo de convolución, ya que cada muestra se puede acceder inmediatamente. Sin embargo, muchos algoritmos se aplican en etapas. con una señal intermedia que se crea entre cada etapa. Por ejemplo, un filtro recursivo lleva a cabo como una serie de biquads opera de esta manera. El método de fuerza bruta es almacenar toda la longitud de cada señal intermedia en la memoria. búfer circular proporciona otra opción: almacenar únicamente las muestras intermedias necesarias para el cálculo a mano. Esto reduce la cantidad requerida de la memoria, a expensas de un algoritmo más complicado. La idea importante es que buffers circulares son útiles para el procesamiento fuera de línea, pero crítico para aplicaciones en tiempo real. Ahora podemos ver los pasos necesarios para implementar un filtro FIR utilizando tampones circulares, tanto para la señal de entrada y los coeficientes. Esta lista puede parecer trivial y overexamined - no es el manejo eficiente de estas tareas individuales es lo que separa a un DSP de un microprocesador tradicional. Para cada nueva muestra, todos los siguientes pasos deben tomarse: El objetivo es hacer que estos pasos se ejecutan rápidamente. Dado que los pasos 6-12 se repiten muchas veces (una vez para cada coeficiente en el filtro), se debe prestar especial atención a estas operaciones. microprocesadores tradicionales deben llevar a cabo por lo general estos 14 pasos en serie (uno tras otro), mientras que los DSP están diseñados para funcionar en paralelo. En algunos casos, todas las operaciones dentro del bucle (pasos 6-12) se puede completar en un solo ciclo de reloj. Deja mirada en la arquitectura interna que permite que esta magnífica performance. Ive lo utilizó para un registro en memoria con un tamaño restringido. Por ejemplo, la aplicación podría escribir entradas de registro al procesar solicitudes de los usuarios. Cada vez que se produjo una excepción (que sería perjudicial para el procesamiento) las entradas de registro actualmente en la memoria serían objeto de dumping junto con él. El beneficio de un buffer circular es, que usted no necesita una cantidad infinita de memoria, ya que las entradas más antiguas quedan anulados automáticamente. El desafio es, que es necesario encontrar un tamaño adecuado para su caso de uso. En el ejemplo anterior, sería muy desafortunado cuando ya se habría anulado el registro de registro con la información vital acerca de la excepción. Algunos sistemas / aplicaciones disponen de herramientas que le permiten extraer el contenido actual de la memoria intermedia en la demanda, y no sólo cuando sería extraen automáticamente (si alguna vez). Creo ETW y los CLRs hincapié en log. entre muchos otros sistemas del núcleo o de alto rendimiento de rastreo / registro, se apliquen de esa manera. El concepto de la utilización de tales tampones para el rastreo en memoria / registro es en realidad bastante común (no quiere decir que este es el único uso - ciertamente no), porque es mucho más rápido que los registros escritos en un archivo / base de datos que nunca podría ser interesado en menos que se produzca un error. Y en una nota relacionada, se ahorra espacio en disco duro. buffers circulares son buenos para los flujos de datos en serie en sistemas embebidos. Microcontroladores a menudo tienen una UART para manejar un byte en serie que entra, estos deben ser almacenados en orden y tratado más tarde (a menudo vienen en bytes a un ritmo más rápido que puedan ser manipulados). El tampón divide de forma efectiva la respuesta de crítica de la sincronización requerida (cuando los bytes entran, en microsegundos) a la respuesta no-crítica de la sincronización de todo el mensaje (por ejemplo, mostrando el mensaje de lo que entró, en milisegundos), por ejemplo: 1) En el momento la recepción de un byte de la UART puede generar una interrupción a la que el software responde al tomar rápidamente el byte recibido y lo empuja en el extremo de la memoria intermedia. 2) Antecedentes rutinas de software pueden comprobar regularmente si el tampón tiene nada en ella todavía y vaciarlo según sea necesario. A medida que el tamaño del buffer circular puede ser definida antes de la compilación del tamaño se limita entonces. Esto ayuda a mejorar la eficiencia del espacio y debe eliminar la corrupción de memoria en una solución de compromiso a la cantidad de bytes puede ser recibida antes de los datos comienza a perderse. Sé que esto es hacer trampa, pero Wikipedia tiene una muy buena explicación. Un buffer circular, cíclico o búfer de memoria cíclica es una estructura de datos que utiliza un único búfer de tamaño fijo como si estuviera conectado de extremo a extremo. Esta estructura se presta fácilmente a los datos de amortiguación arroyos Un ejemplo que podría utilizar posiblemente un buffer circular sobreescritura es con multimedia. Si el tampón se utiliza como el búfer limitado en el problema productor-consumidor entonces es probable que se desea para el productor (por ejemplo, un generador de audio) para sobrescribir los datos antiguos si el consumidor (por ejemplo, la tarjeta de sonido) es incapaz de mantener momentáneamente. Otro ejemplo es el método de síntesis de guía de onda digital que utiliza buffers circulares para simular de manera eficiente el sonido de las cuerdas vibrantes o instrumentos de viento. En lo que respecta a la comparación de las listas de doble ligado, me imagino que realmente depende de lo que usted está utilizando la lista de. Implementación de tampones Cirular parece ser más compleja, por favor (de nuevo) se refieren a la página wiki esto explica la implementación, consideraciones, etc. y también muestra el código de ejemplo. respondió el 31 de Mar 10 en el 14: 25I sabe esto se consigue con impulso según: Pero realmente me gustaría evitar el uso de impulso. He buscado en Google y que no se encuentra ningún ejemplos adecuados o legibles. Básicamente quiero realizar un seguimiento de la media móvil de un flujo continuo de una corriente de números de punto utilizando los más recientes números de 1000 como una muestra de datos flotante. ¿Cuál es la forma más fácil de lograr esto he experimentado con el uso de un conjunto circular, media móvil exponencial de media y un movimiento más sencillo y se encontró que los resultados de la matriz circular satisfizo mis necesidades. preguntó Jun 12 12 de la 04:38 Si sus necesidades son simples, que sólo podría tratar de usar un promedio móvil exponencial. En pocas palabras, se hace una variable acumulador, y por ejemplo el código mira a cada muestra, el código actualiza el acumulador con el nuevo valor. Usted escoge un alfa constante que oscila entre 0 y 1, y calcular esto: Usted sólo tiene que encontrar un valor de alfa en el que el efecto de una muestra dada sólo dura alrededor de 1000 muestras. Hmm, no estoy realmente seguro de que esto es adecuado para usted, ahora que he puesto aquí. El problema es que 1000 es un tiempo bastante largo para una ventana móvil exponencial Im medio no seguro de que es un alfa que se extendería la media de los últimos números de 1000, sin desbordamiento en el cálculo de coma flotante. Pero si querías un medio más pequeño, como 30 números más o menos, esta es una manera muy fácil y rápida de hacerlo. contestado 12 12 Jun a las 04:44 1 en su puesto. La media móvil exponencial puede permitir que el alfa para ser variable. Así que esto permite que se utiliza para calcular los promedios de base de tiempo (por ejemplo, bytes por segundo). Si el tiempo transcurrido desde la última actualización del acumulador es más de 1 segundo, deja que sea la alfa 1,0. De lo contrario, puede dejar alfa (usecs ser desde la última actualización / 1000000). ndash JXH 12 Jun 12 de la 6:21 Básicamente quiero realizar un seguimiento de la media móvil de un flujo continuo de una corriente de números de punto utilizando los más recientes números de 1000 como una muestra de datos flotante. Tenga en cuenta que el siguiente actualiza el total de como elementos como sustituido, evitando O costoso recorrido añadido / (N) para calcular la suma - necesaria para la media - bajo demanda. Total se hace un parámetro diferente de T para soportar, por ejemplo, usando un largo tiempo en el total del 1000 s largas, un int char s, o un doble de flotación total s. Esto es un poco deficiente en ese numsamples podría ir más allá de INTMAX - si la atención que podría utilizar un tiempo largo sin signo. o utilizar un miembro de datos bool extra para grabar cuando el contenedor está lleno, mientras que numsamples primera bicicleta por la matriz (mejor entonces a llamarse algo inocuo como POS). 12 Jun contestado las 12 de la 05:19 se supone que el operador quotvoid (muestra T) es en realidad quot operatorltlt quotvoid (muestra T) quot. ndash oPless Jun 8 14 a las 11:52 oPless ahhh. bien descrito. en realidad quería decir para que sea operador void () (muestra T), pero por supuesto que podía usar cualquier notación te gustó. Fijará, gracias. ndash Tony D Jun 8 14 a las 14: 27A otros han mencionado, se debe considerar un IIR (respuesta al impulso infinita) de filtro en lugar de la FIR (respuesta de impulso finita) de filtro que está utilizando ahora. No hay más que eso, pero a primera vista filtros FIR se implementan como circunvoluciones explícitos e IIR con ecuaciones. El filtro IIR particular, yo uso mucho en los microcontroladores es un filtro de paso bajo monopolar. Este es el equivalente digital de un simple filtro analógico R-C. Para la mayoría de las aplicaciones, estos tendrán mejores características que el filtro de la caja que está utilizando. La mayoría de los usos de un filtro de caja que he encontrado son resultado de que alguien no prestar atención en clase procesamiento digital de señales, no como resultado de la necesidad de sus características particulares. Si lo que desea es atenuar las frecuencias altas que sabe que son el ruido, un filtro de paso bajo monopolar es mejor. La mejor manera de poner en práctica una forma digital en un microcontrolador está generalmente: FILT lt-- FILT FF (NUEVO - FILT) FILT es una pieza de estado persistente. Esta es la única variable persistente que necesita para calcular este filtro. NUEVO es el nuevo valor que el filtro está siendo actualizada con esta iteración. FF es la fracción del filtro. que ajusta la pesadez del filtro. Mira este algoritmo y ver que para FF 0 el filtro es infinitamente pesada ya que la salida no cambia nunca. Para FF 1, es realmente ningún filtro ya que la salida se limita a seguir la entrada. Los valores útiles están en el medio. En sistemas pequeños a elegir FF ser 1/2 N de modo que la multiplica por FF se puede realizar como un desplazamiento a la derecha por la N bits. Por ejemplo, FF puede ser 1/16 y la multiplica por FF, por tanto, un desplazamiento a la derecha de 4 bits. De lo contrario, este filtro sólo necesita una restar y un add, aunque los números en general tienen que ser más amplio que el valor de entrada (más en la precisión numérica en una sección separada más adelante). Normalmente tomar lecturas A / D significativamente más rápido de lo que son necesarios y aplicar dos de estos filtros en cascada. Este es el equivalente digital de dos filtros R-C en serie, y atenúa en 12 dB / octava por encima de la frecuencia de corte. Sin embargo, para A / D lecturas de su ser más relevante para mirar el filtro en el dominio del tiempo considerando su respuesta al escalón. Esto le indica la velocidad de su sistema verá un cambio cuando lo que se está midiendo cambios. Para facilitar el diseño de estos filtros (que sólo significa recoger FF y decidir cómo muchos de ellos en cascada), utilizo mis FILTBITS programa. Se especifica el número de bits de desplazamiento para cada FF en la serie en cascada de filtros, y se calcula la respuesta al escalón y otros valores. La verdad es que por lo general este funciono a través de mi PLOTFILT guión envoltorio. Esto va en FILTBITS, lo que hace que un archivo CSV, después representa el archivo CSV. Por ejemplo, aquí es el resultado de PLOTFILT 4 4: Los dos parámetros para PLOTFILT significan que habrá dos filtros en cascada del tipo descrito anteriormente. Los valores de 4 indican el número de bits de desplazamiento para realizar el multiplicar por FF. Los dos valores FF son, por tanto, 1/16 en este caso. La línea roja es la respuesta al escalón unidad, y es lo más importante a la vista. Por ejemplo, este le dice que si la entrada cambia de forma instantánea, la salida del filtro combinado se asentará a 90 del nuevo valor en 60 iteraciones. Si usted se preocupa por el tiempo de asentamiento 95, entonces usted tiene que esperar unos 73 iteraciones, y el 50 tiempo de establecimiento sólo 26 iteraciones. La traza verde que muestra la salida de un solo pico de amplitud completa. Esto le da una idea de la supresión de ruido aleatorio. Parece que no hay una sola muestra causará más que un cambio de 2,5 en la salida. El trazo azul es para dar una sensación subjetiva de lo que hace este filtro con el ruido blanco. Esta no es una prueba rigurosa ya que no hay ninguna garantía de qué es exactamente lo que el contenido era de los números aleatorios escogidas como la entrada de ruido blanco para esta ejecución de PLOTFILT. Su única para darle una sensación áspera de cuánto va a ser aplastada y la suavidad que es. PLOTFILT, tal vez FILTBITS, y muchas otras cosas útiles, especialmente para el desarrollo de CFP firmware está disponible en la versión de software Herramientas de desarrollo de PIC en mi página de descargas de software. Agregado sobre la precisión numérica que veo de los comentarios y ahora una nueva respuesta que hay interés en discutir el número de bits necesarios para implementar este filtro. Tenga en cuenta que la multiplica por FF creará Log 2 (FF) nuevos bits por debajo del punto binario. En los sistemas pequeños, FF por lo general se elige para que sea 1/2 N de manera que esta multiplicación se convierte en realidad gracias un desplazamiento a la derecha de N bits. FILT tanto, es por lo general un punto entero fijo. Tenga en cuenta que esto no cambia ninguna de las matemáticas desde el punto de vista de los procesadores. Por ejemplo, si se está filtrando 10 lecturas bits A / D y N 4 (FF 1/16), entonces usted necesita 4 bits de fracción por debajo de las lecturas de 10 bits enteros A / D. Una mayoría de los procesadores, youd estar haciendo operaciones de 16 bits enteros debido a las lecturas de 10 bits A / D. En este caso, todavía se puede hacer exactamente los mismos 16 bits opertions enteros, pero comenzar con las lecturas A / D izquierda desplazado por 4 bits. El procesador no sabe la diferencia y tampoco necesita. Hacer las matemáticas, en conjunto, los enteros de 16 bits funciona si se tiene en cuenta que sean 12.4 punto fijo o verdaderos números enteros de 16 bits (16.0 punto fijo). En general, es necesario añadir N bits cada polo del filtro si no quieres añadir ruido debido a la representación numérica. En el ejemplo anterior, el segundo filtro de dos tendría que tener 18 bits de 1044 para no perder información. En la práctica en una máquina de 8 bits que significa valores youd uso de 24 bits. Técnicamente sólo el segundo polo de dos tendría el valor más amplio, pero para simplificar el firmware que suelo usar la misma representación, y por lo tanto el mismo código, para todos los polos de un filtro. Por lo general escribo una subrutina o macro para realizar una operación de polos del filtro, a continuación, aplicar eso a cada polo. Ya sea una subrutina o macro depende de si los ciclos o la memoria del programa son más importantes en ese proyecto en particular. De cualquier manera, yo uso un estado cero para pasar NUEVO a la subrutina / macro, que actualiza FILT, pero también carga que en el mismo estado cero NUEVO estaba. Esto hace que sea fácil de aplicar múltiples polos ya que el FILT actualizada de uno de los polos es la NUEVA de la siguiente. Cuando una subrutina, su utilidad para tener un punto puntero a FILT en la forma en que se actualiza hasta justo después de FILT en la salida. De esa manera la subrutina funciona automáticamente en filtros consecutivos en la memoria si es llamado varias veces. Con una macro que no necesita un puntero ya que se pasa en la dirección que opere en cada iteración. Ejemplos de código Aquí está un ejemplo de una macro como se ha descrito anteriormente para un PIC 18: Y aquí es una macro similar para un PIC 24 o 30 o 33 dsPIC: Ambos ejemplos son implementadas como macros utilizando mi preprocesador PIC ensamblador. que es más capaz que cualquiera de las instalaciones de macro incorporadas. clabacchio: Otra cuestión que debería haber mencionado es la implementación de firmware. Usted puede escribir un solo polo filtro de paso bajo subrutina una vez, luego aplicarlo varias veces. De hecho, yo suelo escribir una subrutina como para tomar un puntero en la memoria al estado del filtro, entonces tengo que avanzar el puntero de modo que pueda ser llamado en la serie fácil de realizar filtros multipolares. ndash Olin Lathrop Abr 20 15:03 12 de la 1. Muchas gracias por sus respuestas - todos ellos. Decidí usar este filtro IIR, pero este filtro no se utiliza como filtro de paso bajo estándar, ya que necesito para promediar los valores del contador y compararlas para detectar cambios en un cierto rango. Puesto que estos valores van ser de dimensiones muy distintas dependiendo del hardware que quería tomar un promedio con el fin de ser capaz de reaccionar a estos cambios específicos de hardware de forma automática. ndash sensslen 21 de mayo a las 12:06 12 Si se puede vivir con la restricción de una potencia de dos número de elementos a la media (es decir, 2,4,8,16,32 etc), entonces la brecha con facilidad y eficacia se puede hacer en una bajo rendimiento micro sin división dedicada, ya que puede hacerse como un desplazamiento de bits. Cada desplazamiento a la derecha es una potencia de dos, por ejemplo: El PO pensaba que tenía dos problemas, que divide en un PIC16 y memoria para su memoria cíclica. Esta respuesta muestra que la división no es difícil. La verdad es que no aborda el problema de memoria, pero el sistema permite SE respuestas parciales, y los usuarios pueden tomar algo de cada respuesta por sí mismos, o incluso editar y combinar respuestas other39s. Dado que algunas de las otras respuestas requieren una operación de división, que son también incompleta, ya que no muestran cómo lograr de manera eficiente esta en un PIC16. ndash Martin Abr 20 12 de la 13:01 Hay una respuesta para un verdadero filtro de media móvil (también conocido como filtro de vagón de carga) con menos requisitos de memoria, si no te importa la disminución de resolución. Se llama un filtro en cascada integrador-peine (CIC). La idea es que usted tiene un integrador que se toma de las diferencias en un período de tiempo, y el dispositivo de llave de bajo consumo de memoria es que por la disminución de resolución, que no tiene que almacenar todos los valores del integrador. Se puede implementar utilizando el siguiente pseudocódigo: Su longitud media móvil efectiva es decimationFactorstatesize pero sólo se necesita para mantener en torno muestras statesize. Obviamente, usted puede obtener un mejor rendimiento si su statesize y decimationFactor son potencias de 2, por lo que los operadores de división y el resto son reemplazados por los cambios y la máscara-ands. Posdata: Estoy de acuerdo con Olin que siempre se debe considerar simples filtros IIR antes de que un filtro de media móvil. Si usted no necesita la frecuencia de la nulos de un filtro de vagón de carga, a 1 o 2 polos polos del filtro de paso bajo es probable que trabajar muy bien. Por otro lado, si se está filtrando a los efectos de decimación (teniendo una entrada de alta Tasa de muestreo y promediando para su uso por un proceso de baja velocidad) y luego un filtro CIC puede ser justo lo que usted está buscando. (Especialmente si se puede usar statesize1 y evitar el buffer circular por completo con sólo un único valor integrador anterior) Theres un análisis a fondo de las matemáticas detrás de usar el filtro IIR de primer orden que Olin Lathrop ya se ha descrito más en la bolsa de pila Procesamiento Digital de Señales (incluye un montón de bonitas imágenes.) la ecuación para este filtro IIR es: esto se puede implementar utilizando sólo los números enteros y sin división, usando el siguiente código (que podría necesitar algo de depuración como yo estaba escribiendo de memoria.) este filtro se aproxima a una media móvil de las últimas muestras K estableciendo el valor de alfa de 1 / K. Para ello, en el código anterior por definir BITS ING LOG2 (K), es decir, para K 16 bits puestos a 4, de 4 K bits puestos a 2, etc (Ill verificar el código que aparece aquí tan pronto como llegue a un cambio y editar esta respuesta si es necesario.) respondieron Jun 23 de las 12 de la 4:04 Heres un filtro de paso bajo de un solo polo (media móvil, con un corte CutoffFrequency frecuencia). Muy sencillo, muy rápido, funciona muy bien, y casi ninguna sobrecarga de la memoria. Nota: Todas las variables tienen el alcance más allá de la función de filtro, excepto la aprobada en newInput Nota: Este es un filtro de una sola etapa. etapas múltiples se pueden conectar en cascada juntos para aumentar la nitidez del filtro. Si usa más de una etapa, usted tendrá que ajustar DecayFactor (como se refiere a la frecuencia de corte) para compensar. Y, obviamente, todo lo que necesita es esas dos líneas colocar en cualquier lugar, ellos no necesitan su propia función. Este filtro tiene un tiempo de aceleración antes de la media móvil representa la de la señal de entrada. Si tiene que pasar por alto que el tiempo de aceleración, sólo puede inicializar media móvil con el primer valor de newInput en lugar de 0, y la esperanza de la primera newInput isnt un valor atípico. (CutoffFrequency / SampleRate) tiene un rango de entre 0 y 0,5. DecayFactor es un valor entre 0 y 1, por lo general cerca de 1. Los flotadores de precisión simple son lo suficientemente bueno para la mayoría de las cosas, yo prefiero dobles. Si tiene que pegarse con números enteros, se puede convertir el Factor DecayFactor y amplitud en enteros fraccionarios, en la que el numerador se almacena como el número entero, y el denominador es una potencia entera de 2 (para que pueda bits de desplazamiento hacia la derecha como de la denominador en lugar de tener que dividir durante el bucle de filtro). Por ejemplo, si DecayFactor 0.99, y desea utilizar números enteros, se puede establecer DecayFactor 0.99 65536 64881. Y a continuación, en cualquier momento se multiplica por DecayFactor en su bucle de filtro, simplemente desplace el resultado 16. Para obtener más información sobre esto, eso es un excelente libro en línea, el capítulo 19 sobre los filtros recursivos: www. dspguide / PS ch19.htm Para el Moving paradigma de media, un enfoque diferente para establecer DecayFactor y AmplitudeFactor que puede ser más relevante para sus necesidades, digamos que desea que los anteriores, alrededor de 6 artículos promediaron juntos, haciéndolo de forma discreta, youd añadir 6 artículos y dividir por 6, por lo se puede establecer el AmplitudeFactor a 1/6, y DecayFactor de (1,0 - AmplitudeFactor). contestada 14 de de mayo de las 12 de la 22:55 todos los demás han comentado a fondo sobre la utilidad de IIR vs. FIR, y en la división de potencias de dos. Id al igual que para dar algunos detalles de implementación. El siguiente funciona bien en pequeños microcontroladores sin FPU. Theres ninguna multiplicación, y si se mantiene N una potencia de dos, toda la división es de un solo ciclo de bits de desplazamiento. Básica memoria cíclica FIR: mantener un tampón de desarrollo de los últimos N valores, y una suma acumulada de todos los valores en la memoria intermedia. Cada vez que una nueva muestra entra, restar el valor más antiguo en la memoria intermedia de SUMA, sustituirla por la nueva muestra, agregar la nueva muestra de SUMA y la suma de salida / N. Modificado memoria cíclica IIR: mantener una suma acumulada de los últimos N valores. Cada vez que una nueva muestra entra, SUM - Suma / N, poner en la nueva muestra y la suma de salida / N. contestada 28 de Ago 13 a las 13:45 Si I39m que la lectura correcta, you39re que describe un primer orden IIR filtrar el valor you39re restando isn39t el valor más antiguo que se está cayendo a cabo, sino que es el promedio de los valores anteriores. De primer orden filtros IIR sin duda puede ser útil, pero I39m no está seguro de lo que quiere decir cuando sugiere que la salida es la misma para todas las señales periódicas. A una frecuencia de muestreo de 10 KHz, la alimentación de una onda cuadrada de 100 Hz en una caja de filtro de 20 etapas producirá una señal que se eleva de manera uniforme para 20 muestras, se sienta alto por 30, gotas uniformemente durante 20 muestras, y se sienta bajo de 30. Un primer orden filtro IIR. ndash SUPERCAT 28 de Ago 13 a las 15:31 dará lugar a una ola que comienza bruscamente niveles crecientes y gradualmente fuera a (pero no en) la máxima de servicio, a continuación, se inicia bruscamente cayendo poco a poco y los niveles rozando (pero no en) el mínimo de entrada. Un comportamiento muy diferente. ndash SUPERCAT 28 13 de agosto a las 15:32 Uno de los problemas es que una media móvil simple puede o no ser útil. Con un filtro IIR, se puede conseguir un buen filtro con relativamente pocas calculadoras. La FIR usted describe sólo puede darle un rectángulo en el tiempo - un sincronismo en frecuencia - y can39t gestionar los lóbulos laterales. Puede ser bien vale la pena para lanzar en unos pocos multiplica enteros para que sea un buen FIR sintonizable simétrica si usted puede ahorrar el reloj avanza. ndash de Scott Seidman 29 de agosto 13 a las 13:50 ScottSeidman: No hay necesidad de multiplica si uno simplemente tiene cada etapa de la FIR o bien de salida de la media de la entrada a esa etapa y su valor almacenado anterior, y luego almacenar la entrada (si uno tiene el rango numérico, se podría utilizar la suma en lugar de la media). Ya sea that39s mejor que un filtro de caja depende de la aplicación (la respuesta al escalón de un filtro de caja con un retraso total de 1 ms, por ejemplo, tendrá un d2 desagradable / dt pico cuando el cambio de entrada, y de nuevo de 1 ms más tarde, pero tendrán el mínimo posible d / dt para un filtro con un retardo de 1 ms total). ndash SUPERCAT Ago 29 de 13 a las 15:25 Como dijo mikeselectricstuff, si realmente se necesita para reducir sus necesidades de memoria, y no te importa su respuesta al impulso de ser un exponencial (en lugar de un impulso rectangular), me gustaría ir para un filtro de media móvil exponencial . Las uso ampliamente. Con ese tipo de filtro, que no necesita ninguna memoria intermedia. Usted no tiene que almacenar muestras N pasadas. Solo uno. Por lo tanto, los requisitos de memoria se cortan en un factor de N. Además, usted no necesita ninguna división para eso. Sólo multiplicaciones. Si usted tiene acceso a la aritmética de punto flotante, usar multiplicaciones en coma flotante. De lo contrario, hacer multiplicaciones de números enteros y se desplaza hacia la derecha. Sin embargo, estamos en 2012, y se lo recomendaría a utilizar compiladores y (MCUs) que le permiten trabajar con números en coma flotante. Además de ser más eficiente de la memoria y más rápido (que no tiene que actualizar los elementos de cualquier buffer circular), yo diría que también es más natural. porque una respuesta de impulso exponencial coincide mejor la forma en la naturaleza se comporta, en la mayoría de los casos. Abr 20 contestado las 12 de la 09:59 Un problema con el filtro IIR, ya que casi tocado por Olin y supercat pero aparentemente ignorada por los demás es que el redondeo a la baja introduce cierta imprecisión (y potencialmente sesgo / truncamiento). suponiendo que N es una potencia de dos, y sólo se utiliza aritmética de enteros, el desplazamiento a la derecha no eliminar sistemáticamente los bits menos significativos de la muestra nueva.

No comments:

Post a Comment