Skip to content
Merged
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
57 changes: 40 additions & 17 deletions src/edgepi/dac/dac_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,45 @@

from dataclasses import dataclass

# TODO: need to combine this calibration dataclass into one to avoid confusion.
# This requires some more research and revision in calculation
@dataclass
class DAChWCalibConst:
"""Calibration constants for DAC error values"""

gain = 0
offset = 0


@dataclass
class DACsWCalibConst:
"""Calibration constants for DAC amplifier values"""

gain = 2.5
offset = 0


# TODO: add functions/classes for calibration
class DACcalibParam:
"""
Calibration constants for DAC
gain_1: gain calibration parameter when internal_gain is disabled
offset_1: offset calibration parameter when internal_gain is disabled

gain_2: gain calibration parameter when internal_gain is enabled
offset_2: offset calibration parameter when internal_gain is enabled

Note: default value of 2.5 and 0 are set, these values will be overwritten
during the run-time.
"""
# TODO: add documentation regading how these parameters are provided
gain_1: float = 2.5
offset_1: float = 0

gain_2: float = 5.0
offset_2:float = 0


def generate_dict_calibration(calib: DACcalibParam = None,
list_ch: list = None,
list_param: list = None):
"""
Function to generate dictionary of channel to calibration parameter dataclass
Args:
calib: DACcalibParam: dataclass containing calibration parameters
list_ch: list of channel numbers from 0-7
list_param: list of parameters for each channel, this should've be read from eeprom
Return:
dict_calib_param: dictionary of calibration parameter
{channel(int) : DACcalibParam(gain_1, offset_1, gain_2, offset_2)}
"""
dict_calib_param = {}
for i, ch in enumerate(list_ch, 0):
dict_calib_param[ch] = calib(gain_1 = list_param[i][0],
offset_1 = list_param[i][1],
gain_2 = list_param[i][2],
offset_2 = list_param[i][3])
return dict_calib_param
35 changes: 13 additions & 22 deletions src/edgepi/dac/dac_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
class DACCommands:
"""Class for representing DAC device commands"""

def __init__(self, dach_w_calib_const, dacs_w_calib_const):
def __init__(self, dict_calib_param):
_logger.info("Initializing DAC Methods")
self.dach_w_calib_const = dach_w_calib_const
self.dacs_w_calib_consts_list = dacs_w_calib_const
self.dict_calib_param = dict_calib_param

def generate_write_and_update_command(self, ch: int, data: int) -> list:
"""Construct a write and update command"""
Expand All @@ -30,16 +29,9 @@ def generate_write_and_update_command(self, ch: int, data: int) -> list:

def __voltage_to_float_code(self, ch: int, expected: float):
"""Convert a voltage to full precision binary code value"""
float_code = (
(
(expected + self.dacs_w_calib_consts_list[ch].offset)
/ self.dacs_w_calib_consts_list[ch].gain
)
+ self.dach_w_calib_const.offset
) / (
(CALIB_CONSTS.VOLTAGE_REF.value / CALIB_CONSTS.RANGE.value)
+ self.dach_w_calib_const.gain
)
float_code =(expected + self.dict_calib_param[ch].offset_1) / \
(self.dict_calib_param[ch].gain_1 +
(CALIB_CONSTS.VOLTAGE_REF.value / CALIB_CONSTS.RANGE.value))
_logger.debug(f"Full code generated {float_code}")
return float_code

Expand Down Expand Up @@ -87,6 +79,13 @@ def extract_read_data(read_code: list) -> int:
# DB19 to DB4 DAC register contents. B23 (MSB) is index 0 here.
return bits[-16:].uint

def __code_to_float_voltage(self, ch: int, code: int) -> float:
"""Convert a voltage to float voltage"""
voltage = (CALIB_CONSTS.VOLTAGE_REF.value /
CALIB_CONSTS.RANGE.value + self.dict_calib_param[ch].gain_1) *\
code - self.dict_calib_param[ch].offset_1
return voltage

def code_to_voltage(self, ch: int, code: int) -> float:
"""
Convert a 16 bit binary code value to voltage
Expand All @@ -99,15 +98,7 @@ def code_to_voltage(self, ch: int, code: int) -> float:
Returns:
float: voltage corresponding to 16 bit binary code
"""
# DAC gain/offset errors
dac_gain_err = (
CALIB_CONSTS.VOLTAGE_REF.value / CALIB_CONSTS.RANGE.value
) + self.dach_w_calib_const.gain
dac_offset_err = self.dach_w_calib_const.offset
# amplifier gain/offset for this channel
amp_gain = self.dacs_w_calib_consts_list[ch].gain
amp_offset = self.dacs_w_calib_consts_list[ch].offset
voltage = (((code * dac_gain_err) - dac_offset_err) * amp_gain) - amp_offset
voltage = self.__code_to_float_voltage(ch, code)
_logger.debug(f"code_to_voltage: code {hex(code)} = {voltage} V")
return voltage

Expand Down
18 changes: 16 additions & 2 deletions src/edgepi/dac/edgepi_dac.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

import logging
from edgepi.dac.dac_commands import DACCommands
from edgepi.dac.dac_calibration import DAChWCalibConst, DACsWCalibConst
from edgepi.dac.dac_calibration import (
DACcalibParam,
generate_dict_calibration
)
from edgepi.dac.dac_constants import (
NULL_BITS,
NUM_PINS,
Expand Down Expand Up @@ -53,11 +56,22 @@ class EdgePiDAC(spi):
8: 7,
}

