Skip to content

Pico-sdk library test #15

Open
Open
@lavara123

Description

@lavara123

Header

// nau7802.h
#ifndef NAU7802_H
#define NAU7802_H

#include "pico/stdlib.h"
#include "hardware/i2c.h"

// Register Map
#define NAU7802_PU_CTRL        0x00
#define NAU7802_CTRL1          0x01
#define NAU7802_CTRL2          0x02
#define NAU7802_OCAL1_B2       0x03
#define NAU7802_OCAL1_B1       0x04
#define NAU7802_OCAL1_B0       0x05
#define NAU7802_GCAL1_B3       0x06
#define NAU7802_GCAL1_B2       0x07
#define NAU7802_GCAL1_B1       0x08
#define NAU7802_GCAL1_B0       0x09
#define NAU7802_OCAL2_B2       0x0A
#define NAU7802_OCAL2_B1       0x0B
#define NAU7802_OCAL2_B0       0x0C
#define NAU7802_GCAL2_B3       0x0D
#define NAU7802_GCAL2_B2       0x0E
#define NAU7802_GCAL2_B1       0x0F
#define NAU7802_GCAL2_B0       0x10
#define NAU7802_I2C_CONTROL    0x11
#define NAU7802_ADCO_B2        0x12
#define NAU7802_ADCO_B1        0x13
#define NAU7802_ADCO_B0        0x14
#define NAU7802_ADC            0x15
#define NAU7802_OTP_B1         0x16
#define NAU7802_OTP_B0         0x17
#define NAU7802_PGA            0x1B
#define NAU7802_PGA_PWR        0x1C
#define NAU7802_DEVICE_REV     0x1F

// PU_CTRL Bits
#define NAU7802_PU_CTRL_RR     0
#define NAU7802_PU_CTRL_PUD    1
#define NAU7802_PU_CTRL_PUA    2
#define NAU7802_PU_CTRL_PUR    3
#define NAU7802_PU_CTRL_CS     4
#define NAU7802_PU_CTRL_CR     5
#define NAU7802_PU_CTRL_OSCS   6
#define NAU7802_PU_CTRL_AVDDS  7

// CTRL1 Bits
#define NAU7802_CTRL1_GAIN     2
#define NAU7802_CTRL1_VLDO     5
#define NAU7802_CTRL1_DRDY_SEL 6
#define NAU7802_CTRL1_CRP      7

// CTRL2 Bits
#define NAU7802_CTRL2_CALMOD   0
#define NAU7802_CTRL2_CALS     2
#define NAU7802_CTRL2_CAL_ERROR 3
#define NAU7802_CTRL2_CRS      4
#define NAU7802_CTRL2_CHS      7

// PGA Bits
#define NAU7802_PGA_CHP_DIS    0
#define NAU7802_PGA_INV        3
#define NAU7802_PGA_BYPASS_EN  4
#define NAU7802_PGA_OUT_EN     5
#define NAU7802_PGA_LDOMODE    6
#define NAU7802_PGA_RD_OTP_SEL 7

// PGA PWR Bits
#define NAU7802_PGA_PWR_PGA_CURR 0
#define NAU7802_PGA_PWR_ADC_CURR 2
#define NAU7802_PGA_PWR_MSTR_BIAS_CURR 4
#define NAU7802_PGA_PWR_PGA_CAP_EN 7

// LDO Values
#define NAU7802_LDO_2V4        0b111
#define NAU7802_LDO_2V7        0b110
#define NAU7802_LDO_3V0        0b101
#define NAU7802_LDO_3V3        0b100
#define NAU7802_LDO_3V6        0b011
#define NAU7802_LDO_3V9        0b010
#define NAU7802_LDO_4V2        0b001
#define NAU7802_LDO_4V5        0b000

