Actualmente estoy desarrollando un sistema gráfico LCD para mostrar temperaturas, flujos, voltajes, potencia y energía en un sistema de bomba de calor. El uso de una pantalla LCD gráfica significa que la mitad de mi SRAM y ~ 75% de mi flash han sido utilizados por un búfer de pantalla y cadenas.
Actualmente estoy mostrando cifras mínimas / máximas / promedio de energía A la medianoche, cuando se restablece la cifra diaria, el sistema verifica si el consumo del día está por encima o por debajo del mínimo o máximo anterior, y almacena el valor. El promedio se calcula dividiendo el consumo de energía acumulado por el número de días.
Me gustaría mostrar el promedio diario durante la última semana y mes (4 semanas para simplificar), es decir, un promedio móvil. En la actualidad, esto implica mantener una matriz de valores durante los últimos 28 días y calcular un promedio sobre la matriz completa por mes y los últimos 7 días por semana.
Inicialmente estaba haciendo esto usando una matriz de flotadores (ya que la energía está en la forma "12.12kWh"), pero estaba usando 28 * 4 bytes = 112 bytes (5.4% de SRAM). No me importa tener solo un punto decimal de resolución, así que cambié a usar uint16_t y multiplicar la cifra por 100. Esto significa que 12.12 se representa como 1212 y divido por 100 para mostrar.
El tamaño de la matriz ahora se ha reducido a 56 bytes (¡mucho mejor!).
No hay una forma trivial de reducir la cifra a un uint8_t que pueda ver. Podría tolerar la pérdida de un lugar decimal ("12.1kWh" en lugar de "12.12kWh"), pero el consumo es con frecuencia superior a 25.5kWh (255 es el valor más alto representado por un entero sin signo de 8 bits). El consumo nunca ha sido inferior a 10.0kWh o superior a 35.0kWh, por lo que posiblemente podría restar 10 de las cifras almacenadas, pero sé que algún día superaremos estos límites.
Luego probé el código para empaquetar valores de 9 bits en una matriz. Esto proporciona un rango de 0-51.2kWh y utiliza 32 bytes en total. Sin embargo, acceder a una matriz como esta es bastante lento, especialmente cuando tiene que iterar sobre todos los valores para calcular un promedio.
Entonces mi pregunta es: ¿hay una forma más eficiente de calcular un promedio móvil con tres ventanas: de por vida, 28 días y 7 días? Eficiencia significa menor en términos de uso de SRAM, pero sin la penalización de un gran código. ¿Puedo evitar almacenar todos los valores?
fuente
Respuestas:
Si sus datos tienen una desviación estándar baja, entonces un método sería sumar valores sobre la ventana y luego restar la media de la suma, mientras agrega el nuevo valor.
Esto funcionaría bien si no hay valores atípicos , lo que llevaría al error agregado que tiende a cero con el tiempo.
fuente
puedes usar un método diferente, mantienes el promedio actual y luego haces
No es un promedio móvil real y tiene una semántica diferente, pero puede satisfacer sus necesidades de todos modos.
para un método de cálculo más eficiente para su solución de 9 bits por valor, podría mantener los 8 bits más altos de los valores en una matriz y separar los bits menos significativos:
para establecer un valor necesitas dividirlo
resultando en 2 desplazamientos un AND y un OR y un no
Para calcular el promedio, puede usar varios trucos de bits para acelerarlo:
puede usar una cuenta de bits paralela eficiente para
bitcount()
fuente
¿Qué tal si solo almacenamos la diferencia del valor anterior? En electrónica hay un concepto similar llamado convertidor Delta Sigma, que se utiliza para convertidores DA / AD. Se basa en el hecho de que la medición anterior está razonablemente cerca de la actual.
fuente
¿Por qué no podría simplemente agregar los valores juntos tan pronto como los obtenga? Entonces, lo que quiero decir es que obtienes el valor para el día 1, lo divides por 1 y lo almacenas y el 1 en algún lugar. Luego, multiplica el 1 por el valor y lo sumas al siguiente valor y los divides por 2.
Hacer este método crearía un promedio móvil con dos o tres variables como puedo pensar. Escribiría un código, pero soy nuevo en stackexchange, así que tengan paciencia conmigo.
fuente
Puede acercarse lo suficiente para almacenar 11 valores en lugar de 28 valores, tal vez algo como:
En otras palabras, en lugar de almacenar cada detalle de cada día durante los últimos 27 días, (a) almacene 7 o más valores de información diaria detallada de los últimos 7 días, y también (b) almacene 4 más o menos "resumidos" valores de información total o promedio para cada una de las últimas 4 semanas.
fuente