Napisz program dla arduino GIGA wyświetlający biorytmy dla osoby urodzonej 10.06.1955 roku z wykorzystaniem
#include "stm32h7xx.h"
#include "Arduino_H7_Video.h"
#include "lvgl.h"
#include "Arduino_GigaDisplayTouch.h"
Arduino_GigaDisplayTouch TouchDetector;
#include "Arduino_GigaDisplay_GFX.h"
Kod (wklej całość do Arduino IDE):
/*
* Biorytmy – Arduino GIGA R1 + GIGA Display Shield + LVGL
* Data urodzenia: 10.06.1955
* Zakres wykresu: 31 dni (−15…+15), Y: −100…+100 %
* Wymagane biblioteki:
* - Arduino_GigaDisplay_GFX
* - Arduino_GigaDisplayTouch
* - Arduino_H7_Video (instalowana z GIGA core)
* - lvgl (konf.: LV_COLOR_DEPTH 16)
*/
#include "stm32h7xx.h"
#include "Arduino_H7_Video.h"
#include "lvgl.h"
#include "Arduino_GigaDisplayTouch.h"
Arduino_GigaDisplayTouch TouchDetector;
#include "Arduino_GigaDisplay_GFX.h"
#include <cmath>
#include <ctime>
// --- Parametry użytkownika ---
static const int BIRTH_Y = 1955;
static const int BIRTH_M = 6;
static const int BIRTH_D = 10;
// Zakres prezentacji (liczba dni i przesunięcie względem dziś)
static const int DAYS_WINDOW = 31; // liczba punktów (dni)
static const int DAYS_HALF = 15; // dni po lewej/prawej od dnia bieżącego
// --- Obiekty wyświetlacza/GFX/LVGL ---
static Arduino_GigaDisplay_GFX gfx;
// Bufor rysowania LVGL – 40 linii (bezpiecznie dla RAM)
#define SCREEN_W 800
#define SCREEN_H 480
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[SCREEN_W * 40];
// Obiekty LVGL UI
static lv_obj_t* chart = nullptr;
static lv_chart_series_t* ser_phys = nullptr;
static lv_chart_series_t* ser_emo = nullptr;
static lv_chart_series_t* ser_int = nullptr;
static lv_obj_t* lbl_title = nullptr;
static lv_obj_t* lbl_date = nullptr;
// --- Narzędzia czasu/dat (JDN) ---
// Zwraca numer JDN dla daty kalendarza gregoriańskiego
static long jdn(int y, int m, int d) {
int a = (14 - m) / 12;
int yy = y + 4800 - a;
int mm = m + 12 * a - 3;
return d + (153 * mm + 2) / 5 + 365 * yy + yy / 4 - yy / 100 + yy / 400 - 32045;
}
// Różnica dni pomiędzy datą bieżącą a urodzinami
static long days_since_birth(int y, int m, int d) {
long j_birth = jdn(BIRTH_Y, BIRTH_M, BIRTH_D);
long j_cur = jdn(y, m, d);
return j_cur - j_birth;
}
// Pobiera „dziś” z RTC; jeśli nieustawiony – fallback do 31.12.2025
static void get_today(int& y, int& m, int& d) {
time_t now = time(nullptr);
// próg: 1.01.2021 00:00:00 UTC – jeśli RTC wcześniej, uznaj nieustawione
if (now < 1609459200) {
y = 2025; m = 12; d = 31; // Fallback – ostatnia znana data
} else {
struct tm* lt = localtime(&now);
y = lt->tm_year + 1900;
m = lt->tm_mon + 1;
d = lt->tm_mday;
}
}
// --- Biorytmy ---
static inline float bio_val(long t, float period_days) {
return sinf(2.0f * (float)M_PI * (float)t / period_days); // −1..+1
}
// --- LVGL: flush callback (wysyłka bufora na ekran) ---
static void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
// kolor w lv_color_t jest kompatybilny z RGB565 przy LV_COLOR_DEPTH 16
gfx.drawRGBBitmap(area->x1, area->y1, (const uint16_t*)color_p, w, h);
lv_disp_flush_ready(disp);
}
// --- LVGL: touch -> indev ---
static void my_touchpad_read(lv_indev_drv_t* indev, lv_indev_data_t* data) {
GDTpoint_t p[1];
uint8_t n = TouchDetector.getTouchPoints(p);
if (n > 0) {
data->state = LV_INDEV_STATE_PRESSED;
data->point.x = p[0].x;
data->point.y = p[0].y;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
// Budowa/odświeżenie UI
static void build_or_refresh_ui() {
// 1) Bieżąca data i dni życia
int cy, cm, cd;
get_today(cy, cm, cd);
long dlife = days_since_birth(cy, cm, cd);
// 2) Tytuł i data
if (!lbl_title) {
lbl_title = lv_label_create(lv_scr_act());
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 8);
}
lv_label_set_text(lbl_title, "Biorytmy – ur. 10.06.1955");
if (!lbl_date) {
lbl_date = lv_label_create(lv_scr_act());
lv_obj_align(lbl_date, LV_ALIGN_TOP_MID, 0, 36);
}
static char datebuf[64];
snprintf(datebuf, sizeof(datebuf), "Dzisiaj: %02d.%02d.%04d | Dni od urodzenia: %ld",
cd, cm, cy, dlife);
lv_label_set_text(lbl_date, datebuf);
// 3) Wykres – przy pierwszym wywołaniu utwórz, potem tylko uzupełniaj
const int CH_W = 740, CH_H = 360;
if (!chart) {
chart = lv_chart_create(lv_scr_act());
lv_obj_set_size(chart, CH_W, CH_H);
lv_obj_align(chart, LV_ALIGN_CENTER, 0, 30);
lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT);
lv_chart_set_point_count(chart, DAYS_WINDOW);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, -100, +100);
lv_obj_set_style_line_width(chart, 2, LV_PART_ITEMS);
ser_phys = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
ser_emo = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y);
ser_int = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_GREEN), LV_CHART_AXIS_PRIMARY_Y);
}
// Wyczyść serie (ustaw wartości na „brak”) i wypełnij ponownie
lv_chart_set_all_value(chart, ser_phys, LV_CHART_POINT_NONE);
lv_chart_set_all_value(chart, ser_emo, LV_CHART_POINT_NONE);
lv_chart_set_all_value(chart, ser_int, LV_CHART_POINT_NONE);
for (int i = 0; i < DAYS_WINDOW; ++i) {
long t = dlife + (i - DAYS_HALF); // −15…+15
int phys = (int)roundf(bio_val(t, 23.0f) * 100.0f);
int emo = (int)roundf(bio_val(t, 28.0f) * 100.0f);
int intel= (int)roundf(bio_val(t, 33.0f) * 100.0f);
lv_chart_set_next_value(chart, ser_phys, phys);
lv_chart_set_next_value(chart, ser_emo, emo);
lv_chart_set_next_value(chart, ser_int, intel);
}
lv_chart_refresh(chart);
}
void setup() {
// Inicjalizacja sprzętu wyświetlacza i dotyku
gfx.begin(); // inicjuje GIGA Display Shield
TouchDetector.begin(); // Goodix GT911
// LVGL init
lv_init();
// Bufor rysowania
lv_disp_draw_buf_init(&draw_buf, buf1, NULL, SCREEN_W * 40);
// Sterownik wyświetlacza LVGL
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = SCREEN_W;
disp_drv.ver_res = SCREEN_H;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
// Sterownik dotyku LVGL
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
// Tło
gfx.fillScreen(0x0000);
// Pierwszy rysunek
build_or_refresh_ui();
}
void loop() {
// Utrzymanie zegara LVGL
static uint32_t last_ms = 0;
uint32_t now_ms = millis();
lv_tick_inc(now_ms - last_ms);
last_ms = now_ms;
lv_timer_handler();
// Prosta obsługa dotyku: dotknięcie ekranu wymusza odświeżenie (np. po zmianie dnia)
GDTpoint_t p[1];
if (TouchDetector.getTouchPoints(p) > 0) {
build_or_refresh_ui();
delay(250);
}
// Okresowe odświeżenie raz na ~minutę, aby uchwycić zmianę daty/RTC
static uint32_t tmr = 0;
if (millis() - tmr > 60000UL) {
tmr = millis();
build_or_refresh_ui();
}
delay(5);
}
Wymogi konfiguracyjne LVGL (plik lv_conf.h):