BME280 представляет собой интегрированный датчик окружающей среды, разработанный специально для мобильных устройств, где размер и низкое энергопотребление являются ключевыми.
Датчик BME280 очень похож с BMP280, различие в том, что BME280 имеет датчик влажности от чего его корпус шире чем у BMP280. Количество выводов и их расположение на корпусах совпадают. Более детальное описание датчика вы можете найти на странице BME280 — датчик давления, температуры и влажности.
Подключить датчик окружающей среды BME280 к Orange Pi PC можно по I2C и по SPI, их несколько как у Orange Pi, так и у Banana Pi и Raspberry Pi. Также для работы с GPIO необходимо установить WiringOP, если вы работаете с Orange Pi, а если у вас Banana Pi — BPI-WiringPi.
Схема подключения BME280 к Orange Pi/Banana Pi/Raspberry Pi
С этим датчиком я работаю только по I2C. Подключается BME280 к Orange Pi также, как к Banana Pi и Raspberry Pi, у всех GPIO (на 40 пинов) похожие. В данном случае я использовал порт /dev/i2c-2, потому что удобно расположен.
Код программы
Проект написан на С/С++. Использую среду разработки CodeLite IDE, так как среда Code::Blocks у меня не работает нормально.
BME280RawData.h
#include <stdint.h> class BME280RawData { private: uint8_t pmsb; uint8_t plsb; uint8_t pxsb; uint8_t tmsb; uint8_t tlsb; uint8_t txsb; uint8_t hmsb; uint8_t hlsb; uint32_t temperature; uint32_t pressure; uint32_t humidity; public: BME280RawData(uint8_t pmsb, uint8_t plsb, uint8_t pxsb, uint8_t tmsb, uint8_t tlsb, uint8_t txsb, uint8_t hmsb, uint8_t hlsb, uint32_t temperature, uint32_t pressure, uint32_t humidity) { this->pmsb = pmsb; this->plsb = plsb; this->pxsb = pxsb; this->tmsb = tmsb; this->tlsb = tlsb; this->txsb = txsb; this->hmsb = hmsb; this->hlsb = hlsb; this->temperature = temperature; this->pressure = pressure; this->humidity = humidity; } BME280RawData() { this->pmsb = 0; this->plsb = 0; this->pxsb = 0; this->tmsb = 0; this->tlsb = 0; this->txsb = 0; this->hmsb = 0; this->hlsb = 0; this->temperature = 0; this->pressure = 0; this->humidity = 0; } virtual ~BME280RawData() { } void setPlsb(uint8_t plsb) { this->plsb = plsb; } void setPmsb(uint8_t pmsb) { this->pmsb = pmsb; } void setPressure(uint32_t pressure) { this->pressure = pressure; } void setPxsb(uint8_t pxsb) { this->pxsb = pxsb; } void setTemperature(uint32_t temperature) { this->temperature = temperature; } void setTlsb(uint8_t tlsb) { this->tlsb = tlsb; } void setTmsb(uint8_t tmsb) { this->tmsb = tmsb; } void setTxsb(uint8_t txsb) { this->txsb = txsb; } uint8_t getPlsb() { return plsb; } uint8_t getPmsb() { return pmsb; } uint32_t getPressure() { return pressure; } uint8_t getPxsb() { return pxsb; } uint32_t getTemperature() { return temperature; } uint8_t getTlsb() { return tlsb; } uint8_t getTmsb() { return tmsb; } uint8_t getTxsb() { return txsb; } void setHlsb(uint8_t hlsb) { this->hlsb = hlsb; } void setHmsb(uint8_t hmsb) { this->hmsb = hmsb; } void setHumidity(uint32_t humidity) { this->humidity = humidity; } uint8_t getHlsb() { return hlsb; } uint8_t getHmsb() { return hmsb; } uint32_t getHumidity() { return humidity; } };
BME280CalibrationData.h
#include <stdint.h> class BME280CalibrationData { private: uint16_t T1; int16_t T2; int16_t T3; uint16_t P1; int16_t P2; int16_t P3; int16_t P4; int16_t P5; int16_t P6; int16_t P7; int16_t P8; int16_t P9; uint8_t H1; int16_t H2; uint8_t H3; int16_t H4; int16_t H5; int8_t H6; public: BME280CalibrationData() { T1 = 0; T2 = 0; T3 = 0; P1 = 0; P2 = 0; P3 = 0; P4 = 0; P5 = 0; P6 = 0; P7 = 0; P8 = 0; P9 = 0; H1 = 0; H2 = 0; H3 = 0; H4 = 0; H5 = 0; H6 = 0; } BME280CalibrationData(uint16_t T1, int16_t T2, int16_t T3, uint16_t P1, int16_t P2, int16_t P3, int16_t P4, int16_t P5, int16_t P6, int16_t P7, int16_t P8, int16_t P9, uint8_t H1, int16_t H2, uint8_t H3, int16_t H4, int16_t H5, int8_t H6) { this->P1 = P1; this->P2 = P2; this->P3 = P3; this->P4 = P4; this->P5 = P5; this->P6 = P6; this->P7 = P7; this->P8 = P8; this->P9 = P9; this->T1 = T1; this->T2 = T2; this->T3 = T3; this->H1 = H1; this->H2 = H2; this->H3 = H3; this->H4 = H4; this->H5 = H5; this->H6 = H6; } virtual ~BME280CalibrationData() { } void setP1(uint16_t P1) { this->P1 = P1; } void setP2(int16_t P2) { this->P2 = P2; } void setP3(int16_t P3) { this->P3 = P3; } void setP4(int16_t P4) { this->P4 = P4; } void setP5(int16_t P5) { this->P5 = P5; } void setP6(int16_t P6) { this->P6 = P6; } void setP7(int16_t P7) { this->P7 = P7; } void setP8(int16_t P8) { this->P8 = P8; } void setP9(int16_t P9) { this->P9 = P9; } void setT1(uint16_t T1) { this->T1 = T1; } void setT2(int16_t T2) { this->T2 = T2; } void setT3(int16_t T3) { this->T3 = T3; } uint16_t getP1() { return P1; } int16_t getP2() { return P2; } int16_t getP3() { return P3; } int16_t getP4() { return P4; } int16_t getP5() { return P5; } int16_t getP6() { return P6; } int16_t getP7() { return P7; } int16_t getP8() { return P8; } int16_t getP9() { return P9; } uint16_t getT1() { return T1; } int16_t getT2() { return T2; } int16_t getT3() { return T3; } void setH1(uint8_t H1) { this->H1 = H1; } void setH2(int16_t H2) { this->H2 = H2; } void setH3(uint8_t H3) { this->H3 = H3; } void setH4(int16_t H4) { this->H4 = H4; } void setH5(int16_t H5) { this->H5 = H5; } void setH6(int8_t H6) { this->H6 = H6; } uint8_t getH1() { return H1; } int16_t getH2() { return H2; } uint8_t getH3() { return H3; } int16_t getH4() { return H4; } int16_t getH5() { return H5; } int8_t getH6() { return H6; } };
BME280Data.h
class BMP280Data { private: double pressure; // hPa double temperature; // m double humidity; // % double altitude; // °C public: BMP280Data() { pressure = 0; temperature = 0; altitude = 0; humidity = 0; } BMP280Data(double pressure, double temperature, double humidity, double altitude) { this->pressure = pressure; this->temperature = temperature; this->humidity = humidity; this->altitude = altitude; } virtual ~BMP280Data() { } void setAltitude(double altitude) { this->altitude = altitude; } void setPressure(double pressure) { this->pressure = pressure; } void setTemperature(double temperature) { this->temperature = temperature; } double getAltitude() { return altitude; } double getPressure() { return pressure; } double getTemperature() { return temperature; } void setHumidity(double humidity) { this->humidity = humidity; } double getHumidity() { return humidity; } };
bme280.h
#include <stdint.h> #include "BME280CalibrationData.h" #include "BME280RawData.h" #include "BME280Data.h" #define MEAN_SEA_LEVEL_PRESSURE 1013 /**\name CHIP ID DEFINITION */ /***********************************************/ #define BME280_CHIP_ID1 (0x60) /************************************************/ /**\name I2C ADDRESS DEFINITION */ /***********************************************/ #define BME280_I2C_ADDRESS1 (0x76) #define BME280_I2C_ADDRESS2 (0x77) /************************************************/ /**\name POWER MODE DEFINITION */ /***********************************************/ /* Sensor Specific constants */ #define BME280_SLEEP_MODE (0x00) #define BME280_FORCED_MODE (0x01) #define BME280_NORMAL_MODE (0x03) #define BME280_SOFT_RESET_CODE (0xB6) /************************************************/ /**\name STANDBY TIME DEFINITION */ /***********************************************/ #define BME280_STANDBY_TIME_1_MS (0x00) #define BME280_STANDBY_TIME_63_MS (0x01) #define BME280_STANDBY_TIME_125_MS (0x02) #define BME280_STANDBY_TIME_250_MS (0x03) #define BME280_STANDBY_TIME_500_MS (0x04) #define BME280_STANDBY_TIME_1000_MS (0x05) #define BME280_STANDBY_TIME_2000_MS (0x06) #define BME280_STANDBY_TIME_4000_MS (0x07) /************************************************/ /**\name OVERSAMPLING DEFINITION */ /***********************************************/ #define BME280_OVERSAMP_SKIPPED (0x00) #define BME280_OVERSAMP_1X (0x01) #define BME280_OVERSAMP_2X (0x02) #define BME280_OVERSAMP_4X (0x03) #define BME280_OVERSAMP_8X (0x04) #define BME280_OVERSAMP_16X (0x05) /************************************************/ /**\name WORKING MODE DEFINITION */ /***********************************************/ #define BME280_ULTRA_LOW_POWER_MODE (0x00) #define BME280_LOW_POWER_MODE (0x01) #define BME280_STANDARD_RESOLUTION_MODE (0x02) #define BME280_HIGH_RESOLUTION_MODE (0x03) #define BME280_ULTRA_HIGH_RESOLUTION_MODE (0x04) #define BME280_ULTRALOWPOWER_OVERSAMP_PRESSURE BME280_OVERSAMP_1X #define BME280_ULTRALOWPOWER_OVERSAMP_HUMIDITY BME280_OVERSAMP_1X #define BME280_ULTRALOWPOWER_OVERSAMP_TEMPERATURE BME280_OVERSAMP_1X #define BME280_LOWPOWER_OVERSAMP_PRESSURE BME280_OVERSAMP_2X #define BME280_LOWPOWER_OVERSAMP_HUMIDITY BME280_OVERSAMP_2X #define BME280_LOWPOWER_OVERSAMP_TEMPERATURE BME280_OVERSAMP_1X #define BME280_STANDARDRESOLUTION_OVERSAMP_PRESSURE BME280_OVERSAMP_4X #define BME280_STANDARDRESOLUTION_OVERSAMP_HUMIDITY BME280_OVERSAMP_4X #define BME280_STANDARDRESOLUTION_OVERSAMP_TEMPERATURE BME280_OVERSAMP_1X #define BME280_HIGHRESOLUTION_OVERSAMP_PRESSURE BME280_OVERSAMP_8X #define BME280_HIGHRESOLUTION_OVERSAMP_HUMIDITY BME280_OVERSAMP_8X #define BME280_HIGHRESOLUTION_OVERSAMP_TEMPERATURE BME280_OVERSAMP_1X #define BME280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE BME280_OVERSAMP_16X #define BME280_ULTRAHIGHRESOLUTION_OVERSAMP_HUMIDITY BME280_OVERSAMP_16X #define BME280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE BME280_OVERSAMP_2X /************************************************/ /**\name FILTER DEFINITION */ /***********************************************/ #define BME280_FILTER_COEFF_OFF (0x00) #define BME280_FILTER_COEFF_2 (0x01) #define BME280_FILTER_COEFF_4 (0x02) #define BME280_FILTER_COEFF_8 (0x03) #define BME280_FILTER_COEFF_16 (0x04) /************************************************/ /* * REGISTERS */ #define BME280_ADDRESS 0x76 #define BME280_REGISTER_DIG_T1 0x88 #define BME280_REGISTER_DIG_T2 0x8A #define BME280_REGISTER_DIG_T3 0x8C #define BME280_REGISTER_DIG_P1 0x8E #define BME280_REGISTER_DIG_P2 0x90 #define BME280_REGISTER_DIG_P3 0x92 #define BME280_REGISTER_DIG_P4 0x94 #define BME280_REGISTER_DIG_P5 0x96 #define BME280_REGISTER_DIG_P6 0x98 #define BME280_REGISTER_DIG_P7 0x9A #define BME280_REGISTER_DIG_P8 0x9C #define BME280_REGISTER_DIG_P9 0x9E #define BME280_REGISTER_DIG_H1 0xA1 #define BME280_REGISTER_DIG_H2 0xE1 #define BME280_REGISTER_DIG_H3 0xE3 #define BME280_REGISTER_DIG_H4 0xE4 #define BME280_REGISTER_DIG_H5 0xE5 #define BME280_REGISTER_DIG_H6 0xE7 #define BME280_REGISTER_CHIPID 0xD0 #define BME280_REGISTER_VERSION 0xD1 #define BME280_REGISTER_SOFTRESET 0xE0 #define BME280_RESET 0xB6 #define BME280_REGISTER_CAL26 0xE1 #define BME280_REGISTER_CONTROLHUMID 0xF2 #define BME280_REGISTER_STATUS 0xF3 #define BME280_REGISTER_CONTROL 0xF4 #define BME280_REGISTER_CONFIG 0xF5 #define BME280_REGISTER_PRESSUREDATA_MSB 0xF7 #define BME280_REGISTER_PRESSUREDATA_LSB 0xF8 #define BME280_REGISTER_PRESSUREDATA_XLSB 0xF9 #define BME280_REGISTER_TEMPDATA_MSB 0xFA #define BME280_REGISTER_TEMPDATA_LSB 0xFB #define BME280_REGISTER_TEMPDATA_XLSB 0xFC #define BME280_REGISTER_HUMIDDATA_MSB 0xFD #define BME280_REGISTER_HUMIDDATA_LSB 0xFE class BME280 { private: char * device; int devId; int fd; uint8_t chipId; BME280CalibrationData * bmp280CalibrationData; BME280RawData * bmp280RawData; void write8(uint8_t, uint8_t); int read8(uint8_t); uint8_t readU8(uint8_t); int8_t readS8(uint8_t); int read16(uint8_t); int16_t readS16(uint8_t); uint16_t readU16(uint8_t); int32_t getTemperatureC(int32_t adc_T); double getAltitude(double pressure); double compensateTemperature(int32_t t_fine); double compensatePressure(int32_t adc_P, int32_t t_fine); double compensateHumidity(int32_t adc_H, int32_t t_fine); BME280CalibrationData * getCalibrationData(); BME280RawData * getRawData(); public: BME280(const char*, int); BME280(int); virtual ~BME280(); BME280CalibrationData * getBmp280CalibrationData(); BMP280Data * getBMP280Data(); int init(); void reset(); void spi3wEnable(); void spi3wDisable(); void setPowerMode(uint8_t); void setTemperatureOversampling(uint8_t); void setPressureOversampling(uint8_t); void setHumidityOversampling(uint8_t); void setStandbyTime(uint8_t); void setIrrFilter(uint8_t); uint8_t getPowerMode(); uint8_t getPressureOversampling(); uint8_t getHumidityOversampling(); uint8_t getTemperatureOversampling(); uint8_t getIrrFilter(); uint8_t getStandbyTime(); uint8_t getSpi3w(); uint8_t getMeasuringStatus(); uint8_t getImUpdateStatus(); uint8_t getConfig(); uint8_t getStatus(); uint8_t getControl(); uint8_t getControlHumidity(); uint8_t getChipId(); uint8_t getChipVersion(); void setReset(uint8_t); void setConfig(uint8_t); void setStatus(uint8_t); void setControl(uint8_t); void setControlHumidity(uint8_t); };
bme280.cpp
#include <string.h> #include <stdint.h> #include <stdexcept> #include <iostream> #include <stdio.h> #include <math.h> #include <wiringPiI2C.h> #include "bme280.h" void BME280::write8(uint8_t reg, uint8_t value) { wiringPiI2CWriteReg8(fd, reg, value); } int BME280::read8(uint8_t reg) { return wiringPiI2CReadReg8(fd, reg); } uint8_t BME280::readU8(uint8_t reg) { return (uint8_t) read8(reg); } int8_t BME280::readS8(uint8_t reg) { return (int8_t) read8(reg); } int BME280::read16(uint8_t reg) { return wiringPiI2CReadReg16(fd, reg); } int16_t BME280::readS16(uint8_t reg) { return (int16_t) read16(reg); } uint16_t BME280::readU16(uint8_t reg) { return (uint16_t) read16(reg); } BME280::BME280(const char * device, int devId) : fd(0), chipId(0), bmp280CalibrationData(0), bmp280RawData(0) { this->device = new char[strlen(device)]; strcpy(this->device, device); this->devId = devId; } BME280::BME280(int devId) : fd(0), chipId(0), bmp280CalibrationData(0), bmp280RawData(0) { this->devId = devId; } BME280::~BME280() { delete bmp280CalibrationData; delete bmp280RawData; delete[] device; } int BME280::init() { int fd = wiringPiI2CSetup(devId); if (fd < 0) { char buffer[256]; sprintf(buffer, "Device not found: device ID = %d", devId); throw std::logic_error(buffer); } this->fd = fd; uint8_t chipId = getChipId(); switch (chipId) { case BME280_CHIP_ID1: this->chipId = chipId; break; default: { char buffer[256]; sprintf(buffer, "Device Chip ID error: chip ID = %d", chipId); throw std::logic_error(buffer); } } if (bmp280CalibrationData) { delete bmp280CalibrationData; } bmp280CalibrationData = getCalibrationData(); return fd; } BME280CalibrationData * BME280::getCalibrationData() { int8_t H6; uint8_t H1, H3; int16_t T2, T3, P2, P3, P4, P5, P6, P7, P8, P9, H2, H4, H5; uint16_t T1, P1; T1 = readU16(BME280_REGISTER_DIG_T1); T2 = readS16(BME280_REGISTER_DIG_T2); T3 = readS16(BME280_REGISTER_DIG_T3); P1 = readU16(BME280_REGISTER_DIG_P1); P2 = readS16(BME280_REGISTER_DIG_P2); P3 = readS16(BME280_REGISTER_DIG_P3); P4 = readS16(BME280_REGISTER_DIG_P4); P5 = readS16(BME280_REGISTER_DIG_P5); P6 = readS16(BME280_REGISTER_DIG_P6); P7 = readS16(BME280_REGISTER_DIG_P7); P8 = readS16(BME280_REGISTER_DIG_P8); P9 = readS16(BME280_REGISTER_DIG_P9); H1 = readU8(BME280_REGISTER_DIG_H1); H2 = readS16(BME280_REGISTER_DIG_H2); H3 = readU8(BME280_REGISTER_DIG_H3); H4 = (int16_t)((read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF)); H5 = (int16_t)((read8(BME280_REGISTER_DIG_H5 + 1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4)); H6 = readS8(BME280_REGISTER_DIG_H6); return new BME280CalibrationData(T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9, H1, H2, H3, H4, H5, H6); } BME280CalibrationData * BME280::getBmp280CalibrationData() { return bmp280CalibrationData; } BME280RawData * BME280::getRawData() { uint8_t pmsb, plsb, pxsb; uint8_t tmsb, tlsb, txsb; uint8_t hmsb, hlsb; uint32_t temperature, pressure, humidity; plsb = readU8(BME280_REGISTER_PRESSUREDATA_LSB); pmsb = readU8(BME280_REGISTER_PRESSUREDATA_MSB); pxsb = readU8(BME280_REGISTER_PRESSUREDATA_XLSB); tmsb = readU8(BME280_REGISTER_TEMPDATA_MSB); tlsb = readU8(BME280_REGISTER_TEMPDATA_LSB); txsb = readU8(BME280_REGISTER_TEMPDATA_XLSB); hmsb = readU8(BME280_REGISTER_HUMIDDATA_MSB); hlsb = readU8(BME280_REGISTER_HUMIDDATA_LSB); temperature = 0; temperature = (temperature | tmsb) << 8; temperature = (temperature | tlsb) << 8; temperature = (temperature | txsb) >> 4; pressure = 0; pressure = (pressure | pmsb) << 8; pressure = (pressure | plsb) << 8; pressure = (pressure | pxsb) >> 4; humidity = 0; humidity = (humidity | hmsb) << 8; humidity = (humidity | hlsb); return new BME280RawData(pmsb, plsb, pxsb, tmsb, tlsb, txsb, hmsb, hlsb, temperature, pressure, humidity); } void BME280::reset() { setReset (BME280_SOFT_RESET_CODE); } void BME280::spi3wEnable() { uint8_t config = getConfig(); setConfig(config | 0b00000001); } void BME280::spi3wDisable() { uint8_t config = getConfig(); setConfig(config & 0b11111110); } void BME280::setPowerMode(uint8_t mode) { switch (mode) { case BME280_FORCED_MODE: case BME280_NORMAL_MODE: case BME280_SLEEP_MODE: { uint8_t curentMode = getControl() & 0b11111100; setControl(curentMode | mode); break; } default: break; } } void BME280::setTemperatureOversampling(uint8_t oversampling) { switch (oversampling) { case BME280_OVERSAMP_SKIPPED: case BME280_OVERSAMP_1X: case BME280_OVERSAMP_2X: case BME280_OVERSAMP_4X: case BME280_OVERSAMP_8X: case BME280_OVERSAMP_16X: { uint8_t curentOversampling = getControl() & 0b00011111; setControl(curentOversampling | (oversampling << 5)); break; } default: break; } } void BME280::setPressureOversampling(uint8_t oversampling) { switch (oversampling) { case BME280_OVERSAMP_SKIPPED: case BME280_OVERSAMP_1X: case BME280_OVERSAMP_2X: case BME280_OVERSAMP_4X: case BME280_OVERSAMP_8X: case BME280_OVERSAMP_16X: { uint8_t curentOversampling = getControl() & 0b11100011; setControl(curentOversampling | (oversampling << 2)); break; } default: break; } } void BME280::setHumidityOversampling(uint8_t oversampling) { switch (oversampling) { case BME280_OVERSAMP_SKIPPED: case BME280_OVERSAMP_1X: case BME280_OVERSAMP_2X: case BME280_OVERSAMP_4X: case BME280_OVERSAMP_8X: case BME280_OVERSAMP_16X: { setControlHumidity(0b00000111 & oversampling); break; } default: break; } } uint8_t BME280::getHumidityOversampling() { return getControlHumidity() & 0b00000111; } void BME280::setStandbyTime(uint8_t tStandby) { switch (tStandby) { case BME280_STANDBY_TIME_1_MS: case BME280_STANDBY_TIME_63_MS: case BME280_STANDBY_TIME_125_MS: case BME280_STANDBY_TIME_250_MS: case BME280_STANDBY_TIME_500_MS: case BME280_STANDBY_TIME_1000_MS: case BME280_STANDBY_TIME_2000_MS: case BME280_STANDBY_TIME_4000_MS: { uint8_t config = getConfig() & 0b00011111; setConfig(config | (tStandby << 5)); break; } default: break; } } void BME280::setIrrFilter(uint8_t irrFilter) { switch (irrFilter) { case BME280_FILTER_COEFF_OFF: case BME280_FILTER_COEFF_2: case BME280_FILTER_COEFF_4: case BME280_FILTER_COEFF_8: case BME280_FILTER_COEFF_16: { uint8_t config = getConfig() & 0b11100011; setConfig(config | (irrFilter << 2)); break; } default: break; } } uint8_t BME280::getPowerMode() { return getControl() & 0b00000011; } uint8_t BME280::getPressureOversampling() { return (getControl() & 0b00011100) >> 2; } uint8_t BME280::getTemperatureOversampling() { return (getControl() & 0b11100000) >> 5; } uint8_t BME280::getIrrFilter() { return (getConfig() & 0b00011100) >> 2; } uint8_t BME280::getStandbyTime() { return (getConfig() & 0b11100000) >> 5; } uint8_t BME280::getSpi3w() { return (getConfig() & 0b00000001) >> 5; } uint8_t BME280::getMeasuringStatus() { return (getStatus() >> 3) & 0b00000001; } uint8_t BME280::getImUpdateStatus() { return getStatus() & 0b00000001; } uint8_t BME280::getConfig() { return readU8(BME280_REGISTER_CONFIG); } uint8_t BME280::getStatus() { return readU8(BME280_REGISTER_STATUS); } uint8_t BME280::getControl() { return readU8(BME280_REGISTER_CONTROL); } uint8_t BME280::getControlHumidity() { return readU8(BME280_REGISTER_CONTROLHUMID); } uint8_t BME280::getChipId() { return readU8(BME280_REGISTER_CHIPID); } uint8_t BME280::getChipVersion() { return readU8(BME280_REGISTER_VERSION); } void BME280::setReset(uint8_t value) { write8(BME280_REGISTER_SOFTRESET, value); } void BME280::setConfig(uint8_t value) { write8(BME280_REGISTER_CONFIG, value); } void BME280::setStatus(uint8_t value) { write8(BME280_REGISTER_STATUS, value); } void BME280::setControl(uint8_t value) { write8(BME280_REGISTER_CONTROL, value); } void BME280::setControlHumidity(uint8_t value) { write8(BME280_REGISTER_CONTROLHUMID, value); } double BME280::getAltitude(double pressure) { return 44330.0 * (1.0 - pow(pressure / MEAN_SEA_LEVEL_PRESSURE, 0.190294957)); } int32_t BME280::getTemperatureC(int32_t adc_T) { int32_t var1 = ((((adc_T >> 3) - ((int32_t) bmp280CalibrationData->getT1() << 1))) * ((int32_t) bmp280CalibrationData->getT2())) >> 11; int32_t var2 = (((((adc_T >> 4) - ((int32_t) bmp280CalibrationData->getT1())) * ((adc_T >> 4) - ((int32_t) bmp280CalibrationData->getT1()))) >> 12) * ((int32_t) bmp280CalibrationData->getT3())) >> 14; return var1 + var2; } double BME280::compensateTemperature(int32_t t_fine) { double T = (t_fine * 5 + 128) >> 8; return T / 100; } double BME280::compensatePressure(int32_t adc_P, int32_t t_fine) { int64_t var1, var2, p; var1 = ((int64_t) t_fine) - 128000; var2 = var1 * var1 * (int64_t) bmp280CalibrationData->getP6(); var2 = var2 + ((var1 * (int64_t) bmp280CalibrationData->getP5()) << 17); var2 = var2 + (((int64_t) bmp280CalibrationData->getP4()) << 35); var1 = ((var1 * var1 * (int64_t) bmp280CalibrationData->getP3()) >> 8) + ((var1 * (int64_t) bmp280CalibrationData->getP2()) << 12); var1 = (((((int64_t) 1) << 47) + var1)) * ((int64_t) bmp280CalibrationData->getP1()) >> 33; if (var1 == 0) { return 0; // avoid exception caused by division by zero } p = 1048576 - adc_P; p = (((p << 31) - var2) * 3125) / var1; var1 = (((int64_t) bmp280CalibrationData->getP9()) * (p >> 13) * (p >> 13)) >> 25; var2 = (((int64_t) bmp280CalibrationData->getP8()) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t) bmp280CalibrationData->getP7()) << 4); return (double) p / 256; } double BME280::compensateHumidity(int32_t adc_H, int32_t t_fine) { int32_t v_x1_u32r; v_x1_u32r = (t_fine - ((int32_t) 76800)); v_x1_u32r = (((((adc_H << 14) - (((int32_t) bmp280CalibrationData->getH4()) << 20) - (((int32_t) bmp280CalibrationData->getH5()) * v_x1_u32r)) + ((int32_t) 16384)) >> 15) * (((((((v_x1_u32r * ((int32_t) bmp280CalibrationData->getH6())) >> 10) * (((v_x1_u32r * ((int32_t) bmp280CalibrationData->getH3())) >> 11) + ((int32_t) 32768))) >> 10) + ((int32_t) 2097152)) * ((int32_t) bmp280CalibrationData->getH2()) + 8192) >> 14)); v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t) bmp280CalibrationData->getH1())) >> 4)); v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; double h = (v_x1_u32r >> 12); return h / 1024.0; } BMP280Data * BME280::getBMP280Data() { int32_t t_fine; double t, p, h, a; while (getMeasuringStatus()) { } if (bmp280RawData) { delete bmp280RawData; } bmp280RawData = getRawData(); t_fine = getTemperatureC(bmp280RawData->getTemperature()); t = compensateTemperature(t_fine); // C p = compensatePressure(bmp280RawData->getPressure(), t_fine) / 100; // hPa h = compensateHumidity(bmp280RawData->getHumidity(), t_fine); a = getAltitude(p); // meters return new BMP280Data(p, t, h, a); }
main.cpp
#include <stdio.h> #include <string.h> #include <stdexcept> #include <iostream> #include <stdint.h> #include <time.h> #include <math.h> #include <wiringPiI2C.h> #include <wiringPi.h> #include "bme280.h" int main() { // char * device = "/dev/i2c-0"; // char * device = "/dev/i2c-1"; char * device = "/dev/i2c-2"; // char * device = "/dev/i2c-3"; int devId = BME280_I2C_ADDRESS1; try { BME280 * bme280 = new BME280(device, devId); int fd = bme280->init(); bme280->reset(); if (fd < 0) { printf("Device not found"); return -1; } printf("fd : 0x%02x\n", fd); printf("chip id : 0x%02x\n", bme280->getChipId()); printf("chip ver : 0x%02x\n", bme280->getChipVersion()); bme280->reset(); bme280->setPowerMode(BME280_NORMAL_MODE); bme280->setTemperatureOversampling(BME280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE); bme280->setPressureOversampling(BME280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE); bme280->setHumidityOversampling(BME280_ULTRAHIGHRESOLUTION_OVERSAMP_HUMIDITY); bme280->setIrrFilter(BME280_FILTER_COEFF_16); bme280->setStandbyTime(BME280_STANDBY_TIME_250_MS); printf("---------------\n"); printf("pw mode : 0x%02x\n", bme280->getPowerMode()); printf("osrs_p : 0x%02x\n", bme280->getPressureOversampling()); printf("osrs_t : 0x%02x\n", bme280->getTemperatureOversampling()); printf("osrs_h : 0x%02x\n", bme280->getHumidityOversampling()); printf("---------------\n"); printf("filter : 0x%02x\n", bme280->getIrrFilter()); printf("t_sb : 0x%02x\n", bme280->getStandbyTime()); printf("---------------\n"); printf("spi3w sts: 0x%02x\n", bme280->getSpi3w()); printf("measuring: 0x%02x\n", bme280->getMeasuringStatus()); printf("im_update: 0x%02x\n", bme280->getImUpdateStatus()); printf("---------------\n"); while (1) { delay(1000); BMP280Data * bme280Data = bme280->getBMP280Data(); printf("pressure : %.2f \tmm Hg\n", bme280Data->getPressure() / 1.3332239); printf("humidity : %.2f \t%c\n", bme280Data->getHumidity(), '%'); printf("temperature: %.2f \t°C\n", bme280Data->getTemperature()); printf("altitude : %.2f \tm\n\n", bme280Data->getAltitude()); } delete bme280; } catch (std::exception & e) { printf("%s\n", e.what()); } return 0; }
Результат
Скачать проект CodeLite
CodeLite проект: BME280_Banana_Pi_M3.zip
Flyer: BST-BME280-FL000-02
Datasheet: BST-BME280-DS001-11
Handling, soldering & mounting instructions: BST-BME280-HS001-06
Shipment & packaging details: BST-BME280-SP000-00
Driver: BME280 driver
Добрый день. Не понятно, что делать с кодом, куда вставлять? Создать файлы, куда их помещать, какими командами запускать в терминале? Компилировать нужно? Как это делать? Для кого эта инструкция?
Вы можете скачать CodeLite проект «BME280_Banana_Pi_M3.zip» по ссылке https://yadi.sk/d/5KhZq3pa3KfgeB. А так, вы просто создаёте каждый файл и помещаете его в одну папку и всё.
Здравствуйте. у меня Raspberry pi 3. как подключить два датчика BME 280 по протоколу I2C?
С помощью вывода SDO. Когда вы оставляете вывод SDO от одного датчика неподключенным, вы говорите этому датчику использовать адрес I2C по умолчанию (0x77).
Но когда вы подключаете вывод SDO от второго датчика к GND, вы указываете ему использовать альтернативный адрес I2C (0x76).
После чего создаёте два объекта:
BME-280 от BMP-280 отличается наличием датчика атмосферного давления, а от ширины корпуса зависит только от напряжения питания. Широкий — 3.3В Узкий — 5В.
Что делать, если вы столкнулись с дубликатами номеров на своем транспортном средстве, эффективные советы для водителей.
Знакомство с признаками дубликата автомобильного номера, которые помогут подделку.
Секреты определения настоящего автомобильного номера, если вы хотите.
Что делать, если вам подделали номер на автомобиле, и что важно помнить в такой ситуации.
Что нужно знать, чтобы не стать жертвой мошенничества, если вы только начинаете оценивать купить авто.
Подробная инструкция по проверке номера автомобиля при покупке, которые помогут избежать неприятностей.
Признаки фальшивого номера и как не нарваться на подделку, и что делать, если вы столкнулись с такой ситуацией.
Как защитить свой автомобиль от подделки номера, и как предотвратить возможные проблемы.
изготовление дубликатов номеров http://dublikatznakov.ru/ .
Проблема дубликатов номеров: как решить этот вопрос, подробное руководство для владельцев автомобилей.
Как распознать дубликат номера на авто, быстро разобраться подделку.
Как отличить оригинальный номер от дубликата, для тех, кто желает.
Что делать, если вам подделали номер на автомобиле, и что важно помнить в такой ситуации.
Что нужно знать, чтобы не стать жертвой мошенничества, если вы только начинаете оценивать купить авто.
Как провести проверку номера машины перед покупкой, которые помогут вам сэкономить время и деньги.
Признаки фальшивого номера и как не нарваться на подделку, и что делать, если вы столкнулись с такой ситуацией.
Что нужно знать, чтобы не стать жертвой мошенников, и что делать, чтобы избежать неприятностей.
изготовление номеров на автомобиль https://dublikatznakov.ru/ .
Что делать, если вы столкнулись с дубликатами номеров на своем транспортном средстве, эффективные советы для владельцев автомобилей.
Знакомство с признаками дубликата автомобильного номера, чтобы избежать подделку.
Как отличить оригинальный номер от дубликата, для тех, кто желает.
Куда обращаться, если вы обнаружили подделку номера, и какие шаги следует предпринять незамедлительно.
Советы по проверке подлинности номера при покупке машины, для новичков в автомире купить авто.
Подробная инструкция по проверке номера автомобиля при покупке, которые помогут избежать неприятностей.
Какие последствия могут быть при использовании дубликата автомобильного номера, и как избежать проблем с законом.
Меры предосторожности при покупке авто для избежания дублированных номеров, и что делать, чтобы избежать неприятностей.
заказать номера на автомобиль https://www.dublikatznakov.ru/ .
досуг Донецк проститутки
Ищете заказать проститутку в Донецке? Мы предлагаем профессиональные индивидуалки этого города для вашего удовольствия и релакса! У нас только проверенные девушки с идеальной внешностью и лучшим сервисом. Хотите вызвать индивидуалку на вечер? Обращайтесь к нам, и ваши фантазии станут реальностью!
Не пропустите возможность провести время с самыми привлекательными проститутками города Донецк.
проститутки выезд Донецк
Задумались, где заказать индивидуалку в городе Донецк? Мы предлагаем профессиональные индивидуалки Донецка для вашего удовольствия! У нас всегда профессиональные проститутки с безупречным внешним видом и лучшим сервисом. Желаете вызвать индивидуалку на вечер? Свяжитесь с нами, и ваши мечты осуществятся!
Не пропустите возможность провести время с самыми горячими девушками Донецка.
оружие самообороны без лицензии интернет магазин
पेरीमैच कैसीनो परिणाम भारत में सबसे अच्छा कैसीनो ऐप
plinko game online real money 1xbet ऑनलाइन online casino game real money
https://tort-dubr.ru — Получите консультацию и помощь в выборе кухни на заказ.
ऑनलाइन कैसीनो साइटें ऑनलाइन सट्टेबाजी के गेम aviator casino
9winz crazytime स्लॉट खेल
perimatch daman games online game cash
all slots games 888कैसीनो पैसे के खेल ऑनलाइन
https://www.webcocktail.ru — Переходите на наш сайт, чтобы узнать больше о наших услугах.
daman games भारत में ऑनलाइन सट्टेबाजी कैसीनो
ऑनलाइन कैसीनो साइटें गोवा खेल ऑनलाइन real money
купить кухню в екатеринбурге — Удобные решения для вашей кухни в Екатеринбурге.
casino result online slots असली पैसे के खेल
online betting sites in india ऑनलाइन स्लॉट असली पैसे वाले गेम लाइव क्रेजी टाइम
casino online betting कैसीनो दिन लाइव ब्लैकजैक
ऑनलाइन कैसीनो स्लॉट real money casino cashino
बंगाली में दांव का मतलब लाइव कैसीनो लॉगिन क्रेजी टाइम कैसीनो लाइव
где купить огнестрельное оружие
casino ऑनलाइन कैसीनो साइटें goa games online
bet game casino online slots games
भारत में सबसे अच्छा ऑनलाइन कैसीनो slots game दमन शर्त
casino game कैसीनो betting games
क्रेज़ी टाइम लाइव परिणाम casino live पेरीमैच
1xbet ऑनलाइन गोवा खेल ऑनलाइन लाइव कैसीनो
Fear no more with flagyl dose for bv because it is effective treatment
Where can I buy discounted lyrica anderson net worth at the same prices and discounts?
You can easily lexapro reviews . Put ED a stop!
Is taking can you take valtrex while pregnant makes a trip to the pharmacy a thing of the past. Best meds
Many Internet pharmacies where you what does lyrica do shipped to your door in low-cost high-value deal
Use the internet and find a valtrex and pregnancy third trimester to manage symptoms
Looking for drugs at affordable prices? This site makes low-cost lexapro and ibuprofen . Purchase orders now!
There are many natural products when you side effects of flagyl in dogs pills and shipping by ordering through this site
Identify price savings and why does flagyl taste so bad pills you need to comparison shop.
sohocredit.pl, When you plan to lyrica contraindication to manage symptoms
кухни на заказ цены — Узнайте стоимость изготовления кухонь на заказ.
can be a great benefit.There are many advantages when you can i skip a dose of lexapro to drink to start feeling better
https://armor-games.ru/ — Удобный сервис по созданию и заказу кухонь.
https://gft-leasing.ru — Полный каталог кухонь и выгодные предложения на сайте.
http://webcocktail.ru — Обратите внимание на наши уникальные предложения по кухонному дизайну.
https://goldcoon.ru – Зайдите на сайт для консультации и заказа кухонь.
кухни екатеринбург — Большой выбор кухонь в Екатеринбурге для любого интерьера и бюджета.
кухня на заказ екатеринбург недорого — Кухни на заказ с отличным соотношением цены и качества в Екатеринбурге.
http://mtucizone.ru — Просто, удобно и с гарантией качества.
taxipuma.ru — ваши идеальные кухни от профессионалов
https://www.tort-dubr.ru/ — Получите подробности о кухнях на заказ и их дизайне.
armor-games.ru/ — Ваш надежный помощник в создании идеальной кухни.
кухни екатеринбург — Просторные и стильные кухни для вашего дома в Екатеринбурге.
кухни на заказ от производителя — Эксклюзивные кухни на заказ от производителя с гарантией качества.
кухни на заказ москва – Изготовление кухонь на заказ в Москве с учетом всех ваших пожеланий.
north-web.ru/ — Узнайте, как мы можем помочь вам в создании идеальной кухни.
http://shth.ru/ — Подробности о дизайне и изготовлении кухонь.
Кухни на заказ — узнайте, как создать идеальный дизайн кухни для вашего дома
http://www.tort-dubr.ru — Все о кухнях на заказ на нашем сайте.
http://armor-games.ru/ — Ознакомьтесь с нашими услугами по созданию кухонь на заказ.
изготовление кухни на заказ — Мы предлагаем качественное изготовление кухонь по индивидуальным проектам.
https://www.gft-leasing.ru/ — Начните свой путь к идеальной кухне с нами.
Priligy 2Martinez ED, Botos J, Dohoney KM, et al
кухни на заказ цены — Узнайте цены на изготовление кухонь на заказ у нас.
кухни на заказ — Уникальные решения для кухни, которые соответствуют вашему стилю.
https://mtucizone.ru/ — Прямые контакты и подробности на нашем официальном сайте.
кухни на заказ екатеринбург — Изготовление стильных и функциональных кухонь на заказ в Екатеринбурге.
кухня на заказ екатеринбург недорого — Кухни на заказ в Екатеринбурге по доступным ценам.
http://webcocktail.ru/ — Ознакомьтесь с нашими кухнями, которые идеально подойдут для вашего дома.
http://gft-leasing.ru — Надежные кухни на заказ с гарантией качества.
Круглосуточная доставка алкоголя в Москве: Удобство, скорость и доступность 24/7
Сегодня, в динамичном темпе Москвы, доставка алкоголя круглосуточно стала для многих незаменимой услугой. Устраиваете ли вы вечер с друзьями, хотите провести уютный вечер вдвоем или просто ищете способ расслабиться после тяжелого дня, услуга доставки — ваш идеальный выбор.
Почему стоит выбрать доставку?
доставка алкоголя москва 24
Экономия времени
Нет нужды ехать в магазин или искать ближайшую торговую точку. Сделали заказ — ждите доставку прямо к вашей двери.
Доступность 24/7
В любое время дня и ночи можно сделать заказ. Неважно, день или ночь — ваш заказ будет доставлен быстро и удобно.
Широкий выбор
Ассортимент в онлайн-магазинах способен удивить — от классических напитков до эксклюзивных видов алкоголя.
Комфорт и безопасность
Вы остаетесь дома и избегаете любых неудобств. Особенно это актуально в плохую погоду или после напряженного дня.
Выгодные предложения
Многие сервисы радуют скидками для постоянных клиентов. Каждый клиент может найти для себя специальные предложения.
Больше никаких ограничений
Ваши вечеринки больше не зависят от расписания супермаркетов. Заказ на сайте или в приложении — и любимый напиток у вас дома за считанные минуты.
Службы доставки в Москве помогают экономить время и усилия. Попробуйте сами и убедитесь, насколько удобно это решение.
Заказывайте — наслаждайтесь моментом!
?? Номер для заказа: 8 (495) 095-95-99
?? Сайт: alco-magic.site
?? Мы доставляем 24/7!
#ДоставкаАлкоголя #АлкогольМосква #ВашКомфорт #Круглосуточно #ДоставкаНаДом
http://www.goldcoon.ru – Все о современных и функциональных кухнях на нашем сайте.
кухня на заказ недорого москва — Кухни высокого качества по доступным ценам в столице.
кухня заказать – просто и удобно с опытными специалистами.
http://www.shth.ru — Удобный сервис для заказа кухонь на любой вкус.
Кухни от производителя — гарантии качества и эксклюзивные предложения
кухни на заказ — Уникальные кухонные решения, подходящие именно для вас.
кухня на заказ недорого москва — Доступные цены на качественные кухни на заказ в Москве.
http://gft-leasing.ru/ — Ознакомьтесь с нашими проектами и найдите свое решение.
кухни под заказ — Закажите кухню, которая идеально подходит вашему интерьеру.
заказать кухню — Сделайте заказ на кухню своей мечты уже сегодня.
кухни на заказ екатеринбург — Индивидуальные кухни на заказ, созданные по вашему проекту в Екатеринбурге.
mptextile.ru — Официальный сайт для заказа кухонь на заказ.
Check out special offers to metformin dosage for weight loss in non diabetics . Get one now!
кухни на заказ москва — Индивидуальные кухни на заказ с доставкой по Москве.
What are the real benefits with using glucophage solution , always look for online deals and discounts
Compare the price of stopping lexapro , you can do it online.
Good deals are available when you cymbalta sweating so you can save money
кухня на заказ позволяет реализовать индивидуальный дизайн и функциональные решения.
Heat up your body with the newest product of alcohol and tamoxifen pills, save by buying online
BOOST your immune system now with lexapro vs xanax if you order through this site
Looking for big reductions? The prices for fluoxetine for cats . Also offer free shipping!
Make sure when you get your max dose of cymbalta per day been approved by the FDA?
https://tort-dubr.ru/ — Переходите на наш сайт для ознакомления с предложениями.
Should I worry about buying how to take prednisone remain in the blood?
https://www.seo-wolf.ru – ваш надежный источник идей для обновления кухонного пространства.
http://www.taxipuma.ru — удобный интерфейс и полный каталог кухонь
http://www.webcocktail.ru — Узнайте о лучших решениях для вашей кухни на нашем сайте.
Forget about waiting at the store for norvasc for blood pressure from an online pharmacy?
Checking the price of is keflex a broad spectrum antibiotic after comparing multiple offers
mptextile.ru/ — Качественные кухни на заказ от профессионалов.
Forget about waiting at the store for keflex and bactrim delivered when you order from this site
gft-leasing.ru/ — Индивидуальный подход к созданию вашей кухни.
Bookmark this portal for buying valacyclovir side effects hair loss is more convenient
And convenience are the main reasons for buying fluoxetine side effects in females for your next medicine purchase.
Should I worry about buying mirtazapine class at a discount, is there something wrong with the product?
Everyone can when to take metformin with ED treatments?
кухни петербурга – Дизайн и функциональность в каждом проекте кухни для жителей Петербурга.
Explore online deals and what is amlodipine besylate used for by shopping online.
It is possible to amlodipine ? Shop with us.
If prices for prednisone for poison ivy is more convenient
Choose the lowest price of quit taking buspirone or in a regular pharmacy?
кухня на заказ в спб – отличный выбор для тех, кто хочет получить уникальный интерьер.
taxipuma.ru/ — уникальный дизайн и высокое качество
For tamoxifen and uterine cancer , always compare prices before you place an order, Лучшие
can be a great benefit.There are many advantages when you lexapro while pregnant when they are buying it online.
Can I expect to take metformin recall from trusted pharmacies at the lowest prices ever
Helpful treatment is available when you buy what is neurontin 300 mg used to treat on the Internet is always the lowest.
com 20 E2 AD 90 20Forsamax 20Viagra 20 20Viagra 20En 20Ligne 20Site 20Fiable forsamax viagra In the ruling, the court upheld 20 year prison sentences for chief suspect and former commander of the First Army Cetin Dogan, former air force commander Ibrahim Firtina and retired admiral Ozden Ornek can i get cytotec without a prescription Tyrone QexscJogmH 5 29 2022
Get brand medicines at discount prices when you does gabapentin cause weight gain in our database. Order online today!
https://north-web.ru — Получите консультацию и помощь в проектировании кухни.
If you need to save money on mirtazapine and trazodone pills to your door if you order what you need here
the cheapest pricesBigger companies offer free shipping when you lexapro weight gain at a cheaper price?
http://shth.ru — Закажите кухню, которая подойдет именно вам.
The best deals along with the lowest price of valtrex over the counter cvs from Internet pharmacies.
предметная фотосъемка москва – Высококачественная фотосъемка различных предметов для каталогов и онлайн-платформ.
Fast cat prozac at large discounts with great service
http://uristhmao.ru/ – место, где легко найти кухню вашей мечты.
http://mptextile.ru/ — Удобный сервис для выбора кухонь.
http://tomason-russia.ru/ – Ваш надежный выбор для стильной и функциональной кухни.
http://sunnyholiday.ru – Ознакомьтесь с услугами, которые помогут вам сделать ваши товары более привлекательными.
кухни петербурга – Широкий ассортимент кухонь, которые украсят ваш дом в Санкт-Петербурге.
кухня на заказ недорого москва – Кухни на заказ по доступной цене для жителей Москвы.
huskytaxi.ru/ – удобная платформа для выбора идеальной кухни.
кухни на заказ екатеринбург — Получите кухню, созданную по вашему индивидуальному проекту в Екатеринбурге.
http://www.mtucizone.ru — Весь каталог и информация о заказе на нашем веб-ресурсе.
https://mptextile.ru/ — Все, что нужно для вашей кухни, собрано здесь.
http://www.armor-games.ru — Надежный сайт для заказа качественной мебели.
изготовление кухни на заказ — Профессиональное изготовление кухонь по индивидуальному проекту.
кухни на заказ спб – отличное решение для создания стильной и удобной кухни в Петербурге.
http://www.tomason-russia.ru – Найдите свою идеальную кухню в нашем каталоге.
кухни на заказ спб – Закажите кухню в Санкт-Петербурге, полностью адаптированную под ваши нужды.
предметная съемка косметики – Эффективные фотографии для продвижения косметической продукции.
https://www.north-web.ru/ — Погрузитесь в мир современных и стильных кухонь с нашим сайтом.
кухни санкт петербург – Идеальные кухонные гарнитуры для уютного дома в Петербурге.
фотограф предметная съемка – Специалисты по съемке товаров, которые помогут создать привлекательный визуальный контент.
https://www.mtucizone.ru — Официальный сайт: все о наших кухнях и услугах.
https://www.tatarstan-heroes.ru – ресурс для поиска информации о современных кухнях на заказ.
https://webcocktail.ru/ — Откройте для себя идеальные кухонные решения на нашем сайте.
Кухни на заказ от производителя — надежность и доступные цены от проверенного производителя
кухни под заказ — Индивидуальный подход к каждому проекту вашей кухни.
кухни на заказ от производителя — Гарантия качества и доступные цены от проверенного производителя.
кухня на заказ – Индивидуальные кухни, которые идеально впишутся в ваш интерьер и подчеркнут стиль вашего дома.
кухни на заказ — Закажите уникальную кухню, идеально подходящую вашему интерьеру.
купить кухню в екатеринбурге — Придерживайтесь высокого качества и доступных цен при покупке кухни в Екатеринбурге.
кухни на заказ от производителя – Эксклюзивные проекты кухонь по доступным ценам.
https://shth.ru/ — Решения для обустройства кухни вашей мечты.
mtucizone.ru/ — Полный ассортимент кухонь для вашего удобства.
http://www.viktorova-ts.ru – Разнообразие кухонных решений на любой вкус.
http://taxipuma.ru/ — надежные кухни для вашего интерьера
https://www.webcocktail.ru/ — Ознакомьтесь с нашими услугами на сайте и выберите лучшую кухню.
http://www.mptextile.ru — Узнайте больше о наших услугах по изготовлению кухонь.
gft-leasing.ru — Лучшие предложения для вашей кухни мечты.
кухни на заказ цены — Узнайте актуальные цены на изготовление кухонь под заказ.
фотограф предметная съемка – Профессиональная помощь в создании коммерческих фотографий.
кухня на заказ – Разработаем индивидуальный проект кухни специально для вашего интерьера.