Arduino vacuum/boost gauge sensor calibration

hello friends I saw a video about a boost gauge on YouTube and decided to make the same device. The scheme is simple - arduino nano, 1.3” oled display, bmp085 / in my case bmp180/ and pressure sensor mpx4250 / 2.5 bar / I will try to upload the code that is in the description of the video. the problem is the following - according to the way the calibration is described in the code, when the boost meter is attached to the car and the engine is running, the display shows -0.9/-1.0 bar vacuum, which is impossible. when I checked with car diagnostics, it uses -0.35 bar vacuum. To be sure I checked what my lpg ecu was showing too - the readings were the same -0.35 bar vacuum. I doubted the correct operation of the sensor and therefore tried with another / I took the voltage from its specification / mpx5700, but the result was the same. I also tried with a third sensor / BMW original / - the readings were again the same.Can somebody help me make this boostmeter work properly ? Here is a link to the video https://youtu.be/dPYfYAu3kfI?si=tykQVdrlKphNA8ZZ


// Created by Steven Marshall
// Created 23/03/2020
// v1.0.3-beta.1.0
// https://github.com/smarshall-rightside/Project_Power/
// Licensed for non-commercial use ONLY
// Do not remove this header



#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>

U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R2);

unsigned long startMillis;
unsigned long currentMillis;
unsigned long time_passed;
unsigned long lastReset;

const unsigned long period = 50;

const int sensorHistoryLength = 128;
int sensorHistory[sensorHistoryLength];
int sensorHistoryPos = sensorHistoryLength - 1;
int boostPressure;
int boostMax = 0;
int BoostMaxTop = 0;
int boostMin = 0;
float inbar;
float maxinbar;

void setup(void) {
  u8g2.begin();
  startMillis = millis();
  time_passed = millis();
}


void loop(void) {
  // Only read from the sensors every 50 ms
  currentMillis = millis();
  if (currentMillis - startMillis >= period) {
    readSensorData();
    startMillis = currentMillis;
    // Set Max Boost Value
    if (boostPressure >= BoostMaxTop)
    {
      BoostMaxTop = boostPressure;
    }
    else if (boostPressure <  BoostMaxTop)
    {
      if (millis() - lastReset > 5000) {
        lastReset += 5000;
        time_passed = 0;
        BoostMaxTop = boostPressure;
      }
    }
  }

  u8g2.firstPage();
  do {
    // Draw current pressure
    u8g2.setFont(u8g2_font_fub20_tf);
    // Change PSI to BAR
    inbar = boostPressure / 100;
    char cstd[6];
    dtostrf((float)inbar / 14.504, 1, 1, cstd);
    u8g2.drawStr(0, 20, cstd);

    // Draw boost text
    // If statment fixes Bug #1
    if (boostPressure >=0)
    {
      u8g2.setFont(u8g2_font_helvR08_tf);
      u8g2.drawStr(40, 20, "BOOST");
    }
    else if (boostPressure < 0)
    {
      u8g2.setFont(u8g2_font_helvR08_tf);
      u8g2.drawStr(50, 20, "VAC");
    }
    // Draw boost text
    if (boostPressure >= 3500)
    {
      u8g2.setFont(u8g2_font_fub11_tf);
      u8g2.drawStr(40, 10, "MAX");
    }
    else if (boostPressure < 3500)
    {
      u8g2.setFont(u8g2_font_helvR08_tf);
      u8g2.drawStr(40, 10, "");
    }

    // Draw max pressure
    u8g2.setFont(u8g2_font_fub11_tf);
    // Change PSI to BAR
    maxinbar = BoostMaxTop / 100;
    char csta[6];
    dtostrf((float)maxinbar / 14.504, 1, 1, csta);

    int yPos = u8g2.getStrWidth(csta);
    u8g2.drawStr(128 - yPos, 11, csta);

    drawBarGraph(0, 22, 128, 8);
    drawGraph(0, 32, 128, 31);

  } while ( u8g2.nextPage() );
}

float normaliseSensorData(int m) {
  /*
    Scale the sensor reading into range
    m = measurement to be scaled
    rmin = minimum of the range of the measurement
    rmax = maximum of the range of the measurement
    tmin = minimum of the range of the desired target scaling
    tmax = maximum of the range of the desired target scaling
    normalisedValue = ((m − rmin) / (rmax − rmin)) * (tmax − tmin) + tmin
    https://stats.stackexchange.com/a/281164
  */

  /*
    Sensor voltage ranges from 0.5v to 4.5v, converted to analogRead values (0 min, 1023 max) that's 102 to 921. Times the voltage by 204.66
    rmin = 102
    rmax = 921
    Sensor reads from 0 to 50psi
    tmin = 0
    tmax = 5000
    normalisedValue = ((m − 102) / (921 − 102)) * (5000 − 0) + 0
    normalisedValue = ((m − 102) / 819) * 5000
    normalisedValue = (m − 102) / 0.1638
  */

  return (m - 102) / 0.1638;
}

void readSensorData(void) {
  float absolutePressure = normaliseSensorData(analogRead(A0));

  // Subtract 14.7 psi == pressure at sea level
  // Additional 2.57psi subtracted as boost was showing 2.57 with engine off
  boostPressure = absolutePressure - 1727;

  // Update max and min
  if (boostPressure > boostMax) boostMax = boostPressure;
  if (boostPressure < boostMin) boostMin = boostPressure;

  // Log the history
  addSensorHistory(boostPressure);
}

