Skip to content

Commit

Permalink
Added basic support for the ADXL345 3-axis accelerometer
Browse files Browse the repository at this point in the history
WIP!
  • Loading branch information
rondlh committed Dec 13, 2024
1 parent 45ebd12 commit 8d49354
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 14 deletions.
6 changes: 6 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3496,6 +3496,12 @@

#endif // HAS_TRINAMIC_CONFIG

// @section spibus

// This feature is EXPERIMENTAL
// Warning: Enabling the sensor will probably conflict with the onboard SD Card
//#define HAS_ADXL345_ACCELEROMETER; // uncomment to enable the 3-axis accelerometer

// @section i2cbus

//
Expand Down
35 changes: 21 additions & 14 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
#include "HAL/shared/FDCAN.h"
#endif

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

#if ENABLED(WIFISUPPORT)
#include "HAL/shared/esp_wifi.h"
#endif
Expand Down Expand Up @@ -1210,20 +1214,6 @@ void setup() {
#endif
SERIAL_ECHOLNPGM("start\n");

#if ENABLED(CAN_MASTER)
SERIAL_ECHOLN(
F(">>> CAN1 Start: "),
CAN1_Start() == HAL_OK ? F("OK") : F("FAILED!")
);
#endif

#if ENABLED(CAN_TOOLHEAD)
SERIAL_ECHOLN(
F(">>> FDCAN2 Start: "),
FDCAN2_Start() == HAL_OK ? F("OK") : F("FAILED!")
);
#endif

// Set up these pins early to prevent suicide
#if HAS_KILL
SETUP_LOG("KILL_PIN");
Expand Down Expand Up @@ -1268,6 +1258,23 @@ void setup() {

SETUP_RUN(hal.init());

#if ENABLED(CAN_MASTER)
SERIAL_ECHOLN(
F(">>> CAN1 Start: "),
CAN1_Start() == HAL_OK ? F("OK") : F("FAILED!")
);
#endif

#if ENABLED(CAN_TOOLHEAD)
SERIAL_ECHOLN(
F(">>> FDCAN2 Start: "),
FDCAN2_Start() == HAL_OK ? F("OK") : F("FAILED!")
);
#endif
#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
Expand Down
73 changes: 73 additions & 0 deletions Marlin/src/feature/accelerometer/acc_adxl345.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/***************************************************************
*
* 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::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 accleration measurement for the X, Y and Z axis
void ADXL345::readMeasurement(ADXL345_measurement_t *acceleration) {
readRegister(ADXL345_DATA_X0_REG, 6, (uint8_t*)acceleration);
}

void ADXL345::select(const bool select) {
WRITE(SD_SS_PIN, !select); // ADXL345 is selected on LOW
}

#endif // HAS_ADXL345_ACCELEROMETER
98 changes: 98 additions & 0 deletions Marlin/src/feature/accelerometer/acc_adxl345.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* 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 <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

struct ADXL345_measurement_t {
int16_t x;
int16_t y;
int16_t z;
};

class ADXL345 {
public:
void begin();
void end();
void readMeasurement(ADXL345_measurement_t * acceleration);
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 @@ -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=+<src/feature/accelerometer/acc_adxl345.cpp>
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=+<src/lcd/extui/mks_ui>
Expand Down

0 comments on commit 8d49354

Please sign in to comment.