# TODO: the calib parameter should be saved in an eeprom, and parameters should be read from the
# eeprom during the class isntantiation instead of this hardcoded value
__analog_out_calib_param = [[2.5, 0, 5.0, 0], [2.5, 0, 5.0, 0],
[2.5, 0, 5.0, 0], [2.5, 0, 5.0, 0],
[2.5, 0, 5.0, 0], [2.5, 0, 5.0, 0],
[2.5, 0, 5.0, 0], [2.5, 0, 5.0, 0]]

def __init__(self):
_logger.info("Initializing DAC Bus")
super().__init__(bus_num=6, dev_id=3, mode=1, max_speed=1000000)

self.dac_ops = DACCommands(DAChWCalibConst, [DACsWCalibConst] * 8)
self.dac_ops = DACCommands(generate_dict_calibration(DACcalibParam,
list(
self.__analog_out_to_dac_ch.values()
),
self.__analog_out_calib_param))
self.gpio = EdgePiGPIO(GpioConfigs.DAC.value)
self.gpio.set_expander_default()

Expand Down
32 changes: 32 additions & 0 deletions src/test_edgepi/unit_tests/test_dac/test_dac_calibration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""unit test for dac module"""

import pytest
from edgepi.dac.dac_calibration import DACcalibParam, generate_dict_calibration


@pytest.mark.parametrize(
"list_ch, list_param, result",
[
([1], [[1.3, 1.2, 3.3, 4.5]], {1 : DACcalibParam(1.3, 1.2, 3.3, 4.5)}),
([1, 2], [[1.3, 1.2, 3.3, 4.5], [1, 2, 3, 4]], {1 : DACcalibParam(1.3, 1.2, 3.3, 4.5),
2 : DACcalibParam(1, 2, 3, 4)}),
([0, 1, 2, 3, 4, 5, 6, 7], [[1.3, 1.2, 3.3, 4.5],
[1, 2, 3, 4],
[3, 4, 5, 8],
[1.3, 1.2, 3.3, 41.5],
[2.3, 3.2, 35.3, 24.5],
[5.3, 5.2, 3.3, 34.5],
[3.3, 7.2, 3.3, 45.5],
[2.3, 19.2, 9.3, 46.5]],
{0 : DACcalibParam(1.3, 1.2, 3.3, 4.5),
1 : DACcalibParam(1, 2, 3, 4),
2 : DACcalibParam(3, 4, 5, 8),
3 : DACcalibParam(1.3, 1.2, 3.3, 41.5),
4 : DACcalibParam(2.3, 3.2, 35.3, 24.5),
5 : DACcalibParam(5.3, 5.2, 3.3, 34.5),
6 : DACcalibParam(3.3, 7.2, 3.3, 45.5),
7 : DACcalibParam(2.3, 19.2, 9.3, 46.5)})
])
def test_dac_generate_dict_calibration(list_ch, list_param, result):
dict_calib_param = generate_dict_calibration(DACcalibParam, list_ch, list_param)
assert dict_calib_param == result
20 changes: 14 additions & 6 deletions src/test_edgepi/unit_tests/test_dac/test_dac_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
from edgepi.dac.dac_constants import EdgePiDacChannel as CH
from edgepi.dac.dac_commands import DACCommands
from edgepi.dac.dac_constants import EdgePiDacCalibrationConstants as CALIB_CONSTS, PowerMode
from edgepi.dac.dac_calibration import DAChWCalibConst, DACsWCalibConst
from edgepi.dac.dac_calibration import DACcalibParam


@pytest.fixture(name="dac_ops")
def fixture_test_dac_ops():
dac_ops = DACCommands(DAChWCalibConst, [DACsWCalibConst] * 8)
dict_calibration_param = {0 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
1 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
2 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
3 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
4 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
5 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
6 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
7 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0)}
dac_ops = DACCommands(dict_calibration_param)
return dac_ops


Expand Down Expand Up @@ -99,7 +107,7 @@ def test_dac_generate_write_and_update_command(a, b, c, dac_ops):


@pytest.mark.parametrize(
"ch, expected, result", [(1, 2.345, 30030), (0, 2.345, 30030), (3, 2.345, 30030)]
"ch, expected, result", [(1, 2.345, 33798), (0, 2.345, 33798), (3, 2.345, 33798)]
)
def test_dac_voltage_to_code(ch, expected, result, dac_ops):
assert dac_ops.voltage_to_code(ch, expected) == result
Expand All @@ -108,9 +116,9 @@ def test_dac_voltage_to_code(ch, expected, result, dac_ops):
@pytest.mark.parametrize(
"ch, code, result",
[
(1, 30030, 2.345),
(0, 30030, 2.345),
(3, 30030, 2.345),
(1, 33798, 2.345),
(0, 33798, 2.345),
(3, 33798, 2.345),
],
)
def test_dac_code_to_voltage(ch, code, result, dac_ops):
Expand Down
12 changes: 10 additions & 2 deletions tests/test_edgepi_dac.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@
from edgepi.dac.dac_constants import EdgePiDacChannel as CH
from edgepi.dac.dac_commands import DACCommands
from edgepi.dac.dac_constants import EdgePiDacCalibrationConstants as CALIB_CONSTS
from edgepi.dac.dac_calibration import DAChWCalibConst, DACsWCalibConst
from edgepi.dac.dac_calibration import DACcalibParam


@pytest.fixture(name="dac_ops")
def fixture_test_dac_ops():
dac_ops = DACCommands(DAChWCalibConst, [DACsWCalibConst] * 8)
dict_calibration_param = {0 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
1 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
2 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
3 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
4 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
5 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
6 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0),
7 : DACcalibParam(2.5/65535, 0, 5.0/65535, 0)}
dac_ops = DACCommands(dict_calibration_param)
return dac_ops


Expand Down