Anfänger fragt: Mittelwert aus Sensorwerten (Gewicht)

Das sollte so passen...

Ich persöhnlich mürde mich für die Kräfte die wirken wenn so ein Vogel anfliegt interessieren... Daher wird in dem Code auh die Anflugkurve ungefiltert mitgeschnitten... vieleicht kannst du das mit deinen Tools zu einer Kurve plotten und dann mal posten...

from time import sleep
from statistics import pstdev, mean

# Parameter zum Anpassen
gl_BufferSize = 7
gl_MessIntervall = 0.1
gl_MaxAbweichung = 2.0

# Globale Variablen
gl_Gewichte =[0] * gl_BufferSize
gl_WrPtr = 0

# zum Aufzeichnen der Kräfte die bei einem Anflug oder Abflug auftreten
gl_AnflugkurveSize = 100    # bei einem Messinterval von 0.1 S ist die Kurve maximal 10 s Lang
gl_Anflugkurve = []

def loop():
    global gl_Gewichte
    global gl_MaxAbweichung
    global gl_MessIntervall
    global gl_Gewichte
    global gl_WrPtr
    global gl_Anflugkurve
    global gl_AnflugkurveSize

    Gewicht = MessIrgendwas()

    # Messwerte sind hier als Ringspeicher organisiert
    gl_Gewichte[gl_WrPtr] = Gewicht
    gl_WrPtr += 1
    if (gl_WrPtr >= gl_BufferSize):
        gl_WrPtr = 0

    Abweichung = pstdev(gl_Gewichte)
    if Abweichung < gl_MaxAbweichung:
        Mittelwert = mean(gl_Gewichte)
        # ==> auf das Display oder wo auch immer hin
        print(Mittelwert)  # Nun kann man mit dem Wert machen was immer auch man will

        # Anflugkurve auf den Plotter :-)
        # plot(gl_Anflugkurve)

        gl_Anflugkurve = [] # Kurve resetten für einen neuen Anflugversuch
    else:
        if len(gl_Anflugkurve) < gl_AnflugkurveSize:
            gl_Anflugkurve.append(Gewicht)

    sleep(gl_MessIntervall)

1 Like

Mach mal einen Versuch für mich.
Lies den HX711 nur 1 mal pro Sekunde aus und zeig den Wert an.

Grüße Uwe

1 Like

Danke für den Code :smiley:
Ich mach das alles online über UiFlow2.0
Da gibt es leider keine Library "Statistics" :frowning:

sowas ähnliches hatte ih mir schon gedacht, daher hatte ich numPy erst gar nicht angefasst

def mean(a):
    Summe=0
    for w in a:
        Summe += w
    return Summe / len(a)

def pstdev(a):
    mittelwert = mean(a)
    Summe = 0
    for w in a:
        delta = (w - mittelwert)
        Summe = Summe + (delta * delta)
    return sqrt(Summe / len(a))

1 Like

Vielen Dank :slight_smile:
Ich hab das jetzt so eingebunden:

import os, sys, io
import M5
from time import sleep 
from M5 import *
from hardware import *
from unit import WEIGHTUnit

label0 = None
title0 = None
label1 = None
label2 = None
weight_0 = None

import math
gewicht = None

# Parameter zum Anpassen
gl_BufferSize = 7
gl_MessIntervall = 0.1
gl_MaxAbweichung = 2.0

# Globale Variablen
gl_Gewichte =[0] * gl_BufferSize
gl_WrPtr = 0

# zum Aufzeichnen der Kräfte die bei einem Anflug oder Abflug auftreten
gl_AnflugkurveSize = 100    # bei einem Messinterval von 0.1 S ist die Kurve maximal 10 s Lang
gl_Anflugkurve = []


def btnA_wasClicked_event(state):
  global label0, weight_0
  weight_0.set_calibrate_scale(978)

def mean(a):
    Summe=0
    for w in a:
        Summe += w
    return Summe / len(a)

def pstdev(a):
    mittelwert = mean(a)
    Summe = 0
    for w in a:
        delta = (w - Mittelwert)
        Summe = Summe + (delta * delta)
    return sqrt(Summe / len(a))

