Sviečkové grafy s reálnymi číslami

Zápisník experimentátora

Hierarchy: Sviečkové grafy

V dnešnom dieli prerobíme sviečkové grafy z celých čísiel na reálne. Toto bude iba drobná zmena voči pôvodnému algoritmu, pretože sme ho od začiatku písali cez šablóny. Vďaka tomuto kódu budeme môcť v nasledovnom článku zobrazovať reálnu teplotu zo senzora DS18B20.

Schéma zapojenia sa v ničom neodlišuje od predchádzajúcich zapojení s displejom Nokia 5110, kde sme nepotrebovali pripojiť žiadne ďalšie súčiastky. Iba Arduino, level shifter a displej Nokia 5110.

Program

Pretože chceme používať reálne čísla namiesto celých, musíme v celom kóde nahradiť funkciu map za jej alternatívu, ktorá zvládne aj reálne čísla. Urobíme to tak, že zoberieme pôvodný zdrojový kód funkcie a urobíme z neho šablónovú funkciu, ktorá sa automaticky dokáže prispôsobiť svojim parametrom. Všetky parametre musia mať rovnaký typ a vďaka tomu vystačíme iba s jedným šablónovým parametrom.

template<typename ohlcvalue>
ohlcvalue fmap(ohlcvalue x, ohlcvalue in_min, ohlcvalue in_max, ohlcvalue out_min, ohlcvalue out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Potom už musíme len nahradiť volania pôvodnej funkcie za novú. Pritom je rozumné, ak použijeme pretypovanie parametra na ohlcvalue, čo pomôže kompilátoru s uhádnutím toho, aké presne parametre dávame do funkcie.

template<class ohlcvalue>
class OHLCNokia5110BarRender : public OHLCNokia5110BaseRender<ohlcvalue> {
public:
  void drawBar(int pos, OHLCData<ohlcvalue> *bar, ohlcvalue minimum, ohlcvalue maximum) {
    if(this->display==NULL)
      return;
    if(minimum==maximum)
      return;

    OHLCData<ohlcvalue> _bar=*bar;
      
    int START = 5 + pos * 6;
    const int BW = 2;
    const int HEIGHT = 47;
    int top;
    int bottom;

    // transformation
    _bar.o = fmap(_bar.o,minimum,maximum,(ohlcvalue)0,(ohlcvalue)HEIGHT);
    _bar.h = fmap(_bar.h,minimum,maximum,(ohlcvalue)0,(ohlcvalue)HEIGHT);
    _bar.l = fmap(_bar.l,minimum,maximum,(ohlcvalue)0,(ohlcvalue)HEIGHT);
    _bar.c = fmap(_bar.c,minimum,maximum,(ohlcvalue)0,(ohlcvalue)HEIGHT);

    if(_bar.o < _bar.c) {
      top = _bar.c;
      bottom = _bar.o;
    } else {
      top = _bar.o;
      bottom = _bar.c;
    }

    // high
    this->display->drawLine(START+1*BW,HEIGHT-_bar.h,START+1*BW,HEIGHT-top,BLACK);

    // low
    this->display->drawLine(START+1*BW,HEIGHT-_bar.l,START+1*BW,HEIGHT-bottom,BLACK);

    // bar
    if(_bar.o < _bar.c) {
      this->display->fillRect(START,HEIGHT-bottom,2*BW+1,bottom-top+1,WHITE);
      this->display->drawRect(START,HEIGHT-bottom,2*BW+1,bottom-top+1,BLACK);
      }
    else
      this->display->fillRect(START,HEIGHT-bottom,2*BW+1,bottom-top+1,BLACK);
    }
};

A to je všetko. Vidíte, že niekedy sú šablóny úžasná vec, ako sa veľa nenarobiť a ako rovnaký algoritmus aplikovať na rôzne dátové typy.

OHLCChart<double, 12, 10000, OHLCNokia5110BarRender<double> > ohlc;

double value=22.4;

void loop() {
  // update random data
  int valuemove=random(30)-15;
  value+=valuemove/100.;
  value=constrain(value,10,40);
  //Serial.println(value);
  ohlc.addValue(value);

  // render chart
  display.clearDisplay();
  // draw candlesticks
  ohlc.draw();
  // draw last value
  display.fillRect(5,5,5+5*5+3,11,BLACK);
  display.fillRect(6,6,5+5*5+1,9,WHITE);
  display.setCursor(7,7);
  display.print(value);
  // draw indicator
  int _v=fmap(value,ohlc.minimum,ohlc.maximum,0.,47.);
  display.drawLine(82,47-_v,83,47-_v,BLACK);
  display.drawLine(83,47-_v+1,83,47-_v-1,BLACK);
  display.display();
  
  delay(200); // 5 values/second
} 

Zdrojový kód

Zdrojový kód sa nachádza na GitHub.


21.10.2016


Menu