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=+