def setup():
  global label0, title0, label1, label2, weight_0, gewicht

  weight_0 = WEIGHTUnit((33,32))
  M5.begin()
  Widgets.fillScreen(0x222222)
  label0 = Widgets.Label("label0", 30, 87, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu72)
  title0 = Widgets.Title("Futter/Feed", 3, 0xffffff, 0x0000FF, Widgets.FONTS.DejaVu40)
  label1 = Widgets.Label("Kg", 30, 163, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu24)
  label2 = Widgets.Label(">0<", 30, 224, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu12)

  BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btnA_wasClicked_event)

  weight_0.set_tare()

def loop():
  global label0, title0, label1, label2, weight_0, gewicht, gl_BufferSize, gl_MessIntervall, gl_MaxAbweichung, gl_Gewichte, gl_WrPtr, gl_AnflugkurveSize, gl_Anflugkurve
  M5.update()
  global gl_Gewichte
  global gl_MaxAbweichung
  global gl_MessIntervall
  global gl_Gewichte
  global gl_WrPtr
  global gl_Anflugkurve
  global gl_AnflugkurveSize

  Gewicht = weight_0.get_scale_weight

  # Messwerte sind hier als Ringspeicher organisiert
  gl_Gewichte[gl_WrPtr] = Gewicht
  gl_WrPtr += 1
  if (gl_WrPtr >= gl_BufferSize):
      gl_WrPtr = 0

  Abweichung = pstdev(gl_Gewichte)
  if Abweichung < gl_MaxAbweichung:
      Mittelwert = mean(gl_Gewichte)
      # ==> auf das Display oder wo auch immer hin
      label0.setText(str(Mittelwert))  # Nun kann man mit dem Wert machen was immer auch man will

      # Anflugkurve auf den Plotter :-)
      # plot(gl_Anflugkurve)

      gl_Anflugkurve = [] # Kurve resetten für einen neuen Anflugversuch
  else:
      if len(gl_Anflugkurve) < gl_AnflugkurveSize:
          gl_Anflugkurve.append(Gewicht)

  sleep(gl_MessIntervall)
  

if __name__ == '__main__':
  try:
    setup()
    while True:
      loop()
  except (Exception, KeyboardInterrupt) as e:
    try:
      from utility import print_error_msg
      print_error_msg(e)
    except ImportError:
      print("please update to latest firmware")

Display:

Da komm ich leider nicht weiter :frowning: ist irgendwas im Code falsch?

du hast in deinem Code mit

import math

die gesamte math Bibliothek geladen

dann sollte sqrt() in math.sqrt() geändert werden

1 Like
import os, sys, io
import M5
from time import sleep 
from M5 import *
from hardware import *
from unit import WEIGHTUnit

label0 = None
title0 = None
label1 = None
label2 = None
weight_0 = None

import math
gewicht = None

# Parameter zum Anpassen
gl_BufferSize = 7
gl_MessIntervall = 0.1
gl_MaxAbweichung = 2.0

# Globale Variablen
gl_Gewichte =[0] * gl_BufferSize
gl_WrPtr = 0

# zum Aufzeichnen der Kräfte die bei einem Anflug oder Abflug auftreten
gl_AnflugkurveSize = 100    # bei einem Messinterval von 0.1 S ist die Kurve maximal 10 s Lang
gl_Anflugkurve = []


def btnA_wasClicked_event(state):
  global label0, weight_0
  weight_0.set_calibrate_scale(978)

def mean(a):
    Summe=0
    for w in a:
        Summe += w
    return Summe / len(a)

def pstdev(a):
    mittelwert = mean(a)
    Summe = 0
    for w in a:
        delta = (w - Mittelwert)
        Summe = Summe + (delta * delta)
    return math.sqrt(Summe / len(a))

def setup():
  global label0, title0, label1, label2, weight_0, gewicht

  weight_0 = WEIGHTUnit((33,32))
  M5.begin()
  Widgets.fillScreen(0x222222)
  label0 = Widgets.Label("label0", 30, 87, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu72)
  title0 = Widgets.Title("Futter/Feed", 3, 0xffffff, 0x0000FF, Widgets.FONTS.DejaVu40)
  label1 = Widgets.Label("Kg", 30, 163, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu24)
  label2 = Widgets.Label(">0<", 30, 224, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu12)

  BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btnA_wasClicked_event)

  weight_0.set_tare()

