Go Down

Topic: Ausgabe auf Serial Monitor und ausrechnen eine Zahl (Read 874 times) previous topic - next topic

ht81

Jun 29, 2013, 09:38 pm Last Edit: Jun 29, 2013, 09:40 pm by ht81 Reason: 1
Hallo zusammen,

habe mal wieder ein Problemchen wo ich nicht wirklich weiter komme. Also erstmal kurz was ich machen möchte. Ich habe einen DHT22 und einen BMP085 und möchte Temperatur, Luftfeuchte und Luftdruck auf meinem Serial Monitor ausgeben. Dabei habe ich 2 Probleme.

1. Die Temperatur wird zwar korrekt angezeigt, jedoch mit einem Hieroglyphen. Also zwischen der Temperatur (welches mit Absicht auf eine Stelle nach dem Komma begrenzt ist) und dem °C. Wie bekomme ich das weg, bzw. wieso kommt das? Wo liegt der Fehler?
z.B. hier das Copy aus dem Monitor:

Code: [Select]
Temperatur: 24.2 °C
Luftfeuchte: 55%
Luftdruck Sensor: 99074 hPa
Luftdruck Gerechnet: 964 hPa
 

2. Der Luftdruck wird so gemessen wie unter "Luftdruck Sensor". Soweit so gut. Jedoch Stimmt diese nicht ganz, weil ich diesen Druck noch auf meinen Standort (Meereshöhe) umrechnen muss. Formel hierzu: p0 = 990 hPa / 0,97259771 = 1017,9 hPa. Also 990hPa wird vom Sensor gemessen. Die 0,97259771 ist mein errechneter Exponentialkoeffizient. Ich möchte das der "Luftdruck Gerechnet" die 1017,9 hPa anzeigt und nicht die 964 hPa. Leider sehe ich hier auch nicht meinen Fehler. Zumindest ist es mit meiner jetzigen Art so das ich zumindest überhaupt irgendwas angezeigt bekomme, sonst zeigt er nur 0 hPa an..... Direkte Ausrechnung mit der oben stehende Formel sowie dem Exponentialkoeffizient scheint der Arduino generell nicht zu mögen. Zumindest scheint er falsch zu rechnen? Excel, mein Taschenrechner sowie Windows Taschenrechner rechnen richtig

Anbei noch mein Code (Ist kein endgültiger Code, nur zum Spielen und lernen, bitte nicht wundern):

Code: [Select]
//####################################################################//
//                         Librarys einbinden                         //
//####################################################################//

#include <Wire.h>  // Wire Library
#include <dht.h> // DHT Library

//####################################################################//
//                   Konfiguration DHT Sensor                         //
//####################################################################//

// DHT Library starten
dht DHT;
// Definiere Pin für Innensensor
#define DHT22_PIN 6 // Innensensor
int interval_update = 10000;  // Intervalzeit für Temperaturabfrage (10s)
unsigned long prev_update; // Variable "prev_update" wird als "unsigned long" deklariert

//####################################################################//
//                  Konfiguration BMP085 Sensor                       //
//####################################################################//

#define BMP085_ADDRESS 0x77  // I2C address of BMP085
const unsigned char OSS = 0;  // Oversampling Setting
// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;
short temperature;
float pressure;

//####################################################################//
//                     Konstanten und Variablen                       //
//####################################################################//

float Humidity_Out; // Variable um die Innenluftfeuchte zu speichern
float Temperature_Out; // Variable um die Innentemperatur zu speichern
float k_wert_out = 0.2; // Korrekturwert für den Innensensor
byte Sensor_Out_Fail = 0; // Variable um einen möglichen fehlenden / defekten Innensensor (zu beginn) zu speichern
byte Sensor_Out_Check_Fail = 0; // Variable um einen möglichen fehlenden / defekten Innensensor (zur Laufzeit) zu speichern

//####################################################################//
//                Setup (wird einmalig durchlaufen)                   //
//####################################################################//


