5

I recently tried measuring the resistance of a thermistor using the .resistance() method, the results are sadly not accurate. I measured the resistance with a multimeter and it showed 100kΩ, while the different EV3's all showed something between 330kΩ and 360kΩ. Even with no resistance the EV3 shows around 10kΩ resistance, so the results are not off by a fixed amount, but the results are repeatable.

Here is the code I used:

#!/usr/bin/env pybricks-micropython

from pybricks.hubs import EV3Brick
from pybricks.iodevices import AnalogSensor
from pybricks.parameters import Port

ev3 = EV3Brick()
 
thermistor = AnalogSensor(Port.S1)
 
x = thermistor.resistance()
 
print(x)

Any help, explanation or like a formula to calculate the real resistance would be very appreciated.

8

Here is the schematic of an input port on the EV3 (available on official LEGO MINDSTORMS download page):

schematic of an input port on the EV3

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:

schematic of equivalent circuit

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.