def loop():
  global label0, title0, label1, label2, weight_0, gewicht, gl_BufferSize, gl_MessIntervall, gl_MaxAbweichung, gl_Gewichte, gl_WrPtr, gl_AnflugkurveSize, gl_Anflugkurve
  M5.update()
  global gl_Gewichte
  global gl_MaxAbweichung
  global gl_MessIntervall
  global gl_Gewichte
  global gl_WrPtr
  global gl_Anflugkurve
  global gl_AnflugkurveSize

  Gewicht = weight_0.get_scale_weight

  # Messwerte sind hier als Ringspeicher organisiert
  gl_Gewichte[gl_WrPtr] = Gewicht
  gl_WrPtr += 1
  if (gl_WrPtr >= gl_BufferSize):
      gl_WrPtr = 0

  Abweichung = pstdev(gl_Gewichte)
  if Abweichung < gl_MaxAbweichung:
      Mittelwert = mean(gl_Gewichte)
      # ==> auf das Display oder wo auch immer hin
      label0.setText(str(Mittelwert))  # Nun kann man mit dem Wert machen was immer auch man will

      # Anflugkurve auf den Plotter :-)
      # plot(gl_Anflugkurve)

      gl_Anflugkurve = [] # Kurve resetten für einen neuen Anflugversuch
  else:
      if len(gl_Anflugkurve) < gl_AnflugkurveSize:
          gl_Anflugkurve.append(Gewicht)

  sleep(gl_MessIntervall)
  

if __name__ == '__main__':
  try:
    setup()
    while True:
      loop()
  except (Exception, KeyboardInterrupt) as e:
    try:
      from utility import print_error_msg
      print_error_msg(e)
    except ImportError:
      print("please update to latest firmware")

ok, und wenn du die Wurzel weg lässt ... ich kann das leider bei mir nicht debuggen, da ich die Device nicht habe...

1 Like

Also aus Zeile 47 "return math.sqrt(Summe / len(a))" wird "return Summe / len(a)"?
Da bekomm ich leider exakt den selben Fehler...

Ich hab gerade ein Video gesehen. Könnte das vielleicht auch gehen?

Veruch macht glug :slight_smile:

1 Like

Kannst du ein print oder ein serial.println() vor der Fraglichen Zeile einfügen, damit wir sehen was da susammengerechnet werden soll...

print(a)
print(Summe)
print(len(a))
1 Like

Also so hier:

import os, sys, io
import M5
from time import sleep 
from M5 import *
from hardware import *
from unit import WEIGHTUnit

label0 = None
title0 = None
label1 = None
label2 = None
weight_0 = None

import math
gewicht = None

# Parameter zum Anpassen
gl_BufferSize = 7
gl_MessIntervall = 0.1
gl_MaxAbweichung = 2.0

# Globale Variablen
gl_Gewichte =[0] * gl_BufferSize
gl_WrPtr = 0

# zum Aufzeichnen der Kräfte die bei einem Anflug oder Abflug auftreten
gl_AnflugkurveSize = 100    # bei einem Messinterval von 0.1 S ist die Kurve maximal 10 s Lang
gl_Anflugkurve = []


def btnA_wasClicked_event(state):
  global label0, weight_0
  weight_0.set_calibrate_scale(978)

def mean(a):
    Summe=0
    for w in a:
        Summe += w
    return Summe / len(a)

def pstdev(a):
    mittelwert = mean(a)
    Summe = 0
    for w in a:
        delta = (w - Mittelwert)
        Summe = Summe + (delta * delta)
    print(a)
    print(Summe)
    print(len(a))
    return Summe / len(a)

def setup():
  global label0, title0, label1, label2, weight_0, gewicht

  weight_0 = WEIGHTUnit((33,32))
  M5.begin()
  Widgets.fillScreen(0x222222)
  label0 = Widgets.Label("label0", 30, 87, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu72)
  title0 = Widgets.Title("Futter/Feed", 3, 0xffffff, 0x0000FF, Widgets.FONTS.DejaVu40)
  label1 = Widgets.Label("Kg", 30, 163, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu24)
  label2 = Widgets.Label(">0<", 30, 224, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu12)

  BtnA.setCallback(type=BtnA.CB_TYPE.WAS_CLICKED, cb=btnA_wasClicked_event)

  weight_0.set_tare()

