Wgranie zmian do repozytorium

This commit is contained in:
2026-05-10 16:46:04 +02:00
commit a68b81ed4a
1608 changed files with 254964 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
#pragma once
#include <Arduino.h>
#include <SPI.h>
#include "ADXL345FreshSPI.h"
class ADXL345ArraySPI {
public:
static constexpr uint8_t MAX_SENSORS = 4;
explicit ADXL345ArraySPI(const uint8_t cs_pins[MAX_SENSORS]) {
for (uint8_t i=0;i<MAX_SENSORS;i++){ cs_[i]=cs_pins[i]; }
}
// Inicjalizacja wszystkich (SPI MODE3, STREAM FIFO, full-res, wybrany ODR/Range).
// Zwraca liczbę poprawnie wykrytych czujników.
uint8_t beginAll(SPIClass *spi, uint32_t spiHz, float odr_hz, ADXL345FreshSPI::Range range = ADXL345FreshSPI::Range::G16) {
presentMask_ = 0;
// Zbezpieczenie: inicjalizacja CS na HIGH przed startem.
for (uint8_t i=0;i<MAX_SENSORS;i++){
pinMode(cs_[i], OUTPUT);
digitalWrite(cs_[i], HIGH);
}
delayMicroseconds(5);
for (uint8_t i=0;i<MAX_SENSORS;i++){
if (!acc_[i].begin(spi, cs_[i], spiHz)) continue;
acc_[i].write8(0x2D, 0x00); // POWER_CTL = standby (MEASURE=0)
if (!acc_[i].setRange(range, true)) continue;
acc_[i].write8(0x2D, 0x08); // POWER_CTL = measure
if (!acc_[i].setODR_Hz(odr_hz)) continue;
// Tryb STREAM najbezpieczniejszy dla jitteru CPU
acc_[i].enableFIFO(ADXL345FreshSPI::FIFOmode::STREAM, 32);
presentMask_ |= (1u << i);
}
return countPresent();
}
inline uint8_t size() const { return MAX_SENSORS; }
inline bool isPresent(uint8_t i) const { return (presentMask_ & (1u << i)) != 0; }
inline uint8_t countPresent() const { return __builtin_popcount(presentMask_); }
// Sprawdza, czy KAŻDY obecny sensor ma >=1 nową próbkę (DATA_READY).
bool availableAll() {
for (uint8_t i=0;i<MAX_SENSORS;i++){
if (!isPresent(i)) continue;
if (!acc_[i].available()) return false;
}
return true;
}
// Zdejmuje po 1 NAJSTARSZEJ próbce z FIFO każdego obecnego sensora.
// Zwraca liczbę faktycznie zebranych próbek (== liczbie obecnych sensorów, jeśli sukces).
uint8_t readAlignedOnce(int16_t x[], int16_t y[], int16_t z[], uint32_t ts_us[]) {
uint8_t got = 0;
for (uint8_t i=0;i<MAX_SENSORS;i++){
if (!isPresent(i)) continue;
ADXL345FreshSPI::SampleI16 one[1];
size_t n = acc_[i].readFIFOBurst(one, 1); // NAJSTARSZA próbka z FIFO
if (n == 0) {
// sporadycznie: awaryjnie dociągnij świeżą (rzadkie)
ADXL345FreshSPI::SampleI16 s;
if (!acc_[i].readFresh(s, 1)) return got; // przerwij zbieranie ramki
one[0] = s;
}
x[i] = one[0].x; y[i] = one[0].y; z[i] = one[0].z; ts_us[i] = one[0].ts_us;
got++;
}
return got;
}
ADXL345FreshSPI& at(uint8_t i) { return acc_[i]; }
private:
uint8_t cs_[MAX_SENSORS]{};
ADXL345FreshSPI acc_[MAX_SENSORS];
uint32_t presentMask_ = 0;
};

View File