void addSensorHistory(int val) {
  sensorHistory[sensorHistoryPos] = val;
  sensorHistoryPos--;
  if (sensorHistoryPos < 0) sensorHistoryPos = sensorHistoryLength - 1;
}

int getSensorHistory(int index) {
  index += sensorHistoryPos;
  if (index >= sensorHistoryLength) index = index - sensorHistoryLength;
  return sensorHistory[index];
}

// Display functions
void drawGraph(int x, int y, int len, int height) {
  // Draw the lines
  drawHorizontalDottedLine(x, y, len);
  drawHorizontalDottedLine(x, y + height, len);

  //var absMin = Math.abs(boostMin);
  int absMin = abs(boostMin);
  int range = absMin + boostMax;

  // Draw 0 line
  int zeroYPos = mapValueToYPos(absMin, range, y, height);
  drawHorizontalDottedLine(x, zeroYPos, len);

  // Draw the graph line
  for (int i = 0; i < 128; i++) {
    // Scale the values so that the min is always 0
    int valueY = getSensorHistory(i) + absMin;

    // Calculate the coordinants
    int yPos = mapValueToYPos(valueY, range, y, height);
    int xPos = len - i;
    if (yPos < zeroYPos) {
      // Point is above zero line, fill in space under graph
      u8g2.drawVLine(xPos, yPos, zeroYPos + 1 - yPos);
    } else {
      // Point is below zero line, draw graph line without filling in
      u8g2.drawPixel(xPos, yPos);
    }
  }
}

void drawBarGraph(int x, int y, int len, int height) {
  if (boostPressure > 0) {
    // Draw the pressure bar behind the graph
    int barLength = ((float)boostPressure / boostMax) * len;
    u8g2.setDrawColor(2);
    u8g2.drawBox(x, y, barLength, height);
    u8g2.setDrawColor(1);
  }
}

// Maps a value to a y height
int mapValueToYPos(int val, int range, int y, int height) {
  float valueY = ((float)val / range) * height;
  return y + height - (int)valueY;
}

void drawHorizontalDottedLine(int x, int y, int len) {
  for (int i = 0; i < len; i++) {
    if (!(i % 4)) u8g2.drawPixel(x + i, y);
  }
}

Why are you using beta when the author of the code has offered release version?
...with completely different calibration/conversion....

// Subtract 14.7 psi == pressure at sea level
  // Additional 2.57psi subtracted as boost was showing 2.57 with engine off
  boostPressure = absolutePressure - 855;//was 865

I think there is no difference between 1.0.3 beta and 1.0.3 versions. Calculations for scaling are the same. Can you look at these two versions and try to find the difference? May be i miss something… I can not upload the third version on my arduino,the program says that the code is too big or too long, i can’t remember

the boostpressure formula I posted above looks very much different.

// Subtract 14.7 psi == pressure at sea level
// Additional 2.57psi subtracted as boost was showing 2.57 with engine off
boostPressure = absolutePressure - 855;//was 865

This is from version 1.0.3 releese , i can’t see the difference…. Am i blind?!

Either you or me.
The code you posted has:
boostPressure = absolutePressure - 1727;

O yeah,i am blind :confused: what this digits mean? And how the reflect to calculation? And what version is suitable with my sensors? I am not sure , but i think a time ago i’ve been tried the bought codes,but with no luck…. I will try again

1727 is about twice 855.
I can't answer that.
The point was to use release when available, instead of beta.

I will try today and will say is there some difference

Ok i just try with other code,upload it on nano but now display shows 0.5 bar of boost without any pressure applied / positive or negative/

Then you need to get your hands dirty. Either the code is crap, or your sensor is not compatible with it, or you have hardware issue.
You could start just with simple analogread and follow how it responses to changes in pressure.

Like i said,i used 3 different sensors and result is the same. I tried with another arduino /uno/…. The same… i think is something with the code. The problem is i am too far from writing codes on arduino. Because of this i am looking for help. Is there another way to calibrate pressure sensor on arduino?

Why not if you have a way to produce known pressure as calibration points.

how can this be possible? give me an idea…?

First you should make sure you have your sensor working properly.
Are you using mpx4250D (differential pressure sensor) or mpx4250A (manifold absolute pressure sensor)?

My sensor is MPX4250AP,next….?

Datasheet gives this function:


Vo= Vcc*(0.004P-0.04)
so the conversion to pressure in kPa is:
P=Vo/0.004Vcc + 10
Try what you get out with this code without pressure on sensor.

int average = 0; 
float pressure = 0;       

void setup()
{
  Serial.begin(9600);             
}

void loop()
{
 average = 0;
 for (int i=0; i < 10; i++) {
 average = average + analogRead(A0);
 }
 average = average/10;
pressure = average/(0.004*1023)+10;//MPX4250A

Serial.print("Averaged analog read: "); 
Serial.println(average); 
Serial.print("Pressure reading (kPa): "); 
Serial.println(pressure);
delay(1000);
}

Edit: Corrected one missing line

Without a pressure sensor display shows 0.0 bar

Ok i check the sensor with multimeter… according to specification of sensor on atmospheric pressure 100kpa,1bar the output voltage must be aroud 1.8 volts. My sensor shows 1.86v and when i apply vacuum voltage drops down,when i apply pressure voltage increase. That mean the sensor is working properly

What it shows in serial monitor? The code doesn't have display, was just to test that conversion is correct. It should display around 100 kPa