def loop():
  global label0, title0, label1, label2, weight_0, gewicht, gl_BufferSize, gl_MessIntervall, gl_MaxAbweichung, gl_Gewichte, gl_WrPtr, gl_AnflugkurveSize, gl_Anflugkurve
  M5.update()
  global gl_Gewichte
  global gl_MaxAbweichung
  global gl_MessIntervall
  global gl_Gewichte
  global gl_WrPtr
  global gl_Anflugkurve
  global gl_AnflugkurveSize

  Gewicht = weight_0.get_scale_weight

  # Messwerte sind hier als Ringspeicher organisiert
  gl_Gewichte[gl_WrPtr] = Gewicht
  gl_WrPtr += 1
  if (gl_WrPtr >= gl_BufferSize):
      gl_WrPtr = 0

  Abweichung = pstdev(gl_Gewichte)
  if Abweichung < gl_MaxAbweichung:
      Mittelwert = mean(gl_Gewichte)
      # ==> auf das Display oder wo auch immer hin
      label0.setText(str(Mittelwert))  # Nun kann man mit dem Wert machen was immer auch man will

      # Anflugkurve auf den Plotter :-)
      # plot(gl_Anflugkurve)

      gl_Anflugkurve = [] # Kurve resetten für einen neuen Anflugversuch
  else:
      if len(gl_Anflugkurve) < gl_AnflugkurveSize:
          gl_Anflugkurve.append(Gewicht)

  sleep(gl_MessIntervall)
  

if __name__ == '__main__':
  try:
    setup()
    while True:
      loop()
  except (Exception, KeyboardInterrupt) as e:
    try:
      from utility import print_error_msg
      print_error_msg(e)
    except ImportError:
      print("please update to latest firmware")

Meine einzige Ausgabe ist das Display. Ich hab zwar auch eine Konsole bei UiFlow aber die zeigt das hier (das selbe wie auf dem Display:

Ok, dann tut mir es leid, aber da bin ich raus.

Der Code hatte in meiner IDE das gemacht was er sollte... wenn es auf deiner Device nicht funtioniert kann ich das leidere nicht nachvollziehen.

Vieleicht findest du auf der Platform auf der du Programmierst jemanden, der dir helfen kann.

1 Like

Ich danke dir trotzdem für deine Mühe und Zeit :slight_smile:

1 Like

Gerne :slight_smile:

Ich hab mir jetzt einfach ein fertiges Arduino-Programm aus dem Netz drauf gezogen.
Das ist auch ganz gut gemacht und die Anzeige ist auf 10 Gram genau :slight_smile:

Das ist also die Lösung des Threads:

/*
*******************************************************************************
* Copyright (c) 2022 by M5Stack
*                  Equipped with M5Core2 sample source code
*                          配套  M5Core2 示例源代码
* Visit for more information: https://docs.m5stack.com/en/app/scales_kit
* 获取更多资料请访问: https://docs.m5stack.com/zh_CN/app/scales_kit
*
* describe: SCALES KIT WEIGHT UNIT EXAMPLE.
* Date: 2022/02/23
*******************************************************************************
  Connect WEIGHT UNIT to port A (G32/33), calibration instructions: touch button
A to remove the tare weight when there is no load, touch button B, switch the
standard weight value left and right and put down the corresponding weight,
confirm for calibration. 将WEIGHT UNIT连接至端口A(G32/33), 校准说明:
无负重情况下触摸按键A去处皮重,
触摸按键B,左右触摸切换标准重量值并放下对应重量砝码,comfirm进行校准。
  Libraries:
  - [HX711](https://github.com/bogde/HX711)

*/

#include <M5Unified.h>
#include <M5GFX.h>
#include "HX711.h"

M5GFX display;
M5Canvas canvas(&display);

// HX711 related pin Settings.  HX711 相关引脚设置
#define LOADCELL_DOUT_PIN 33
#define LOADCELL_SCK_PIN  32

HX711 scale;

void setup() {
    M5.begin();  // Init M5Stack.  初始化M5Stack
    display.begin();
    canvas.setColorDepth(1);  // mono color
    canvas.createSprite(display.width(), display.height());
    canvas.setTextDatum(MC_DATUM);
    canvas.setPaletteColor(1, GREEN);

    canvas.drawString("Calibration sensor....", 160, 80);
    canvas.pushSprite(0, 0);
    scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);

    scale.set_gain();
    // The scale value is the adc value corresponding to 1g
    scale.set_scale(27.61f);  // set scale
    scale.tare();             // auto set offset
}

