Here is the schematic of an input port on the EV3 (available on official LEGO MINDSTORMS download page):
And this is the implementation of the resistance()
method from Pybricks MicroPython:
STATIC mp_obj_t iodevices_AnalogSensor_resistance(mp_obj_t self_in) {
iodevices_AnalogSensor_obj_t *self = MP_OBJ_TO_PTR(self_in);
int32_t voltage;
uint8_t mode = self->active ? PBIO_IODEV_MODE_NXT_ANALOG__ACTIVE : PBIO_IODEV_MODE_NXT_ANALOG__PASSIVE;
pb_device_get_values(self->pbdev, mode, &voltage);
// Open terminal/infinite resistance, return infinite resistance
const int32_t vmax = 4972;
if (voltage >= vmax) {
return mp_obj_new_int(MP_SSIZE_MAX);
}
// Return as if a pure voltage divider between load and 10K internal resistor
return mp_obj_new_int((10000 * voltage) / (vmax - voltage));
}
A seen in the schematic, R119
pulls up pin 1 to 5V with a 10k resistor. This is why the resistance()
method measures 10k without anything connected.
The resistance()
method assumes that you are connecting the external resistance between pin 1 and pin 3 (ground) and it assumes that the 5V supply is actually 4.972V.
Here is the equivalent circuit - a voltage divider:
With a bit of algebra, we can see that the equation in implementation is correct.
TH1 = (10k*MES1)/(VCC-MES1)
The inaccuracy comes from the hard-coded values for the VCC voltage and the R119 resistance (Rinternal
). These could be measured more precisely. First to measure VCC, simply record the value using the voltage()
method when nothing is attached to the port. To calculate R119, get a 10k resistor and measure it with your multimeter to get an exact value (Rtest
). Then connect it to pins 1 and 3 and measure the voltage with the voltage()
method (Vtest
). Then:
Rinternal = (Rtest*Vtest)/(VCC-Vtest)
Then you can make your own resistance function using those values:
# replace ... with exact measure values
VCC = ...
R_INTERNAL_PORT_A = ...
sensor = AnalogSensor(Port.A)
def resistance():
v = sensor.voltage()
return R_INTERNAL_PORT_A * v / (VCC - v)
However, the further away from 10k that the thermistor gets, the less precise the measurement will be due to the fact that the value approaches infinity as v
approaches VCC
.
Another alternative could be a hardware solution. Using an op amp, you could create a circuit that has an output in the range of 0-5V. The op amp circuit could even be designed to make the output linear with respect to temperature rather than linear to resistance. With the analog circuit eliminating the non-linearity, the analog digital converter in the EV3 would have equal precision across the full range of temperatures.