@@ -0,0 +1,91 @@
#pragma once
#include <Arduino.h>
#include <SPI.h>
#include "ADXL345FreshSPI.h"
#include <Logger.h>
class ADXL345FastSPI {
public:
enum Rate { RATE_100HZ, RATE_200HZ, RATE_400HZ, RATE_800HZ, RATE_1600HZ, RATE_3200HZ };
enum Range { RANGE_2G, RANGE_4G, RANGE_8G, RANGE_16G };
ADXL345FastSPI(const uint8_t* csPins, uint8_t count) : count_(count > MAX_NUM ? MAX_NUM : count){
for (uint8_t i = 0; i < count_; ++i) cs_[i] = csPins[i];
}
/* Pobierz konfigurację zakres akcelerometru */
uint8_t getRange(uint8_t accel);
/* Zwraca czy jest FUL_RES*/
bool getFullRes(uint8_t accel);
// Wersja podstawowa: podaj SPIClass* (np. &SPI)
bool begin(SPIClass *spi, uint32_t spiHz, Rate rate, Range range, uint8_t options = 0);
// Wersja wygodna: deleguje do powyższej, używając globalnego SPI
inline bool begin(uint32_t spiHz, Rate rate, Range range, uint8_t options = 0) {
return begin(&SPI, spiHz, rate, range, options);
}
// Informacje / dostępność
inline uint8_t size() const { return presentCnt_; }
inline bool isPresent(uint8_t i) const { return (i < count_) && present_[i]; }
bool availableAll();
// Wariant B: zdejmuje po 1 NAJSTARSZEJ próbce z FIFO każdego obecnego sensora
// Zwraca liczbę zebranych próbek (== size(), jeśli pełna ramka).
uint8_t readAlignedOnce(int16_t* x, int16_t* y, int16_t* z, uint32_t* ts_us);
// Zgodność: pojedynczy sensor 1 próbka
bool readNewSample(uint8_t idx, int16_t& x, int16_t& y, int16_t& z, bool& ready);
// Zwraca ilośc podłączonych czujników po inicjalizacji - ale nie jest dynamiczna!
inline uint8_t connectedSensorsCount() const { return presentCnt_; }
// dynamiczne odświeżenie liczby działających czujników zawsze sprawdzi na bieżąco i zwróci przy działającym urządzeniu
uint8_t refreshConnectedSensorsCount();
// Maska aktywnych sensorów wg bieżącego stanu (bit i = sensor i)
inline uint8_t activeMask() const {
uint8_t m = 0;
for (uint8_t i = 0; i < count_; ++i) if (present_[i]) m |= (1u << i);
return m;
}
// Odświeża stan (ping) i zwraca zaktualizowaną maskę aktywnych sensorów
uint8_t refreshActiveMask();
private:
static constexpr uint8_t MAX_NUM = 4; // MAX Ilość ADXL345
SPIClass* spi_ = &SPI;
ADXL345FreshSPI dev_[MAX_NUM];
uint8_t cs_[MAX_NUM]{};
bool present_[MAX_NUM]{};
uint8_t count_ = 0;
uint8_t presentCnt_ = 0;
uint32_t spiHz_ = 5000000;
float odrHz_ = 3200.0f;
static float mapRateToHz(Rate r) {
switch (r) {
case RATE_100HZ: return 100.0f;
case RATE_200HZ: return 200.0f;
case RATE_400HZ: return 400.0f;
case RATE_800HZ: return 800.0f;
case RATE_1600HZ: return 1600.0f;
case RATE_3200HZ: return 3200.0f;
default: return 3200.0f;
}
}
static ADXL345FreshSPI::Range mapRange(Range r) {
switch (r) {
case RANGE_2G: return ADXL345FreshSPI::Range::G2;
case RANGE_4G: return ADXL345FreshSPI::Range::G4;
case RANGE_8G: return ADXL345FreshSPI::Range::G8;
case RANGE_16G: return ADXL345FreshSPI::Range::G16;
default: return ADXL345FreshSPI::Range::G16;
}
}
};

View File

