#include "ADXL345FreshSPI.h" static const char *TAG_FRESH = "ADXLFRESH"; static inline int16_t u8pair_to_i16(uint8_t lo, uint8_t hi) { return (int16_t)((hi << 8) | lo); } bool ADXL345FreshSPI::begin(SPIClass* s, uint8_t csPin, uint32_t clockHz) { spi = s; cs = csPin; spiHz = clockHz; pinMode(cs, OUTPUT); digitalWrite(cs, HIGH); //spi->begin(); // tymczas delay(1); if (!ping()) return false; // 1. Wymuś STANDBY przed jakąkolwiek konfiguracją write8(ADXL345_REG_POWER_CTL, 0x00); delay(1); // 2. Skonfiguruj format danych (Range i Full_Res) if (!setRange(Range::G16, true)) { // było if (!setRange(Range::G2, true)) return false; ESP_LOGI(TAG_FRESH, "Range G16 ERROR!"); return false; } // 3. Skonfiguruj ODR if (!setODR_Hz(100.0f)) return false; // domyślnie 100 Hz // 4. Dopiero teraz włącz pomiar if (!configurePowerMeasure()) return false; showRangeFull(); return true; } bool ADXL345FreshSPI::ping() { uint8_t id=0; if (!read8(ADXL345_REG_DEVID, id)) return false; return id == 0xE5; } bool ADXL345FreshSPI::configurePowerMeasure() { return write8(ADXL345_REG_POWER_CTL, ADXL345_POWER_MEASURE); } bool ADXL345FreshSPI::setRange(Range r, bool fullRes_) { fullRes = fullRes_; // Wymuś STANDBY (MEASURE=0) – kluczowe dla zmiany RANGE/FULL_RES write8(ADXL345_REG_POWER_CTL, 0x00); delayMicroseconds(5); uint8_t fmt = 0; if (!read8(ADXL345_REG_DATA_FORMAT, fmt)) return false; fmt &= ~ADXL345_DATA_FORMAT_RANGE_MASK; // bity 1:0 fmt |= (uint8_t)r; if (fullRes) fmt |= ADXL345_DATA_FORMAT_FULL_RES; // bit 3 else fmt &= ~ADXL345_DATA_FORMAT_FULL_RES; if (!write8(ADXL345_REG_DATA_FORMAT, fmt)) return false; // Kontrola: odczyt po zapisie //uint8_t verify = 0; //read8(ADXL345_REG_DATA_FORMAT, verify); // tu możesz logować verify // Wróć do MEASURE write8(ADXL345_REG_POWER_CTL, ADXL345_POWER_MEASURE); scale_g_per_lsb = fullRes ? 0.0039f : (1.0f/256.0f) * (2 << (uint8_t)r); return true; } uint8_t ADXL345FreshSPI::odrCodeFromHz(float hz) { struct { uint8_t code; float f; } map[] = { {0x06, 6.25f},{0x07,12.5f},{0x08,25.f},{0x09,50.f},{0x0A,100.f}, {0x0B,200.f},{0x0C,400.f},{0x0D,800.f},{0x0E,1600.f},{0x0F,3200.f} }; uint8_t best=0x0A; float bestErr=1e9f; for (auto &e: map){ float err=fabsf(e.f-hz); if (err timeout_ms) return false; delayMicroseconds(200); } uint8_t buf[6]; if (!readMulti(ADXL345_REG_DATAX0, buf, 6)) return false; out.x = u8pair_to_i16(buf[0], buf[1]); out.y = u8pair_to_i16(buf[2], buf[3]); out.z = u8pair_to_i16(buf[4], buf[5]); out.ts_us = micros(); return true; } bool ADXL345FreshSPI::readFresh(SampleSI& out, uint32_t timeout_ms) { SampleI16 raw; if (!readFresh(raw, timeout_ms)) return false; countsToSI(raw, out); return true; } size_t ADXL345FreshSPI::readFIFOBurst(SampleI16* buf, size_t maxCount) { if (!buf || maxCount==0) return 0; uint8_t status=0; if (!read8(ADXL345_REG_FIFO_STATUS, status)) return 0; uint8_t entries = status & 0x3F; // 0..32 size_t n = min(entries, maxCount); for (size_t i=0;ibeginTransaction(SPISettings(spiHz, MSBFIRST, SPI_MODE3)); spiSelect(); spi->transfer(reg & 0x3F); // write, single spi->transfer(val); spiDeselect(); spi->endTransaction(); return true; } bool ADXL345FreshSPI::read8(uint8_t reg, uint8_t& val) { spi->beginTransaction(SPISettings(spiHz, MSBFIRST, SPI_MODE3)); spiSelect(); spi->transfer(0x80 | (reg & 0x3F)); // read, single val = spi->transfer(0x00); spiDeselect(); spi->endTransaction(); return true; } bool ADXL345FreshSPI::readMulti(uint8_t reg, uint8_t *dst, size_t n) { if (n==0) return true; spi->beginTransaction(SPISettings(spiHz, MSBFIRST, SPI_MODE3)); spiSelect(); spi->transfer(0xC0 | (reg & 0x3F)); // read, multi (MB=1, R/W=1) for (size_t i=0;itransfer(0x00); spiDeselect(); spi->endTransaction(); return true; } void ADXL345FreshSPI::spiSelect() { digitalWrite(cs, LOW); } void ADXL345FreshSPI::spiDeselect() { digitalWrite(cs, HIGH); } uint8_t ADXL345FreshSPI::getADXLRange() { uint8_t format = 0; if (!read8(0x31, format)) return 255; // albo 0 switch (format & 0x03) { case 0: return 2; case 1: return 4; case 2: return 8; case 3: return 16; } return 255; } bool ADXL345FreshSPI::getADXLFullRes() { uint8_t format = 0; if (!read8(0x31, format)) return false; //bool ok = read8(0x31, format); //ESP_LOGI(TAG_FRESH, "read8 ok=%d DATA_FORMAT=0x%02X", ok, format); return (format & 0x08) != 0; } void ADXL345FreshSPI::showRangeFull(String txt) { uint8_t format = getADXLRange(); bool full_res = getADXLFullRes(); ESP_LOGI(TAG_FRESH, "%s ADXL345: RANGE=%dG FULL_RES=%d", txt, format, full_res); }