Wetterstation - Probleme mit der Ausführung des Programmes

Guten Tag,

Wir, ein Projektteam der TH Köln, bauen eine Wettterstation inkl. der Programmierung auf.
Die Wetterstation soll können:
-Luftdruck
-Temperatur
-Luftfeuchte
-Windrichtung
-Windgeschwindigkeit
-Niederschlagsmenge

Zu unserem Problem:
Wir verwenden ein Arduino UNO. Wir können alle Sensoren einzelnd auslesen.
Da wir die Werte auf einem Display ausgeben wollen, müssen die Programme zusammengefasst werden.
Das haben wir auch gemacht und anfangs lief das Programm auch so wie wir wollten. Durch das Speichern des Programmes ist anscheinend irgendetwas karput gegangen, da das Programm nun garnicht mehr läuft. Programm wird von Arduino kompeliert und auch hochgeladen, aber der Bildschirm gibt nicht mehr aus.
Kennt jemand dieses Problem?

Der Quellcode befindet sich hinter diesem Eintrag.

Vielen Dank für eure Hilfe!

luftdruck_bmp180_temp_wind_FERTIG.ino (8.17 KB)

Schon mal getestet, ob das Display überhaupt noch läuft?
Also "Hello world" Sketch aufspielen.

Wäre nicht das erste Mal, dass es an Kabel, Verbindung, Lötstelle etc. pp. liegt und man sucht sich den Wolf im Programm.

Ach ja, mich würde mal euer Niederschlagsmesser interessieren. Welcher ist das und wie sind eure Erfahrungen damit?

Es wäre prima, wenn du den Sketch hier postest. Füge den bitte in Code-Tags (Schaltfläche </>) in deinem Thread ein.
Ich kann am Tabled die Datei nicht öffnen.
Und schreibe uns bitte welches Display du verwendest, Link ist auch gut.

THKoelnStudent:
, aber der Bildschirm gibt nicht mehr aus.
Kennt jemand dieses Problem?

Was für ein Problem?

Wenn Dein Programm keine Bildschirmausgaben macht, dann macht es keine.

Nimm mal zum Beispiel Deine loop() Funktion:

void loop()
{
  if(barometer.IsConnected)
  {
...
  }
}

Wenn also die Variable "barometer.IsConnected" nicht true ergibt, dann passiert in der loop() Funktion Deines Programms überhaupt nichts.

Und eine Fehlerbehandlung ist nicht vorgesehen, z.B. in der Art:

void loop()
{
  if(barometer.IsConnected)
  {
...
  }
  else  // Fehlerbehandlung hier
}

Ohne Fehlerbehandlung bekommst Du im Fehlerfall auch nix angezeigt.
So ein Programm macht doch immer das, was Du programmierst.
So what?

Warum soll eigentlich ein fehlender Luftdrucksensor das gesamte Programm in den Abgrund reißen und für den Fall der Nichtverfügbarkeit des Luftdrucksensor komplett alle Betriebsamkeit und jegliche Displayausgaben einstellen und sich tot stellen?

Das ist eine vollkommen beschissene Programmlogik.

Wenn eine Wetterstation 10 Sensoren hat und einer davon fällt aus, dann macht man üblicherweise die Programmlogik so, dass auch beim Ausfall eines Sensors immer noch die 9 anderen Sensoren einwandfrei verarbeitet und die Werte angezeigt werdne, und für den fehlenden Wert vom fehlenden Sensor macht man dann eine Anzeige"---" oder sowas in der Art.

Klaus_ww:
Ach ja, mich würde mal euer Niederschlagsmesser interessieren. Welcher ist das und wie sind eure Erfahrungen damit?

