Skip to content
Open
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
67 changes: 52 additions & 15 deletions pslab/sciencelab.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
from __future__ import annotations

import time
from typing import Iterable, List
from typing import Dict, Iterable, List, Tuple

import numpy as np
import pslab.protocol as CP
from pslab.connection import ConnectionHandler, SerialHandler, autoconnect
from pslab.instrument.logic_analyzer import LogicAnalyzer
Expand Down Expand Up @@ -44,21 +45,57 @@ def __init__(self, device: ConnectionHandler | None = None):
self.multimeter = Multimeter(device=self.device)
self.power_supply = PowerSupply(device=self.device)

# Calibration parameters for CTMU temperature measurement
# Format: {current_range_index: (offset_mV, slope)}
_CTMU_TEMPERATURE_CALIBRATION: Dict[int, Tuple[float, float]] = {
1: (646, 1.92),
2: (701.5, 1.74),
3: (760, 1.56),
}

# CTMU ADC channel used for internal temperature sensor
_CTMU_CHANNEL_TEMPERATURE = 0b11110

# Unit conversion factor
_VOLTS_TO_MILLIVOLTS = 1000

# Minimum valid CTMU voltage before switching current range (Volts)
_MIN_CTMU_VOLTAGE = 0.3

@property
def temperature(self):
"""float: Temperature of the MCU in degrees Celsius."""
# TODO: Get rid of magic numbers.
cs = 3
V = self._get_ctmu_voltage(0b11110, cs, 0)

if cs == 1:
return (646 - V * 1000) / 1.92 # current source = 1
elif cs == 2:
return (701.5 - V * 1000) / 1.74 # current source = 2
elif cs == 3:
return (760 - V * 1000) / 1.56 # current source = 3

def _get_ctmu_voltage(self, channel: int, current_range: int, tgen: bool = True):
def temperature(self) -> float:
"""Get the temperature of the MCU."""
# CTMU current range index (higher index = higher current)
current_range = 3

V = self._get_ctmu_voltage(
self._CTMU_CHANNEL_TEMPERATURE,
current_range,
0,
)

# If the voltage is too low, we might be using a too high current source
# range. Try to lower the range until we get a reasonable voltage.
while V < self._MIN_CTMU_VOLTAGE and current_range > 1:
current_range -= 1
V = self._get_ctmu_voltage(
self._CTMU_CHANNEL_TEMPERATURE,
current_range,
0,
)

try:
offset, slope = self._CTMU_TEMPERATURE_CALIBRATION[current_range]
except KeyError as exc:
raise ValueError(
f"Unsupported CTMU current range: {current_range}"
) from exc

return (offset - V * self._VOLTS_TO_MILLIVOLTS) / slope

def _get_ctmu_voltage(
self, channel: int, current_range: int, tgen: bool = True
) -> float:
"""Control the Charge Time Measurement Unit (CTMU).

ctmu_voltage(5, 2) will activate a constant current source of 5.5 µA on
Expand Down