czwartek, 18 sierpnia 2016

[26] Arduino - Cyfrowy czujnik ciśnienia MPL3115A2

Tym razem chciałbym opisać sposób obsługi cyfrowego czujnika z interfejsem I2C. Pozwala on na pomiar takich parametrów jak ciśnienie, wysokość nad poziomem morza oraz temperaturę.

MPL3115A2 - Opis


Parametry czujnika:

  • Wartość napięcia zasilania od 1,95 do 3,6V;
  • Wyprowadzenia pracują z napięciem od 1,6V do 3,6V;
  • Komunikacja poprzez interfejs I2C;
  • Barometr: zakres pracy od 50 do 110 kPa, dokładnosć +/- 0,05kPa, rozdzielczość 20 bitów;
  • Termometr: zakres pomiarowy od -40 do 85 st. C, dokładność +/- 1 st. C dla 25 st. C, +/- 3 w pozostałym zakresie;
  • Wysokość: dokładność do 30cm, rodzielczość 20 bitów;
  • Wbudowana kolejka FIFO;


MPL3115A2 pressure sensor breakout board
Rys. 1. Moduł Sparkfun z czujnkiem MPL3115A2

Płytka przedstawiona na rysunku zawiera czujnik MPL3115A2. Dodatkowo na płytce umieszczono dodatkowe kondensatory filtrujące oraz rezystory podciągające linie SDA oraz SCL do zasilania.
Rys. 2. Schemat płytki

Czujnik oraz wspomniana płytka prototypowa posiada następujące wyprowadzenia z układu:

  • INT2 - wyzwalanie dla przerwań od układu;
  • INT1 - wyzwalanie dla przerwań od układu;
  • SDA - linia danych;
  • SCL - linia zegarowa;
  • VCC - zasilanie układu, akceptowane od 1,95 do 3,6V;
  • GND - masa układu;

Podłączenie


Układ należy podłączyć do płytki Arduino w następujący sposób:

  • INT2 - NC
  • INT1 - NC
  • SDA - SDA Arduino
  • SCL - SCL Arduino
  • VCC - 3.3V
  • GND - GND

Jeśli wykorzystuje się Arduino Uno posiadające piny 5V wtedy należy zastosować konwerter poziomów logicznych. W przypadku montażu rezystorów, jak opisano na stronie producenta, nie udaje się skomunikować z czujnikiem. Konwerter można pominąć w przypadku obsługi układu na Arduino Pro mini. 

Biblioteka


Poniżej przedstawię opis biblioteki układu wraz z opisem poszczególnych rejestrów oraz głównych funkcji.

Biblioteka dla obsługi interfejsu I2C wykorzystuje wire.h, Główna część biblioteki MPL3115A2 zawiera sposób rozpoczęcia transmisji oraz pobrania danych.