Hallo Klaus, einen Niederschlagsmesser aufzubauen ist sehr simpel, wenn man weiß, wie man messen kann.
Habe damals eine Wetterstation auf einem Firmengelände instand gehalten.
Der Niederschlagsmesser besteht lediglich aus einer Wippe und einem/zwei Endschaltern. Sehr simpel. Der Entschalter wird jedesmal bestätigt,wenn eine Seite der Wippe voll ist. Danach wird die Wippe der anderen Seite befüllt. Einzig das Problem der Dimensioniert bleibt dir überlassen. Die Fläche des Einlasses (zB Trichter) kannst du berechnen. Danach musst du testen, wieviele Impulse (Wippwechsel) zB. ein Liter Wasser auslöst. Fertig :wink:

Sehr cooles Prinzip - wie so oft so einfach dass man selbst nicht draufkommt. Danke!

Gibt auch noch andere Verfahren, die eher denkbar wären. Zum Beispiel mit einer Wägezelle. Aber finde ich DEUTLICH aufwendiger. Die Wägezelle muss dann auch noch richtig gut kalibriert werden. Bei der Wippe kann eigentlich nicht viel schiefgehen, solange diese leichtgängig bleibt. Ist auch ohne geeignetes Kalibrierungsgerät einstellbar.

Ein Messbecher wird mal noch zu Hause haben. Und die Fläche berechnen sollte auch nicht das Problem sein.

// Include the Wire library for I2C access.
#include <Wire.h>
// Include the Love Electronics BMP180 library.
#include <BMP180.h>

#include <LiquidCrystal.h>
#include "DHT.h"
//DHT dht(10, DHT11); //wenn ihr einen DHT 11 benutzt
DHT dht(10, DHT22); //wenn ihr einen DHT 22 benutzt
//Die 10 gibt den digitalen Ein-/Ausgang auf dem Board an, an dem der Datenbus des DHT-Sensors angeschlossen ist
//___________________________________________________________________________________
#define uint unsigned int
#define ulong unsigned long

#define PIN_ANEMOMETER 2 // Digital 2
#define PIN_RAINGAUGE 3 // Digital 3
#define PIN_VANE 5 // Analog 5

// How often we want to calculate wind speed or direction
#define MSECS_CALC_WIND_SPEED 5000
#define MSECS_CALC_WIND_DIR 5000
#define MSECS_CALC_RAIN_FALL 30000

volatile int numRevsAnemometer = 0; // Incremented in the interrupt
volatile int numDropsRainGauge = 0; // Incremented in the interrupt
ulong nextCalcSpeed; // When we next calc the wind speed
ulong nextCalcDir; // When we next calc the direction
ulong nextCalcRain; // When we next calc the rain drop
ulong time; // Millis() at each start of loop().

// ADC readings:
#define NUMDIRS 8
ulong adc[NUMDIRS] = {26, 45, 77, 118, 161, 196, 220, 256};

// These directions match 1-for-1 with the values in adc, but
// will have to be adjusted as noted above. Modify 'dirOffset'
// to which direction is 'away' (it's West here).
char *strVals[NUMDIRS] = {"W","NW","N","SW","NE","O","SO","O"};
byte dirOffset=0;
//___________________________________________________________________________________

LiquidCrystal lcd(12, 11, 5, 4, 1, 0);

// Store an instance of the BMP180 sensor.
BMP180 barometer;
// We are going to use the on board LED for an indicator.
int indicatorLed = 13;

// Store the current sea level pressure at your location in Pascals.
float seaLevelPressure = 102400;

void setup()
{
dht.begin();
lcd.begin(16, 2);
// We start the serial library to output our messages.
//Serial.begin(9600);
// We start the I2C on the Arduino for communication with the BMP180 sensor.
Wire.begin();
// Set up the Indicator LED.
pinMode(indicatorLed, OUTPUT);
// We create an instance of our BMP180 sensor.
barometer = BMP180();
// We check to see if we can connect to the sensor.
if(barometer.EnsureConnected())
{
lcd.setCursor(0,0);
lcd.println("Connected to BMP180."); // Output we are connected to the computer.
digitalWrite(indicatorLed, HIGH); // Set our LED.
delay(1000);

// When we have connected, we reset the device to ensure a clean start.
barometer.SoftReset();
// Now we initialize the sensor and pull the calibration data.
barometer.Initialize();
}
else
{
lcd.setCursor(0,0);
lcd.println("Could not connect to BMP180.");
digitalWrite(indicatorLed, LOW); // Set our LED.
delay(1000);
}
//________________________________________________________
// Serial.begin(9600);
pinMode(PIN_ANEMOMETER, INPUT);
digitalWrite(PIN_ANEMOMETER, HIGH);
digitalWrite(PIN_RAINGAUGE, HIGH);
attachInterrupt(0, countAnemometer, FALLING);
attachInterrupt(1, countRainGauge, FALLING);
nextCalcRain = millis() + MSECS_CALC_RAIN_FALL;
nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
nextCalcDir = millis() + MSECS_CALC_WIND_DIR;
//________________________________________________________
}