// Gain Values
#define NAU7802_GAIN_128       0b111
#define NAU7802_GAIN_64        0b110
#define NAU7802_GAIN_32        0b101
#define NAU7802_GAIN_16        0b100
#define NAU7802_GAIN_8         0b011
#define NAU7802_GAIN_4         0b010
#define NAU7802_GAIN_2         0b001
#define NAU7802_GAIN_1         0b000

// Samples per second
#define NAU7802_SPS_320        0b111
#define NAU7802_SPS_80         0b011
#define NAU7802_SPS_40         0b010
#define NAU7802_SPS_20         0b001
#define NAU7802_SPS_10         0b000

// Channels
#define NAU7802_CHANNEL_1      0
#define NAU7802_CHANNEL_2      1

// Calibration Status
#define NAU7802_CAL_SUCCESS    0
#define NAU7802_CAL_IN_PROGRESS 1
#define NAU7802_CAL_FAILURE    2

// Calibration Mode
#define NAU7802_CALMOD_INTERNAL 0
#define NAU7802_CALMOD_OFFSET  2
#define NAU7802_CALMOD_GAIN    3

typedef struct {
    i2c_inst_t* i2c;
    uint8_t address;
    int32_t zero_offset;
    float calibration_factor;
    uint32_t ldo_ramp_delay;
} NAU7802;

// Function prototypes
void nau7802_init(NAU7802* dev, i2c_inst_t* i2c, uint8_t address);
bool nau7802_begin(NAU7802* dev, bool initialize);
bool nau7802_is_connected(NAU7802* dev);
bool nau7802_available(NAU7802* dev);
int32_t nau7802_get_reading(NAU7802* dev);
int32_t nau7802_get_average(NAU7802* dev, uint8_t average_amount, uint32_t timeout_ms);
void nau7802_calculate_zero_offset(NAU7802* dev, uint8_t average_amount, uint32_t timeout_ms);
void nau7802_set_zero_offset(NAU7802* dev, int32_t new_zero_offset);
int32_t nau7802_get_zero_offset(NAU7802* dev);
void nau7802_calculate_calibration_factor(NAU7802* dev, float weight_on_scale, uint8_t average_amount, uint32_t timeout_ms);
void nau7802_set_calibration_factor(NAU7802* dev, float new_cal_factor);
float nau7802_get_calibration_factor(NAU7802* dev);
float nau7802_get_weight(NAU7802* dev, bool allow_negative_weights, uint8_t samples_to_take, uint32_t timeout_ms);
bool nau7802_set_gain(NAU7802* dev, uint8_t gain_value);
bool nau7802_set_ldo(NAU7802* dev, uint8_t ldo_value);
void nau7802_set_ldo_ramp_delay(NAU7802* dev, uint32_t delay);
uint32_t nau7802_get_ldo_ramp_delay(NAU7802* dev);
bool nau7802_set_sample_rate(NAU7802* dev, uint8_t rate);
bool nau7802_set_channel(NAU7802* dev, uint8_t channel_number);
bool nau7802_calibrate_afe(NAU7802* dev, uint8_t mode);
void nau7802_begin_calibrate_afe(NAU7802* dev, uint8_t mode);
bool nau7802_wait_for_calibrate_afe(NAU7802* dev, uint32_t timeout_ms);
uint8_t nau7802_cal_afe_status(NAU7802* dev);
bool nau7802_reset(NAU7802* dev);
bool nau7802_power_up(NAU7802* dev);
bool nau7802_power_down(NAU7802* dev);
bool nau7802_set_int_polarity_high(NAU7802* dev);
bool nau7802_set_int_polarity_low(NAU7802* dev);
uint8_t nau7802_get_revision_code(NAU7802* dev);
bool nau7802_set_bit(NAU7802* dev, uint8_t bit_number, uint8_t register_address);
bool nau7802_clear_bit(NAU7802* dev, uint8_t bit_number, uint8_t register_address);
bool nau7802_get_bit(NAU7802* dev, uint8_t bit_number, uint8_t register_address);
uint8_t nau7802_get_register(NAU7802* dev, uint8_t register_address);
bool nau7802_set_register(NAU7802* dev, uint8_t register_address, uint8_t value);
int32_t nau7802_get_24bit_register(NAU7802* dev, uint8_t register_address);
bool nau7802_set_24bit_register(NAU7802* dev, uint8_t register_address, int32_t value);
uint32_t nau7802_get_32bit_register(NAU7802* dev, uint8_t register_address);
bool nau7802_set_32bit_register(NAU7802* dev, uint8_t register_address, uint32_t value);
int32_t nau7802_get_channel1_offset(NAU7802* dev);
bool nau7802_set_channel1_offset(NAU7802* dev, int32_t value);
uint32_t nau7802_get_channel1_gain(NAU7802* dev);
bool nau7802_set_channel1_gain(NAU7802* dev, uint32_t value);

