-
Notifications
You must be signed in to change notification settings - Fork 0
/
OLEDPlotter.h
173 lines (128 loc) · 4.37 KB
/
OLEDPlotter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
*
* Record Player Tachometer
* ========================
*
* Helper functions to plot the cartesian graph on the OLED
* we use the u8g2 grafic library, see https://github.com/olikraus/u8g2/wiki/u8g2reference
*
*/
#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>
#ifndef OLEDPlotter_h
#define OLEDPlotter_h
#include "Debugger.h"
class OLEDPlotter {
public:
static constexpr int button_pin = 3; // pin 3 is int 1 on nano
void init(); // initialize everything
void toggleScale(); // toggle scale between 33 and 45
void plotGraph(float values[], int numVals); // main method to plot rhe graph
int value2Pixels(float value); // calculates an RPM value into pixels forthe OLED
private:
void drawYAxis(); // pretty Y axis
// lib instance
U8G2_SH1107_SEEED_128X128_2_HW_I2C *u8g2;
// scaling
enum scales {UNSET, THIRTYTHREE, FOURTYFIVE};
// physical dimensions of the OLED
const float oled_width = 128.0;
const float oled_height = 128.0;
// scaling definition
struct t_scaling {
float vmax;
float vmin;
float vtarget;
float resolution;
String labelTarget;
String labelMin;
String labelMax;
};
// Scale for 33
const t_scaling scale_33 = { 36.0, 30.0, 33.33, oled_height / (36.0 - 30.0), "33", "30", "36" };
// Scale for 45
const t_scaling scale_45 = { 48.0, 42.0, 45.0, oled_height / (48.0 - 42.0), "45", "42", "48" };
t_scaling scaleset = scale_45;
scales scale;
Debugger debugger;
const int stretch = 4; // number of pixels on x-axis to increase on each value on y
};
void OLEDPlotter::init() {
debugger.setDebug(Debugger::TRACE);
// we init the toggle button on input pin 3 (2 and 3 support interrupts on a nano)
pinMode(OLEDPlotter::button_pin, INPUT_PULLUP);
/**
* init the OLED, we have a seeed Oled v2.1 with 128x128 pixels and an SH1107 controller
* connected to the I2C pin-out of the nano
* we use the u8g2 grafic library, see https://github.com/olikraus/u8g2/wiki/u8g2reference
*
*/
u8g2 = new U8G2_SH1107_SEEED_128X128_2_HW_I2C(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);;
u8g2->begin();
u8g2->setFont(u8g2_font_5x7_tf); //u8g2_font_7x14B_mr);
u8g2->setFontMode(0);
}
int OLEDPlotter::value2Pixels(float value) {
int px = (int)((value - scaleset.vmin) * scaleset.resolution);
px = max( min(px, oled_height -1), 0);
//debugger.print(Debugger::TRACE, "pxY ");
//debugger.println(Debugger::TRACE, px);
return px;
}
void OLEDPlotter::drawYAxis() {
// first, plot the Y axis, we have 17 pix width
u8g2->drawVLine(17, 0, 128);
// invert as we have 0/0 in top left
int pxY = oled_height - this->value2Pixels(scaleset.vtarget);
u8g2->drawHLine(12, pxY, 5);
u8g2->setCursor(0, pxY + 3);
u8g2->print(scaleset.labelTarget);
pxY = oled_height - this->value2Pixels(scaleset.vmin);
u8g2->setCursor(0, pxY);
u8g2->print(scaleset.labelMin);
pxY = oled_height - this->value2Pixels(scaleset.vmax);
u8g2->setCursor(0, pxY + 6);
u8g2->print(scaleset.labelMax);
}
/**
* plotGraph
* redraws all current values to the display
*/
void OLEDPlotter::plotGraph(float values[], int numVals) {
u8g2->firstPage();
do {
int height = oled_height - 1;
u8g2->setDrawColor(1);
drawYAxis();
//debugger.print(Debugger::TRACE, "numVals ");
//debugger.println(Debugger::TRACE, numVals);
int last = height - this->value2Pixels(values[0]);
int pxX = 0;
for ( int i = 0; i < numVals; i ++ ) {
float nval = values[i];
int pxY = height - this->value2Pixels(nval);
u8g2->drawLine(oled_width - (pxX - stretch - 1), last, oled_width - pxX, pxY);
last = pxY;
pxX = pxX + stretch;
}
} while ( u8g2->nextPage() );
}
void OLEDPlotter::toggleScale() {
if ( scale == THIRTYTHREE ) {
scale = FOURTYFIVE;
scaleset = scale_45;
}
else {
scale = THIRTYTHREE;
scaleset = scale_33;
}
// debugger.print(Debugger::INFO, "vmax ");
// debugger.println(Debugger::INFO, scaleset.vmax);
// debugger.print(Debugger::INFO, "vmin ");
// debugger.println(Debugger::INFO, scaleset.vmin);
// debugger.print(Debugger::INFO, "resolution ");
// debugger.println(Debugger::INFO, scaleset.resolution);
}
#endif