Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the adxl345 accelerometer for the BTT EBB42 V1.2 toolhead #27635

Open
wants to merge 2 commits into
base: bugfix-2.1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,13 @@
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
#endif

// @section accelerometer

/**
* Enable support for the ADXL345 accelerometer over SPI
*/
//#define ACCELEROMETER_ADXL345

// @section motion

#define AXIS_RELATIVE_MODES { false, false, false, false }
Expand Down
9 changes: 9 additions & 0 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
#include "HAL/shared/esp_wifi.h"
#include "HAL/shared/cpu_exception/exception_hook.h"

#if ENABLED(ACCELEROMETER_ADXL345)
#include "feature/accelerometer/acc_adxl345.h"
#endif

#if ENABLED(WIFISUPPORT)
#include "HAL/shared/esp_wifi.h"
#endif
Expand Down Expand Up @@ -1236,6 +1240,11 @@ void setup() {

SETUP_RUN(hal.init());

// Accelerometer quick initialization
#if ENABLED(ACCELEROMETER_ADXL345)
SETUP_RUN(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
Expand Down
113 changes: 113 additions & 0 deletions Marlin/src/feature/accelerometer/acc_adxl345.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*
*/

/***************************************************************
*
* 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(ACCELEROMETER_ADXL345)

#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 an 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 an acceleration measurement for the X axis
void ADXL345::readMeasurementX(ADXL345_measurement_t *acceleration) {
readRegister(ADXL345_DATA_X0_REG, 2, (uint8_t*)acceleration);
}

// get an acceleration measurement for the Y axis
void ADXL345::readMeasurementY(ADXL345_measurement_t *acceleration) {
readRegister(ADXL345_DATA_Y0_REG, 2, (uint8_t*)acceleration);
}
// get an 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 // ACCELEROMETER_ADXL345
104 changes: 104 additions & 0 deletions Marlin/src/feature/accelerometer/acc_adxl345.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*
*/
#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;
1 change: 1 addition & 0 deletions ini/features.ini
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ BACKLASH_COMPENSATION = build_src_filter=+<src/feature/backlash
BARICUDA = build_src_filter=+<src/feature/baricuda.cpp> +<src/gcode/feature/baricuda>
BINARY_FILE_TRANSFER = build_src_filter=+<src/feature/binary_stream.cpp> +<src/libs/heatshrink>
BLTOUCH = build_src_filter=+<src/feature/bltouch.cpp>
ACCELEROMETER_ADXL345 = build_src_filter=+<src/feature/accelerometer/acc_adxl345.cpp>
CANCEL_OBJECTS = build_src_filter=+<src/feature/cancel_object.cpp> +<src/gcode/feature/cancel>
CASE_LIGHT_ENABLE = build_src_filter=+<src/feature/caselight.cpp> +<src/gcode/feature/caselight>
EXTERNAL_CLOSED_LOOP_CONTROLLER = build_src_filter=+<src/feature/closedloop.cpp> +<src/gcode/calibrate/M12.cpp>
Expand Down