| # Copyright 2024 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| """ADC related math functions.""" |
| |
| import logging |
| |
| _CSV_LOG = logging.getLogger('gonk.csv') |
| |
| # CHANNEL_MASK should be set to same value used by |
| # SelectContinuousReadAdcs in the MCU |
| CHANNEL_MASK = 0b011100111001 |
| ADC_COUNT = CHANNEL_MASK.bit_count() |
| |
| CHANNEL_NAMES_ALL = [ |
| "VDD_EE", |
| "VCC18", |
| "VDDIOAO18", |
| "VDDCPU_B", |
| "DCIN", |
| "VDDQ(DDR)", |
| "VCC33", |
| "VCC5V", |
| "VDDCPU_A", |
| "VSYS3V3", |
| "EMMC18", |
| ] |
| |
| SHUNT_RESISTANCES = [ |
| 0.03, |
| 0.50, |
| 0.50, |
| 0.10, |
| 0.05, |
| 0.08, |
| 0.13, |
| 0.05, |
| 0.027, |
| 0.03, |
| 0.5, |
| ] |
| |
| # From INA229 Datasheet |
| VBUS_VOLTS_PER_COUNT = 195.3125e-6 |
| VSHUNT_VOLTS_PER_COUNT = 312.5e-9 |
| |
| |
| def get_channel_names(channel_mask: int = CHANNEL_MASK) -> list[str]: |
| """Returns list of channel names based on channel_mask.""" |
| retval = [] |
| |
| for name in CHANNEL_NAMES_ALL: |
| if channel_mask & 0x01: |
| retval.append(name) |
| channel_mask = channel_mask >> 1 |
| return retval |
| |
| |
| def log_csv_header(channel_mask: int = CHANNEL_MASK) -> None: |
| csv_header = [ |
| 'host_time', |
| 'delta_micros', |
| ] |
| for measurement_prefix in ['V', 'I', 'P']: |
| csv_header.extend( |
| [ |
| f'{measurement_prefix}_{channel}' |
| for channel in get_channel_names(channel_mask) |
| ] |
| ) |
| csv_header.append('comment') |
| _CSV_LOG.info(', '.join(csv_header)) |
| |
| |
| def get_resistances(channel_mask: int = CHANNEL_MASK) -> list[float]: |
| """Returns list of shunt resistance values for the activated channels.""" |
| retval = [] |
| |
| for ohms in SHUNT_RESISTANCES: |
| if channel_mask & 0x01: |
| retval.append(ohms) |
| channel_mask = channel_mask >> 1 |
| return retval |
| |
| |
| def get_shunt_currents( |
| vshunt_measurements, channel_mask: int = CHANNEL_MASK |
| ) -> list[float]: |
| """Calculate shunt currents for activated channels.""" |
| retvals = [] |
| resistances = get_resistances(channel_mask) |
| for i, resistance in enumerate(resistances): |
| retvals.append( |
| VSHUNT_VOLTS_PER_COUNT * vshunt_measurements[i] / resistance |
| ) |
| return retvals |
| |
| |
| def get_bus_voltages(vbus_measurements) -> list[float]: |
| """Calculate bus voltages from raw vbus measurements.""" |
| retvals = [] |
| for measurement in vbus_measurements: |
| retvals.append(VBUS_VOLTS_PER_COUNT * measurement) |
| return retvals |
| |
| |
| def calc_power(voltages, currents) -> list[float]: |
| """Calculate power from voltage and current measurements.""" |
| retvals = [] |
| for i, volts in enumerate(voltages): |
| retvals.append(volts * currents[i]) |
| return retvals |