Podstawowym elementem jest opis poszczególnych adresów rejestrów czujnika:

  1. #define MPL3115A2_ADDRESS 0x60
  2. #define STATUS     0x00
  3. #define OUT_P_MSB  0x01
  4. #define OUT_P_CSB  0x02
  5. #define OUT_P_LSB  0x03
  6. #define OUT_T_MSB  0x04
  7. #define OUT_T_LSB  0x05
  8. #define DR_STATUS  0x06
  9. #define OUT_P_DELTA_MSB  0x07
  10. #define OUT_P_DELTA_CSB  0x08
  11. #define OUT_P_DELTA_LSB  0x09
  12. #define OUT_T_DELTA_MSB  0x0A
  13. #define OUT_T_DELTA_LSB  0x0B
  14. #define WHO_AM_I   0x0C
  15. #define F_STATUS   0x0D
  16. #define F_DATA     0x0E
  17. #define F_SETUP    0x0F
  18. #define TIME_DLY   0x10
  19. #define SYSMOD     0x11
  20. #define INT_SOURCE 0x12
  21. #define PT_DATA_CFG 0x13
  22. #define BAR_IN_MSB 0x14
  23. #define BAR_IN_LSB 0x15
  24. #define P_TGT_MSB  0x16
  25. #define P_TGT_LSB  0x17
  26. #define T_TGT      0x18
  27. #define P_WND_MSB  0x19
  28. #define P_WND_LSB  0x1A
  29. #define T_WND      0x1B
  30. #define P_MIN_MSB  0x1C
  31. #define P_MIN_CSB  0x1D
  32. #define P_MIN_LSB  0x1E
  33. #define T_MIN_MSB  0x1F
  34. #define T_MIN_LSB  0x20
  35. #define P_MAX_MSB  0x21
  36. #define P_MAX_CSB  0x22
  37. #define P_MAX_LSB  0x23
  38. #define T_MAX_MSB  0x24
  39. #define T_MAX_LSB  0x25
  40. #define CTRL_REG1  0x26
  41. #define CTRL_REG2  0x27
  42. #define CTRL_REG3  0x28
  43. #define CTRL_REG4  0x29
  44. #define CTRL_REG5  0x2A
  45. #define OFF_P      0x2B
  46. #define OFF_T      0x2C
  47. #define OFF_H      0x2D

Procedura rozpoczęcia transmisji jest inicjowana poprzez wywołanie funkcji z biblioteki Wire.h

  1. bool MPL3115A2::begin(void)
  2. {
  3.   Wire.begin();
  4. }

Następnie pojawiają się funkcje obsługujące odczytywanie wartości. W pierwszej kolejneści pojawia się opcja odczytania wysokości nad poziomem morza. Zdefiniowane są jej dwa warianty, zwracające wartość w metrach oraz stopach. Gdy wystąpi błąd odczytu to zwrócona zostanie wartość -1.

  1. float MPL3115A2::readAltitude()
  2. {
  3.     //Ustawienie i wyzerowanie bitu OST, pozwalającemu na ponowny odczyt danych
  4.     toggleOneShot();
  5.     //Czekanie na bit PDR, informujący o pobraniu nowych danych
  6.     int counter = 0;
  7.     while( (IIC_Read(STATUS) & (1<<1)) == 0)
  8.     {
  9.         //Wywołanie errora po max 512ms
  10.         if(++counter > 600) return(-999);
  11.         delay(1);
  12.     }
  13.     //Odczytanie danych z rejestru
  14.     Wire.beginTransmission(MPL3115A2_ADDRESS);
  15.     //Adres danych do pobrania
  16.     Wire.write(OUT_P_MSB);
  17.     //Zakonczenie transmisji, przesłanie danych przez I2C z opcją ponownego startu
  18.     Wire.endTransmission(false);
  19.     //Ządanie 3 bitów
  20.     Wire.requestFrom(MPL3115A2_ADDRESS, 3); // Request three bytes
  21.     //Odczekanie na dostępność danych
  22.     counter = 0;
  23.     while(Wire.available() < 3)
  24.     {
  25.         if(counter++ > 100) return(-999); ==
  26.         delay(1);
  27.     }
  28.    
  29.     //Odczytanie danych
  30.     byte msb, csb, lsb;
  31.     msb = Wire.read();
  32.     csb = Wire.read();
  33.     lsb = Wire.read();
  34.     //Dane sa 4 bitowe, nalezy przesunąc je o 4 bity i podzielic przez 16
  35.     //poniewaz na 4 bitach mozna zapisac 16 wartosci
  36.     float tempcsb = (lsb>>4)/16.0;
  37.    
  38.     //Obliczenie wysokosci
  39.     float altitude = (float)( (msb << 8) | csb) + tempcsb;
  40.     return(altitude);
  41. }