//=======================================================
// Interrupt handler for anemometer. Called each time the reed
// switch triggers (one revolution).
//=======================================================
void countAnemometer() {
numRevsAnemometer++;
}
//=======================================================
// Interrupt handler for rain gauge. Called each time the reed
// switch triggers (one drop).
//=======================================================
void countRainGauge() {
numDropsRainGauge++;
}

//=======================================================
// Find vane direction.
//=======================================================
void calcWindDir() {
int val;
byte x, reading;

val = analogRead(PIN_VANE);
val >>=2; // Shift to 255 range
reading = val;

// Look the reading up in directions table. Find the first value
// that's >= to what we got.
for (x=0; x<NUMDIRS; x++) {
if (adc[x] >= reading)
break;
}
//Serial.println(reading, DEC);
x = (x + dirOffset) % 8; // Adjust for orientation
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Dir: ");
lcd.print(strVals[x]); // vorher println !!!
delay(1000);
}

//=======================================================
// Calculate the wind speed, and display it (or log it, whatever).
// 1 rev/sec = 1.492 mph = 2.40114125 kph
//=======================================================
void calcWindSpeed() {
int x, iSpeed;
// This will produce kph * 10
// (didn't calc right when done as one statement)
long speed = 24011;
speed *= numRevsAnemometer;
speed /= MSECS_CALC_WIND_SPEED;
iSpeed = speed; // Need this for formatting below

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Wind: ");
x = iSpeed / 10;
lcd.print(x);
lcd.print('.');
x = iSpeed % 10;
lcd.print(x);
lcd.setCursor(10,0);
lcd.print("(");
lcd.print(strVals[x]);
lcd.print(")");
//lcd.setCursor(0,1);
//calcRainFall(); // ------> !!!
delay(1000);

numRevsAnemometer = 0; // Reset counter
}
//=======================================================
// Calculate the rain , and display it (or log it, whatever).
// 1 bucket = 0.2794 mm
//=======================================================
void calcRainFall() {
int x, iVol;
// This will produce mm * 10000
// (didn't calc right when done as one statement)
long vol = 2794; // 0.2794 mm
vol *= numDropsRainGauge;
vol /= MSECS_CALC_RAIN_FALL;
iVol = vol; // Need this for formatting below

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Rain fall: ");
x = iVol / 10000;
lcd.print(x);
lcd.print('.');
x = iVol % 10000;
lcd.print(x);
lcd.println(); //
delay(1000);
numDropsRainGauge = 0; // Reset counter
}