@@ -0,0 +1,87 @@
#pragma once
#include <Arduino.h>
#include <SPI.h>
#include "ADXL345Registers.h"
#include <Logger.h>
class ADXL345FreshSPI {
public:
enum class Range { G2=0, G4=1, G8=2, G16=3 };
enum class FIFOmode { BYPASS, FIFO, STREAM, TRIGGER };
struct SampleI16 {
int16_t x, y, z;
uint32_t ts_us;
};
struct SampleSI {
float ax_g, ay_g, az_g;
float ax_ms2, ay_ms2, az_ms2;
uint32_t ts_us;
};
ADXL345FreshSPI() = default;
// --- Init (SPI) ---
// Uwaga: ADXL345 wymaga SPI MODE3, zegar ≤ ~5 MHz.
bool begin(SPIClass *spi, uint8_t csPin, uint32_t clockHz = 5000000);
// --- Konfiguracja ---
bool setODR_Hz(float odr_hz);
bool setRange(Range r, bool fullRes=true);
bool enableFIFO(FIFOmode mode, uint8_t triggerLevel=16);
bool enableDataReadyInterrupt(bool enable=true); // przy pollingu pozostaw false
// --- Status ---
bool ping(); // DEVID == 0xE5 ?
bool available(); // DATA_READY z INT_SOURCE
// --- Odczyty „świeże” (blokujące do timeout_ms) ---
bool readFresh(SampleI16& out, uint32_t timeout_ms = 100);
bool readFresh(SampleSI& out, uint32_t timeout_ms = 100);
// --- Zrzut FIFO (do n elementów) ---
size_t readFIFOBurst(SampleI16* buf, size_t maxCount);
size_t readFIFOBurst(SampleSI* buf, size_t maxCount);
// --- Parametry pomocnicze ---
void setGConstant(float g = 9.80665f) { g_ms2 = g; }
float lsb_per_g() const { return 1.0f / scale_g_per_lsb; }
//bool write8(uint8_t reg, uint8_t val);
//bool read8(uint8_t reg, uint8_t& val);
/*
Zwraca tryb pracy akcelerometru
*/
uint8_t getADXLRange();
/* Zwraca czy jest FULL_RES w akcelerometrze */
bool getADXLFullRes();
void showRangeFull(String txt="");
// niskopoziomowe
bool write8(uint8_t reg, uint8_t val);
bool read8(uint8_t reg, uint8_t& val);
private:
SPIClass* spi = nullptr;
uint8_t cs = 255;
uint32_t spiHz = 5000000;
float scale_g_per_lsb = 0.0039f; // full-res ~3.9 mg/LSB
float g_ms2 = 9.80665f;
bool fullRes = true;
// niskopoziomowe
//bool write8(uint8_t reg, uint8_t val);
//bool read8(uint8_t reg, uint8_t& val);
bool readMulti(uint8_t reg, uint8_t* dst, size_t n);
void spiSelect();
void spiDeselect();
bool configurePowerMeasure();
uint8_t odrCodeFromHz(float hz);
void countsToSI(const SampleI16& in, SampleSI& out);
};

View File

@@ -0,0 +1,27 @@
#pragma once
#define ADXL345_REG_DEVID 0x00
#define ADXL345_REG_BW_RATE 0x2C
#define ADXL345_REG_POWER_CTL 0x2D
#define ADXL345_REG_INT_ENABLE 0x2E
#define ADXL345_REG_INT_MAP 0x2F
#define ADXL345_REG_INT_SOURCE 0x30
#define ADXL345_REG_DATA_FORMAT 0x31
#define ADXL345_REG_DATAX0 0x32
#define ADXL345_REG_DATAX1 0x33
#define ADXL345_REG_DATAY0 0x34
#define ADXL345_REG_DATAY1 0x35
#define ADXL345_REG_DATAZ0 0x36
#define ADXL345_REG_DATAZ1 0x37
#define ADXL345_REG_FIFO_CTL 0x38
#define ADXL345_REG_FIFO_STATUS 0x39
#define ADXL345_POWER_MEASURE 0x08
#define ADXL345_DATA_READY_BIT 0x80 // INT_SOURCE[7]
#define ADXL345_DATA_FORMAT_FULL_RES 0x08
#define ADXL345_DATA_FORMAT_RANGE_MASK 0x03
#define ADXL345_FIFO_BYPASS 0x00
#define ADXL345_FIFO_FIFO 0x40
#define ADXL345_FIFO_STREAM 0x80
#define ADXL345_FIFO_TRIGGER 0xC0

View File

@@ -0,0 +1,22 @@
#ifndef APICLIENT_H
#define APICLIENT_H
#include <Arduino.h>
#include <WiFiClient.h>
#include <HTTPClient.h>
#include <FS.h>
#include <SD.h>
#include "Config.h"
#include "Watchdog.h"
class APIClient {
public:
APIClient();
bool uploadMeasurement(const String& filePath);
private:
const String boundary = "----ESP32Boundary123456789";
};
#endif

