ATmega328P.pdf ( Register summary on p 428 )
SPI-enheten - Väderstationen
Tänk om man hade en egen barometer. Då skulle man kunna göra egna väderprognoser genom att läsa av lufttrycket och se hur det förändras.
Det normala lufttrycket (vid havsnivå) är 1013 hPa (hekto Pascal).
Över 1020 hPa så råder högtryck och under 1005 hPa så är det lågtryck.
Räkna med regn om lufttrycket faller med mer än 3 hPa/timme.
Lufttrycket sjunker med ökande höjd över havet med 1 hPa/10 m (egentligen 1hPa/8m). En barometern kan därför också användas som "höjdmätare".
Barometerdata är vanligtvis omräknade till vad som skulle gälla vid havsytans nivå. Klassiska mekaniska barometrar brukar ha en justerskruv på baksidan så att barometern kan kalibreras.

BOSCH BMP280 Digital Pressure Sensor är en trycksensor med exeptionella data. Upplösningen är 0.12 hPa motsvarande en höjdskillnad på 1m.
Denna höga prestanda har uppnåtts genom att varje sensor har lagrade individuella kalibreringskonstanter, som den avläsande mikroprocessorn använder i en kompensationsformel. Sensorn har en inbyggd temperaturgivare så även chip-temperaturen används vid beräkningen av tryckvärdet.

Med en sensor som är mindre än ett "riskorn" är det inte konstigt om hobbyister väljer att köpa ett breakoutboard med sensorn färdiglödd på plats.
För användning tillsammans med Arduino UNO så måste man då köpa ett kort som har inbyggd omvandling från 5V till 3V logiknivå (tex. Adafruit "BMP280 I2C or SPI Barometric Pressure & Altitude Sensor").
OBSERVERA att BMP280 inte tål 5V logiknivåer!

