Graf na OLED 0.96"

Odpovědět
hafca
Příspěvky: 86
Registrován: 23 říj 2017, 23:05
Reputation: 0

Graf na OLED 0.96"

Příspěvek od hafca » 15 čer 2021, 20:45

Postavil jsem si monitor ovzuší s MQ-135, kde by se na displeji měla zobrazovat naměřená hodnota v % a střídat se s grafem. Hodnota se ukazuje, ale místo grafu je jen rámeček bez hodnot.
Vím, že je to spíš hračka než seriózní měřidlo, ale stejně bych ten graf rád viděl.
Problém je v tom že program jsem nepsal já, byl u stl souborů na krabičku.
Tyhle displeje jsou zatím pro mě jako začátečníka velká neznámá. Stjně tak v tom ostatním taky trochu plavu. Zvlášť tady, kde je plno zaremovaných příkazů.
Může se nějaká dobrá duše podívat, kde je chyba?

Kód: Vybrat vše

 #include <ESP8266WiFi.h>
#include "SSD1306.h"
#define GAS_SENSOR_PIN A0
const boolean DEBUG = false;
SSD1306  display(0x3C, D2, D1);
long frame = 1; //1 instead of 0, to avoid all modulo checks from triggering on first frame
int sensorValue = 0;
float tempAveragedSensorValue = 0;
float averagedSensorValue = 0;
const int INTERVALS_PER_UI = 50;
bool showGraph = false;
const int UPDATE_INTERVAL = 100; //ms
const int AVERAGING_SAMPLES = 10;
const int GRAPH_SAMPLES_PER_PIXEL = DEBUG ? 5 : (5*60*1000 / UPDATE_INTERVAL); //each vertical line on the graph represents 5 minutes
const int GRAPH_MARKER_SPACING = 12; //show a marker in the graph for every hour
const int X_RES = 128;
const int Y_RES = 64;
const int LOWEST_OBSERVED_READING = 198;
const int HIGHEST_OBSERVED_READING = 330 + 20;
int graphValues[128];
int currentGraphSampleCount = 0;
void setup() {  
  disableWifi();
  Serial.begin(9600);
  display.init();
  display.flipScreenVertically();
  if(!DEBUG) 
  {
    showHeatupMessage();
  }
}
void loop(){
  readSensor();
  displayUi();
    delay(UPDATE_INTERVAL);
  frame++;
}
void displayUi() 
{
  display.clear();
  if(showGraph)
  {
    displayGraph();
  } else {
    displayReading();
  }

  if(frame % INTERVALS_PER_UI == 0)
  {
    showGraph = !showGraph;
  }
  display.display();
}
void displayGraph() 
{
  display.drawRect(0, 0, X_RES, Y_RES);
  for(int x = 0; x < X_RES; x++)
  {
    int actualX = X_RES - x-1;

    display.setFont(ArialMT_Plain_10);
    display.setTextAlignment(TEXT_ALIGN_LEFT);
       int loggedValue = graphValues[x];
    int actualY = int(normalizeSensorValue(float(loggedValue)) * float(Y_RES));
        if(loggedValue == 0.0)
    {
      actualY = Y_RES;
    }
   // display.drawString(0, x*10, String(actualY));
   // display.setPixel(actualX, actualY);
        //display.drawString(0, x*10, String(int(float(loggedValue)*float(Y_RES)/float(1023))));
    display.setPixel(actualX, int(float(loggedValue)*float(Y_RES)/float(1023)));
    if((x+1) % GRAPH_MARKER_SPACING == 0)
    {
      //render marker 
     // display.drawRect(actualX, 0, 1, actualY);
    } else {
      display.drawRect(actualX, actualY, 1, Y_RES - actualY);
      display.drawVerticalLine(actualX, actualY, Y_RES - actualY);
           } 
       }
}
void displayReading()
{
  float pollution = normalizeSensorValue(averagedSensorValue);
  float quality = 1.0 - pollution;
  display.setFont(ArialMT_Plain_16);
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(X_RES/2, 0, "Air Quality:");
  display.setFont(ArialMT_Plain_24);
  display.drawString(X_RES/2, 15, String(int(quality * 100)) + "%"); 
  if(DEBUG || true) {
    display.setFont(ArialMT_Plain_10);
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.drawString(0, Y_RES-11, String(sensorValue));
    display.setTextAlignment(TEXT_ALIGN_RIGHT);
    display.drawString(X_RES, Y_RES-11, String(sensorValue/1023.0*3.3) + "v");
  }
}
void readSensor() 
{
  sensorValue = analogRead(GAS_SENSOR_PIN);
  if(tempAveragedSensorValue == 0) 
  {
    tempAveragedSensorValue = sensorValue;
  } else {
    tempAveragedSensorValue = (averagedSensorValue * float(AVERAGING_SAMPLES-1) / float(AVERAGING_SAMPLES)) + sensorValue / float(AVERAGING_SAMPLES);
  }
  if((frame % AVERAGING_SAMPLES == 0) || averagedSensorValue == 0)
  {
    averagedSensorValue = tempAveragedSensorValue;
  }

  if(++currentGraphSampleCount > GRAPH_SAMPLES_PER_PIXEL)
  {
    addDatapointToGraph(averagedSensorValue);
    currentGraphSampleCount = 0;
  }  
}