View File

@@ -0,0 +1,71 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <Logger.h>
#include <Arduino.h>
#include <EEPROM.h>
#define EEPROM_SIZE 1024
//constexpr size_t EEPROM_SIZE = sizeof(Config) + 32; // z lekkim zapasem
extern bool isRebootRequired;
extern bool isClearLog;
extern bool connected;
extern long countConnect;
extern long countDisconnect;
extern String act_rssi_percent;
extern int8_t rssi;
extern String actDate;
extern String actTime;
struct Config {
bool connect; // czy łączyć z Internetem?
bool measure; // true - pomiary ciągłe, false - nie rób nic (tryb konfiguracji)
char ip[16];
char subnet[16];
char gateway[16];
char dns[16];
char ssid[32];
char ntp[50];
char password[32];
char hostname[32];
char place[100]; // miejsce instalacji
bool dhcp; // czy włączyć DHCP?
char user[10]; // użytkownik konfiguracji
char pass[20]; // hasło użytkownika konfiguracji
char updateUrl[150]; // adres pliku aktualizacji
char restURL[150]; // adres Rest API
int restPort; // Port systemu Api na serwerze
char restUser[30]; // login RestAPI
char restPass[50]; // hasło RestAPi
uint8_t apiKey[32]; // Klucz API KEY
uint16_t pause; // Pomiar co sekund
uint8_t duration; // Czas pomiaru w sekundach 1-25
char S0[12]; // nazwy czujników 1-8
char S1[12];
char S2[12];
char S3[12];
char S4[12];
char S5[12];
char S6[12];
char S7[12];
};
// Global config declaration
extern Config config;
class ConfigManager {
public:
ConfigManager();
void begin(); // EEPROM initialization
void readConfig(); // Odczyt konfiguracji z EEPROM
void saveConfig(); // Zapis konfiguracji do EEPROM
void resetToDefaults(); // Reset do ustawień domyślnych
void showConfig();
void generateApiKey(uint8_t *buf, size_t len);
private:
bool isEEPROMEmpty();
};
#endif

View File

@@ -0,0 +1,93 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#pragma once
#include "esp_log.h"
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Version.h>
#include <RTClib.h>
#include <Config.h>
#define SCREEN_WIDTH 40
#define SCREEN_HEIGHT 4
#define SCREEN_ADDRESS 0x27
class Display {
public:
Display(RTC_DS3231 &rtc,
uint8_t address = SCREEN_ADDRESS,
uint8_t columns = SCREEN_WIDTH,
uint8_t rows = SCREEN_HEIGHT);
// Zwraca true, jeśli urządzenie na I2C odpowiada
bool begin(TwoWire *wire = &Wire);
/* Ekran startowy urządzenia */
void welcomeScreen();
/* Czyście wiersz */
void clearRow(uint16_t line);
/* Wyświetla wyśrodkowany tekst w danym wierszu */
void textCenter(uint8_t line, const char *txt);
/* Wyświetla tekst w danym wierszu od lewej, bez centrowania */
void text(uint8_t line, const char *text);
/* Status - najniższy wiersz. Czyści przed zapisaniem */
void textStatus(const char *text);
void clear();
/* Ekran po uruchomieniu */
void mainScreen();
/* Ekran jeśli offline miga co 1 sek */
void displayOffline(bool measure, uint8_t count, float freeSpace, long licznik, bool refresh = false);
/* Podsumowanie po pomiarze: ramki, sampling, etc. */
void displaySampleRateSummary(uint32_t reccount, uint32_t captureSeconds, float khz, String filename);
void updateNetwork(String ip, bool connected);
void updateBarWiFi(long signal, bool connected);
void textStyle(const uint8_t st, String text);
void message(String text);
void print(String text);
void println(String text);
void setCursor(int16_t x, int16_t y);
void showAccel(float a, float b, float c);
void displayOnOffM(bool measure, String myDir, String myFile);
void initMeasure(
bool measure, // czy pomiar ciągły?
bool run, // czy uruchomiony?
bool runmes,
uint16_t pause, // Czas (s) pomiędzy próbkami
uint8_t duration, // Czas (s) trwania próbki
bool connect, // Czy połączenie Network
long counter, // główny licznik long
String gdate, // Data aktualna
String gtime); // Czas aktualny
private:
LiquidCrystal_I2C *_lcd;
RTC_DS3231 &rtc_;
uint8_t _columns;
uint8_t _rows;
uint8_t _address;
// Poprzednie
uint16_t oyear;
uint8_t omonth;
uint8_t oday;
uint8_t ohour;
uint8_t omin;
uint8_t osec;
float ospace;
uint8_t oadxlcnt;
bool omode;
};
#endif

