From e24a9490c428276cc329e899fa35b9f98d9986ab Mon Sep 17 00:00:00 2001
From: rondlh <77279634+rondlh@users.noreply.github.com>
Date: Sat, 11 Jan 2025 14:42:04 +0800
Subject: [PATCH] Add support for the adxl345 accelerometer
Add support for the adxl345 accelerometer
---
Marlin/Configuration_adv.h | 3 +
Marlin/src/MarlinCore.cpp | 8 ++
.../src/feature/accelerometer/acc_adxl345.cpp | 91 +++++++++++++++
.../src/feature/accelerometer/acc_adxl345.h | 104 ++++++++++++++++++
ini/features.ini | 1 +
5 files changed, 207 insertions(+)
create mode 100644 Marlin/src/feature/accelerometer/acc_adxl345.cpp
create mode 100644 Marlin/src/feature/accelerometer/acc_adxl345.h
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 417bea4718d3..71c606cbb62b 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -1226,6 +1226,9 @@
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
#endif
+// @section accelerometer
+// Enable support for the ADXL345 accelerometer
+//#define HAS_ADXL345_ACCELEROMETER
// @section motion
#define AXIS_RELATIVE_MODES { false, false, false, false }
diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp
index 140423f25c76..cf9d839fbacd 100644
--- a/Marlin/src/MarlinCore.cpp
+++ b/Marlin/src/MarlinCore.cpp
@@ -34,6 +34,10 @@
#include "HAL/shared/esp_wifi.h"
#include "HAL/shared/cpu_exception/exception_hook.h"
+#if ENABLED(HAS_ADXL345_ACCELEROMETER)
+ #include "feature/accelerometer/acc_adxl345.h"
+#endif
+
#if ENABLED(WIFISUPPORT)
#include "HAL/shared/esp_wifi.h"
#endif
@@ -1236,6 +1240,10 @@ void setup() {
SETUP_RUN(hal.init());
+ #if ENABLED(HAS_ADXL345_ACCELEROMETER)
+ adxl345.begin();
+ #endif
+
// Init and disable SPI thermocouples; this is still needed
#if TEMP_SENSOR_IS_MAX_TC(0) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E0))
OUT_WRITE(TEMP_0_CS_PIN, HIGH); // Disable
diff --git a/Marlin/src/feature/accelerometer/acc_adxl345.cpp b/Marlin/src/feature/accelerometer/acc_adxl345.cpp
new file mode 100644
index 000000000000..c4de1326ac15
--- /dev/null
+++ b/Marlin/src/feature/accelerometer/acc_adxl345.cpp
@@ -0,0 +1,91 @@
+/***************************************************************
+ *
+ * ADXL345 3-AXIS ACCELEROMETER ON SPI BUS
+ * 4-WIRE SPI COMMUNICATION
+ * Define: SD_SS_PIN, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN
+ *
+ ****************************************************************/
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(HAS_ADXL345_ACCELEROMETER)
+
+#include "acc_ADXL345.h"
+
+#include "../../MarlinCore.h"
+#include "../../HAL/shared/Delay.h"
+
+#include "SPI.h"
+extern SPIClass SPI;
+
+ADXL345 adxl345;
+
+void ADXL345::begin() {
+ pinMode(SD_SS_PIN, OUTPUT); // set ADXL345 Chip Select pin to output mode
+ pinMode(SD_SS_PIN, HIGH); // set ADXL345 Chip Select to HIGH before configuratin SPI
+ spiBegin(); // sets Chip Select to HIGH (again)
+ spiInit(SPI_HALF_SPEED); // calls SPI.begin(), sets speed to 4MHz, max is 5MHz for ADXL345
+ SPI.setDataMode(SPI_MODE3); // ADXL345 uses SPI_MODE3 to communicate (CPOL=1, CPHA = 1)
+
+ // set range to 2g (4wire SPI, right justify data, 10-bit resolution)
+ writeRegister(ADXL345_DATA_FORMAT_REG, ADXL345_DATA_RANGE_2G);
+
+ // enable measurement mode, use streaming mode
+ writeRegister(ADXL345_POWER_CTL_REG, ADXL345_POWER_CTL_MEASURE | ADXL345_FIFO_CTL_MODE_STREAM);
+
+ // set to 100Hz sampling rate
+ writeRegister(ADXL345_RATE_REG, ADXL345_RATE_100HZ);
+}
+
+void ADXL345::end() { // put device in standby mode
+ writeRegister(ADXL345_POWER_CTL_REG, ADXL345_POWER_CTL_STANDBY);
+}
+
+void ADXL345::select(const bool select) {
+ WRITE(SD_SS_PIN, !select); // ADXL345 is selected on LOW
+}
+
+void ADXL345::writeRegister(uint8_t registerAddress, uint8_t data) {
+ digitalWrite(SD_SS_PIN, LOW); // set Chip Select to LOW to start the write
+ spiSend(registerAddress); // send the register address
+ spiSend(data); // send the data
+ digitalWrite(SD_SS_PIN, HIGH); // set Chip Select to HIGH to complete the write
+}
+
+void ADXL345::readRegister(uint8_t registerAddress, int numBytes, uint8_t * buffer) {
+ uint8_t address = registerAddress | 0x80; // set read bit
+ if (numBytes > 1)
+ address = address | 0x40; // also set multi-byte read if needed
+
+ digitalWrite(SD_SS_PIN, LOW); // set Chip Select to LOW to start the read
+ spiSend(address); // send the register address
+ for (int i = 0; i < numBytes; i++)
+ buffer[i] = spiRec(); // read the data
+ digitalWrite(SD_SS_PIN, HIGH); // set Chip Select to HIGH to complete the read
+ delayMicroseconds(5); // allow 5us for the FIFO/registers to update (see datasheet)
+}
+
+// get a acceleration measurement for the X, Y and Z axis
+void ADXL345::readMeasurementXYZ(ADXL345_measurementXYZ_t *acceleration) {
+ readRegister(ADXL345_DATA_X0_REG, 6, (uint8_t*)acceleration);
+}
+
+// get a acceleration measurement for the X axis
+void ADXL345::readMeasurementX(ADXL345_measurement_t *acceleration) {
+ readRegister(ADXL345_DATA_X0_REG, 2, (uint8_t*)acceleration);
+}
+
+// get a acceleration measurement for the Y axis
+void ADXL345::readMeasurementY(ADXL345_measurement_t *acceleration) {
+ readRegister(ADXL345_DATA_Y0_REG, 2, (uint8_t*)acceleration);
+}
+// get a acceleration measurement for the Z axis
+void ADXL345::readMeasurementZ(ADXL345_measurement_t *acceleration) {
+ readRegister(ADXL345_DATA_Z0_REG, 2, (uint8_t*)acceleration);
+}
+
+void ADXL345::setDataRate(uint8_t dataRate) { // 0->0.1Hz ... 15->3200Hz
+ writeRegister(ADXL345_DATA_FORMAT_REG, dataRate & 0xF);
+}
+
+#endif // HAS_ADXL345_ACCELEROMETER
\ No newline at end of file
diff --git a/Marlin/src/feature/accelerometer/acc_adxl345.h b/Marlin/src/feature/accelerometer/acc_adxl345.h
new file mode 100644
index 000000000000..666c27f623bb
--- /dev/null
+++ b/Marlin/src/feature/accelerometer/acc_adxl345.h
@@ -0,0 +1,104 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+// ADXL345 registers and defines
+#define ADXL345_DEV_ID_REG 0x00
+
+#define ADXL345_OFFSET_X_REG 0x1E // int8_t, 15.6mg/LSB (0x7F=2G)
+#define ADXL345_OFFSET_Y_REG 0x1F // int8_t, 15.6mg/LSB (0x7F=2G)
+#define ADXL345_OFFSET_Z_REG 0x20 // int8_t, 15.6mg/LSB (0x7F=2G)
+
+#define ADXL345_RATE_REG 0x2C // Sample rate register 0.1 - 3200Hz
+#define ADXL345_RATE_0_1HZ 0x0
+#define ADXL345_RATE_0_2HZ 0x1
+#define ADXL345_RATE_0_39HZ 0x2
+#define ADXL345_RATE_0_78HZ 0x3
+#define ADXL345_RATE_1_56HZ 0x4
+#define ADXL345_RATE_3_13HZ 0x5
+#define ADXL345_RATE_6_25HZ 0x6
+#define ADXL345_RATE_12_5HZ 0x7
+#define ADXL345_RATE_25HZ 0x8
+#define ADXL345_RATE_50HZ 0x9
+#define ADXL345_RATE_100HZ 0xA
+#define ADXL345_RATE_200HZ 0xB
+#define ADXL345_RATE_400HZ 0xC
+#define ADXL345_RATE_800HZ 0xD
+#define ADXL345_RATE_1600HZ 0xE
+#define ADXL345_RATE_3200HZ 0xF
+
+#define ADXL345_POWER_CTL_REG 0x2D // Power control register
+#define ADXL345_POWER_CTL_STANDBY 0x00
+#define ADXL345_POWER_CTL_MEASURE 0x08
+
+#define ADXL345_DATA_FORMAT_REG 0x31 // Data format register
+#define ADXL345_DATA_SELFTEST_BIT 0x80
+#define ADXL345_DATA_3WIRE_BIT 0x40
+#define ADXL345_DATA_FULLRES_BIT 0x08
+#define ADXL345_DATA_MSB_BIT 0x04
+#define ADXL345_DATA_RANGE_MASK 3
+#define ADXL345_DATA_RANGE_2G 0
+#define ADXL345_DATA_RANGE_4G 1
+#define ADXL345_DATA_RANGE_8G 2
+#define ADXL345_DATA_RANGE_16G 3
+
+#define ADXL345_DATA_X0_REG 0x32 // Measurement data registers
+#define ADXL345_DATA_X1_REG 0x33
+#define ADXL345_DATA_Y0_REG 0x34
+#define ADXL345_DATA_Y1_REG 0x35
+#define ADXL345_DATA_Z0_REG 0x36
+#define ADXL345_DATA_Z1_REG 0x37
+
+#define ADXL345_FIFO_CTL_REG 0x38 // FIFO control register
+#define ADXL345_FIFO_CTL_MODE_BYPASS 0x00
+#define ADXL345_FIFO_CTL_MODE_ENABLED 0x40
+#define ADXL345_FIFO_CTL_MODE_STREAM 0x80
+#define ADXL345_FIFO_CTL_MODE_TRIGGER 0xC0
+#define ADXL345_FIFO_CTL_SAMPLE_COUNT_MASK 0x1F
+
+#define ADXL345_FIFO_STATUS_REG 0x39 // FIFO status register
+#define ADXL345_FIFO_STATUS_ENTRIES_MASK 0x3F
+
+typedef int16_t ADXL345_measurement_t;
+
+struct ADXL345_measurementXYZ_t {
+ ADXL345_measurement_t x;
+ ADXL345_measurement_t y;
+ ADXL345_measurement_t z;
+};
+
+class ADXL345 {
+ public:
+ void begin();
+ void end();
+ void readMeasurementXYZ(ADXL345_measurementXYZ_t * acceleration);
+ void readMeasurementX(ADXL345_measurement_t * acceleration);
+ void readMeasurementY(ADXL345_measurement_t * acceleration);
+ void readMeasurementZ(ADXL345_measurement_t * acceleration);
+ void setDataRate(uint8_t dataRate); // 0->0.1Hz ... 15->3200Hz
+ void writeRegister(uint8_t registerAddress, uint8_t data);
+ void readRegister(uint8_t registerAddress, int numBytes, uint8_t * buffer);
+ private:
+ void select(const bool select);
+};
+
+extern ADXL345 adxl345;
\ No newline at end of file
diff --git a/ini/features.ini b/ini/features.ini
index b2e9d6884e75..4d6ad7b55641 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -12,6 +12,7 @@
# The order of the features matters for source-filter resolution inside of common-dependencies.py.
[features]
+HAS_ADXL345_ACCELEROMETER = build_src_filter=+
YHCB2004 = LiquidCrystal_AIP31068=https://github.com/ellensp/LiquidCrystal_AIP31068/archive/3fc43b7.zip, red-scorp/SoftSPIB@^1.1.1
HAS_TFT_LVGL_UI = lvgl=https://github.com/makerbase-mks/LVGL-6.1.1-MKS/archive/a3ebe98bc6.zip
build_src_filter=+