Actuellement, je développe un système LCD graphique pour afficher les températures, les débits, les tensions, la puissance et l'énergie dans un système de pompe à chaleur. L'utilisation d'un écran LCD graphique signifie que la moitié de ma SRAM et ~ 75% de mon flash ont été utilisés par un tampon d'écran et des chaînes.
J'affiche actuellement des chiffres d'énergie min / max / moyenne À minuit, lorsque le chiffre journalier est réinitialisé, le système vérifie si la consommation pour la journée est supérieure ou inférieure au minimum ou au maximum précédent, et enregistre la valeur. La moyenne est calculée en divisant la consommation d'énergie cumulée par le nombre de jours.
Je voudrais afficher la moyenne quotidienne de la dernière semaine et du dernier mois (4 semaines pour plus de simplicité), c'est-à-dire une moyenne mobile. Actuellement, cela implique de maintenir un tableau de valeurs pour les 28 derniers jours et de calculer une moyenne sur l'ensemble du tableau pour les mois et les 7 derniers jours pour les semaines.
Au départ, je faisais cela en utilisant un tableau de flotteurs (car l'énergie est sous la forme "12.12kWh"), mais cela utilisait 28 * 4 octets = 112 octets (5,4% de SRAM). Cela ne me dérange pas d'avoir une seule décimale de résolution, j'ai donc changé en utilisant uint16_t et en multipliant le chiffre par 100. Cela signifie que 12,12 est représenté par 1212 et que je divise par 100 à des fins d'affichage.
La taille du tableau est désormais réduite à 56 octets (bien mieux!).
Il n'y a aucun moyen trivial de réduire le chiffre à un uint8_t que je puisse voir. Je pouvais tolérer la perte d'une décimale ("12,1 kWh" au lieu de "12,12 kWh"), mais la consommation est souvent supérieure à 25,5 kWh (255 étant la valeur la plus élevée représentée par un entier non signé 8 bits). La consommation n'a jamais été inférieure à 10,0 kWh ou supérieure à 35,0 kWh, donc je pense que je pourrais soustraire 10 des chiffres stockés, mais je sais qu'un jour nous dépasserons ces limites.
J'ai ensuite testé du code pour emballer des valeurs 9 bits dans un tableau. Cela donne une plage de 0 à 51,2 kWh et utilise au total 32 octets. Cependant, l'accès à un tableau comme celui-ci est assez lent, surtout lorsque vous devez parcourir toutes les valeurs pour calculer une moyenne.
Ma question est donc - existe-t-il un moyen plus efficace de calculer une moyenne mobile avec trois fenêtres - durée de vie, 28 jours et 7 jours? L'efficacité signifie moins en termes d'utilisation de SRAM, mais sans la pénalité d'un code énorme. Puis-je éviter de stocker toutes les valeurs?
la source
Réponses:
Si vos données ont un faible écart-type, une méthode consiste à additionner les valeurs sur la fenêtre, puis à soustraire la moyenne de la somme, tout en ajoutant la nouvelle valeur.
Cela fonctionnerait bien s'il n'y avait pas de valeurs aberrantes , ce qui conduirait à l'erreur agrégée tendant à zéro au fil du temps.
la source
vous pouvez utiliser une méthode différente, vous gardez la moyenne actuelle et ensuite
ce n'est pas une vraie moyenne mobile et a une sémantique différente, mais cela peut néanmoins correspondre à vos besoins
pour une méthode de calcul plus efficace pour votre solution à 9 bits par valeur, vous pouvez conserver les 8 bits les plus élevés des valeurs dans un tableau et séparer les bits les moins significatifs:
pour définir une valeur dont vous avez besoin pour le diviser
résultant en 2 décalages un ET et un OU et un non
pour calculer la moyenne, vous pouvez utiliser différentes astuces pour l'accélérer:
vous pouvez utiliser un nombre de bits parallèle efficace pour le
bitcount()
la source
Que diriez-vous de ne stocker que la différence par rapport à la valeur précédente? En électronique, il existe un concept similaire appelé convertisseur Delta Sigma, qui est utilisé pour les convertisseurs DA / AD. Elle repose sur le fait que la mesure précédente est raisonnablement proche de la mesure actuelle.
la source
Pourquoi ne pourriez-vous pas simplement additionner les valeurs dès que vous les avez obtenues. Donc, ce que je veux dire, c'est que vous obtenez la valeur pour le jour 1, vous la divisez par 1 et la stockez et le 1 quelque part. Ensuite, vous multipliez le 1 par la valeur et l'ajoutez à la valeur suivante et les divisez tous les deux par 2.
Faire cette méthode créerait une moyenne mobile avec deux ou trois variables comme je peux le penser. J'écrirais du code mais je suis nouveau sur stackexchange, alors soyez indulgent avec moi.
la source
Vous pouvez vous rapprocher suffisamment en stockant 11 valeurs plutôt que 28 valeurs, peut-être quelque chose comme:
En d'autres termes, plutôt que de stocker chaque détail de chaque jour au cours des 27 derniers jours, (a) stocker 7 ou plus de valeurs d'informations quotidiennes détaillées pour les 7 derniers jours, et (b) stocker 4 ou plus "résumées" valeurs des informations totales ou moyennes pour chacune des 4 dernières semaines environ.
la source