View File

@@ -0,0 +1,15 @@
#ifndef LOGGER_H
#define LOGGER_H
#include "esp_log.h"
// Wszystkie tagi logowania w jednym miejscu
extern const char *TAG_MAIN;
extern const char *TAG_DISP;
extern const char *TAG_ADXL;
extern const char *TAG_CONF;
// Funkcja inicjalizacji poziomów logowania
void init_log_levels();
#endif

View File

@@ -0,0 +1,127 @@
#ifndef MEASURE_H
#define MEASURE_H
#include "ADXL345FastSPI.h" // <-- zgodnie z main.cpp
#include <Arduino.h>
#include <Display.h>
#include <FS.h>
#include <Logger.h>
#include <Pinout.h>
#include <RTClib.h>
#include <SD.h>
#include <SPI.h>
#include <Watchdog.h>
// Domyślne parametry akwizycji ADXL345 (mogą być nadpisane w
// ADXL345FastSPI::begin)
static constexpr uint32_t SPI_HZ = 5000000; // 5 MHz (MODE3)
static constexpr float ODR_HZ = 3200.0f; // maks. ODR
// Zakres ustawiany w main.cpp przez ADXL345FastSPI::begin(..., RANGE_2G, ...)
struct FileInfo {
String path; // np. "/3/00000057.wmt"
uint64_t size; // bajty
bool exists; // true, jeśli ostatni plik istnieje
};
struct SpaceInfo {
double value;
const char *unit; // "GB" | "MB" | "UNKNOWN"
};
class DataCapture {
// --- Nagłówek pliku WMT ---
struct FileHeader {
char magic[3]; // "WMT"
uint16_t version; // 1
uint16_t headerSize; // sizeof(FileHeader)
uint32_t sampleSize; // sizeof(Sample)
uint32_t timestamp; // UNIX startu akwizycji
uint32_t reccount; // liczba rekordów Sample w pliku
} __attribute__((packed));
public:
// --- Rekord próbki ---
struct Sample {
uint32_t offset; // µs od startu akwizycji (wspólny dla ramki)
uint8_t sensor_id; // 0..3
int16_t x, y, z; // surowe ADXL345
bool ready; // 1 = obecna
} __attribute__((packed));
// Konstruktor dopasowany do main.cpp przyjmuje ADXL345FastSPI
DataCapture(ADXL345FastSPI &adxl, Display &display, RTC_DS3231 &rtc,
fs::FS &storage, size_t bufferSize = 131072 /* 128 KB */);
~DataCapture();
bool capture(uint32_t captureSeconds, const char *filename);
bool captureAuto(uint32_t captureSeconds,
const char *baseDirectory = "/logs");
void printSamplingRate(uint32_t reccount, uint32_t captureSeconds,
String filename);
void readHeaderAndPrint(const char *path);
void stop();
bool isActive() const { return measurementActive_; }
// SD utils
SpaceInfo freeSpaceMB();
float freeSpaceFloat(bool *isGB = nullptr);
String unixToDateTime(uint32_t ts);
// plik z najwyższym indeksem
FileInfo getLastFileInfo();
bool deleteAllOnSD();
bool isExit = false; // true oznacza przerwanie pomiaru
private:
ADXL345FastSPI &adxl_;
Display &display_;
RTC_DS3231 &rtc_;
fs::FS &_fs;
// Katalogowanie
const String _baseDir = "/";
const String _ext = ".wmt";
const uint8_t _digits = 8;
const uint16_t _maxFilesPerDir = 400;
// Bufor zapisu (PSRAM)
uint8_t *buffer_ = nullptr;
size_t bufferSize_ = 0;
size_t bufferIndex_ = 0;
bool measurementActive_ = false;
bool flushToFile(File &f);
static uint8_t crc8(const uint8_t *data, size_t len);
void setTestingIndicator_(bool on, String myDir, String myFile);
bool isEscape() {
bool ispress = (GPIO.in & (1UL << BTN_OK)) == 0;
if (ispress) {
isExit = true;
measurementActive_;
display_.textStatus("Cancelling. Wait!");
}
return ispress;
} // szybkidigitalRead : czy BTN stop???
public:
bool isAllDigits(const char *s);
uint32_t toUint(const char *s);
static const char *basenameFromPath(const char *full);
bool isWmtWithDigits(const char *name, uint32_t &idxOut) const;
String makeIndexedName(uint32_t idx) const;
static String joinPath(const String &a, const String &b);
bool ensureDir(uint32_t dirNum);
uint32_t findHighestNumericDir();
void scanDirForWmt(uint32_t dirNum, uint32_t &count, uint32_t &highestIdx);
bool recursiveDelete(const String &path);
String dirPath(uint32_t dirNum) const;
String allocateNextFilePath();
String generateNextFilename();
void printLastFileInfoSerial();
};
#endif // MEASURE_H