void loop()
{
if(barometer.IsConnected)
{
// Retrive the current pressure in Pascals.
long currentPressure = barometer.GetPressure();

// Print out the Pressure.
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pressure: ");
lcd.print(currentPressure);
lcd.print(" Pa");

// Retrive the current altitude (in meters). Current Sea Level Pressure is required for this.
float altitude = barometer.GetAltitude(seaLevelPressure);

// Print out the Altitude.
lcd.setCursor(0,1);
lcd.print("Altitude: ");
lcd.print(altitude);
lcd.print(" m");
delay(1000);

// Retrive the current temperature in degrees celcius.
float currentTemperature = barometer.GetTemperature();

// Print out the Temperature
/lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temperature: ");
lcd.print(currentTemperature);
//lcd.write(176);
lcd.print("C");
/

//Auslesen und Zwischenspeichern der Temperarur- und Feuchtigkeitswerte
int t = dht.readTemperature();
int h = dht.readHumidity();

//Anzeigen der Werte
lcd.clear();
lcd.setCursor(0,0); //Selektion 1. Zeile (man beginnt beim Zählen mit 0)
lcd.print("T.: ");
lcd.print(t);
lcd.print("'C");

lcd.setCursor(0,1); //Selektion 2. Zeile
lcd.print("F.: ");
lcd.print(h);
lcd.print("%");
delay(2000);

time = millis();

if (time >= nextCalcSpeed) {
calcWindSpeed();
nextCalcSpeed = time + MSECS_CALC_WIND_SPEED;
}
if (time >= nextCalcDir) {
calcWindDir();
nextCalcDir = time + MSECS_CALC_WIND_DIR;
}
if (time >= nextCalcRain) {
calcRainFall();
nextCalcRain = time + MSECS_CALC_RAIN_FALL;
}

calcRainFall(); // Kann entweder hier benutzt werden oder in der calcWindSpeed()-Funktion weiter oben !!!
lcd.println(); // Start a new line. //
delay(2000); // Show new results every second.
}
}

Sorry das ich mich erst so spät zurück melde.
Einfache Programme funktionieren auf dem Bildschirm einwandfrei.
Bildschirm: http://www.amazon.de/HD44780-Module-Display-Anzeigen-Zeichen/dp/B009GEPZRE/ref=sr_1_1?ie=UTF8&qid=1453208624&sr=8-1&keywords=display+arduino
Niederschlagssensor: http://www.watterott.com/de/Wetter-Messeinheit

Danke!

Wie schon mal geschrieben, setze den Sketch in Code-Tags (Schaltfläche </>), das geht auch nachträglich.

Und bitte auch unsere Kommentare lesen.

<// Include the Wire library for I2C access.
#include <Wire.h>
// Include the Love Electronics BMP180 library.
#include <BMP180.h>

#include <LiquidCrystal.h>
#include "DHT.h"
//DHT dht(10, DHT11); //wenn ihr einen DHT 11 benutzt
DHT dht(10, DHT22); //wenn ihr einen DHT 22 benutzt
//Die 10 gibt den digitalen Ein-/Ausgang auf dem Board an, an dem der Datenbus des DHT-Sensors angeschlossen ist
//___________________________________________________________________________________
#define uint unsigned int
#define ulong unsigned long

#define PIN_ANEMOMETER 2 // Digital 2
#define PIN_RAINGAUGE 3 // Digital 3
#define PIN_VANE 5 // Analog 5

// How often we want to calculate wind speed or direction
#define MSECS_CALC_WIND_SPEED 5000
#define MSECS_CALC_WIND_DIR 5000
#define MSECS_CALC_RAIN_FALL 30000

volatile int numRevsAnemometer = 0; // Incremented in the interrupt
volatile int numDropsRainGauge = 0; // Incremented in the interrupt
ulong nextCalcSpeed; // When we next calc the wind speed
ulong nextCalcDir; // When we next calc the direction
ulong nextCalcRain; // When we next calc the rain drop
ulong time; // Millis() at each start of loop().

// ADC readings:
#define NUMDIRS 8
ulong adc[NUMDIRS] = {26, 45, 77, 118, 161, 196, 220, 256};

// These directions match 1-for-1 with the values in adc, but
// will have to be adjusted as noted above. Modify 'dirOffset'
// to which direction is 'away' (it's West here).
char *strVals[NUMDIRS] = {"W","NW","N","SW","NE","O","SO","O"};
byte dirOffset=0;
//___________________________________________________________________________________

LiquidCrystal lcd(12, 11, 5, 4, 1, 0);

// Store an instance of the BMP180 sensor.
BMP180 barometer;
// We are going to use the on board LED for an indicator.
int indicatorLed = 13;

