arduino-oled-auto-gauges icon indicating copy to clipboard operation
arduino-oled-auto-gauges copied to clipboard

some Code ideas

Open rolextm opened this issue 3 years ago • 6 comments

Hey man,

i have been using your oil pressure program, and i made some minor improvements.

First, the sensor calibration is off. I dont know if its because voltage drop over the cable, but just cutting negative pressure is not accurate. Instead i try to raise the baseline for 0 PSI as long as the value is negative. Second, i am building a median in values to make the display a little more consistent. I generate the measurements as fast as it runs and then feed the average to the display.

See the attached files, it were only minor fast hacks while sitting in the car, forgive the lacking code style, but for me its making the final thing a bit better ;)

Regards Alex

rolextm avatar Mar 11 '21 12:03 rolextm

@rolextm sounds awesome!!

I'd love to see the files but they weren't attached correctly. Happy to accept PR if you want to do that too.

I think I am due to reflash my arduinos with some updates from this project so I'd really like to give your additions a go!

matt-downs avatar Mar 26 '21 10:03 matt-downs

Id love to see the updated code too!

gurvir44 avatar Apr 11 '21 23:04 gurvir44

ouch! i was sure they were attached. I need to pull them of the work Laptop and will do so tonight. Thanks for the heads up in the M5 vid gurvir44 :D funny how things go :D

rolextm avatar Apr 19 '21 15:04 rolextm

// Version 2 mit Median und Auto Nullpunkt

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

// RunningMedian samples = RunningMedian(9);
RunningMedian samples = RunningMedian(3);



U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R2);

int boostPressure;
int boostMax = 0;
int boostMin = 0;
int correction = 0;

bool flashTracker = false;

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 50;

const int sensorHistoryLength = 128;
int sensorHistory[sensorHistoryLength];
int sensorHistoryPos = sensorHistoryLength - 1;


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

// u8g2.setContrast(0x2B * 255); //Set Contrast
// u8g2.sendF("c", 0x0a7);  // inversion
  
}


void loop(void) {
  // Only read from the sensors every 50 ms
  readSensorData();
  currentMillis = millis();
  if (currentMillis - startMillis >= period) 
  {
    flashTracker = !flashTracker;
    startMillis = currentMillis;
  }

  u8g2.firstPage();
  do {
    // Draw current pressure
    u8g2.setFont(u8g2_font_fub20_tf);
    char cstr[6];
    dtostrf((float)boostPressure / 100, 1, 1, cstr);
    u8g2.drawStr(0, 20, cstr);

    // Draw max pressure
    u8g2.setFont(u8g2_font_fub11_tf);
    char indicator[5];
    if (boostPressure < 5000) {
      // LOW
      if (flashTracker)  { strcpy(indicator, "LOW") ;
      u8g2.setContrast(255); //Set Contrast 
      // u8g2.sendF("c", 0x0a7);
      
      }
      else { strcpy(indicator, ""); 
      // u8g2.sendF("c", 0x0a6 & 1);
      //u8g2.setContrast(0); //Set Contrast 
      } 
    } else if (boostPressure < 8000) {
      // IDLE
      strcpy(indicator, "IDLE");
      //u8g2.setContrast(255); //Set Contrast
    } else {
      // LOAD
      strcpy(indicator, "LOAD");
      //u8g2.setContrast(255); //Set Contrast
    }
    int yPos = u8g2.getStrWidth(indicator);
    u8g2.drawStr(128 - yPos, 11, indicator);

    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
    rmin = 102
    rmax = 921
    Sensor reads from 0 to 140psi
    tmin = 0
    tmax = 14000

    normalisedValue = ((m − 102) / (921 − 102)) * (14000 − 0) + 0
    normalisedValue = ((m − 102) / 819) * 14000
    normalisedValue = (m − 102) / 0.0585
  */
  samples.add((m - 102) / 0.0585);
  //return (m - 102) / 0.0585  ;
  return samples.getMedian();
}


void readSensorData(void) {
  float absolutePressure = normaliseSensorData(analogRead(A0));
  
  // Subtract 14.7 psi == pressure at sea level
  boostPressure = absolutePressure - 1470 + correction;

  // Oil pressure should never be negative
  //if (boostPressure < 0) boostPressure = 0;
  if ((absolutePressure - 1470) < 0) 
    {
      //boostPressure = 0;
      correction = 0 - (absolutePressure - 1470);
    }

  // 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);
  }
}

rolextm avatar Apr 19 '21 15:04 rolextm

Im having a issue where its reading a random value when ever my finger is touching the arduino or the cable is moved in a certain way. Is this a floating input? Any ideas on how to solve this?

gurvir44 avatar May 25 '21 14:05 gurvir44