#endif // NAU7802_H

Source

// nau7802.c
#include "nau7802.h"
#include <string.h>

void nau7802_init(NAU7802* dev, i2c_inst_t* i2c, uint8_t address) {
    dev->i2c = i2c;
    dev->address = address;
    dev->zero_offset = 0;
    dev->calibration_factor = 1.0f;
    dev->ldo_ramp_delay = 250;
}

bool nau7802_begin(NAU7802* dev, bool initialize) {
    // Check if the device ack's over I2C
    if (!nau7802_is_connected(dev)) {
        // Try one more time
        if (!nau7802_is_connected(dev)) {
            return false;
        }
    }

    bool result = true;

    if (initialize) {
        result &= nau7802_reset(dev);
        result &= nau7802_power_up(dev);
        result &= nau7802_set_ldo(dev, NAU7802_LDO_3V3);
        result &= nau7802_set_gain(dev, NAU7802_GAIN_128);
        result &= nau7802_set_sample_rate(dev, NAU7802_SPS_80);

        // Turn off CLK_CHP
        uint8_t adc = nau7802_get_register(dev, NAU7802_ADC);
        adc |= 0x30;
        result &= nau7802_set_register(dev, NAU7802_ADC, adc);

        result &= nau7802_set_bit(dev, NAU7802_PGA_PWR_PGA_CAP_EN, NAU7802_PGA_PWR);
        result &= nau7802_clear_bit(dev, NAU7802_PGA_LDOMODE, NAU7802_PGA);

        sleep_ms(dev->ldo_ramp_delay);
        nau7802_get_weight(dev, true, 10, 1000);
        result &= nau7802_calibrate_afe(dev, NAU7802_CALMOD_INTERNAL);
    }

    return result;
}

bool nau7802_is_connected(NAU7802* dev) {
    uint8_t dummy;
    int ret = i2c_read_blocking(dev->i2c, dev->address, &dummy, 1, false);
    return ret != PICO_ERROR_GENERIC;
}

bool nau7802_available(NAU7802* dev) {
    return nau7802_get_bit(dev, NAU7802_PU_CTRL_CR, NAU7802_PU_CTRL);
}

bool nau7802_calibrate_afe(NAU7802* dev, uint8_t mode) {
    nau7802_begin_calibrate_afe(dev, mode);
    return nau7802_wait_for_calibrate_afe(dev, 1000);
}

void nau7802_begin_calibrate_afe(NAU7802* dev, uint8_t mode) {
    uint8_t value = nau7802_get_register(dev, NAU7802_CTRL2);
    value &= 0xFC; // Clear CALMOD bits
    uint8_t cal_mode = mode & 0x03; // Limit mode to 2 bits
    value |= cal_mode; // Set the mode
    nau7802_set_register(dev, NAU7802_CTRL2, value);
    nau7802_set_bit(dev, NAU7802_CTRL2_CALS, NAU7802_CTRL2);
}