Następna funkcja odczytuje wartość ciśnienia:

  1. float MPL3115A2::readPressure()
  2. {
  3.     //Sprawdzenie czy bit PDR jest ustawiony, jak nie to wlaczenie
  4.     //i wylaczenie bitu OST
  5.     if(IIC_Read(STATUS) & (1<<2) == 0) toggleOneShot();
  6.     //Odczekanie na bit PDR
  7.     int counter = 0;
  8.     while(IIC_Read(STATUS) & (1<<2) == 0)
  9.     {
  10.         if(++counter > 600) return(-999);
  11.         delay(1);
  12.     }
  13.     // Odczytanie danych z rejestru
  14.     Wire.beginTransmission(MPL3115A2_ADDRESS);
  15.     Wire.write(OUT_P_MSB);  // Address of data to get
  16.     Wire.endTransmission(false);
  17.     Wire.requestFrom(MPL3115A2_ADDRESS, 3); // Request three bytes
  18.     //Odczekanie na dane
  19.     counter = 0;
  20.     while(Wire.available() < 3)
  21.     {
  22.         if(counter++ > 100) return(-999);
  23.         delay(1);
  24.     }
  25.     //Odczytanie danych
  26.     byte msb, csb, lsb;
  27.     msb = Wire.read();
  28.     csb = Wire.read();
  29.     lsb = Wire.read();
  30.    
  31.     //Wlaczenie i wylaczenie OST
  32.     toggleOneShot();
  33.     //Wartość cisnienia jako przesunięty w lewo 20 bitowy
  34.     long pressure_whole = (long)msb<<16 | (long)csb<<8 | (long)lsb;
  35.     pressure_whole >>= 6;
  36.    
  37.     //Bity 5/4 reprezentują część ulamkowa
  38.     lsb &= 0b00110000;
  39.     lsb >>= 4;
  40.     float pressure_decimal = (float)lsb/4.0;
  41.     float pressure = (float)pressure_whole + pressure_decimal;
  42.     return(pressure);
  43. }

Dalej funkja odczytująca temperaturę:

  1. float MPL3115A2::readTemp()
  2. {
  3.     if(IIC_Read(STATUS) & (1<<1) == 0) toggleOneShot();
  4.     int counter = 0;
  5.     while( (IIC_Read(STATUS) & (1<<1)) == 0)
  6.     {
  7.         if(++counter > 600) return(-999);
  8.         delay(1);
  9.     }
  10.     //Odczytanie danych dotyczacych temperatury
  11.     Wire.beginTransmission(MPL3115A2_ADDRESS);
  12.     Wire.write(OUT_T_MSB);  // Address of data to get
  13.     Wire.endTransmission(false);
  14.     //Rządanie dwóch bytow
  15.     Wire.requestFrom(MPL3115A2_ADDRESS, 2);
  16.     //Czekanie na dane
  17.     counter = 0;
  18.     while(Wire.available() < 2)
  19.     {
  20.         if(counter++ > 100) return(-999);
  21.         delay(1);
  22.     }
  23.     byte msb, lsb;
  24.     msb = Wire.read();
  25.     lsb = Wire.read();
  26.     toggleOneShot();
  27.     word foo = 0;
  28.     bool negSign = false;
  29.     //Czekanie na przeslanie wszystkich danych
  30.     if(msb > 0x7F)
  31.     {
  32.         foo = ~((msb << 8) + lsb) + 1;
  33.         msb = foo >> 8;
  34.         lsb = foo & 0x00F0;
  35.         negSign = true;
  36.     }
  37.     float templsb = (lsb>>4)/16.0;
  38.     float temperature = (float)(msb + templsb);
  39.     if (negSign) temperature = 0 - temperature;
  40.    
  41.     return(temperature);
  42. }