// Store the current sea level pressure at your location in Pascals.
float seaLevelPressure = 102400;

void setup()
{
dht.begin();
lcd.begin(16, 2);
// We start the serial library to output our messages.
//Serial.begin(9600);
// We start the I2C on the Arduino for communication with the BMP180 sensor.
Wire.begin();
// Set up the Indicator LED.
pinMode(indicatorLed, OUTPUT);
// We create an instance of our BMP180 sensor.
barometer = BMP180();
// We check to see if we can connect to the sensor.
if(barometer.EnsureConnected())
{
lcd.setCursor(0,0);
lcd.println("Connected to BMP180."); // Output we are connected to the computer.
digitalWrite(indicatorLed, HIGH); // Set our LED.
delay(1000);

// When we have connected, we reset the device to ensure a clean start.
barometer.SoftReset();
// Now we initialize the sensor and pull the calibration data.
barometer.Initialize();
}
else
{
lcd.setCursor(0,0);
lcd.println("Could not connect to BMP180.");
digitalWrite(indicatorLed, LOW); // Set our LED.
delay(1000);
}
//________________________________________________________
// Serial.begin(9600);
pinMode(PIN_ANEMOMETER, INPUT);
digitalWrite(PIN_ANEMOMETER, HIGH);
digitalWrite(PIN_RAINGAUGE, HIGH);
attachInterrupt(0, countAnemometer, FALLING);
attachInterrupt(1, countRainGauge, FALLING);
nextCalcRain = millis() + MSECS_CALC_RAIN_FALL;
nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
nextCalcDir = millis() + MSECS_CALC_WIND_DIR;
//________________________________________________________
}

//=======================================================
// Interrupt handler for anemometer. Called each time the reed
// switch triggers (one revolution).
//=======================================================
void countAnemometer() {
numRevsAnemometer++;
}
//=======================================================
// Interrupt handler for rain gauge. Called each time the reed
// switch triggers (one drop).
//=======================================================
void countRainGauge() {
numDropsRainGauge++;
}

//=======================================================
// Find vane direction.
//=======================================================
void calcWindDir() {
int val;
byte x, reading;

val = analogRead(PIN_VANE);
val >>=2; // Shift to 255 range
reading = val;

// Look the reading up in directions table. Find the first value
// that's >= to what we got.
for (x=0; x<NUMDIRS; x++) {
if (adc[x] >= reading)
break;
}
//Serial.println(reading, DEC);
x = (x + dirOffset) % 8; // Adjust for orientation
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Dir: ");
lcd.print(strVals[x]); // vorher println !!!
delay(1000);
}

//=======================================================
// Calculate the wind speed, and display it (or log it, whatever).
// 1 rev/sec = 1.492 mph = 2.40114125 kph
//=======================================================
void calcWindSpeed() {
int x, iSpeed;
// This will produce kph * 10
// (didn't calc right when done as one statement)
long speed = 24011;
speed *= numRevsAnemometer;
speed /= MSECS_CALC_WIND_SPEED;
iSpeed = speed; // Need this for formatting below

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Wind: ");
x = iSpeed / 10;
lcd.print(x);
lcd.print('.');
x = iSpeed % 10;
lcd.print(x);
lcd.setCursor(10,0);
lcd.print("(");
lcd.print(strVals[x]);
lcd.print(")");
//lcd.setCursor(0,1);
//calcRainFall(); // ------> !!!
delay(1000);

numRevsAnemometer = 0; // Reset counter
}
//=======================================================
// Calculate the rain , and display it (or log it, whatever).
// 1 bucket = 0.2794 mm
//=======================================================
void calcRainFall() {
int x, iVol;
// This will produce mm * 10000
// (didn't calc right when done as one statement)
long vol = 2794; // 0.2794 mm
vol *= numDropsRainGauge;
vol /= MSECS_CALC_RAIN_FALL;
iVol = vol; // Need this for formatting below

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Rain fall: ");
x = iVol / 10000;
lcd.print(x);
lcd.print('.');
x = iVol % 10000;
lcd.print(x);
lcd.println(); //
delay(1000);
numDropsRainGauge = 0; // Reset counter
}

