Hallo,
ich soll mit Hilfe eines Arrays einen flüssigere temperaturanzeige erstellen und dies mit Hilfe eines Mittelwertes der daten. Es sollen insgesamt jeweils aus 10 daten ein Mittelwert entstehen, damit die Temperatur nicht mehr hoch und runter springt sondern "die Sprünge gleiten".Kann mir da vllt jemand helfen.
Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.
mfg ein Moderator.
Hallo
Zeige deinen Sketch, damit wir sehen wie wir helfen können.
Neben dem Feld mit zehn Werten benötigst Du eine Variable für den Index, der auf das älteste Element zeigt. Da schreibst Du den aktuellen wert hin, überschreibst also den ältesten und verschibst den Index auf das nächste Feldelement. Dann bildest Du den anzuzeigenden Mittelwert.
Das nennt sich Mittelwert aus einem Ringpuffer.
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 13, 10, 11, 12);
int tempPin = A0;
byte Speed = 0;
const int RPWM = 2; // connected to pin 7 on the H-bridge
const int LPWM = 3; // connected to pin 2 on the H-bridge
const int enablePin = 9; // connected to pin 1 on the H-bridge
const int directionSwitchPin = 4; // connected to the switch for direction
const int onOffSwitchStateSwitchPin = 5; // connected to the switch for turning the motor on and off
const int sensorPin = A0; // connected to the potentiometer's output
float arrayMid [10];
byte messnr = 0;
int motorEnabled = 0; // Turns the motor on/off
int motorSpeed = 0; // speed of the motor
int motorDirection = 1; // current direction of the motor
void setup() {
// initialize the inputs and outputs
pinMode(RPWM, OUTPUT);
pinMode(LPWM, OUTPUT);
pinMode(enablePin, OUTPUT);
// pull the enable pin LOW to start
lcd.begin(16, 2);
for (int pinNumber = 4; pinNumber < 7; pinNumber++) {
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber, LOW);
}
}
void loop() {
Speed = 255;
int reading = analogRead(sensorPin); // Den Signalausgang des Temperatursensors lesen
float voltage = reading * 5.0; // Umwandlung der Messung in mV
voltage /= 1024.0;
float temperatureC = (voltage - 0.5) * 100 ; // Umrechnung der Spannung in C°
lcd.setCursor(0, 0);
lcd.print(temperatureC);
lcd.print ("\337C");
delay(750);
lcd.clear();
if (temperatureC > 24 && temperatureC < 30) {
analogWrite(9, (25.5 * temperatureC - 510));
analogWrite(RPWM, Speed);
analogWrite(LPWM, 0);
lcd.setCursor(11, 0);
lcd.print ("Rechts");
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
float RPMH = ((25.5 * temperatureC - 510) / 2.55);
lcd.setCursor(0, 15);
lcd.print(RPMH);
}
else if (temperatureC < 22 && temperatureC > 16) {
analogWrite(9, (-25.5 * temperatureC + 663));
analogWrite(RPWM, 0);
analogWrite(LPWM, Speed);
lcd.setCursor(11, 0);
lcd.print ("Links");
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
float RPMC = ((-25.5 * temperatureC + 663) / 2.55);
lcd.setCursor(0, 15);
lcd.print(RPMC);
}
else if (temperatureC >= 22 && temperatureC <= 24) {
analogWrite(RPWM, 0);
analogWrite(LPWM, 0);
lcd.setCursor(11, 0);
lcd.print ("Stop");
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
lcd.setCursor(0, 15);
lcd.print("0%");
}
else if (temperatureC >= 30) {
analogWrite(9, 255);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay (100);
lcd.setCursor(0, 15);
lcd.print("100%");
}
else if (temperatureC <= 16) {
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay (100);
lcd.setCursor(0, 15);
lcd.print("100%");
}
}```
Hier sehe ich eine Kollision:
int tempPin = A0;
...
const int sensorPin = A0; // connected to the potentiometer's output
Naja, die tempartur wird noch weiterhin springen, nur die Ausgabe wird evtl. nicht mehr ganz so extreme Unterschiedwerte haben
Wo klemmt es denn?
10 Werte aufaddieren und das Ergebnis durch 10 teilen?
In Deinem Code ist das recht einfach - alle gelesenen Werte aus dem analogRead nehmen und damit arbeiten.
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 13, 10, 11, 12);
int tempPin = A0;
byte Speed = 0;
const int RPWM = 2; // connected to pin 7 on the H-bridge
const int LPWM = 3; // connected to pin 2 on the H-bridge
const int enablePin = 9; // connected to pin 1 on the H-bridge
const int directionSwitchPin = 4; // connected to the switch for direction
const int onOffSwitchStateSwitchPin = 5; // connected to the switch for turning the motor on and off
const int sensorPin = A0; // connected to the potentiometer's output
float arrayMid [10];
byte messnr = 0;
int motorEnabled = 0; // Turns the motor on/off
int motorSpeed = 0; // speed of the motor
int motorDirection = 1; // current direction of the motor
void setup()
{
// initialize the inputs and outputs
pinMode(RPWM, OUTPUT);
pinMode(LPWM, OUTPUT);
pinMode(enablePin, OUTPUT);
// pull the enable pin LOW to start
lcd.begin(16, 2);
for (int pinNumber = 4; pinNumber < 7; pinNumber++)
{
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber, LOW);
}
for (byte b = 0; b < 10; b++) // Füllt die Elemente mit den ersten Werten
{getVoltage();}
}
uint16_t getVoltage()
{
const byte maxWerte = 10;
static uint16_t readAnalogIn[maxWerte] = {0};
static uint8_t idx = 0;
readAnalogIn[idx] = analogRead(sensorPin); // Den Signalausgang des Temperatursensors lesen
idx++;
if (idx > maxWerte) // Wenn alle Elemente gefüllt
{
idx = 0; // Fange an von vorn
}
uint16_t reading = 0;
for (byte b = 0; b < maxWerte; b++) // ermittlung des gesamtwertes
{
reading += readAnalogIn[b]; // Alle Werte aufaddieren
}
return reading /= maxWerte; // Gibt Gesamt durch Anzahl der Messwerte zurück
}
void loop()
{
Speed = 255;
float voltage = getVoltage() * 5.0; // Umwandlung der Messung in mV
voltage /= 1024.0;
float temperatureC = (voltage - 0.5) * 100 ; // Umrechnung der Spannung in C°
lcd.setCursor(0, 0);
lcd.print(temperatureC);
lcd.print ("\337C");
delay(750);
lcd.clear();
if (temperatureC > 24 && temperatureC < 30)
{
analogWrite(9, (25.5 * temperatureC - 510));
analogWrite(RPWM, Speed);
analogWrite(LPWM, 0);
lcd.setCursor(11, 0);
lcd.print ("Rechts");
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
float RPMH = ((25.5 * temperatureC - 510) / 2.55);
lcd.setCursor(0, 15);
lcd.print(RPMH);
}
else if (temperatureC < 22 && temperatureC > 16)
{
analogWrite(9, (-25.5 * temperatureC + 663));
analogWrite(RPWM, 0);
analogWrite(LPWM, Speed);
lcd.setCursor(11, 0);
lcd.print ("Links");
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
float RPMC = ((-25.5 * temperatureC + 663) / 2.55);
lcd.setCursor(0, 15);
lcd.print(RPMC);
}
else if (temperatureC >= 22 && temperatureC <= 24)
{
analogWrite(RPWM, 0);
analogWrite(LPWM, 0);
lcd.setCursor(11, 0);
lcd.print ("Stop");
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
lcd.setCursor(0, 15);
lcd.print("0%");
}
else if (temperatureC >= 30)
{
analogWrite(9, 255);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay (100);
lcd.setCursor(0, 15);
lcd.print("100%");
}
else if (temperatureC <= 16)
{
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay (100);
lcd.setCursor(0, 15);
lcd.print("100%");
}
}
Hinweis: Ich hab absichtlihc Deine beiden Variablen oben nicht benutzt.
Auch nehme ich immer die ursprünglichen Werte und nicht irgendwelche Zwischenergebnisse.
Ein float braucht mehr Speicher als ein uint16_t
ja danke war noch von ner anderen baustelle
Ich danke dir.
Wenn Du die Zwischenergebnisse nicht brauchst, kannst Du das Array auch komplett weg lassen und reading direkt beschreiben.
Und dann ein ganz gut gemeinter Hinweis:
Du schreibst Dir oben PinVariablen aber im Code benutzt Du magische Numbers.
Mach das nicht.
Was glaubst Du wie lange Du suchst, wenn sich die Pins mal ändern und Du einen Eintarg vergisst.
Noch drei Tipps:
- LCD gibt es auch mit 4x20 und mit I²C-Schnittstelle, benötigt dann nur zwei Datenleitungen als Bus.
- Die Programmbibliothek Noiasca Liquid Crystal wäre die bessere Wahl, kann auch Umlaute.
- Mit float zu rechnen, fühlt sich an wie beim Taschenrechner. Aber Dein Thermometer liefert überhaupt nicht genügend genaue Werte, um in Zehntelgrad anzuzeigen. Daher empfehle ich Dir eine Berechnung nur mit ganzen Zahlen (Integer). Ja, da muß man etwas drüber nachdenken, lohnt sich aber meines Erachtens. Wir sind Dir da gerne behilflich
Habe ich irgendwas übersehen?
Übrigens, bei einer ratiometrischen Messung eines absoluten Wertes, wundert mich ein "hüpfen" nicht wirklich.
Ja, mein Bauchgefühl, was ich immer dann nutze, wenn mir Informationen fehlen
Ein Thermometer, welches nur eine analoge Spannung liefert, keine digitalen Werte, kann doch nur ungenau sein1). Und der ungenaue analoge Eingang eines Arduinos - wir wissen nicht, welcher Typ - macht es nicht besser.
Mein Bauchgefühl ist sehr anpassungsfähig, eben noch Appetit, dann gegessen, jetzt ein großer Espresso für das Wohlbefinden.
Sollte es neue Informationen vom Themensteller @ryvus geben, wird sich mein Bauchgefühl ändern, wie sich ein Fähnchen im Wind dreht.
Selbst Mr. Spock hat vor dem Zeitsprung in die Siebziger die Masse des ihm unbekannten Raumschiffs geschätzt. Ich bin der Evolution für diese Möglichkeit dankbar!
Anm.:
- Ich bitte freundlich um Beachtung der nachfolgenden Beiträge zu diesem Satz!
Nenn eine Funktion, die den Mittelwert von zehn Messungen im Bereich 0 ... 1023 liefert, nicht getVoltage().
getSensorPinMittelwert10();
ist zwar kein schöner Name, passt aber daher gut zur Funktion.
Da sie nicht mehrfach verwendbar ist, ist es ok, dass die Pin-Nr und die Anzahl der Werte intern per MagicNumber bzw eine global definierte Konstante festgelegt sind, aber schön ist es nicht.
mich aschliessend....
Ich würde immer versuchen bis zur Ausgabe nur ganzzahlig zu rechnen.
Da liegst Du falsch. Ein analoges Signal kann auch sehr genau sein. Nur der Fakt, daß ein Signal analog ist, sagt noch nichts über dessen Genauigkeit aus. Ich hatte in meiner vorherigen Arbeit mal ein Gerät, wo ein Teil auf den 100-stel °C genau auf 37,00°C Temperiert wurde. Sensor war ein PT100 und 0,01% genaue Widerstände in der Verstärkerschaltung. Das gleiche Gerät maß einen pH Wert auf 1-tausendstel genau.
Vor dem Aufkommen der schnellen Prozessoren (achzigerjahre) gab es elektrische Analogrechner, die schneller als die digitalen waren.
Grüße Uwe
Mit einem Gruß aus der Vorlesung "Regelungstechnik" mit Bodediagramm und anderen Nachweismethoden.
Ich wollte Dich für die Frage, wie genau Deine Messung eigentlich ist und welche Anzeige sinnvolle Werte zeigt, sensibilisieren. Sollte eine Anzeige von Zehntelgrad entgegen meiner Annahme sinnvoll sein, kann man diese auch in ganzen Zahlen rechnen und erst in der Anzeige das Komma ergänzen.
Meine Aussage "Dein Thermometer liefert überhaupt nicht genügend genaue Werte" sollte Dich zum Nachdenken und ggf. zum Widerspruch ermuntern
@uwefed: Selbstverständlich gibt es hochpräzise analoge Geräte, manche habe ich nur aus der Entfernung gesehen, andere hatte ich im Kofferaum meines Firmenwagens. Allerdings hatte ich noch keine 0,01 % genaue Widerstände in der Hand, da ist mir was entgangen. Die von mir betreuten analogen Regler begnügten sich mit 1 %.
Aber würdest Du einen hochpräzisen Sensor beispielsweise an A0 vom UNO anschließen? Das ist doch Perlen vor die Säue werfen! Auch wenn Deine Ausführungen durchaus richtig sind, gehen sie meiner Meinung nach daher am Thema vorbei.
Hallo,
@ryvus , für eine Mittelwertberechnung mit 10 Werten hast Du eine Lösung bekommen. Eine andere Variante wäre eine gleitende Mittelwertbildung. (Tiefpass) Gerade um Messwerte stabil zu bekommen finde ich die Lösung gut geeignet. Zudem lässt sich das mit nur zwei zusätzlichen Codezeilen realisieren.
Heinz
Braucht auch weniger RAM.
Simuliert ein RC-Glied zur Glättung.