char info[100];

void loop() {
    canvas.fillSprite(BLACK);
    canvas.setTextSize(1);
    canvas.drawString("Connect the Weight Unit to PortB(G26,G36)", 160, 40);
    canvas.drawString("Click Btn A for Tare deduction", 160, 55);
    canvas.drawString("Click Btn B Switch to Calibration mode", 160, 70);
    float weight = scale.get_units(10) / 1000.0;
    // float weight = scale.get_units(10) / 1.0;
    canvas.setTextSize(3);
    if (weight >= 0) {
        Serial.printf("Weight: %.2f", weight);
        sprintf(info, "Weight: %.2f", weight);
        canvas.drawString(String(info) + "kg", 160, 150);
        // canvas.drawString(String(info) + "g", 160, 150);
    } else {
        canvas.drawString("Weight: 0kg", 160, 150);
        // canvas.drawString("Weight: 0g", 160, 150);
    }
    M5.update();
    if (M5.BtnA.wasPressed()) {
        scale.tare();
        canvas.drawString("0g Calibration!", 160, 180);
    }
    if (M5.BtnB.wasPressed()) {
        long kg = 5;
        while (1) {
            M5.update();
            canvas.fillSprite(BLACK);
            canvas.setTextSize(1);
            canvas.drawString("Connect the Weight Unit to PortB(G26,G36)", 160,
                              40);
            canvas.drawString("Click Btn A/C to change kg value", 160, 55);
            canvas.drawString("Click Btn B Calibration Comfirm", 160, 70);
            canvas.setTextSize(3);
            canvas.drawString("Calibration:" + String(kg) + "kg", 160, 150);
            canvas.drawString("comfirm", 160, 200);
            canvas.fillTriangle(40, 200, 60, 220, 60, 180, 1);
            canvas.fillTriangle(280, 200, 260, 220, 260, 180, 1);
            canvas.pushSprite(0, 0);
            if (M5.BtnA.isPressed()) {
                kg--;
            }
            if (M5.BtnC.isPressed()) {
                kg++;
            }
            if (M5.BtnB.wasPressed()) {
                break;
            }
            delay(10);
        }
        long kg_adc = scale.read_average(20);
        kg_adc      = kg_adc - scale.get_offset();
        scale.set_scale(kg_adc / (kg * 1000.0));
        // canvas.drawString(String(kg) + "kg Calibration: " + String(kg_adc /
        // (kg * 1000.0)), 160, 180);
        canvas.drawString("Set Scale: " + String(kg_adc / (kg * 1000.0)), 160,
                          180);
        canvas.pushSprite(0, 0);
        delay(1000);
    }
    canvas.pushSprite(0, 0);
}

Hast Du auch mal mit kleinen Gewichten/Massen getestet? Du willst ja den Vogelfutterverbrauch messen. Da geht es nicht um kg.

Gruß Tommy

1 Like

Ok,

du hat eine andere Bibliothek verwendet... die scheint besser zu funktionieren...

Manchmal ist das Gute so nah wie das Interner :slight_smile:

1 Like

Wahrscheinlich sind die Wägezellen zu groß um so genau zu messen, da könntest du recht haben. Kleinere hab ich noch nicht probiert. Diese hier können 50 Kg maximal (4x 50Kg = 200 Kg) - könnte etwas überdimensioniert sein...
Das Projekt soll im Sommer mal den enormen Futterverbrauch anzeigen. Das sind in den Juni-Monaten ca. 10-12 Kg Futter pro Tag, die da weg gehen. Aktuell ist es ca. 1 Kg...

das finde krass... wo fütterst du im Wald an mehreren Stationen ?