Skip to content

Instantly share code, notes, and snippets.

@bukowa
Last active September 12, 2025 09:54
Show Gist options
  • Save bukowa/8db047fc52b5e56581b41dae7145fb02 to your computer and use it in GitHub Desktop.
Save bukowa/8db047fc52b5e56581b41dae7145fb02 to your computer and use it in GitHub Desktop.
INA226 Arduino Uno LCD Shield 2.4 TFT
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <INA226_WE.h> // Upewnij się, że ta biblioteka jest zainstalowana
// --- Konfiguracja Sieci i Serwera ---
const char *ssid = "ESP_POMIAROWY";
WiFiServer server(80);
// --- Konfiguracja INA226 ---
#define I2C_ADDRESS 0x40
INA226_WE ina226 = INA226_WE(I2C_ADDRESS);
// --- Konfiguracja logiki pomiarowej (przeniesiona z Twojego kodu) ---
#define NUM_SAMPLES 150
int voltage_samples_mV[NUM_SAMPLES];
int current_samples_mA[NUM_SAMPLES];
// Zmienne do automatycznego zakresu
float v_min_dynamic = 4.9, v_max_dynamic = 5.1;
float c_min_dynamic = 0.0, c_max_dynamic = 100.0;
// === Zmienne globalne do przechowywania OSTATNICH wyników ===
// Te zmienne będą odczytywane przez serwer WWW
volatile float last_Vavg = 0.0;
volatile float last_Iavg = 0.0;
volatile float last_freqV = 0.0;
volatile float last_freqC = 0.0;
volatile float last_minV = 0.0;
volatile float last_maxV = 0.0;
volatile float last_minC = 0.0;
volatile float last_maxC = 0.0;
volatile float last_time_span_s = 0.0;
void setup() {
Serial.begin(115200);
// Inicjalizacja I2C dla ESP8266 (GPIO0 = SDA, GPIO2 = SCL)
// WAŻNE: Po wgraniu kodu, odłącz GPIO0 od masy!
Wire.begin(0, 2);
if(!ina226.init()){
Serial.println("Nie znaleziono INA226!");
while(1);
}
Serial.println("Znaleziono INA226!");
// Ustawienia INA226 z Twojego kodu
ina226.setAverage(AVERAGE_1);
ina226.setConversionTime(CONV_TIME_140);
ina226.setResistorRange(0.1, 0.5); // Ustaw rezystor i maksymalny spodziewany prąd
// Konfiguracja punktu dostępowego
Serial.println("Konfiguracja Access Point...");
WiFi.softAP(ssid);
IPAddress myIP = WiFi.softAPIP();
Serial.print("Adres IP: ");
Serial.println(myIP);
// Uruchomienie serwera WWW
server.begin();
Serial.println("Serwer WWW uruchomiony.");
}
void loop() {
// === BLOK 1: ZBIERANIE DANYCH ===
float minV = 100.0, maxV = 0.0, sumV = 0.0;
float minC = 1000.0, maxC = 0.0, sumC = 0.0;
long startTime = micros();
for(int i=0; i<NUM_SAMPLES; i++){
float voltage = ina226.getBusVoltage_V();
float current = ina226.getCurrent_mA();
// Zapisywanie próbek nie jest konieczne, jeśli nie wysyłamy wykresu,
// ale zostawiam logikę na przyszłość.
voltage_samples_mV[i] = voltage * 1000;
current_samples_mA[i] = current;
if(voltage < minV) minV = voltage;
if(voltage > maxV) maxV = voltage;
sumV += voltage;
if(current < minC) minC = current;
if(current > maxC) maxC = current;
sumC += current;
}
long endTime = micros();
// === BLOK 2: OBLICZENIA ===
int v_zero_crossings = 0, c_zero_crossings = 0;
long v_avg_mV = sumV * 1000 / NUM_SAMPLES;
long c_avg_mA = sumC / NUM_SAMPLES;
for (int i = 1; i < NUM_SAMPLES; i++) {
if ((voltage_samples_mV[i-1] < v_avg_mV && voltage_samples_mV[i] >= v_avg_mV) || (voltage_samples_mV[i-1] > v_avg_mV && voltage_samples_mV[i] <= v_avg_mV)) v_zero_crossings++;
if ((current_samples_mA[i-1] < c_avg_mA && current_samples_mA[i] >= c_avg_mA) || (current_samples_mA[i-1] > c_avg_mA && current_samples_mA[i] <= c_avg_mA)) c_zero_crossings++;
}
float time_span_s = (endTime - startTime) / 1000000.0f;
// === AKTUALIZACJA ZMIENNYCH GLOBALNYCH ===
// To jest "atomowa" operacja, która udostępnia nowe dane serwerowi
last_Vavg = sumV / NUM_SAMPLES;
last_Iavg = sumC / NUM_SAMPLES;
last_freqV = (v_zero_crossings / 2.0) / time_span_s;
last_freqC = (c_zero_crossings / 2.0) / time_span_s;
last_minV = minV;
last_maxV = maxV;
last_minC = minC;
last_maxC = maxC;
last_time_span_s = time_span_s;
// === BLOK 4: AKTUALIZACJA ZAKRESU (dla następnej pętli) ===
v_min_dynamic = minV - (maxV - minV)*0.1;
v_max_dynamic = maxV + (maxV - minV)*0.1;
c_min_dynamic = minC - (maxC - minC)*0.1;
c_max_dynamic = maxC + (maxC - minC)*0.1;
if(v_max_dynamic <= v_min_dynamic) v_max_dynamic = v_min_dynamic + 0.1;
if(c_max_dynamic <= c_min_dynamic) c_max_dynamic = c_min_dynamic + 10;
// === BLOK 5: OBSŁUGA KLIENTA WWW ===
// Ta część kodu nie blokuje pomiarów. Działa tylko, gdy ktoś się połączy.
handle_web_client();
}
void handle_web_client() {
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
// Odpowiedź HTTP
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Refresh: 2"); // Odśwież stronę co 2 sekundy
client.println();
client.println("<!DOCTYPE HTML><html><head><title>ESP Pomiar Mocy</title>");
client.println("<style>body { font-family: sans-serif; background-color: #282c34; color: #abb2bf; } table { border-collapse: collapse; width: 50%; } td, th { border: 1px solid #61afef; text-align: left; padding: 8px; } th { background-color: #3e4451; } .val { color: #98c379; }</style>");
client.println("</head><body><h1>Pomiar poboru pradu przez ESP-01</h1>");
client.println("<table>");
client.println("<tr><th>Parametr</th><th>Wartosc</th></tr>");
client.print("<tr><td>Srednie Napiecie</td><td class='val'>"); client.print(last_Vavg, 3); client.println(" V</td></tr>");
client.print("<tr><td>Sredni Prad</td><td class='val'>"); client.print(last_Iavg, 2); client.println(" mA</td></tr>");
client.print("<tr><td>Srednia Moc</td><td class='val'>"); client.print(last_Vavg * last_Iavg, 2); client.println(" mW</td></tr>");
client.print("<tr><td>Min/Max Napiecie</td><td class='val'>"); client.print(last_minV, 3); client.print(" / "); client.print(last_maxV, 3); client.println(" V</td></tr>");
client.print("<tr><td>Min/Max Prad</td><td class='val'>"); client.print(last_minC, 2); client.print(" / "); client.print(last_maxC, 2); client.println(" mA</td></tr>");
client.print("<tr><td>Czestotliwosc (V/I)</td><td class='val'>"); client.print((int)last_freqV); client.print(" / "); client.print((int)last_freqC); client.println(" Hz</td></tr>");
client.print("<tr><td>Czas probkowania</td><td class='val'>"); client.print(last_time_span_s * 1000, 2); client.println(" ms (dla 150 probek)</td></tr>");
client.println("</table></body></html>");
delay(1);
client.stop();
}
/***************************************************************************
* Finalny, działający kod do wyświetlania danych z czujnika INA226
* na wyświetlaczu TFT. Działa po fizycznym rozdzieleniu połączeń I2C.
***************************************************************************/
// Biblioteki dla czujnika INA226
#include <Wire.h>
#include <INA226_WE.h>
// Biblioteki dla wyświetlacza TFT
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
// --- Konfiguracja Czujnika INA226 ---
#define I2C_ADDRESS 0x40
INA226_WE ina226 = INA226_WE(I2C_ADDRESS);
// Definicje pinów sterujących dla Twojego shielda
#define LCD_CS A3
#define LCD_RS A2
#define LCD_WR A1
#define LCD_RD A0
// TUTAJ JEST NASZA ZMIANA! Mówimy, że RESET jest teraz na pinie 10
#define LCD_RESET 0
// Inicjalizujemy sterownik, podając mu wszystkie piny ręcznie
MCUFRIEND_kbv tft(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RESET);
// Definicje kolorów
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
void setup() {
Serial.begin(9600);
Wire.begin();
// --- Inicjalizacja czujnika INA226 ---
if(!ina226.init()){
Serial.println("Nie udalo sie zainicjowac INA226. Sprawdz polaczenia.");
while(1){}
}
ina226.setMeasureMode(CONTINUOUS);
// --- Inicjalizacja wyświetlacza TFT ---
uint16_t id = 0x9341;
tft.begin(id);
tft.setRotation(1);
tft.fillScreen(BLACK);
tft.setTextSize(2);
// Wyświetl statyczne etykiety
tft.setTextColor(WHITE);
tft.setCursor(10, 20);
tft.println("Pomiar Mocy - INA226");
tft.drawRect(5, 10, 310, 35, CYAN);
tft.setTextColor(YELLOW);
tft.setCursor(10, 70);
tft.print("Napiecie V-Bus:");
tft.setCursor(10, 100);
tft.print("Napiecie bocznik:");
tft.setCursor(10, 130);
tft.print("Prad:");
tft.setCursor(10, 160);
tft.print("Moc:");
}
void loop() {
// Zmienne do przechowywania odczytów
float shuntVoltage_mV = 0.0;
float busVoltage_V = 0.0;
float current_mA = 0.0;
float power_mW = 0.0;
// Wartość rezystora i maksymalny oczekiwany prąd
ina226.setResistorRange(0.1, 0.5);
// Odczytaj wartości z czujnika
shuntVoltage_mV = ina226.getShuntVoltage_mV();
busVoltage_V = ina226.getBusVoltage_V();
current_mA = ina226.getCurrent_mA();
power_mW = ina226.getBusPower();
// --- Wyświetlanie danych na ekranie TFT ---
tft.setTextColor(GREEN);
tft.setTextSize(2);
// 1. Napięcie magistrali
tft.fillRect(210, 70, 100, 20, BLACK);
tft.setCursor(210, 70);
tft.print(busVoltage_V, 3);
tft.print(" V");
// 2. Napięcie bocznika
tft.fillRect(210, 100, 100, 20, BLACK);
tft.setCursor(210, 100);
tft.print(shuntVoltage_mV, 3);
tft.print(" mV");
// 3. Prąd
tft.fillRect(210, 130, 100, 20, BLACK);
tft.setCursor(210, 130);
tft.print(current_mA, 3);
tft.print(" mA");
// 4. Moc
tft.fillRect(210, 160, 100, 20, BLACK);
tft.setCursor(210, 160);
tft.print(power_mW, 3);
tft.print(" mW");
// Wyświetl status przepełnienia
tft.fillRect(10, 210, 300, 20, BLACK);
tft.setCursor(10, 210);
if(!ina226.overflow){
tft.setTextColor(GREEN);
tft.print("Status: OK");
} else {
tft.setTextColor(RED);
tft.print("Status: PRZEPELNIENIE!");
}
delay(1000); // Odświeżaj dane co sekundę
}
/***************************************************************************
* INA-skop v3.1: Wersja zoptymalizowana pod kątem RAM
* Zmniejszona liczba próbek, aby zmieścić się w pamięci Arduino Uno.
***************************************************************************/
#include <Wire.h>
#include <INA226_WE.h>
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
// --- Konfiguracja ---
#define I2C_ADDRESS 0x40
INA226_WE ina226 = INA226_WE(I2C_ADDRESS);
#define LCD_CS A3
#define LCD_RS A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET 0
MCUFRIEND_kbv tft(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RESET);
// --- Definicje kolorów ---
#define BLACK 0x0000
#define GREEN 0x07E0
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define GREY 0x8410
// --- Konfiguracja Oscyloskopu ---
// OPTYMALIZACJA RAM: Zmniejszamy liczbę próbek
#define NUM_SAMPLES 150
byte samples_voltage_y[NUM_SAMPLES];
byte samples_current_y[NUM_SAMPLES];
#define GRID_Y_TOP 50
#define GRID_Y_BOTTOM 210
#define GRID_X_LEFT 40
#define GRID_X_RIGHT 280
// Zmienne do automatycznego zakresu
float v_min_dynamic = 4.9, v_max_dynamic = 5.1;
float c_min_dynamic = 0.0, c_max_dynamic = 100.0;
void draw_grid_dual_axis(float v_min, float v_max, float c_min, float c_max);
void setup() {
Wire.begin();
if(!ina226.init()){ while(1); }
ina226.setAverage(AVERAGE_1);
ina226.setConversionTime(CONV_TIME_140);
ina226.setResistorRange(0.1, 0.5);
uint16_t id = 0x9341;
tft.begin(id);
tft.setRotation(1);
tft.fillScreen(BLACK);
}
void loop() {
float minV = 100.0, maxV = 0.0, sumV = 0.0;
float minC = 1000.0, maxC = 0.0, sumC = 0.0;
// 1. ZBIERANIE DANYCH
for(int i=0; i<NUM_SAMPLES; i++){
float voltage = ina226.getBusVoltage_V();
float current = ina226.getCurrent_mA();
if(voltage < minV) minV = voltage;
if(voltage > maxV) maxV = voltage;
sumV += voltage;
if(current < minC) minC = current;
if(current > maxC) maxC = current;
sumC += current;
int y_v = map(voltage*1000, v_min_dynamic*1000, v_max_dynamic*1000, GRID_Y_BOTTOM, GRID_Y_TOP);
int y_c = map(current*1000, c_min_dynamic*1000, c_max_dynamic*1000, GRID_Y_BOTTOM, GRID_Y_TOP);
samples_voltage_y[i] = constrain(y_v, GRID_Y_TOP, GRID_Y_BOTTOM);
samples_current_y[i] = constrain(y_c, GRID_Y_TOP, GRID_Y_BOTTOM);
}
// 2. AKTUALIZACJA ZAKRESU
v_min_dynamic = minV - (maxV - minV)*0.1;
v_max_dynamic = maxV + (maxV - minV)*0.1;
c_min_dynamic = minC - (maxC - minC)*0.1;
c_max_dynamic = maxC + (maxC - minC)*0.1;
if(v_max_dynamic <= v_min_dynamic) v_max_dynamic = v_min_dynamic + 0.1;
if(c_max_dynamic <= c_min_dynamic) c_max_dynamic = c_min_dynamic + 10;
// 3. RYSOWANIE
tft.fillScreen(BLACK);
draw_grid_dual_axis(v_min_dynamic, v_max_dynamic, c_min_dynamic, c_max_dynamic);
for(int i=1; i<NUM_SAMPLES; i++){
int x1 = map(i-1, 0, NUM_SAMPLES, GRID_X_LEFT, GRID_X_RIGHT);
int x2 = map(i, 0, NUM_SAMPLES, GRID_X_LEFT, GRID_X_RIGHT);
tft.drawLine(x1, samples_voltage_y[i-1], x2, samples_voltage_y[i], GREEN);
tft.drawLine(x1, samples_current_y[i-1], x2, samples_current_y[i], YELLOW);
}
// 4. WYŚWIETL STATYSTYKI
float Vavg = sumV / NUM_SAMPLES;
float Iavg = sumC / NUM_SAMPLES;
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.setTextColor(GREEN);
tft.print("V: ");
tft.print(Vavg, 2);
tft.setCursor(160, 10);
tft.setTextColor(YELLOW);
tft.print("I: ");
tft.print(Iavg, 1);
tft.print("mA");
}
void draw_grid_dual_axis(float v_min, float v_max, float c_min, float c_max){
tft.drawRect(GRID_X_LEFT, GRID_Y_TOP, GRID_X_RIGHT - GRID_X_LEFT, GRID_Y_BOTTOM - GRID_Y_TOP, GREY);
tft.setTextSize(1);
tft.setTextColor(GREEN);
tft.setCursor(2, GRID_Y_TOP + 5);
tft.print(v_max, 2);
tft.print("V");
tft.setCursor(2, GRID_Y_BOTTOM - 10);
tft.print(v_min, 2);
tft.print("V");
tft.setTextColor(YELLOW);
tft.setCursor(GRID_X_RIGHT + 5, GRID_Y_TOP + 5);
tft.print(c_max, 0);
tft.print("mA");
tft.setCursor(GRID_X_RIGHT + 5, GRID_Y_BOTTOM - 10);
tft.print(c_min, 0);
tft.print("mA");
}
/***************************************************************************
* INA-skop v4.3: Wersja OSTATECZNA.
* NAPRAWIONO błąd z obcinaniem precyzji w funkcji map() dla prądu.
* Przywrócono oryginalną, działającą logikę skalowania.
***************************************************************************/
#include <Wire.h>
#include <INA226_WE.h>
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
// --- Konfiguracja ---
#define I2C_ADDRESS 0x40
INA226_WE ina226 = INA226_WE(I2C_ADDRESS);
#define LCD_CS A3
#define LCD_RS A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET 0
MCUFRIEND_kbv tft(LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RESET);
// --- Definicje kolorów ---
#define BLACK 0x0000
#define GREEN 0x07E0
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define GREY 0x8410
#define ORANGE 0xFD20
// --- Konfiguracja Oscyloskopu ---
#define NUM_SAMPLES 150
byte samples_voltage_y[NUM_SAMPLES];
byte samples_current_y[NUM_SAMPLES];
int voltage_samples_mV[NUM_SAMPLES];
int current_samples_mA[NUM_SAMPLES];
#define GRID_Y_TOP 60
#define GRID_Y_BOTTOM 210
#define GRID_X_LEFT 40
#define GRID_X_RIGHT 280
// Zmienne do automatycznego zakresu (serce oryginalnej logiki)
float v_min_dynamic = 4.9, v_max_dynamic = 5.1;
float c_min_dynamic = 0.0, c_max_dynamic = 100.0;
void draw_grid_dual_axis(float v_min, float v_max, float c_min, float c_max);
void setup() {
Wire.begin();
if(!ina226.init()){ while(1); }
ina226.setAverage(AVERAGE_1);
ina226.setConversionTime(CONV_TIME_140);
ina226.setResistorRange(0.1, 0.5);
uint16_t id = 0x9341;
tft.begin(id);
tft.setRotation(1);
tft.fillScreen(BLACK);
}
void loop() {
// === BLOK 1: ZBIERANIE DANYCH (pozostaje bez zmian) ===
float minV = 100.0, maxV = 0.0, sumV = 0.0;
float minC = 1000.0, maxC = 0.0, sumC = 0.0;
long startTime = micros();
for(int i=0; i<NUM_SAMPLES; i++){
float voltage = ina226.getBusVoltage_V();
float current = ina226.getCurrent_mA();
voltage_samples_mV[i] = voltage * 1000;
current_samples_mA[i] = current;
if(voltage < minV) minV = voltage;
if(voltage > maxV) maxV = voltage;
sumV += voltage;
if(current < minC) minC = current;
if(current > maxC) maxC = current;
sumC += current;
int y_v = map(voltage*1000, v_min_dynamic*1000, v_max_dynamic*1000, GRID_Y_BOTTOM, GRID_Y_TOP);
int y_c = map(current*100, c_min_dynamic*100, c_max_dynamic*100, GRID_Y_BOTTOM, GRID_Y_TOP);
samples_voltage_y[i] = constrain(y_v, GRID_Y_TOP, GRID_Y_BOTTOM);
samples_current_y[i] = constrain(y_c, GRID_Y_TOP, GRID_Y_BOTTOM);
}
long endTime = micros();
// === BLOK 2: OBLICZENIA (pozostaje bez zmian) ===
int v_zero_crossings = 0, c_zero_crossings = 0;
long v_avg_mV = sumV * 1000 / NUM_SAMPLES;
long c_avg_mA = sumC / NUM_SAMPLES;
for (int i = 1; i < NUM_SAMPLES; i++) {
if ((voltage_samples_mV[i-1] < v_avg_mV && voltage_samples_mV[i] >= v_avg_mV) || (voltage_samples_mV[i-1] > v_avg_mV && voltage_samples_mV[i] <= v_avg_mV)) v_zero_crossings++;
if ((current_samples_mA[i-1] < c_avg_mA && current_samples_mA[i] >= c_avg_mA) || (current_samples_mA[i-1] > c_avg_mA && current_samples_mA[i] <= c_avg_mA)) c_zero_crossings++;
}
float time_span_s = (endTime - startTime) / 1000000.0f;
float freqV = (v_zero_crossings / 2.0) / time_span_s;
float freqC = (c_zero_crossings / 2.0) / time_span_s;
float Vavg = sumV / NUM_SAMPLES;
float Iavg = sumC / NUM_SAMPLES;
// === BLOK 3: RYSOWANIE I WYŚWIETLANIE (NOWA KOLEJNOŚĆ) ===
// 3a. Najpierw przygotuj tło i siatkę
tft.fillScreen(BLACK);
draw_grid_dual_axis(v_min_dynamic, v_max_dynamic, c_min_dynamic, c_max_dynamic);
// 3b. Wyświetl statystyki (SZYBKIE) - PRZENIESIONE NA POCZĄTEK
tft.setTextSize(2);
tft.setCursor(10, 10); tft.setTextColor(GREEN); tft.print("V: "); tft.print(Vavg, 2);
tft.setCursor(160, 10); tft.setTextColor(YELLOW); tft.print("I: "); tft.print(Iavg, 1); tft.print("mA");
tft.setCursor(10, 35); tft.setTextColor(ORANGE); tft.print("F(v):"); tft.print((int)freqV);
tft.setCursor(160, 35); tft.print("F(i):"); tft.print((int)freqC);
// 3c. Dopiero teraz narysuj wykres (CZASOCHŁONNE)
for(int i=1; i<NUM_SAMPLES; i++){
int x1 = map(i-1, 0, NUM_SAMPLES, GRID_X_LEFT, GRID_X_RIGHT);
int x2 = map(i, 0, NUM_SAMPLES, GRID_X_LEFT, GRID_X_RIGHT);
tft.drawLine(x1, samples_voltage_y[i-1], x2, samples_voltage_y[i], GREEN);
tft.drawLine(x1, samples_current_y[i-1], x2, samples_current_y[i], YELLOW);
}
// === BLOK 4: AKTUALIZACJA ZAKRESU (pozostaje bez zmian) ===
v_min_dynamic = minV - (maxV - minV)*0.1;
v_max_dynamic = maxV + (maxV - minV)*0.1;
c_min_dynamic = minC - (maxC - minC)*0.1;
c_max_dynamic = maxC + (maxC - minC)*0.1;
if(v_max_dynamic <= v_min_dynamic) v_max_dynamic = v_min_dynamic + 0.1;
if(c_max_dynamic <= c_min_dynamic) c_max_dynamic = c_min_dynamic + 10;
}
void draw_grid_dual_axis(float v_min, float v_max, float c_min, float c_max){
tft.drawRect(GRID_X_LEFT, GRID_Y_TOP, GRID_X_RIGHT - GRID_X_LEFT, GRID_Y_BOTTOM - GRID_Y_TOP, GREY);
tft.setTextSize(1);
tft.setTextColor(GREEN);
tft.setCursor(2, GRID_Y_TOP + 5); tft.print(v_max, 2); tft.print("V");
tft.setCursor(2, GRID_Y_BOTTOM - 10); tft.print(v_min, 2); tft.print("V");
tft.setTextColor(YELLOW);
tft.setCursor(GRID_X_RIGHT + 5, GRID_Y_TOP + 5); tft.print(c_max, 0); tft.print("mA");
tft.setCursor(GRID_X_RIGHT + 5, GRID_Y_BOTTOM - 10); tft.print(c_min, 0); tft.print("mA");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment