forked from Akcelerometry_drgania_WMT/PI_mikrokontroler
Dodanie folderów include i src
This commit is contained in:
79
include/ADXL345ArraySPI.h
Normal file
79
include/ADXL345ArraySPI.h
Normal 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;
|
||||
};
|
||||
91
include/ADXL345FastSPI.h
Normal file
91
include/ADXL345FastSPI.h
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
87
include/ADXL345FreshSPI.h
Normal file
87
include/ADXL345FreshSPI.h
Normal 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 only) ---
|
||||
// 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);
|
||||
};
|
||||
27
include/ADXL345Registers.h
Normal file
27
include/ADXL345Registers.h
Normal 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
|
||||
71
include/Config.h
Normal file
71
include/Config.h
Normal 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
|
||||
86
include/Display.h
Normal file
86
include/Display.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#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);
|
||||
|
||||
// Metoda sterująca ikoną SSL (dodana do klasy)
|
||||
void setSSLStatus(bool active);
|
||||
|
||||
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 _address;
|
||||
uint8_t _columns;
|
||||
uint8_t _rows;
|
||||
};
|
||||
|
||||
#endif
|
||||
15
include/Logger.h
Normal file
15
include/Logger.h
Normal 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
|
||||
127
include/Measure.h
Normal file
127
include/Measure.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef MEASURE_H
|
||||
#define MEASURE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Watchdog.h>
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <FS.h>
|
||||
#include <RTClib.h>
|
||||
#include <Display.h>
|
||||
#include "ADXL345FastSPI.h" // <-- zgodnie z main.cpp
|
||||
#include <Logger.h>
|
||||
#include <Pinout.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, ...)
|
||||
|
||||
//extern Display display;
|
||||
|
||||
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 (jak w oryginale) ---
|
||||
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 (jak w oryginale) ---
|
||||
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???
|
||||
|
||||
|
||||
// Helpers (zachowane z Twojej wersji)
|
||||
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
|
||||
92
include/Network.h
Normal file
92
include/Network.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#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>
|
||||
#include <ESP8266WebServer.h>
|
||||
#endif
|
||||
|
||||
#include <DNSServer.h> // Dodano dla Captive Portal
|
||||
//#include <Pinout.h>
|
||||
//#include <IPAddress.h>
|
||||
//#include <WiFiUdp.h>
|
||||
|
||||
//#include <WiFiClientSecureBearSSL.h>
|
||||
|
||||
// OTA
|
||||
#include <HTTPUpdate.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <functional>
|
||||
// OTA
|
||||
|
||||
#include "Display.h" // Dodano dla obsługi komunikatów na LCD
|
||||
|
||||
extern Config config; // Deklaracja zewnętrznej struktury config
|
||||
extern ConfigManager configManager; // Deklaracja zewnętrznego managera (to naprawi błąd)
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
* NOWA METODA: Portal konfiguracyjny (Captive Portal)
|
||||
* Uruchamiany automatycznie przy braku połączenia.
|
||||
*/
|
||||
void startConfigPortal(Display &display);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// Obiekty serwerów dla Portalu (ESP32/ESP8266)
|
||||
#ifdef ESP32
|
||||
WebServer server{80};
|
||||
#elif defined(ESP8266)
|
||||
ESP8266WebServer server{80};
|
||||
#endif
|
||||
DNSServer dnsServer;
|
||||
void handleRoot();
|
||||
void handleSave();
|
||||
};
|
||||
|
||||
extern WiFiManager wifi;
|
||||
|
||||
#endif // WIFIMANAGER_H
|
||||
52
include/Pinout.h
Normal file
52
include/Pinout.h
Normal 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
|
||||
|
||||
52
include/Settings.h
Normal file
52
include/Settings.h
Normal 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 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
|
||||
14
include/Tool.h
Normal file
14
include/Tool.h
Normal 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
|
||||
24
include/Uploader.h
Normal file
24
include/Uploader.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef UPLOADER_H
|
||||
#define UPLOADER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <SD.h>
|
||||
#include "Config.h"
|
||||
#include "Display.h"
|
||||
#include "Watchdog.h"
|
||||
|
||||
class Uploader {
|
||||
public:
|
||||
Uploader(Display &display);
|
||||
void processQueue(int maxFiles = 3);
|
||||
|
||||
private:
|
||||
Display &_display;
|
||||
String loadCACert(const char* path);
|
||||
bool sendFile(String filePath, String& caCert);
|
||||
};
|
||||
|
||||
#endif
|
||||
9
include/Version.h
Normal file
9
include/Version.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION "1.3.2"
|
||||
|
||||
// 1: graphical 128x64, 2: LCD I2C Text 4x20
|
||||
#define LCD_TYPE 2
|
||||
|
||||
#endif
|
||||
38
include/Watchdog.h
Normal file
38
include/Watchdog.h
Normal 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
|
||||
Reference in New Issue
Block a user