Pozostałe funkcje służą do ustawienia odpowiednich parametrów transmisji i do odpowiedniego zainicjowania transmisji.

  1. //Ustawienie pomiaru ciśnienia
  2. void MPL3115A2::setModeBarometer()
  3. {
  4.   //Odczytanie aktualnych ustawien z rejestru
  5.   byte tempSetting = IIC_Read(CTRL_REG1);
  6.   //Wyczyszczenie bitu ALT
  7.   tempSetting &= ~(1<<7);
  8.   //Wprowadzenie ustawien
  9.   IIC_Write(CTRL_REG1, tempSetting);
  10. }
  11. //Ustawienie pomiaru wysokości
  12. void MPL3115A2::setModeAltimeter()
  13. {
  14.   byte tempSetting = IIC_Read(CTRL_REG1);
  15.   tempSetting |= (1<<7);
  16.   IIC_Write(CTRL_REG1, tempSetting);
  17. }
  18. //Wprowadzenie czujnika w tryb StandBy
  19. void MPL3115A2::setModeStandby()
  20. {
  21.   byte tempSetting = IIC_Read(CTRL_REG1);
  22.   //Czyszczenie bitu SBYB
  23.   tempSetting &= ~(1<<0);
  24.   IIC_Write(CTRL_REG1, tempSetting);
  25. }
  26. //Wprowadzenie ukladu w tryb aktywny
  27. void MPL3115A2::setModeActive()
  28. {
  29.   byte tempSetting = IIC_Read(CTRL_REG1);
  30.   //Bit SBYB ustawiony na 1
  31.   tempSetting |= (1<<0);
  32.   IIC_Write(CTRL_REG1, tempSetting);
  33. }
  34. //Wywowywane z parametrem od 0 do 7. Ustawianie ilości probek od 1 do 128.
  35. //Im większa liczba próbek tym większa doklodnosc oraz wiekszy czas pomiedzy
  36. //kolejnymi próbkami danych
  37. void MPL3115A2::setOversampleRate(byte sampleRate)
  38. {
  39.    
  40.   if(sampleRate > 7) sampleRate = 7;
  41.   //Ustawienie dla rejestry CTRL
  42.   sampleRate <<= 3;
  43.   //Odczytanie aktyalnych ustawien
  44.   byte tempSetting = IIC_Read(CTRL_REG1);
  45.   //Wyczyszczenie bitow OS
  46.   tempSetting &= 0b11000111;
  47.   //Zamaskowanie bitow
  48.   tempSetting |= sampleRate;
  49.   //Wprowadzenie danych
  50.   IIC_Write(CTRL_REG1, tempSetting);
  51. }
  52. //Wlaczenie flag wystąpienia zdarzenia dla temperatur, i cisnienia
  53. void MPL3115A2::enableEventFlags()
  54. {
  55.   IIC_Write(PT_DATA_CFG, 0x07);
  56. }
  57. //Czysci i ustawia bit OST, co powoduje ponowny odczyt danych,
  58. void MPL3115A2::toggleOneShot(void)
  59. {
  60.   byte tempSetting = IIC_Read(CTRL_REG1);
  61.   //Czyszczenie bitu OST
  62.   tempSetting &= ~(1<<1);
  63.   IIC_Write(CTRL_REG1, tempSetting);
  64.   tempSetting = IIC_Read(CTRL_REG1);
  65.   //ustawianie bitu OST
  66.   tempSetting |= (1<<1);
  67.   IIC_Write(CTRL_REG1, tempSetting);
  68. }

  69. // Odczytanie jednego byta danych
  70. byte MPL3115A2::IIC_Read(byte regAddr)
  71. {
  72.   //Rozpoczęcie transmisji
  73.   Wire.beginTransmission(MPL3115A2_ADDRESS);
  74.   //Wprowadzenie adresu rejestru kontrolnego
  75.   Wire.write(regAddr);
  76.   Wire.endTransmission(false);
  77.   //Zadanie danych
  78.   Wire.requestFrom(MPL3115A2_ADDRESS, 1); // Request the data...
  79.   return Wire.read();
  80. }
  81. //Wpisanie za pomocą interfejsu I2C
  82. void MPL3115A2::IIC_Write(byte regAddr, byte value)
  83. {
  84.   Wire.beginTransmission(MPL3115A2_ADDRESS);
  85.   Wire.write(regAddr);
  86.   Wire.write(value);
  87.   Wire.endTransmission(true);
  88. }