View File

@@ -0,0 +1,66 @@
#ifndef NETWORK_H
#define NETWORK_H
#include "esp_log.h"
#include <Arduino.h>
#include <Config.h>
#ifdef ESP32
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#endif
//#include <Pinout.h>
//#include <IPAddress.h>
//#include <WiFiUdp.h>
//#include <WiFiClientSecureBearSSL.h>
// OTA
#include <HTTPUpdate.h>
#include <WiFiClientSecure.h>
#include <functional>
// OTA
class WiFiManager {
public:
WiFiManager();
void begin();
void connectToWiFi();
void setupAccessPoint(const char *newSSID, const char *newPassword);
void checkWiFiConnection();
void updateLED();
void setupMDNS();
void ReadConnection();
bool isConnected(); // Zwraca stan połączenia
bool convertCharToIPAddress(const char *str, IPAddress& ip);
void ledBlink(); // Z innego projektu - niepotrzebne, bo nie ma LED WiFi...
bool isWiFiOK(); // True, gdy WiFi połączone i false, gdy brak połączenia
int rssiToPercent(int rssi); // rssi na procenty
int8_t getRSSI();
/**
* Aktualizacja systemu przez internet z adresu config.updateUrl.
* @param allowInsecureTLS true => dla https wyłącz weryfikację certyfikatu.
* @param progressCb callback progress (opcjonalnie) (bytes, total).
* @return true, jeśli update zakończony sukcesem (urządzenie się zrestartuje).
*/
bool performOTAUpdate(bool allowInsecureTLS = true, std::function<void(int,int)> progressCb = nullptr);
int8_t rssi = 0;
bool useDHCP = true;
IPAddress local_IP;
IPAddress gateway;
IPAddress subnet;
IPAddress dns;
String ssidAP = "ACCEL666";
String passwordAP = "12345678";
private:
bool isAccessPoint = false;
};
#endif // WIFIMANAGER_H

View File

@@ -0,0 +1,52 @@
#ifndef PINOUT_H
#define PINOUT_H
#if defined(ESP32)
// SPI3 (HSPI) - SD Card nie kolidują z PSRAM
#define SD_SCK 16 // 36 //18
#define SD_MOSI 17 // 35 //17
#define SD_MISO 18 // 37 //16
#define SD_CS 15 // 34 //15 ?? 34
// SPI2 (VSPI) - ADXL345
#define MOSI_ADSX 11 // SDA
#define CLK_ADSX 12 // SCL
#define MISO_ADSX 13 // SDO
//I2C C3
#define PIN_SDA 47 // szary
#define PIN_SCL 48 // niebieski
// Przycisk
#define BTN_UP 5
#define BTN_OK 6
#define BTN_DOWN 7
#endif
/*
CS {5, 6, 7, 10, 14, 21}
SPI2 (VSPI) — preferowane do ADXL345 (wysoka prędkość, stabilność). ASXL345
SPI3 (HSPI) — dowolne piny do SD (niższa prędkość, ale elastyczność). SD
Nie używać ESP32-S3:
integrated SPI flash: 26, 27, 28, 29, 30, 31, 32,
USB: 19, 20, 43, 44
PSRAM 35, 37
*/
#if defined(ARDUINO_RASPBERRY_PI_PICO)
#define CLK_ADSX 18
#define MOSI_ADSX 19
#define MISO_ADSX 16
#define SD_MISO 12
#define SD_CS 13
#define SD_SCK 14
#define SD_MOSI 15
#define I2C_SDA 20
#define I2C_SCL 21
#endif
#endif