void setup(void) // Setup wird einmalig durchlaufen
{
 Serial.begin(9600);
 Wire.begin();
 bmp085Calibration();
 prev_update = millis(); // Millis (Zeit seitdem der µC läuft) wird in Variable "prev" geschrieben
 // Anzahl der angeschlossenen Sensoren auswerten und erste Temperatur- / Luftfeuchte abfrage
 int chk = DHT.read22(DHT22_PIN); // Initialisieren und DHT22_PIN einlesen
     switch (chk){ // Case check
       case DHTLIB_OK: // Wenn DHTLIB_OK
            Humidity_Out = DHT.humidity; // Luftfeuchte in Humidity_In speichern
            Temperature_Out = DHT.temperature - k_wert_out, 1; // Temperatur in Temperature_In abzüglich dem Korrekturwert speichern
            break; // abbrechen
       case DHTLIB_ERROR_CHECKSUM: // Wenn DHTLIB_ERROR_CHECKSUM
            break; // abbrechen
       case DHTLIB_ERROR_TIMEOUT: // Wenn DHTLIB_ERROR_TIMEOUT
            Sensor_Out_Fail = 1; // Innensensor fehlt oder defekt --> eine 1 in Variable schreiben
            break; // abbrechen
       default: // Wenn default
            break; // abbrechen
      }  
}

//####################################################################//
//                Loop (wird ständig durchlaufen)                     //
//####################################################################//

void loop(void)
{
 TemperaturSensor(); // Sensor abfragen und Wert verarbeiten
 LuftfeuchteSensor(); // Sensor abfragen und Wert verarbeiten
 SerialAusgabe(); // Ausgabe auf Serial Monitor
}

void LuftfeuchteSensor()
{
 temperature = bmp085GetTemperature(bmp085ReadUT());
 pressure = bmp085GetPressure(bmp085ReadUP());
 delay(1000);
}

ht81

Teil 2 vom Code:

Code: [Select]
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}

// Calculate temperature given ut.
// Value returned will be in units of 0.1 deg C
short bmp085GetTemperature(unsigned int ut)
{
  long x1, x2;
 
  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;

  return ((b5 + 8)>>4); 
}

long bmp085GetPressure(unsigned long up)
{
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;
 
  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
 
  // Calculate B4
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
 
  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;
   
  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;
 
  return p;
}

// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;
 
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
 
  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available())
    ;
   
  return Wire.read();
}

int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;
 
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
 
  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2)
    ;
  msb = Wire.read();
  lsb = Wire.read();
 
  return (int) msb<<8 | lsb;
}

// Read the uncompensated temperature value
unsigned int bmp085ReadUT()
{
  unsigned int ut;
 
  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();
 
  // Wait at least 4.5ms
  delay(5);
 
  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Read the uncompensated pressure value
unsigned long bmp085ReadUP()
{
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;
 
  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();
 
  // Wait for conversion, delay time dependent on OSS
  delay(2 + (3<<OSS));
 
  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF6);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 3);
 
  // Wait for data to become available
  while(Wire.available() < 3)
    ;
  msb = Wire.read();
  lsb = Wire.read();
  xlsb = Wire.read();
 
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
 
  return up;
}

void SerialAusgabe()
{
  Serial.print("Temperatur: ");
  OutTemperature();
  Serial.println(" °C");
  Serial.print("Luftfeuchte: ");
  HumidityOutside();
  Serial.println("%");
  Serial.print("Luftdruck Sensor: ");
  Serial.print(pressure, DEC);
  Serial.println(" Pa");
  Serial.print("Luftdruck Gerechnet: ");
  Serial.print((((pressure*97259771)/1000000))/10000, 0);
  Serial.println(" hPa");
  Serial.println();
}