Programowanie

Programowanie najlepiej rozpocząć od wgrania biblioteki, która znacząco ułatwi wykonanie całego projektu.

Poniżej pierwszy z programów. Będzie on w pętli odczytywał i wyświetlał dane poprzez port szeregowy. Jest to mała przeróbka jednego z programów jakie można znaleźć w przykładach.

  1. #include <Wire.h>
  2. #include "SparkFunMPL3115A2.h"
  3. //Stworzenie obiektu funkcji
  4. MPL3115A2 MPL311;
  5. void setup()
  6. {
  7.   //Wlaczenie transmisji po interfejsie I2C
  8.   Wire.begin();
  9.   //Opcje transmisji po porcie szeregowym
  10.   Serial.begin(9600);
  11.   //Rozpoczęcie pracy z czujnikiem
  12.   MPL311.begin(); // Get sensor online
  13.   //Konfiguracja czujnikow
  14.   MPL311.setModeAltimeter();
  15.   MPL311.setModeBarometer();
  16.   MPL311.setOversampleRate(3);
  17.   MPL311.enableEventFlags();
  18. }
  19. void loop()
  20. {
  21.   float altitude = myPressure.readAltitude();
  22.   Serial.print("Wysokosc npm(m):");
  23.   Serial.print(altitude, 2);
  24.   float pressure = myPressure.readPressure();
  25.   Serial.print("Cisnienie(Pa):");
  26.   Serial.print(pressure, 2);
  27.   float temperature = myPressure.readTemp();
  28.   Serial.print("Temperatura(c):");
  29.   Serial.print(temperature, 2);
  30.   delay(1000);
  31.   Serial.println();
  32. }

Oprócz opisanej powyżej biblioteki można jeszcze wykorzystać bibliotekę udostępnioną przez Adafruit. Poniżej zmodyfikowany przykład do obsługi czujnika:

  1. #include <Wire.h>
  2. #include <Adafruit_MPL3115A2.h>
  3. Adafruit_MPL3115A2 MPL311 = Adafruit_MPL3115A2();
  4. void setup()
  5. {
  6.   Serial.begin(9600);
  7.   Serial.println("MPL3115A2!");
  8. }
  9. void loop()
  10. {
  11.   float altm, pascals, tempC;
  12.   //Wlaczenie czujnika, sprawdzenie odpowiedzi
  13.   if (!MPL311.begin())
  14.   {
  15.     Serial.println("Couldnt find sensor");
  16.     return;
  17.   }
  18.   //Odebranie cisnienia
  19.   pascals = MPL311.getPressure();
  20.   Serial.print(pascals/3377);
  21.   Serial.println(" - Cisnienie");
  22.   altm = MPL311.getAltitude();
  23.   Serial.print(altm);
  24.   Serial.println(" - Wysokosc");
  25.   tempC = MPL311.getTemperature();
  26.   Serial.print(tempC);
  27.   Serial.println(" - Temperatura");
  28.   delay(1000);
  29. }

