Точное измерение высоты с помощью BMP180

Тема в разделе "Arduino & Shields", создана пользователем Danil_2002, 13 авг 2019.

  1. Danil_2002

    Danil_2002 Гик

    Доброго времени суток!

    Возникла необходимость контролировать высоту с помощью BMP180, но для этого мне нужно получить максимально точные значения (+/- 30cm). Использую Wemos d1 (это важно, не все библиотеке поддерживаются) . Пытаюсь уже несколько дней, но максимальная точность что у меня получилась это +/- 1m.

    Вот последний код что я слепил:

    Код (C++):
    #include<Wire.h>

    #define BMP085_ADDRESS 0x77 // I2C address

    const unsigned char OSS = 0;

    long pressure_start; // Начальное давление

    int ac1;
    int ac2;
    int ac3;
    unsigned int ac4;
    unsigned int ac5;
    unsigned int ac6;
    int b1;
    int b2;
    int mb;
    int mc;
    int md;
    long b5;
    short temperature;
    long pressure;
    void setup()
    {
    Serial.begin(9600);
    Wire.begin();
    bmp085Calibration();
    delay(80);
    temperature = bmp085GetTemperature(bmp085ReadUT());
    pressure_start = bmp085GetPressure(bmp085ReadUP());
    }
    void loop()
    {
    temperature = bmp085GetTemperature(bmp085ReadUT());
    pressure = bmp085GetPressure(bmp085ReadUP());
    /*Serial.print("Temperature: ");
    Serial.print(temperature, DEC);
    Serial.println(" *0.1 deg C");
    Serial.print("Pressure: ");
    Serial.print(pressure, DEC);
    Serial.println(" Pa");
    Serial.println(); */

    long delta_pressure = pressure - pressure_start;
    Serial.print("delta (mm): ");
    Serial.println(delta_pressure*0.75);
    Serial.print("height(m): ");
    Serial.println(delta_pressure/11.08);
    delay(1000);
    }
    void bmp085Calibration()
    {
    ac1 = bmp085ReadInt(0xAA);
    ac2 = bmp085ReadInt(0xAC);
    ac3 = bmp085ReadInt(0xAE);
    ac4 = bmp085ReadInt(0xB0);
    ac5 = bmp085ReadInt(0xB2);
    ac6 = bmp085ReadInt(0xB4);
    b1 = bmp085ReadInt(0xB6);
    b2 = bmp085ReadInt(0xB8);
    mb = bmp085ReadInt(0xBA);
    mc = bmp085ReadInt(0xBC);
    md = bmp085ReadInt(0xBE);
    }

    short bmp085GetTemperature(unsigned int ut)
    {
    long x1, x2;
    x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
    x2 = ((long)mc << 11)/(x1 + md);
    b5 = x1 + x2;
    return ((b5 + 8)>>4);
    }

    long bmp085GetPressure(unsigned long up)
    {
    long x1, x2, x3, b3, b6, p;
    unsigned long b4, b7;
    b6 = b5 - 4000;
    // Calculate B3
    x1 = (b2 * (b6 * b6)>>12)>>11;
    x2 = (ac2 * b6)>>11;
    x3 = x1 + x2;
    b3 = (((long)ac1)*4 + x3)>>2;
    x1 = (ac3 * b6)>>13;
    x2 = (b1 * ((b6 * b6)>>12))>>16;
    x3 = ((x1 + x2) + 2)>>2;
    b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
    b7 = ((unsigned long)(up - b3) * (50000>>OSS));
    if (b7 < 0x80000000)
    p = (b7<<1)/b4;
    else
    p = (b7/b4)<<1;
    x1 = (p>>8) * (p>>8);
    x1 = (x1 * 3038)>>16;
    x2 = (-7357 * p)>>16;
    p += (x1 + x2 + 3791)>>4;
    return p;
    }
    char bmp085Read(unsigned char address)
    {
    unsigned char data;
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(address);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 1);
    while(!Wire.available());
    return Wire.read();
    }
    int bmp085ReadInt(unsigned char address)
    {
    unsigned char msb, lsb;
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(address);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 2);
    while(Wire.available()<2);
    msb = Wire.read();
    lsb = Wire.read();
    return (int) msb<<8 | lsb;
    }
    unsigned int bmp085ReadUT()
    {
    unsigned int ut;
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();
    delay(5);

    ut = bmp085ReadInt(0xF6);
    return ut;
    }
    //Read the uncompensated pressure value
    unsigned long bmp085ReadUP()
    {
    unsigned char msb, lsb, xlsb;
    unsigned long up = 0;
    //Write 0x34+(OSS<<6) into register 0xF4
    //Request a pressure reading w/ oversampling setting
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x34 + (OSS<<6));
    Wire.endTransmission();
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF6);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 3);

    while(Wire.available() < 3);
    msb = Wire.read();
    lsb = Wire.read();
    xlsb = Wire.read();
    up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
    return up;
    }
    Результат:
    height(m): 1.62
    delta (mm): 16.50
    height(m): 1.99
    delta (mm): 16.50
    height(m): 1.99
    delta (mm): 1.50
    height(m): 0.18
    delta (mm): 0.00
    height(m): 0.00
    delta (mm): 13.50
    height(m): 1.62

    Может у кого есть готовые примеры? и ещё можете посоветовать более точный способ измерять ну например высоту полёта коптера.
     
  2. parovoZZ

    parovoZZ Гуру

    GNSS, радиовысотомеры. На давлении воздуха на открытом воздухе, где плотность зависит от температуры, а давление от скорости .... требовать такой такой точности и получить один метр на таком хреновом датчике уже достижение.
     
    Danil_2002 нравится это.
  3. Danil_2002

    Danil_2002 Гик

    Окей, спасибо GNSS радиовысотомеры значит
     
  4. noevile

    noevile Гик

    в принципе не такое уж и достижение, если сначала прочитать про альтиметры до покупки сего девайса. в принципе если его привязать к такому же датчику на уровне земли, то в принципе и получим расстояние от земли до датчика. а вообще соглашусь на погрешность альтиметров плюс минус километр.
     
  5. b707

    b707 Гуру

    и нафига писать, если сказать нечего? :)
     
  6. noevile

    noevile Гик

    не знаю нафига городить такой колхоз, но я рекомендую прочитать как работают альтиметры. тогда станет ясно что необходима ещё одна переменная давления. так сказать точка отсчёта высоты. и заодно почитать про датчики атмосферного давления для ардуин и выбрать наименее шумящий. а то так и будет плюс минус километр. заодно в мануалах к этим датчикам формулки будут для расчёта той самой высоты, прямо рядом с формулками предсказания погоды. как ни крути, а с ардуиной получится или метеостанция или метеостанция :D:D:D
     
  7. noevile

    noevile Гик

    нууу да, в принципе сказал, что на одном датчике давления, высоты особо не измерить. или надо было что-то другое сказать?
     
  8. b707

    b707 Гуру

    обратите этот совет к себе
    Равномерное падение давления с высотой бывает только в безветренную пасмурную погоду. В остальных случаях флуктуации давления от ветра и конвективных потоков не позволят получить данные высоты с точностью лучше 2-3х метров
     
  9. b707

    b707 Гуру

    относительную - не проблема, а именно такая, ИМХО, и требуется автору
     
  10. noevile

    noevile Гик

    я правильно понимаю, что альтиметры которые стоят в самолётах и вертолётах это всё ересь и их надо бы выкинуть за ненадобностью?
     
  11. b707

    b707 Гуру

    а у них точность лучше 1м?
    Никто не говорит. что альтиметры бесполезны, вопрос только в том, что точность, треюуемую ТС - с них не получить
     
  12. noevile

    noevile Гик

    ну так что мешает кинуть один датчик на землю , а другой поднять на нужную высоту и измерять уже относительную высоту немногим пренебрегая флуктуации давления от ветра и конвективных потоков? я бы так и поступил применив 2 датчика. особенно учитывая что автор измеряет полтора метра высоты уже целый день и о никаких километрах над уровнем моря ничего не сказано. думаю погрешность плюс минус 0.5 метра вполне реально выжать.
     
  13. Danil_2002

    Danil_2002 Гик

    С двумя датчиками как то костыльно получается. Моё мнение
     
  14. noevile

    noevile Гик

    ну тут несколько путей решения сей задачи. или согласиться на +/- 1м, или дальше копать в сторону высотомеров и выбирать решение по вкусу и по карману.
     
  15. noevile

    noevile Гик

    а какая задача то? какую высоту измерять надо и для чего? а то что-то интересно стало.
     
  16. Danil_2002

    Danil_2002 Гик

    Вообще наверное стоило в самом начале сказать, но я не думал что тема затянется и эта информация понадобится. Вообщем делаю модель дирижабля и нужно знать реальное расстояние до земли. В самом начале знал что барометр не подойдет, но решил попробовать, пока не появится что то более точное. То есть дирижабль находясь на земле меряет давление на поверхности, запоминает и дальше уже...
     
  17. b707

    b707 Гуру

    и главное - озвученную проблему это не решит, точность вырастет совсем ненамного
     
  18. b707

    b707 Гуру

    ну собственно все высотомеры так и работают. Только точность в 3-5. а то и 20м обычно всех устраивает :) Не вполне ясно, зачем модели дирижабля высота с точностью до 10см?
     
  19. noevile

    noevile Гик

    GPS бери. век воли не видать )))
     
  20. b707

    b707 Гуру

    точность определения высоты по GPS - 5-10м