Vielen Dank, bin mit der Darstellung zufrieden. Hoffe das ich die Zeilen richtig kommentiert habe. Einiges ist mir zwar noch rätselhaft, doch es wird ...
Hier nochmals für Interessierte der Sketch:
ADS1115_Balkengrafik.ino
/*
* Reference:
* https://github.com/olikraus/u8g2/wiki
*
* ADS1115 + OLED-Display parallel mit Arduino (SCK->5, SDA->4, +5V, GND) verbinden
*
* zum testen 5 Stück 2k2 (o.ä.) Widerstände seriell zusammenlöten und mit + und GND
* verbinden ergibt 1, 2, 3 und 4V für den AD-Wandler bei 5V Speisespannung
*
*/
#include <Arduino.h> // für Variablen
#include <ADS1115_WE.h> // für AD-Wandler
#include <Wire.h> // für I2C Schnittstelle
#include <U8g2lib.h> // für OLED-Display
#ifdef U8X8_HAVE_HW_SPI // Schriftgruppenauswahl für OLED
#include <SPI.h> // für serielle Kommunikation
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define SPANNUNG_5V // Zeile aktiv 5V Anzeige - Zeile als Kommentar 12V Anzeige
constexpr byte I2C_ADDRESS {0x48}; // Adresse AD-Wandler
constexpr byte NUM_CHANNELS {4}; // 4 Kanäle aktiv
struct ValueStorage { // Struktur Wertspeicher
const ADS1115_MUX channel; // ADC Kanal
const unsigned int x; // Display x-pos
const unsigned int y; // Display y-pos
float voltage; // Wert
};
// Auffüllen des Wertspeicher-Arrays
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}
};
// using OLED = U8G2_SH1106_128X64_NONAME_F_HW_I2C;
// using OLED = U8G2_SSD1306_128X64_NONAME_F_HW_I2C;
using OLED = U8G2_SH1106_128X64_NONAME_1_HW_I2C; // 1,3 Zoll SH1106
// using OLED = U8G2_SSD1306_128X64_NONAME_1_HW_I2C; // 0,96 Zoll SH1306
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); // serielle Übertragungsgeschwindigkeit
Wire.begin();
u8g2.begin();
// u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setFont(u8g2_font_6x10_tr); // OLED Schriftauswahl
// bei angeschlossem AD-Wandler entfernen
/*
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(10); // Pause bei Zufallszahlen auf 1000 verlängern
}
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());
}
// Zufallswerte bei fehlendem AD-Wandler
/*
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
}
*/
// aktiv bei angeschlossem AD-Wandler
//
float readChannel(ADS1115_MUX channel) {
float voltage = 0.0;
adc.setCompareChannels(channel);
adc.startSingleMeasurement();
while (adc.isBusy()) {}
voltage = adc.getResult_V(); // alternativ: getResult_mV für Millivolt
return voltage;
}
//
als Tipp:
Mini Grabber
eignen sich ideal für den Spannungsabriff an den Widerständen. Als hochflexible Anschlußdrähte sind die Adern alter Telefonsteckdosen-Anschlußleitungen ideal.