Ich habe hier eine kleine Wetterstation mit Arduino Mega 2560 und unter anderem einem BMP180 Druck- und Temperatursensor.
Ich möchte die Daten mit Virtual Wire übertragen, was im Prinzip auch funtioniert.
Problem: Sobald ich vw_setup(2000) einbinde, liefert der BMP180 sporadisch falsche Werte, auch ohne angeschlossenen Sender:
19.3.14 11:58:50 12,50°C -73,-60°C 753 hPa 84,30 % 0,69 m/s aus S
19.3.14 11:58:51 12,50°C 21,30°C 1012 hPa 83,0 % 0,69 m/s aus S
19.3.14 11:58:52 12,50°C 21,30°C 1012 hPa 83,0 % 0,68 m/s aus S
19.3.14 11:58:52 12,50°C 21,30°C 1012 hPa 83,0 % 0,67 m/s aus S
19.3.14 11:58:53 12,50°C -87,-80°C 718 hPa 79,60 % 0,67 m/s aus S
Wie wär's mit dem Sketch, der diesen Output erzeugt hat? Ansonsten sind hellseherische Fähigkeiten gefragt und da muss ich passen.
Zudem gehört zu einer solchen Anfrage grundsätzlich ein Link zur verwendeten Hardware, falls möglich gleich zum Datenblatt. Falls die Hardware nicht ein Shield darstellt, das nur auf eine Weise angschlossen werden kann, sollte auch ein Verdrahtungsplan bzw. Schema dabei sein. Und nicht zuletzt einen Link auf die verwendeten Bibliotheken, damit wir auch wissen, welcher Code sonst noch bei Dir läuft.
Pressure: 150757 Pa Altitude: -3482.60 m Temperature: 21.40°C
Pressure: 101129 Pa Altitude: 16.50 m Temperature: 21.40°C
Pressure: 101137 Pa Altitude: 15.83 m Temperature: 21.40°C
Pressure: 150755 Pa Altitude: -3482.05 m Temperature: -187.00°C
Pressure: 150763 Pa Altitude: -3481.15 m Temperature: 21.40°C
Pressure: 101137 Pa Altitude: 16.75 m Temperature: 21.40°C
Pressure: 75244 Pa Altitude: 2440.81 m Temperature: 21.40°C
Der 433-MHz-Sender ist nicht angeschlossen, Hf-Störungen scheiden also aus.
#include <VirtualWire.h>
const int led_pin = 11;
const int transmit_pin = 12;
const int receive_pin = 2;
const int transmit_en_pin = 3;
// Include the Wire library for I2C access.
#include <Wire.h>
// Include the Love Electronics BMP180 library.
#include <BMP180.h>
// 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 = 101325;
void setup()
{
[color=red][font=Verdana] // Wenn diese Inititialisierung eingebaut ist, liefert der BMP 180 falsche Werte:
vw_set_tx_pin(transmit_pin);
vw_set_rx_pin(receive_pin)
vw_set_ptt_pin(transmit_en_pin);
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000); // Bits per sec[/color]
// 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())
{
Serial.println("Connected to BMP180."); // Output we are connected to the computer.
digitalWrite(indicatorLed, HIGH); // Set our LED.
// 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
{
Serial.println("Could not connect to BMP180.");
digitalWrite(indicatorLed, LOW); // Set our LED.
}
}
void loop()
{
if(barometer.IsConnected)
{
// Retrive the current pressure in Pascals.
long currentPressure = barometer.GetPressure();
// Print out the Pressure.
Serial.print("Pressure: ");
Serial.print(currentPressure);
Serial.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.
Serial.print("\tAltitude: ");
Serial.print(altitude);
Serial.print(" m");
// Retrive the current temperature in degrees celcius.
float currentTemperature = barometer.GetTemperature();
// Print out the Temperature
Serial.print("\tTemperature: ");
Serial.print(currentTemperature);
Serial.write(176);
Serial.print("C");
Serial.println(); // Start a new line.
delay(1000); // Show new results every second.
}
}
Lese mal in den Dokus der beiden Lib's nach welche Timer des AVR hier evtl. benutzt werden.
Wenn beide den gleichen Timer verwenden, wird es nicht funktionieren.
Zuerst mal: wenn Du Code postest, musst Du immer Code-Tags verwenden, das Forum-System kann sonst gewisse Teile unterdrücken.
VirtualWire verwendet Timer1, um in regelmässigen Abständen einen Interrupt auszulösen. Da dessen Handler nicht sehr kurz gehalten ist, kann das Timing unter Umständen etwas durcheinander kommen und ggfs. die I2C-Übertragung des BMP180 stören. Da die Lese-Routine der Bibliothek nicht sehr sauber programmiert ist, könnte dies theoretisch sogar zu einem Dead-Lock führen:
char SFE_BMP180::readBytes(unsigned char *values, char length)
// Read an array of bytes from device
// values: external array to hold data. Put starting register in values[0].
// length: number of bytes to read
{
char x;
Wire.beginTransmission(BMP180_ADDR);
Wire.write(values[0]);
_error = Wire.endTransmission();
if (_error == 0)
{
Wire.requestFrom(BMP180_ADDR,length);
while(Wire.available() != length) ; // wait until bytes are ready
for(x=0;x<length;x++)
{
values[x] = Wire.read();
}
return(1);
}
return(0);
}
Der Rückgabewert von Wire.requestFrom() wird nicht geprüft, dafür wird danach unendlich lange gewartet, bis wirklich Daten eingetroffen sind. Das kann verherende Folgen haben. Besser wäre:
char SFE_BMP180::readBytes(unsigned char *values, char length)
// Read an array of bytes from device
// values: external array to hold data. Put starting register in values[0].
// length: number of bytes to read
{
char x;
Wire.beginTransmission(BMP180_ADDR);
Wire.write(values[0]);
_error = Wire.endTransmission();
if (_error == 0)
{
if (Wire.requestFrom(BMP180_ADDR,length) != length) return 0;
for(x=0;x<length;x++)
{
values[x] = Wire.read();
}
return(1);
}
return(0);
}
Allerdings verwendest Du nicht die von Dir verlinkte Bibliothek, denn diese zwei Methoden existieren dort nicht:
// 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();
/*
BMP180.h - Header file for the BMP180 Barometric Pressure Sensor Arduino Library.
Copyright (C) 2012 Love Electronics Ltd (loveelectronics.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Datasheet for BMP180:
http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf
*/
#ifndef BMP180_h
#define BMP180_h
#include <inttypes.h>
#include "../Wire/Wire.h"
#define BMP180_Address 0x77
#define ChipIdData 0x55
#define ControlInstruction_MeasureTemperature 0x2E
#define ControlInstruction_MeasurePressure 0x34
#define Reg_ChipId 0xD0
#define Reg_Control 0xF4
#define Reg_CalibrationStart 0xAA
#define Reg_CalibrationEnd 0xBE
#define Reg_AnalogConverterOutMSB 0xF6
#define Reg_SoftReset 0xE0
#define SoftResetInstruction 0xB6
#define ErrorCode_1 "Entered sample resolution was invalid. See datasheet for details."
#define ErrorCode_1_Num 1
#define BMP180_Mode_UltraLowPower 0
#define BMP180_Mode_Standard 1
#define BMP180_Mode_HighResolution 2
#define BMP180_Mode_UltraHighResolution 3
class BMP180
{
public:
BMP180();
void Initialize(void);
int GetUncompensatedTemperature();
float CompensateTemperature(int uncompensatedTemperature);
long GetUncompensatedPressure();
long CompensatePressure(long uncompensatedPressure);
float GetTemperature();
long GetPressure();
float GetAltitude(float currentSeaLevelPressureInPa);
void SoftReset();
uint8_t SetResolution(uint8_t sampleResolution, bool oversample);
void PrintCalibrationData();
uint8_t EnsureConnected();
uint8_t IsConnected;
char* GetErrorText(int errorCode);
protected:
void Write(int address, int byte);
uint8_t* Read(int address, int length);
void Read2(int address, int length, uint8_t buffer[]);
private:
uint8_t OversamplingSetting;
bool Oversample;
int ConversionWaitTimeMs;
int LastTemperatureData;
int LastTemperatureTime;
int AcceptableTemperatureLatencyForPressure;
int Calibration_AC1;
int Calibration_AC2;
int Calibration_AC3;
unsigned int Calibration_AC4;
unsigned int Calibration_AC5;
unsigned int Calibration_AC6;
int Calibration_B1;
int Calibration_B2;
int Calibration_MB;
int Calibration_MC;
int Calibration_MD;
};
#endif
VirtualWire ist wahrscheinlich auch die Version, die Du einsetzt.
Bitte verwende die hier gepostete Version der BMP180-Bibliothek nicht mehr, die ist furchtbar schlecht programmiert (die Read-Methode ist zum Beispiel schlicht falsch in der Reihenfolge der I2C-Ansteuerung). Schreibe Deinen Sketch mal auf die andere Bibliothek um, vielleicht löst das bereits Dein Problem. Wenn Du dann noch die von mir vorgeschlagene Änderung machst, dürften zumindest weitere Hinweise vorhanden sein, warum Du Probleme hast.
So, ich habe jetzt die Sparfun-Library hier.
Werde ich morgen mal testen.
Die Verdrahtung ist korrekt, einzeln arbeiten die Teile problemlos, nur eben nicht zusammen.
Danke euch allen schonmal für die Hilfe, ich melde mich wieder.