void TemperaturSensor() // Loop für die Luftfeuchtesensoren da diese max. alle 2s ausgelesen werden dürfen. Hier wurde der Interval auf 4s gesetzt
{
  if((millis() - prev_update) > interval_update) { // Delay mit Millis damit der µC nach andere Dinge paralell abarbeiten kann
    prev_update = millis(); // Aktuelle millis Zeit in "prev_update" speichern
    int chk = DHT.read22(DHT22_PIN); // Initialisieren und DHT22_PIN einlesen
      switch (chk){ // Case check
        case DHTLIB_OK: // Wenn DHTLIB_OK
            Humidity_Out = DHT.humidity; // Luftfeuchte in Humidity_In speichern
            Temperature_Out = DHT.temperature - k_wert_out, 1; // Temperatur in Temperature_In abzüglich dem Korrekturwert speichern
            Sensor_Out_Fail = 0; // Variable auf 0 zurücksetzen
            Sensor_Out_Check_Fail = 0; // Variable auf 0 zurücksetzen
            break; // abbrechen
        case DHTLIB_ERROR_TIMEOUT: // Wenn DHTLIB_ERROR_TIMEOUT
            Sensor_Out_Check_Fail++; // Sensor_In_Check_Fail hochzählen
            break; // abbrechen
      }
   }
}


void OutTemperature() // Aussentemperatur verarbeiten
{
  if (Sensor_Out_Check_Fail >= 7 || Sensor_Out_Fail == 1) { // Wenn Sensor zur Laufzeit nach 7 Zyklen nicht antwortet oder von Anfang an fehlt dann
    Serial.print("NoDev."); // wird der Text "NoDev." ausgegeben
    Humidity_Out = -999; // -999 in Humidity_Out speichern
  } else {
      if (Temperature_Out >= -40.0 && Temperature_Out <= 60.0) {
       Serial.print(Temperature_Out,1); // Schreibe Temperatur mit nur 1 Nachkommastelle (,1)
      }
    }
}


void HumidityOutside() // Loop für die Luftfeuchte "Outside"
{
  if (Humidity_Out  == -999) { // Wenn Luftfeuchte Wert "-999"
    Serial.print("Err"); // Text " Err"
  } else { // sonst
      if (Humidity_Out >= 0.0 && Humidity_Out <= 100.0) {
        Serial.print(Humidity_Out,0); // Luftfeuchte ohne Nachkommastelle anzeigen
      }
    }
}

Serenifly

#2
Jun 29, 2013, 09:55 pm Last Edit: Jun 29, 2013, 10:00 pm by Serenifly Reason: 1
Wenn du /10000 machst ist das eine Integer-Division und der schneidet dir die Nachkomma-Stellen ab. Mach mal /10000.0
Bei beiden Divisionen

Wegen dem Grad-Zeichen könntest du mal probieren, den ASCII Code dafür mit Serial.write(176) rauszuschreiben. Weiß aber nicht ob er den Extended Table erkennt. Laut dem hier:
http://www.ascii-code.com/

jurs


1. Die Temperatur wird zwar korrekt angezeigt, jedoch mit einem Hieroglyphen. Also zwischen der Temperatur (welches mit Absicht auf eine Stelle nach dem Komma begrenzt ist) und dem °C. Wie bekomme ich das weg, bzw. wieso kommt das? Wo liegt der Fehler?


Dein Arduino Code-Editor arbeitet mit UTF-8 Zeichensatz, das ist ein Zeichensatz, bei dem Sonderzeichen immer 2 Bytes gross sind. Und Dein serieller Monitor stellt jedes eintreffende Byte einzeln dar.

Das ist bei deutschen Umlauten noch schlimmer in der Ausgabe:
Serial.println("äöüß");

Beim °-Zeichen stimmt wenigstens das Lower-Byte, so dass Du beispielsweise die Bytes einzeln definieren könntest:
char gradC[4]={' ','°','C','\0'};
Und zur Ausgabe dann:
Serial.println(gradC);

Was das rechnen mit Gleitkommazahlen betrifft: Rechts vom Gleichheitszeichen sollte mindestens eine Gleitkommazahl in der Rechnung vorkommen, damit eine Gleitkommarechnung und keine Integer-Rechnung durchgeführt wird.

ht81

Hallo ihr beiden,

danke für eure Antworten. Nun klappt es. Danke

Go Up