void loop()
{
if(barometer.IsConnected)
{
// Retrive the current pressure in Pascals.
long currentPressure = barometer.GetPressure();

// Print out the Pressure.
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pressure: ");
lcd.print(currentPressure);
lcd.print(" Pa");

// Retrive the current altitude (in meters). Current Sea Level Pressure is required for this.
float altitude = barometer.GetAltitude(seaLevelPressure);

// Print out the Altitude.
lcd.setCursor(0,1);
lcd.print("Altitude: ");
lcd.print(altitude);
lcd.print(" m");
delay(1000);

// Retrive the current temperature in degrees celcius.
float currentTemperature = barometer.GetTemperature();

// Print out the Temperature
/lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temperature: ");
lcd.print(currentTemperature);
//lcd.write(176);
lcd.print("C");
/

//Auslesen und Zwischenspeichern der Temperarur- und Feuchtigkeitswerte
int t = dht.readTemperature();
int h = dht.readHumidity();

//Anzeigen der Werte
lcd.clear();
lcd.setCursor(0,0); //Selektion 1. Zeile (man beginnt beim Zählen mit 0)
lcd.print("T.: ");
lcd.print(t);
lcd.print("'C");

lcd.setCursor(0,1); //Selektion 2. Zeile
lcd.print("F.: ");
lcd.print(h);
lcd.print("%");
delay(2000);

time = millis();

if (time >= nextCalcSpeed) {
calcWindSpeed();
nextCalcSpeed = time + MSECS_CALC_WIND_SPEED;
}
if (time >= nextCalcDir) {
calcWindDir();
nextCalcDir = time + MSECS_CALC_WIND_DIR;
}
if (time >= nextCalcRain) {
calcRainFall();
nextCalcRain = time + MSECS_CALC_RAIN_FALL;
}

calcRainFall(); // Kann entweder hier benutzt werden oder in der calcWindSpeed()-Funktion weiter oben !!!
lcd.println(); // Start a new line. //
delay(2000); // Show new results every second.
}
}

Lies dir bitte mal "How to use this forum - please read. " durch.

Und es gibt eine Schaltfläche "Preview".

Student an der TH Köln - und dann nicht lesen, nicht reagieren, nicht verbessern, nicht kommunizieren ... ohne mich, dankeschön >:(

Es scheint, dass Pisa doch Recht hat. :slight_smile:

ElEspanol:
Es scheint, dass Pisa doch Recht hat. :slight_smile:

Meinst Du mangelhaftes Leseverstehen? Also dass er es gelesen hat, aber er hat nicht verstanden, um was es bei "Code-Tags" geht und wie das funktioniert?

Ich vermute ja eher, der bereitet sich momentan viel intensiver auf den Kölner Karneval als auf seine Wetterstation vor, und deshalb kommt er einfach überhaupt nicht dazu, sich in http://forum.arduino.cc/index.php/topic,148850.0.html mal den Punkt "7. If you are posting code or error messages, use "code" tags" überhaupt durchzulesen. Denn schwer zu verstehen ist das dank bebilderter Anleitung im Comic-Stil ja eigentlich nicht.

Zum einen das. Zum anderen hat er ausser 3 ellenlange Code Posts und den Links noch nicht viel gesagt. Wenn ich schon andere Leute um Hilfe bitte, dann gebietet es ja schon der Anstand, dass ich darauf reagiere und die Vorschläge analysiere und teste. Und erst recht als Student.

Was soll denn eigentlich projektiert werden in dem Projektteam? Fertige Hardware kaufen, Code zusammenkopieren und fertig?
Jurs sagte ja schon das keine Ausgabe kommt ohne das Barometer, prüfe mal die Verbindung

Ich befürchte, die heutigen Studenten sind einfach nur überfordert.
Wir müssen da viel Geduld aufbringen, ich habe die aber hier nicht mehr.
Denn lesen und schreiben sollten sie schon können.