Skip to content
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
167 changes: 167 additions & 0 deletions NAU7802/NAU7802.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/**
********************************************************************************
* @file nau7802.cpp
* @author Javier
* @date 2025-11-25
* @brief Implementation of the NAU7802 driver.
********************************************************************************
*/

#include "NAU7802.hpp"
#include "main.h"
#include <cstdint>

NAU7802::NAU7802(I2C_Wrapper* i2c_pointer, std::uint8_t address)
: _i2c(i2c_pointer), _deviceAddress(address) {}

// Begin NAU7802 Startup Sequence
NauStatus NAU7802::begin(uint8_t initialGain) {

// 1. Send a reset command
if (reset() != NauStatus::OK) {
return NauStatus::ERR_I2C; // Failed to reset
}
HAL_Delay(10);

// 2. Power up the analog and digital sections
uint8_t pu_ctrl = NAU7802_PU_CTRL_PUA | NAU7802_PU_CTRL_PUD;
writeRegister(NAU7802_REG_PU_CTRL, pu_ctrl);

// 3. Wait for the Power Up Ready bit
uint8_t attempts = 100;
bool powerReady = false;
while (attempts > 0) {
if (readRegister(NAU7802_REG_PU_CTRL, &pu_ctrl) == NauStatus::OK) {
if (pu_ctrl & NAU7802_PU_CTRL_PUR) {
powerReady = true;
break;
}
}
HAL_Delay(1);
attempts--;
}
return setGain(initialGain);
}

bool NAU7802::isReady() {
uint8_t status;
if (readRegister(NAU7802_REG_PU_CTRL, &status) == NauStatus::OK) {
return (status & NAU7802_PU_CTRL_CR) != 0;
}
return false;
}

NauStatus NAU7802::readSensor(NAU7802_OUT *dest) {
uint8_t buffer[3];

if (readRegisters(NAU7802_REG_ADC_B2, buffer, 3 ) != NauStatus::OK) {
dest -> raw_reading = 0;
return NauStatus::ERR_I2C; // Read failed
}

// Combine the three bytes
int32_t value = ((int32_t)buffer[0] << 16) | \
((int32_t)buffer[1] << 8) | \
(buffer[2]);

// Sign-extend the 24-bit value to a 32-bit integer
if (value & 0x00800000) {
value |= 0xFF000000;
}

dest->raw_reading = value;
return NauStatus::OK;
}

NauStatus NAU7802::reset() {
// RR bit
modifyRegisterBit(NAU7802_REG_PU_CTRL, NAU7802_PU_CTRL_RR, true);

HAL_Delay(1); // Small delay to ensure reset is processed

// Clear RR bit
return modifyRegisterBit(NAU7802_REG_PU_CTRL, NAU7802_PU_CTRL_RR, false);
}

NauStatus NAU7802::setGain(uint8_t gain) {
if (gain > NAU7802_GAIN_128X) {
return NauStatus::ERR_INVALID_ARG; // Invalid gain setting
}

// Read current CTRL1 register state
uint8_t ctrl1;
if (readRegister(NAU7802_REG_CTRL1, &ctrl1) != NauStatus::OK) {
return NauStatus::ERR_I2C; // Failed to read CTRL1 register
}

// Modify gain bits
ctrl1 &= 0b11111000; // Clear existing gain
ctrl1 |= gain; // Set new gain

// Write back modified CTRL1 register
if (writeRegister(NAU7802_REG_CTRL1, ctrl1) != NauStatus::OK) {
return NauStatus::ERR_I2C; // Failed to write CTRL1 register
}

// Verify the gain setting
uint8_t verifyCtrl1;
if (readRegister(NAU7802_REG_CTRL1, &verifyCtrl1) != NauStatus::OK) {
return NauStatus::ERR_I2C; // Failed to read back CTRL1 register
}

// Check if gain bits match
if ((verifyCtrl1 & 0b00000111) == gain) {
return NauStatus::OK; // Success
}
else {
return NauStatus::ERR_I2C; // Verification failed
}
}

