/*
* Reference:
* https://github.com/olikraus/u8g2/wiki
*
*/
#include <Arduino.h>
#include <ADS1115_WE.h> // für AD-Wandler
#include <Wire.h>
#include <U8g2lib.h> // für OLED-Display
//#define SPANNUNG_5V // Zeige 5V Spannung an. Wenn diese Zeile auskommentiert wird, werden 12V angezeigt
//#define DISPLAY_SSH_1106
constexpr byte I2C_ADDRESS {0x48};
constexpr byte NUM_CHANNELS {4};
struct ValueStorage {
const ADS1115_MUX channel; // ADC Channel
const unsigned int x; // Display x-pos
const unsigned int y; // Display y-pos
float voltage; // Value
};
// Initialize struct Valuestorage
ValueStorage voltS[NUM_CHANNELS] {
{ADS1115_COMP_0_GND, 22, 0, 0.0},
{ADS1115_COMP_1_GND, 22, 12, 0.0},
{ADS1115_COMP_2_GND, 22, 24, 0.0},
{ADS1115_COMP_3_GND, 22, 36, 0.0}
};
#if defined DISPLAY_SSH_1106
using OLED = U8G2_SH1106_128X64_NONAME_1_HW_I2C; // 1,3 Inch SH1106
#else
using OLED = U8G2_SSD1306_128X64_NONAME_1_HW_I2C; // 0,96 Inch SH1306
#endif
OLED u8g2(U8G2_R0, U8X8_PIN_NONE); // OLED-Display einrichten
ADS1115_WE adc = ADS1115_WE(I2C_ADDRESS);
void dpPrintError(OLED &, char *);
void dpPrintItems(OLED &, const ValueStorage[], byte);
float readChannel(ADS1115_MUX channel);
void setup(void) {
Serial.begin(115200);
Wire.begin();
u8g2.begin();
// u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setFont(u8g2_font_6x10_tr);
// Uncomment when the sensor is connected.
/*
if (!adc.init()) {
dpPrintError(u8g2,"ADS1115 nicht erkannt!");
while(1) {}
}
*/
adc.setVoltageRange_mV(ADS1115_RANGE_6144); // Eingang AD-Wandler auf 6,1V einstellen
dpPrintItems(u8g2, voltS, NUM_CHANNELS);
}
void loop() {
for (byte i = 0; i < NUM_CHANNELS; ++i) {
float voltage = readChannel(voltS[i].channel);
if (voltage != voltS[i].voltage) {
voltS[i].voltage = voltage;
dpPrintItems(u8g2, voltS, NUM_CHANNELS);
}
}
delay(100);
}
void dpPrintError(OLED &dp, char error[]) {
u8g2.firstPage();
do {
dp.setCursor(1, 30);
dp.print(error);
} while (u8g2.nextPage());
}
//
// Die Schrift ist 6 Pixel Breit und 10 Pixel hoch.
//
void dpPrintItems(OLED &dp, const ValueStorage vs[], byte num) {
constexpr byte FONT_WIDTH {6};
constexpr byte FONT_HIGH {10};
u8g2.firstPage();
do {
dp.setCursor(0, 6); dp.print("ws:");
dp.setCursor(0, 18); dp.print("ge:");
dp.setCursor(0, 30); dp.print("gn:");
dp.setCursor(0, 42); dp.print("sw:");
#ifdef SPANNUNG_5V
dp.setCursor(20, 55); dp.print("| | | | | |");
dp.setCursor(20, 63); dp.print("0.1.2.3.4.5 V");
#else
dp.setCursor(20, 55); dp.print("| | | | |");
dp.setCursor(20, 63); dp.print("0..3..6..9..12 V");
#endif
for (byte i = 0; i < num; ++i) {
#ifdef SPANNUNG_5V
// Skalenschritte = 0,5V. Darum Zeichenbreite * 2
unsigned int barLen = vs[i].voltage * FONT_WIDTH * 2; // Berechne Balkenlänge für 5V
#else
// Skalenschritte = 1V
unsigned int barLen = vs[i].voltage * FONT_WIDTH; // Berechne Balkenlänge für 12V
#endif
dp.drawBox(vs[i].x, vs[i].y, barLen, 6);
unsigned int offset {76};
if (vs[i].voltage < 10) {
offset += FONT_WIDTH;
} // Bei einstelligen Werten den Cursor eine Zeichenbreite weiter rechts setzen
dp.setCursor(vs[i].x + offset, vs[i].y + (FONT_HIGH - 3));
dp.print(vs[i].voltage, 2);
}
} while (u8g2.nextPage());
}
// Comment out if the sensor is connected
float readChannel(ADS1115_MUX channel) {
randomSeed(millis());
#ifdef SPANNUNG_5V
return static_cast<float>(random(0, 5001)) / 1000;
#else
return static_cast<float>(random(0, 12001)) / 1000;
#endif
}
// uncomment when the sensor is connected
/*
float readChannel(ADS1115_MUX channel) {
float voltage = 0.0;
adc.setCompareChannels(channel);
adc.startSingleMeasurement();
while (adc.isBusy()) {}
voltage = adc.getResult_V(); // alternative: getResult_mV for Millivolt
return voltage;
}
*/