Hier das ältere Breakoutboard BMP085.
Links zeigt das Modul mit dem Sensor von Bosch. Zwei 4K7 Widerstände im I²C Bus sind schon integriert. es Scheint auch ein Spannungsregler auf der Platine zu sein. Auf älteren Beschreibungen steht zwar 3,3 Volt. Mit 5Volt werde ich aber nicht testen zumal der Arduino ja auch 3,3V hergibt.
Rechts die Anschlüsse. Neben der Betriebspannung wird nur SCA und SCL benötigt.
Hier ein kleines Programm von Ladyada zum testen. Das Bild rechts zeigt sie Ausgabe der Messwerte auf das Terminal. Es wird auch die Temperatur gemessen.
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3V DC
Connect GROUND to common ground
History
=======
2013/JUN/17 - Updated altitude calculations (KTOWN)
2013/FEB/13 - First version (KTOWN)
*/
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t sensor;
bmp.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" hPa");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" hPa");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" hPa");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(9600);
Serial.println("Pressure Sensor Test"); Serial.println("");
/* Initialise the sensor */
if(!bmp.begin())
{
/* There was a problem detecting the BMP085 ... check your connections */
Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
while(1);
}
/* Display some basic information on this sensor */
displaySensorDetails();
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
bmp.getEvent(&event);
/* Display the results (barometric pressure is measure in hPa) */
if (event.pressure)
{
/* Display atmospheric pressue in hPa */
Serial.print("Pressure: ");
Serial.print(event.pressure);
Serial.println(" hPa");
/* Calculating altitude with reasonable accuracy requires pressure *
* sea level pressure for your position at the moment the data is *
* converted, as well as the ambient temperature in degress *
* celcius. If you don't have these values, a 'generic' value of *
* 1013.25 hPa can be used (defined as SENSORS_PRESSURE_SEALEVELHPA *
* in sensors.h), but this isn't ideal and will give variable *
* results from one day to the next. *
* *
* You can usually find the current SLP value by looking at weather *
* websites or from environmental information centers near any major *
* airport. *
* *
* For example, for Paris, France you can check the current mean *
* pressure and sea level at: http://bit.ly/16Au8ol */
/* First we get the current temperature from the BMP085 */
float temperature;
bmp.getTemperature(&temperature);
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
/* Then convert the atmospheric pressure, SLP and temp to altitude */
/* Update this next line with the current SLP for better results */
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
Serial.print("Altitude: ");
Serial.print(bmp.pressureToAltitude(seaLevelPressure,
event.pressure,
temperature));
Serial.println(" m");
Serial.println("");
}
else
{
Serial.println("Sensor error");
}
delay(1000);
}
Die Ergebnisse decken sich mit den vom deutschen Wetterdienst.
Hier der Dowload der Adafruitlybrary.
Die Library ist aber kompatibel geblieben. Es wird aber immer noch BMP085 als Sensor angezeigt. Das sollte aber nicht stören da die Messwerte nicht abweichen. Auf dem Breakoutboard ist ein Spannungsregler und auch zwei 4k7 Pullupwiderstände. Ich habe diesmal mit 5V getestet.
Hier nochmal die Vorder und Rückansicht des BMP180.
Der Bmp180 wurde nochmals überarbeiet und ist jetzt der BMP280. Was neu ist ist mir unbekannt.
Die Breakouts die ich jetzt bekommen habe bestehen auch nur aus dem Sensor und 4 Widerständen.
Achtung kein Spannungsregler. Es müssen unbedingt 3,3V sein.
Er funktioniert einwandfrei mit Anschluss an SPI in Verbindung mit dem Adafruit Treiber.
Normalerweise ist für den I2C Adresse 0x77 Standard.
Bei diesem hier ist es 0x76. Das muss in die Library Adafruit_BMP280.h geändert werden.
#define BMP280_ADDRESS (0x76) Dann funktioniert es auch mit I2C
Download BMP280 Library
Download Sensor Library
Hier nochmal der Sketch oberhalbs des Setup habe ich den SPI aktiviert
Projekt Digitaluhr mit Arduino Uno und DS1307
Den Bau des LCD-Shield mit nur 3 Pin sowie die Realtimeclock DS1307 habe ich bereits schon beschrieben.In diesem Projekt wurden die fertigen Shields dann nur noch zusammengesteckt. Das Programm habe ich erweitert so das sich die Uhr auch stellen lässt.
Die Schaltung des Keypads habe ich bereits erläutert. Der Befehl anlogRead liefert je nach gedrückten Knopf einen anderen Wert. Im anhängenden Listing frage ich im Loop ab, ob überhaupt ein Knopf gedrückt wurde. Wenn ja springt das Programm in die Setroutine und erhöht den Inhalt der zugehörigen Varible um 1 gemäß dem dem Wert von analogRead. Da der Wert ungenau ist und sich verändert habe ich nochmal durck 10 geteilt. Dann funktioniert es sicher.
Bei Nachbau oder Verwendung eines gekauften Shields müssen die Werte eventuell im Programm etwas angepasst werden. Leider ist für das Jahr ein Knopf zu wenig. Ich habe mir weitergeholfen in dem ich um das Jahr zu stellen eine Drahtbrücke von GND nach Digital 0 setzte. Der Taste für Minute setzt dann das Jahr um 1 vor.
Hier das Listing.
//Arduino 1.0+ Only
//Arduino 1.0+ Only
//aktuelle Version vom 31.03.2013 Johannes Krumm
#include "Wire.h"
#define DS1307_ADDRESS 0x68
#include <LiquidCrystal595.h>
LiquidCrystal595 lcd(7,8,9); // datapin, latchpin, clockpin
byte zero = 0x00; //workaround for issue #527
byte wert = 0;
void setup(){
Wire.begin();
Serial.begin(9600);
lcd.begin(16,2);
lcd.clear();
// setDateTime(); //MUST CONFIGURE IN FUNCTION
}
void loop(){
printDate();
delay(1000);
// Hier werden die Tasten abgefragt und deren Wert angezeigt. Sprung nach Settime
if (analogRead(0)<1010){settime();lcd.setCursor(9,0);lcd.print(analogRead(0));}else {lcd.setCursor(9,0);lcd.print(" ");}
}
// Wenn dieser Teil auskommentier ist wird die Zeit gesezt. Nach dem ersten setzten muss diese Teil
// wieder einkommentiert werden, sonst wird die Zeit nach jedem Reset oder Start wieder so zurückgesetzt.
// Der auskommentierte Teil kann auch ganz geloescht werden. Die Zeit lässt sich ja per Taste setzen.
/*void setDateTime(){
byte second = 45; //0-59
byte minute = 10; //0-59
byte hour = 22; //0-23
byte weekDay = 6; //1-7
byte monthDay = 23; //1-31
byte month = 3; //1-12
byte year = 13; //0-99
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); //stop Oscillator
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekDay));
Wire.write(decToBcd(monthDay));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(zero); //start
Wire.endTransmission();
}*/
byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
void printDate(){
// Reset the register pointer
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
int second = bcdToDec(Wire.read());
int minute = bcdToDec(Wire.read());
int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
int monthDay = bcdToDec(Wire.read());
int month = bcdToDec(Wire.read());
int year = bcdToDec(Wire.read());
//print the date EG 3/1/11 23:59:59
lcd.setCursor(0,1);
if (monthDay<10)
{lcd.print("0");}
lcd.print(monthDay);
lcd.print(".");
lcd.print(month);
lcd.print(".");
lcd.print(year);
lcd.setCursor(0,0);
if (hour < 10) // correct hour if necessary
{
lcd.print("0");
lcd.print(hour);
}
else
lcd.print(hour);
lcd.print(":");
if (minute < 10) // correct minute if necessary
{
lcd.print("0");
lcd.print(minute);
}
else
lcd.print(minute);
lcd.print(":");
if (second < 10) // correct second if necessary
{
lcd.print("0");
lcd.print(second);
}
else
lcd.print(second);
switch (weekDay) // Ausgabe des Wochentages
{
case 1:
lcd.setCursor(8,1);
lcd.print("Montag ");
break;
case 2:
lcd.setCursor(8,1);
lcd.print("Dienstag");
break;
case 3:
lcd.setCursor(8,1);
lcd.print("Mittwoch");
break;
case 4:
lcd.setCursor(8,1);
lcd.print("Donnerst");
break;
case 5:
lcd.setCursor(8,1);
lcd.print("Freitag ");
break;
case 6:
lcd.setCursor(8,1);
lcd.print("Samstag ");
break;
case 7:
lcd.setCursor(8,1);
lcd.print("Sonntag ");
break;
}
}
void settime(){
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
int second = bcdToDec(Wire.read());
int minute = bcdToDec(Wire.read());
int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
int monthDay = bcdToDec(Wire.read());
int month = bcdToDec(Wire.read());
int year = bcdToDec(Wire.read());
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); //stop Oscillator
if (analogRead(0)/10==0){minute=minute+1; if (minute>=60){minute=0;}}
if (analogRead(0)/10==14){hour=hour+1; if (hour>=24){hour=0;}}
if (analogRead(0)/10==33){month=month+1; if (month>=12){month=0;}}
if (analogRead(0)/10==50){monthDay=monthDay+1; if (monthDay>=31){monthDay=0;}}
if (analogRead(0)/10==74 and digitalRead(0)!=LOW){weekDay=weekDay+1; if (weekDay>=8){weekDay=0;}}
if (analogRead(0)/10==74 and digitalRead(0)== LOW){year=year+1;if (year>30){year=0;} }
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekDay));
Wire.write(decToBcd(monthDay));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(zero); //start
Wire.endTransmission();
}
Der von der Fa. FTDI produzierte FTDI232RL wandelt die USB Pegel in ein RS232 Signal um. Es werden die Pins TX RX DTR und DSR unterstützt. Für das Programmieren des Arduino ist das DTR Signal wichtig, das den zum Programmiervorgang benötigte Reset am Ende erzeugt.
Warnung zur Zeit sind die meisten Chips Nachbauten aus China. Mit der aktuellen Treiberversion werden diese Chips zerstört.
Bis die Situation geklärt ist und ich einwandfreie Ware anbieten kann habe ich diesen Artikel aus meinem Shop entfernt.
Hie ein Bild von einem Selbstbau Arduino.
Der Anschluss ist ganz einfach, Betriebspannung, RS an TX und TX an RX wo bei es einem selbst überlassen bleibt obt man direkt an den Atmega oder oben rechts an die digitalen Anschlüsse lötet.
Damit das ganze funktioniert muss das DTR Signal noch über einen Kondensator an Reset angeschlossen werden.
Laut Schaltung ist es ein 100nf (0,1µf). Das hat bei mir auch funktioniert, aber nur auf dem ersten Board. Ich habe dann einen Elko ich glaube 0,47µf eingebaut.
Wer die Schaltung auch in der Arduino Programmierumgebung nutzen will muss noch einen Bootloader installieren.
Bei Ebay wird der Atmega328p auschließlich mit installiertem Bootloader angeboten. Auch in meinen Bausätzen.
Ansonsten müsst Ihr den Bootloader selbst installieren.
Das geht nur über die ISP Schittstelle mit einem Programmiergerät. Man kann auch in einen vorhandenen Aruino einen ISP Sketch laden und diesen dann als Programmer benutzen. Das Kapitel muss ich noch testen.
Mit dem Bootloader aus der Arduino Version 1.04 hat es bei mir nicht funktioniert. Ich habe dann den Optiboot installiert.
Eine ältere Treibervision kann ich auf Wunsch per Mail schicken. Der Aktuelle Treiber steht bei FTDI zum download zur Verfügung.
Downloads: Optiboot Bootloader
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10
//Adafruit_BMP280 bme; // I2C
//Adafruit_BMP280 bme(BMP_CS); // hardware SPI
Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
void setup() {
Serial.begin(9600);
Serial.println(F("BMP280 test"));
if (!bme.begin()) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
while (1);
}
}
void loop() {
Serial.print(F("Temperature = "));
Serial.print(bme.readTemperature());
Serial.println(" *C");
Serial.print(F("Pressure = "));
Serial.print(bme.readPressure());
Serial.println(" Pa");
Serial.print(F("Approx altitude = "));
Serial.print(bme.readAltitude(1013.25)); // this should be adjusted to your local forcase
Serial.println(" m");
Serial.println();
delay(2000);
}