SPI, Serial Peripheral Interface, är en buss för synkron seriekommunikation mellan en masterenhet (Master) och en slavenhet (Slave).
Bussen har fyra signaler, SCLK Serial CLocK från Mastern,
MOSI Master Out Slave In, MISO Master In Slave Out,
och en SS (aktivt låg) Slave Select signal som aktiverar slavenheten. Det går bra att ha flera slavenheter anslutna samtidigt,
varje slavenhet har i så fall en egen SS signal.
Det är bara den slavenhet som ska aktiveras som kopplas in "elektriskt" till bussen (sk. tristate).
Master och Slave består av varsitt 8 bitars skiftregister som kopplats så att data skiftas runt (i en ring). Efter 8 klockpulser har datat bytt plats, man kan säga att Master och Slave både sänder och tar emot data samtidigt.
Mastern måste kunna ställa in en passande klockfrekvens.
Klockpulserna kan vidare börja från ett viloläge som är 0 eller som är 1,
skiftregistren kan klockas med stigande eller fallande flanker, totalt fyra sådana "SPI-Moder" kan behöva kunna ställas in.
Skiftordningen kan vara från bit 7 till 0 eller från bit 0 till 7. Det saknas en formell standard för SPI-bussen.
Man får helt enkelt noga läsa i datablad för att se vilket format den Slave-enhet man vill använda behöver.
ATmega328P processorn på Arduinokortet har en inbyggd SPI-enhet. Den styrs från registren SPCR spi-control register, och SPSR spi-status register.
Pinnen SS styrs inte av spi-enheten när den används som Master,
utan den får man hantera i programmet som en vanlig port-pinne.
Kretsen BMP280 kräver att SS är låg vid uppstart -
annars antas att man vill använda I2C till kommunikationen i stället för SPI.
Viloläget för SS är hög, för att sedan hållas låg vid all kommunikation.
Så fort kommunikationen kommer igång upptäcker BMP280 vilken av de olika SPI-Moderna det är som används, och anpassar sig därefter till detta!
Funktionen: void SPI_init(); gör de nödvändiga inställningar av SPI-enheten.
Funktionerna: void SPI_masterTransmitByte(unsigned char data); och unsigned char SPI_masterReceive(); används för att sända och ta emot data. De använder registren SPDR spi-dataregister och SPSR spi-statusregister.
Man ansluter BMP280-kortet till +5V och GND från Arduino.
Kortet har en egen +3.3V spänningsregulator och inbyggd omvandling av logiknivåerna.
Signalerna ansluts som SCK(D13)-SCK, MISO(D12)-SDO, MOSI(D11)-SDI, SS(D10)-CSB.
Det behövs ett litet program som läser BMP280-chippets ID-register som innehåller ID numret. Detta nummer är "0x58". Om man inte får det värdet vid läsningen måste man dra slutsatsen att man troligen kopplat något fel!
BMP280_CQ.txt
(for Arduino store code as: BMP280_CQ\BMP280_CQ.ino)Varje chip innehåller 12 individuella kalibreringskonstanter som 16 Bitarstal (för Arduino "int"). De ligger lagrade som 8 bitarstal i 24 register. Dessa 24 register måste läsas och därefter måste de 12 konstanterna sammansättas. Konstanterna behövs för att kunna beräkna noggranna mätvärden.
Programmet: BMP280_calibration.c skriver ut dessa konstanter på Arduinos seriella monitor på ett sådant format att de direkt kan kopieras och klistras in i programkod för just detta exemplar av chippet.
BMP280_calibration.txt
(for Arduino store code as: BMP280_calibration\BMP280_calibration.ino)
Det står ingenstans i kretsens datablad vad de olika kalibreringskonstanterna innebär eller vad de har för någon funktion.
I stället ges en färdig kompensationsformel. Indata till formeln,
liksom utdata är 32 bitars heltalsvariabler (för Arduino "long int").
Internt i formeln används 64 bitars heltalsvariabler för multiplikationer (för Arduino "long long int").
Beräkningarna använder "fixed point" format Q24.8 (24 heltals bitar och 8 bråkdels bitar).
Detta innebär att man gör alla beräkningar med heltal, men att man "tänker sig" en binärpunkt vid 8 bitar.
(Precis som ett ekonomiprogram som räknar med ören och sedan skjuter in ett decimalkomma efter två decimaler för att ange resultatet i kronor).
Man vill undvika att behöva ta med det skrymmande kodbiblioteket för flyttal
eftersom processorn är på 8 bitar och den har begränsat med minne.
I databladet finns det angivet typiska värden för konstanterna, och vilket resultat man ska få om man använder kompensations-formeln med dessa värden.
När man skriver av en komplicerad formel från ett datablad finns det alltid en risk för missförstånd, eller för felaktig avskrivning. Programmet: BMP280_calculations.c genomför beräkningarna med databladets konstanter och, som det visar sig, ger rätt resultat.
BMP280_calculations.txt
(for Arduino store code as: BMP280_calculations\BMP280_calculations.ino)För en barometer räcker det med att göra en mätning i minuten. Det behövs inte heller någon filtrering av mätvärdet. BMP280's strömförbrukning blir då låg, liksom egenuppvärmningen av sensorn. Man kan då räkna med att temperaturvärdena motsvarar omgivningstemperaturen.
BMP280 kan även användas till annat, som att upptäcka ett kraftigt höjdfall vid drakflygning,
eller vilken våning en hiss står på i ett höghus.
Då krävs helt andra inställningar av mätintervall och filtrering av mätdata.
barometer.txt
(for Arduino store code as: barometer\barometer.ino)En barometer som läses av en gång i minuten (!) är inte en så krävande uppgift att den kräver en dedikerad SPI-enhet i den processor man använder. Det går naturligtvis att programmera hela dataöverföringen bit för bit, med BitBanging.
Programmet BMP280_CQ_BB.c motsvarar det tidigare presenterade programmet BMP280_CQ.c med den skillnaden att SPI-funktionerna är skrivna utan användning av SPI-enheten. Anslutningarna av BMP280 sensorn har behållits och är desamma, men de kan nu omdefinieras till valfria pinnar på processorn om man så önskar.
BMP280_CQ_BB.txt
(for Arduino store code as: BMP280_CQ_BB\BMP280_CQ_BB.ino)Programmen BMP280_calibration_BB.c och barometer_BB.c motsvarar de tidigare presenterade programmen BMP280_calibration.c och barometer.c med samma skillnad att SPI-funktionerna är skrivna utan användning av SPI-enheten.
BMP280_calibration_BB.txt
(for Arduino store code as: BMP280_calibration_BB\BMP280_calibration_BB.ino)
barometer_BB.txt
(for Arduino store code as: barometer_BB\barometer_BB.ino)
Mer om I2C, TWI-enheten (I2C-Buss).
Bosch lufttryckssensor BMP280 kan alternativt kommunicera med I2C-bussen. Det är svårt att veta varför någon skulle välja I2C-bussen före SPI-bussen eller tvärtom, men valfrihet är ju alltid bra.
Om CSB är ansluten till "1" så väljs I2C. På Adafruit BMP280 breakoutboard så är CSB ansluten via en resistor till "1". (I våra SPI exempel har programmen startat med att hålla CSB på "0" så att det är SPI som blivit valt av sensorn.)
Vid I2C har sensorn två alternativa enhets adresser, så två stycken BMP280 kan vara anslutna till samma I2C-buss utan risk för adresskollision. Enhetsadressen ställs in med SDO. På Adafruit BMP280 breakoutboard håller en pullupresistor SDO på "1" och då är 7-bitars enhetsadressen 0x77.

// BMP280 7-bit device address is 0x77 (with SDO = 1 default by pullup) #define BMP280_WR_ADDRESS 0xEE // 8-bit write address #define BMP280_RD_ADDRESS 0xEF // 8-bit read address // BMP280 alternative 7-bit device address is 0x76 (with SDO = 0, GND) // #define BMP280_WR_ADDRESS 0xEC // 8-bit write address // #define BMP280_RD_ADDRESS 0xED // 8-bit read address
BMP280_CQ_I2C.txt
(for Arduino store code as: BMP280_CQ_I2C\BMP280_CQ_I2C.ino)
BMP280_calibration_I2C.txt
(for Arduino store code as: BMP280_calibration_I2C\BMP280_calibration_I2C.ino)
barometer_I2C.txt
(for Arduino store code as: barometer_I2C\barometer_I2C.ino)
Med två BMP280 kan man göra en differentiell mätning. Om man till exempel vill veta vätskenivån i en tank, kan man mäta trycket i botten av tanken med en slang och en BMP280 (#1). Då inkluderas också lufttrycket vid vätskeytan - men det kan man dra ifrån om man också mäter lufttrycket med en andra BMP280 (#2).
William Sandqvist willsandqvist@gmail.com