//append value to start of array, and push all other values backwards
void addDatapointToGraph(float value) 
{  
  for(int i=X_RES-1; i> 0; i--)
  {
    graphValues[i] = graphValues[i-1];
  }
  graphValues[0] = int(value);
}
float normalizeSensorValue(float value)
{
  return deRange(value, LOWEST_OBSERVED_READING, HIGHEST_OBSERVED_READING);
}

float deRange(float value, int lowerBound, int upperBound)
{
  return (value - lowerBound) / float(upperBound-lowerBound);
}
void showHeatupMessage() 
{
  for(int i=20; i >= 0; i--)
  {
    showHeatupMessageInternal(i);
    delay(1000);
  }
}
void showHeatupMessageInternal(int remainingSeconds) 
{
  display.clear();
  display.drawString(0, 0, "Heating sensor...");
  display.drawString(0, 20,  String(remainingSeconds) + " seconds");
  display.display();
}
//Saves a bit of power/heat, and avoids a silly ESP wifi access point showing up when the device is on.
void disableWifi() {
  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();
  delay(1); //waiting a millisecond is done to cede control to the ESP firmware, so it can actually apply our settings.
}
Edit: nepoužívej QUOTE, ale CODE, hned to líp vypadá. Gilhad

hafca
Příspěvky: 86
Registrován: 23 říj 2017, 23:05
Reputation: 0

Re: Graf na OLED 0.96"

Příspěvek od hafca » 15 čer 2021, 21:36

Tak graf se nakonec objevil, ale kreslí se z pravé strany a pokračuje na levou. :o

Uživatelský avatar
kiRRow
Příspěvky: 1152
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Graf na OLED 0.96"

Příspěvek od kiRRow » 16 čer 2021, 15:59

jen tak ze srandy bych zkusil místo

Kód: Vybrat vše

int actualX = X_RES - x-1;
dát

Kód: Vybrat vše

int actualX = x;
co to provede :)

hafca
Příspěvky: 86
Registrován: 23 říj 2017, 23:05
Reputation: 0

Re: Graf na OLED 0.96"

Příspěvek od hafca » 16 čer 2021, 19:31

Děkuji tip, zabral.
Ale čím víc se v to hrabu, tím míň se mi to líbí. Teď to ukazuje kvalitu 116 až 128%, což je nesmysl. Velkou roli v tom nejspíš bude hrát i napájení jen 3.3V. Údajně by to mělo jít i s Arduino NANO, ale to jsem pro něj nedokázal upravit
Asi se podívám po nějakém jiném měřiči. Je to sice levný senzor, ale tak blbě by asi ukazovat neměl.

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Graf na OLED 0.96"

Příspěvek od AstroMiK » 16 čer 2021, 19:58

Podle názvů konstant v programu bych odhadoval, že tam bude potřeba nějaká kalibrace minima a maxima.

Kód: Vybrat vše

...
const int LOWEST_OBSERVED_READING = 198;
const int HIGHEST_OBSERVED_READING = 330 + 20;
...
LOWEST_OBSERVED_READING .... nejnižší hodnota, jaká byla dlouhodobě zaznamenána
HIGHEST_OBSERVED_READING .... nejvyšší hodnota, jaká byla dlouhodobě zaznamenána + nějaká rezerva (20)


Napájení pro čidlo musí být 5V s dostatečným proudem (120mA podle kat.listu). Je tam topné těleso, které to čidlo vyhřívá.
A pokud používáš analogový vstup s rozsahem 3.3V, tak se to dá řešit odporovým napěťovým děličem na výstupu čidla, který to napětí lineárně sníží.

hafca
Příspěvky: 86
Registrován: 23 říj 2017, 23:05
Reputation: 0

Re: Graf na OLED 0.96"

Příspěvek od hafca » 17 čer 2021, 10:42

Zkoušel jsem ty hodnoty měnit až jsem se dostal na /1.5. S tím to ukazuje asi tak co by mělo. Problém je, že stejně nevím, jak to autor kalibroval nebo kde ty čísla vzal. Zkusil jsem převodník úrovní, ale na analogu to moc nefunguje. Když k tomu udělám dělič aby to šlo na 5V, bude to mít zase jiné hodnoty.
A na UNO nebo NANO abych mohl použít těch 5V se mi to konvertovat nedaří.
Vidím to na slepou cestu, ale i tak ještě jednou dík za pomoc.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 12 hostů