/* -- Private Helpers -- */
NauStatus NAU7802::writeRegister(std::uint8_t reg, std::uint8_t value) {
if (_i2c->writeByte(_deviceAddress, reg, value)) {
return NauStatus::OK;
}
return NauStatus::ERR_I2C;
}

NauStatus NAU7802::readRegister(std::uint8_t reg, std::uint8_t* value) {
if (_i2c->readByte(_deviceAddress, reg, value)) {
return NauStatus::OK;
}
return NauStatus::ERR_I2C;
}

NauStatus NAU7802::readRegisters(std::uint8_t reg, std::uint8_t* buffer, std::uint8_t len) {
if (_i2c->readBytes(_deviceAddress, reg, buffer, len)) {
return NauStatus::OK;
}
return NauStatus::ERR_I2C;
}

NauStatus NAU7802::modifyRegisterBit(std::uint8_t reg, std::uint8_t bitMask, bool state) {
uint8_t val;

// 1. Check Read Status
NauStatus status = readRegister(reg, &val);
if (status != NauStatus::OK) {
return status; // Propagate error
}

// 2. Modify
if (state) {
val |= bitMask;
} else {
val &= ~bitMask;
}

// 3. Return Write Status
return writeRegister(reg, val);
}

NauStatus NAU7802::calibrate() {
// TODO: Implement calibration logic based on datasheet
// Usually involves setting CALS bit in REG0x02
return modifyRegisterBit(NAU7802_REG_CTRL2, NAU7802_CTRL2_CALS, true);
}
101 changes: 101 additions & 0 deletions NAU7802/NAU7802.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
********************************************************************************
* @file NAU7802.hpp
* @author Javier
* @date 2025-11-25
* @brief Header for the NAU7802 24-bit ADC Driver.
********************************************************************************
*/

#ifndef NAU7802_HPP
#define NAU7802_HPP

/************************************
* INCLUDES
************************************/
#include <cstdint>
#include "i2c_wrapper.hpp"
#include "NAU7802_regs.hpp"

/**
* @brief Output data structure for the NAU7802.
*/
typedef struct NAU7802_OUTPUT {
std::int32_t raw_reading;
} NAU7802_OUT;

/************************************
* CLASS DEFINITIONS
************************************/
// New Status Enum
enum class NauStatus : uint8_t {
OK = 0,
ERR_I2C,
ERR_TIMEOUT,
ERR_NOT_READY,
ERR_INVALID_ARG
};


class NAU7802 {
public:
/**
* @brief Constructs the NAU7802 Driver.
* @param configs Configuration settings for the sensor.
* @param i2c_pointer I2C Wrapper for communication.
*/
NAU7802(I2C_Wrapper* i2c_pointer, std::uint8_t address = NAU7802_I2C_ADDRESS);



/**
* @brief Initializes the sensor, resets and waits for power up ready.
* @return true if sensor detected and powered up, false otherwise.
*/
NauStatus begin(uint8_t initialGain = NAU7802_GAIN_1X);

/**
* @brief Checks the Cycle Ready (CR) bit.
* @return true if new data is available.
*/
bool isReady();

/**
* @brief Reads the 24-bit signed ADC value.
* @param dest Pointer to the output struct.
* @return true if read was successful.
*/
NauStatus readSensor(NAU7802_OUT *dest);

/**
* @brief Performs a software reset of the device.
*/
NauStatus reset();

/**
* @brief Sets the Programmable Gain Amplifier (PGA) setting.
* @param gain One of NAU7802_GAIN_xxx constants.
* @return true if write successful.
*/
NauStatus setGain(std::uint8_t gain);

/**
* @brief Calibrates the internal offsets (Optional usage).
*/
NauStatus calibrate();

private:

// Private Helpers
NauStatus writeRegister(std::uint8_t reg, std::uint8_t value);
NauStatus readRegister(std::uint8_t reg, std::uint8_t* value);
NauStatus readRegisters(std::uint8_t reg, std::uint8_t* buffer, std::uint8_t len);
NauStatus modifyRegisterBit(std::uint8_t reg, std::uint8_t bitMask, bool state);

// Member Variables
I2C_Wrapper* _i2c;
std::uint8_t _deviceAddress;

};

#endif /* NAU7802_HPP */
Loading