Program będzie pobierał dane z czujnika, prezentował je na wyświetlaczu oraz zapisywał pobrane dane na kartę SD. Dane zostaną pobrane z czujnika, w między czasie wyświetlone na wyświetlaczu, po tych operacjach nastąpi zapis do pliku .txt.

  1. #include <Wire.h>
  2. #include <SparkFunMPL3115A2.h>
  3. #include <SD.h>
  4. #include <SPI.h>
  5. #define PIN_CE    7
  6. #define PIN_RESET 6
  7. #define PIN_DC    5
  8. #define PIN_DIN   4
  9. #define PIN_CLK   3
  10. #define LCD_C     LOW
  11. #define LCD_D     HIGH
  12. #define LCD_X     84
  13. #define LCD_Y     48
  14. char buff1[10];
  15. char buff2[10];
  16. char buff3[10];
  17. const int CSPin = 10;
  18. int czas=0;
  19. static const byte ASCII[][5] =
  20. {
  21.  {0x00, 0x00, 0x00, 0x00, 0x00} // 20  
  22. ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
  23. ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
  24. ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
  25. ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
  26. ,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
  27. ,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
  28. ,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
  29. ,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
  30. ,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
  31. ,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
  32. ,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
  33. ,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
  34. ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
  35. ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
  36. ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
  37. ,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
  38. ,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
  39. ,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
  40. ,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
  41. ,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
  42. ,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
  43. ,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
  44. ,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
  45. ,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
  46. ,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
  47. ,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
  48. ,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
  49. ,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
  50. ,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
  51. ,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
  52. ,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
  53. ,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
  54. ,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
  55. ,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
  56. ,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
  57. ,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
  58. ,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
  59. ,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
  60. ,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
  61. ,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
  62. ,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
  63. ,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
  64. ,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
  65. ,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
  66. ,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
  67. ,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
  68. ,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
  69. ,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
  70. ,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
  71. ,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
  72. ,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
  73. ,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
  74. ,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
  75. ,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
  76. ,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
  77. ,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
  78. ,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
  79. ,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
  80. ,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
  81. ,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
  82. ,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
  83. ,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
  84. ,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
  85. ,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
  86. };
  87. MPL3115A2 MPL311;
  88. void LcdCharacter(char);
  89. void LcdClear(void);
  90. void LcdString(char *);
  91. void LcdWrite(byte, byte);
  92. void setup()
  93. {
  94.   Serial.begin(9600);
  95.   Serial.println("MPL3115A2!");
  96.   LcdInitialise();
  97.   LcdClear();
  98.   //Rozpoczęcie pracy z czujnikiem
  99.   MPL311.begin(); // Get sensor online
  100.   //Konfiguracja czujnikow
  101.   MPL311.setModeAltimeter();
  102.   MPL311.setModeBarometer();
  103.   MPL311.setOversampleRate(3);
  104.   MPL311.enableEventFlags();
  105.   pinMode(CSPin, OUTPUT);
  106.   if (!SD.begin(CSPin))
  107.   {
  108.     Serial.println("Blad inicjalizacji karty");
  109.     return;
  110.   }
  111.     Serial.println("Karta zostala poprawnie zainicjalizowana");
  112. }
  113. void loop()
  114. {
  115.   float altitude = MPL311.readAltitude();
  116.   Serial.print("Wysokosc: ");
  117.   Serial.print(altitude, 2);
  118.   dtostrf(altitude, 2, 2, buff1);
  119.   LcdString(buff1);
  120.   float pressure = MPL311.readPressure();
  121.   Serial.print("Cisnienie: ");
  122.   Serial.print(pressure, 2);
  123.   dtostrf(pressure, 2, 2, buff1);
  124.   LcdString(buff2);
  125.   float temperature = MPL311.readTemp();
  126.   Serial.print("Temperatura: ");
  127.   Serial.print(temperature, 2);
  128.   dtostrf(temperature, 2, 2, buff1);
  129.   LcdString(buff3);
  130.   delay(1000);
  131.   Serial.println();
  132.   File myFile = SD.open("test.txt", FILE_WRITE);
  133.   if (myFile)
  134.   {
  135.     myFile.print("Wysokosc: ");
  136.     myFile.print(buff1);
  137.    
  138.     myFile.print("Cisnienie: ");
  139.     myFile.print(buff2);
  140.    
  141.     myFile.print("Temperatura: ");
  142.     myFile.print(buff3);
  143.    
  144.     myFile.println();
  145.     myFile.close();
  146.     Serial.print("Dane zapisane");
  147.   }
  148.   else
  149.   {
  150.     Serial.println("Blad otwarcia pliku");
  151.   }
  152.   delay(2000);
  153. }
  154. void LcdWrite(byte dc, byte data)
  155. {
  156.   //Wysłanie podanej wartości na wyświetlacz
  157.   digitalWrite(PIN_DC, dc);
  158.   //Podanie stanu niskiego na pin wybrania urządzenia
  159.   digitalWrite(PIN_CE, LOW);
  160.   //Funckja shiftOut przesyła jeden bit danych co sygnał zegara
  161.   //Wysłanie danych na pin wejścia danych, oraz sygnału zegarowego na CLK
  162.   //transmisja rozpoczęta od najbardziej znaczącego bitu
  163.   shiftOut(PIN_DIN, PIN_CLK, MSBFIRST, data);
  164.   //Podanie stanu wysokiego na pin wybrania urządzenia, zakońćzenie transmisji
  165.   digitalWrite(PIN_CE, HIGH);
  166. }
  167. void LcdString(char *characters)
  168. {
  169.   //Funckja działająca dopóki są znaki w odwołaniu do funkcji
  170.   while (*characters)
  171.   {
  172.     //Wprowadzanie kolejnego znaku
  173.     LcdCharacter(*characters++);
  174.   }
  175. }
  176. void LcdInitialise(void)
  177. {
  178.   //Inicjalizacja poszczególnych pinów
  179.   pinMode(PIN_CE, OUTPUT);
  180.   pinMode(PIN_RESET, OUTPUT);
  181.   pinMode(PIN_DC, OUTPUT);
  182.   pinMode(PIN_DIN, OUTPUT);
  183.   pinMode(PIN_CLK, OUTPUT);
  184.   digitalWrite(PIN_RESET, LOW);
  185.   digitalWrite(PIN_RESET, HIGH);
  186.   //Ustawienie odpowiednich komend na wyświetlacz
  187.   //000100001 Wybranie zewnętrznych instrukcji
  188.   LcdWrite(LCD_C, 0x21 );
  189.   //010110001 Ustawienie kontrastu
  190.   LcdWrite(LCD_C, 0xB1 );
  191.   //000000100 Współczynnik temperaturowy na 0
  192.   LcdWrite(LCD_C, 0x04 );
  193.   //000010011 Ustawienie wartości Bias mode
  194.   //na 4 dla MUX rate 1:48
  195.   LcdWrite(LCD_C, 0x13 );
  196.   //000100000 Właczenie podstawowych komend
  197.   LcdWrite(LCD_C, 0x20 );  // LCD Basic Commands
  198.   //000001100 Normalny tryb pracy
  199.   LcdWrite(LCD_C, 0x0C );
  200. }
  201. void LcdClear(void)
  202. {
  203.   //Funckja przechodzi pomiędzy wszystkimi pikselami na tablicy
  204.   //i wprodzana do nich wartość 0, czyli czyści ekran z umieszczonych znaków.
  205.   for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  206.   {
  207.     LcdWrite(LCD_D, 0);
  208.   }
  209. }
  210. void LcdCharacter(char character)
  211. {
  212.   //Stan wysoki na wyświetlacz wpisanie 0
  213.   LcdWrite(LCD_D, 0);
  214.   //Pętla przechodząca pomiędzy wszystkimi elementami
  215.   for (int index = 0; index < 5; index++)
  216.   {
  217.     /*
  218.     * Wystawienie stanu wysokiego , znaku z kolejnego miejsca
  219.     * W tablicy jest - 0x20 ponieważ przetwarza znak na kod ASCII,
  220.     * który jest wpisany do tablicy, a numerowanie w tablicy od 0
  221.     */
  222.     LcdWrite(LCD_D, ASCII[character - 0x20][index]);
  223.   }
  224.   //Zakończenie wpisanie 0
  225.   LcdWrite(LCD_D, 0);
  226. }