| # 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 |