View File

@@ -0,0 +1,52 @@
#ifndef SETTINGS_H
#define SETTINGS_H
#include <Arduino.h>
#include <Pinout.h>
#include <Watchdog.h>
#include <RTClib.h>
#include <Display.h>
#include <Logger.h>
#include <Config.h>
class Settings {
public:
Settings(Display &display, RTC_DS3231 &rtc);
~Settings();
void setTimeRTC();
void setConfigDevice();
void finishConfigDevice();
void begin();
bool isPressed(uint8_t btnIndex);
// bool is1and3();
bool isBtnReset();
bool isSetClock();
bool readBtnUp() { return digitalRead(BTN_UP) == LOW; }
bool readBtnOk() { return digitalRead(BTN_OK) == LOW; }
bool readBtnDown() { return digitalRead(BTN_DOWN) == LOW; }
// Struktura na datę i czas
struct RtcDateTime {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
};
private:
Display &display_;
RTC_DS3231 &rtc_;
int editField(int value, int minVal, int maxVal, const char *label);
void constrainValue(int &value, int minVal, int maxVal);
void printField(const char *label, int value);
};
#endif

View File

@@ -0,0 +1,14 @@
#ifndef TOOL_H
#define TOOL_H
#include <Arduino.h>
#include <Wire.h>
#include "esp_log.h"
#include "Watchdog.h"
void scanI2C();
/* Funkcja przyjmuje adres jako argument i zwraca true gdy urządzenie odpowiada, w przeciwnym wypadku false */
bool isI2CDevPresent(uint8_t address);
#endif

View File

@@ -0,0 +1,31 @@
#ifndef UPLOADMANAGER_H
#define UPLOADMANAGER_H
#include <Arduino.h>
#include <FS.h>
#include <SD.h>
#include "APIClient.h"
#include "RTClib.h"
#include "Measure.h"
class UploadManager {
public:
UploadManager(APIClient& client, RTC_DS3231& rtc, DataCapture& capture);
// Call this to upload a specific file immediately
void uploadFile(const String& filePath);
// Call this in the background when WiFi is connected
void processPendingUploads();
private:
APIClient& apiClient;
RTC_DS3231& rtc_;
DataCapture& capture_;
bool isAlreadyUploaded(const String& filePath);
void appendLog(const String& filePath, const String& status);
String getCurrentTimestamp();
};
#endif

View File

@@ -0,0 +1,9 @@
#ifndef VERSION_H
#define VERSION_H
#define VERSION "1.4.1"
// 1: graphical 128x64, 2: LCD I2C Text 4x20
#define LCD_TYPE 2
#endif

View File

@@ -0,0 +1,38 @@
#pragma once
/**
* Watchdog — prosty interfejs do inicjalizacji i karmienia WDT z dowolnego modułu.
*
* Obsługiwane środowiska:
* - ESP32 Arduino Core / ESP-IDF (esp_task_wdt)
* - Fallback: no-op na innych platformach
*
* Użycie:
* Watchdog::init(5, true);
* Watchdog::addThisTask();
* ...
* Watchdog::feed();
*/
#include <stdint.h>
namespace Watchdog {
/** Inicjalizacja Task Watchdog (idempotentna). */
bool init(int timeout_seconds = 5, bool panic_on_trigger = true);
/** Dodaje bieżący task (wątki FreeRTOS: wołaj w ciele tego taska). */
bool addThisTask();
/** Usuwa bieżący task z nadzoru WDT. */
bool removeThisTask();
/** Karmi watchdog (reset licznika). */
void feed();
/** Zmienia timeout (wykonuje re-init wewnętrznie, jeśli trzeba). */
bool setTimeout(int timeout_seconds);
/** Czy watchdog jest aktywny (zainicjalizowany)? */
bool isActive();
} // namespace Watchdog