uint8_t nau7802_cal_afe_status(NAU7802* dev) {
    if (nau7802_get_bit(dev, NAU7802_CTRL2_CALS, NAU7802_CTRL2)) {
        return NAU7802_CAL_IN_PROGRESS;
    }

    if (nau7802_get_bit(dev, NAU7802_CTRL2_CAL_ERROR, NAU7802_CTRL2)) {
        return NAU7802_CAL_FAILURE;
    }

    return NAU7802_CAL_SUCCESS;
}

bool nau7802_wait_for_calibrate_afe(NAU7802* dev, uint32_t timeout_ms) {
    uint32_t start_time = to_ms_since_boot(get_absolute_time());
    uint8_t cal_ready;

    while ((cal_ready = nau7802_cal_afe_status(dev)) == NAU7802_CAL_IN_PROGRESS) {
        if (timeout_ms > 0 && (to_ms_since_boot(get_absolute_time()) - start_time > timeout_ms) {
            break;
        }
        sleep_ms(1);
    }

    return cal_ready == NAU7802_CAL_SUCCESS;
}

bool nau7802_set_sample_rate(NAU7802* dev, uint8_t rate) {
    if (rate > 0b111) rate = 0b111;

    uint8_t value = nau7802_get_register(dev, NAU7802_CTRL2);
    value &= 0b10001111; // Clear CRS bits
    value |= rate << 4;  // Mask in new CRS bits

    return nau7802_set_register(dev, NAU7802_CTRL2, value);
}

bool nau7802_set_channel(NAU7802* dev, uint8_t channel_number) {
    if (channel_number == NAU7802_CHANNEL_1) {
        return nau7802_clear_bit(dev, NAU7802_CTRL2_CHS, NAU7802_CTRL2);
    } else {
        return nau7802_set_bit(dev, NAU7802_CTRL2_CHS, NAU7802_CTRL2);
    }
}

bool nau7802_power_up(NAU7802* dev) {
    nau7802_set_bit(dev, NAU7802_PU_CTRL_PUD, NAU7802_PU_CTRL);
    nau7802_set_bit(dev, NAU7802_PU_CTRL_PUA, NAU7802_PU_CTRL);

    // Wait for Power Up bit to be set
    uint8_t counter = 0;
    while (true) {
        if (nau7802_get_bit(dev, NAU7802_PU_CTRL_PUR, NAU7802_PU_CTRL)) {
            break;
        }
        sleep_ms(1);
        if (counter++ > 100) {
            return false;
        }
    }
    return nau7802_set_bit(dev, NAU7802_PU_CTRL_CS, NAU7802_PU_CTRL);
}

bool nau7802_power_down(NAU7802* dev) {
    nau7802_clear_bit(dev, NAU7802_PU_CTRL_PUD, NAU7802_PU_CTRL);
    return nau7802_clear_bit(dev, NAU7802_PU_CTRL_PUA, NAU7802_PU_CTRL);
}

bool nau7802_reset(NAU7802* dev) {
    nau7802_set_bit(dev, NAU7802_PU_CTRL_RR, NAU7802_PU_CTRL);
    sleep_ms(1);
    return nau7802_clear_bit(dev, NAU7802_PU_CTRL_RR, NAU7802_PU_CTRL);
}

bool nau7802_set_ldo(NAU7802* dev, uint8_t ldo_value) {
    if (ldo_value > 0b111) ldo_value = 0b111;

    uint8_t value = nau7802_get_register(dev, NAU7802_CTRL1);
    value &= 0b11000111;    // Clear LDO bits
    value |= ldo_value << 3; // Mask in new LDO bits
    nau7802_set_register(dev, NAU7802_CTRL1, value);

    return nau7802_set_bit(dev, NAU7802_PU_CTRL_AVDDS, NAU7802_PU_CTRL);
}

void nau7802_set_ldo_ramp_delay(NAU7802* dev, uint32_t delay) {
    dev->ldo_ramp_delay = delay;
}

uint32_t nau7802_get_ldo_ramp_delay(NAU7802* dev) {
    return dev->ldo_ramp_delay;
}

bool nau7802_set_gain(NAU7802* dev, uint8_t gain_value) {
    if (gain_value > 0b111) gain_value = 0b111;

    uint8_t value = nau7802_get_register(dev, NAU7802_CTRL1);
    value &= 0b11111000; // Clear gain bits
    value |= gain_value; // Mask in new bits

    return nau7802_set_register(dev, NAU7802_CTRL1, value);
}

uint8_t nau7802_get_revision_code(NAU7802* dev) {
    uint8_t revision_code = nau7802_get_register(dev, NAU7802_DEVICE_REV);
    return revision_code & 0x0F;
}

int32_t nau7802_get_reading(NAU7802* dev) {
    return nau7802_get_24bit_register(dev, NAU7802_ADCO_B2);
}

int32_t nau7802_get_average(NAU7802* dev, uint8_t average_amount, uint32_t timeout_ms) {
    int32_t total = 0;
    uint8_t samples_acquired = 0;

    uint32_t start_time = to_ms_since_boot(get_absolute_time());
    while (true) {
        if (nau7802_available(dev)) {
            total += nau7802_get_reading(dev);
            if (++samples_acquired == average_amount) {
                break;
            }
        }
        if (to_ms_since_boot(get_absolute_time()) - start_time > timeout_ms) {
            return 0;
        }
        sleep_ms(1);
    }
    total /= average_amount;

    return total;
}

void nau7802_calculate_zero_offset(NAU7802* dev, uint8_t average_amount, uint32_t timeout_ms) {
    nau7802_set_zero_offset(dev, nau7802_get_average(dev, average_amount, timeout_ms));
}

void nau7802_set_zero_offset(NAU7802* dev, int32_t new_zero_offset) {
    dev->zero_offset = new_zero_offset;
}

int32_t nau7802_get_zero_offset(NAU7802* dev) {
    return dev->zero_offset;
}

void nau7802_calculate_calibration_factor(NAU7802* dev, float weight_on_scale, uint8_t average_amount, uint32_t timeout_ms) {
    int32_t on_scale = nau7802_get_average(dev, average_amount, timeout_ms);
    float new_cal_factor = ((float)(on_scale - dev->zero_offset)) / weight_on_scale;
    nau7802_set_calibration_factor(dev, new_cal_factor);
}

void nau7802_set_calibration_factor(NAU7802* dev, float new_cal_factor) {
    dev->calibration_factor = new_cal_factor;
}

float nau7802_get_calibration_factor(NAU7802* dev) {
    return dev->calibration_factor;
}

float nau7802_get_weight(NAU7802* dev, bool allow_negative_weights, uint8_t samples_to_take, uint32_t timeout_ms) {
    int32_t on_scale = nau7802_get_average(dev, samples_to_take, timeout_ms);

    if (!allow_negative_weights) {
        if (on_scale < dev->zero_offset) {
            on_scale = dev->zero_offset;
        }
    }

    float weight = ((float)(on_scale - dev->zero_offset)) / dev->calibration_factor;
    return weight;
}

bool nau7802_set_int_polarity_high(NAU7802* dev) {
    return nau7802_clear_bit(dev, NAU7802_CTRL1_CRP, NAU7802_CTRL1);
}

bool nau7802_set_int_polarity_low(NAU7802* dev) {
    return nau7802_set_bit(dev, NAU7802_CTRL1_CRP, NAU7802_CTRL1);
}

bool nau7802_set_bit(NAU7802* dev, uint8_t bit_number, uint8_t register_address) {
    uint8_t value = nau7802_get_register(dev, register_address);
    value |= (1 << bit_number);
    return nau7802_set_register(dev, register_address, value);
}

bool nau7802_clear_bit(NAU7802* dev, uint8_t bit_number, uint8_t register_address) {
    uint8_t value = nau7802_get_register(dev, register_address);
    value &= ~(1 << bit_number);
    return nau7802_set_register(dev, register_address, value);
}

bool nau7802_get_bit(NAU7802* dev, uint8_t bit_number, uint8_t register_address) {
    uint8_t value = nau7802_get_register(dev, register_address);
    value &= (1 << bit_number);
    return value;
}

uint8_t nau7802_get_register(NAU7802* dev, uint8_t register_address) {
    uint8_t value;
    i2c_write_blocking(dev->i2c, dev->address, &register_address, 1, true);
    i2c_read_blocking(dev->i2c, dev->address, &value, 1, false);
    return value;
}

bool nau7802_set_register(NAU7802* dev, uint8_t register_address, uint8_t value) {
    uint8_t data[2] = {register_address, value};
    return i2c_write_blocking(dev->i2c, dev->address, data, 2, false) == 2;
}

int32_t nau7802_get_24bit_register(NAU7802* dev, uint8_t register_address) {
    uint8_t data[3];
    i2c_write_blocking(dev->i2c, dev->address, &register_address, 1, true);
    i2c_read_blocking(dev->i2c, dev->address, data, 3, false);

    union {
        uint32_t unsigned32;
        int32_t signed32;
    } result;

    result.unsigned32 = (uint32_t)data[0] << 16;
    result.unsigned32 |= (uint32_t)data[1] << 8;
    result.unsigned32 |= (uint32_t)data[2];

    if ((result.unsigned32 & 0x00800000) == 0x00800000) {
        result.unsigned32 |= 0xFF000000;
    }

    return result.signed32;
}

bool nau7802_set_24bit_register(NAU7802* dev, uint8_t register_address, int32_t value) {
    union {
        uint32_t unsigned32;
        int32_t signed32;
    } data;

    data.signed32 = value;

    uint8_t buffer[4] = {
        register_address,
        (uint8_t)((data.unsigned32 >> 16) & 0xFF),
        (uint8_t)((data.unsigned32 >> 8) & 0xFF),
        (uint8_t)(data.unsigned32 & 0xFF)
    };

    return i2c_write_blocking(dev->i2c, dev->address, buffer, 4, false) == 4;
}

uint32_t nau7802_get_32bit_register(NAU7802* dev, uint8_t register_address) {
    uint8_t data[4];
    i2c_write_blocking(dev->i2c, dev->address, &register_address, 1, true);
    i2c_read_blocking(dev->i2c, dev->address, data, 4, false);

    uint32_t result = (uint32_t)data[0] << 24;
    result |= (uint32_t)data[1] << 16;
    result |= (uint32_t)data[2] << 8;
    result |= (uint32_t)data[3];

    return result;
}

bool nau7802_set_32bit_register(NAU7802* dev, uint8_t register_address, uint32_t value) {
    uint8_t buffer[5] = {
        register_address,
        (uint8_t)((value >> 24) & 0xFF),
        (uint8_t)((value >> 16) & 0xFF),
        (uint8_t)((value >> 8) & 0xFF),
        (uint8_t)(value & 0xFF)
    };

    return i2c_write_blocking(dev->i2c, dev->address, buffer, 5, false) == 5;
}

int32_t nau7802_get_channel1_offset(NAU7802* dev) {
    return nau7802_get_24bit_register(dev, NAU7802_OCAL1_B2);
}

bool nau7802_set_channel1_offset(NAU7802* dev, int32_t value) {
    return nau7802_set_24bit_register(dev, NAU7802_OCAL1_B2, value);
}

uint32_t nau7802_get_channel1_gain(NAU7802* dev) {
    return nau7802_get_32bit_register(dev, NAU7802_GCAL1_B3);
}

bool nau7802_set_channel1_gain(NAU7802* dev, uint32_t value) {
    return nau7802_set_32bit_register(dev, NAU7802_GCAL1_B3, value);
}

Can you check and correct it and publish it for raspberry pi pico c language?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions