Answers.Body: <p>Here is the schematic of an input port on the EV3 (available on official LEGO MINDSTORMS download page):</p>
  <p><a href="https://i.sstatic.net/T52bm.png" rel="noreferrer"><img src="https://i.sstatic.net/T52bm.png" alt="schematic of an input port on the EV3" /></a></p>
  <p>And this is the implementation of the <code>resistance()</code> method from Pybricks MicroPython:</p>
  <pre><code>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-&gt;active ? PBIO_IODEV_MODE_NXT_ANALOG__ACTIVE : PBIO_IODEV_MODE_NXT_ANALOG__PASSIVE;
      pb_device_get_values(self-&gt;pbdev, mode, &amp;voltage);
  
      // Open terminal/infinite resistance, return infinite resistance
      const int32_t vmax = 4972;
      if (voltage &gt;= 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));
  }
  </code></pre>
  <hr />
  <p>A seen in the schematic, <code>R119</code> pulls up pin 1 to 5V with a 10k resistor. This is why the <code>resistance()</code> method measures 10k without anything connected.</p>
  <p>The <code>resistance()</code> 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.</p>
  <p>Here is the equivalent circuit - a <a href="https://en.wikipedia.org/wiki/Voltage_divider" rel="noreferrer">voltage divider</a>:</p>
  <p><a href="https://i.sstatic.net/olvfX.png" rel="noreferrer"><img src="https://i.sstatic.net/olvfX.png" alt="schematic of equivalent circuit" /></a></p>
  <p>With a bit of algebra, we can see that the equation in implementation is correct.</p>
  <pre><code>TH1 = (10k*MES1)/(VCC-MES1)
  </code></pre>
  <hr />
  <p>The inaccuracy comes from the hard-coded values for the VCC voltage and the R119 resistance (<code>Rinternal</code>). These could be measured more precisely. First to measure VCC, simply record the value using the <code>voltage()</code> 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 (<code>Rtest</code>). Then connect it to pins 1 and 3 and measure the voltage with the <code>voltage()</code> method (<code>Vtest</code>). Then:</p>
  <pre><code>Rinternal = (Rtest*Vtest)/(VCC-Vtest)
  </code></pre>
  <p>Then you can make your own resistance function using those values:</p>
  <pre><code>
  # 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)
  </code></pre>
  <p>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 <code>v</code> approaches <code>VCC</code>.</p>
  <hr />
  <p>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.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-07-24T21:51:05.373Z
Answers.LastActivityDate: 2021-07-24T22:32:53.550Z
Answers.LastEditDate: 2021-07-24T22:32:53.550Z
Answers.UserDisplayName: David Lechner
Body: <p>I recently tried measuring the resistance of a thermistor using the <code>.resistance()</code> 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.</p>
  <p>Here  is the code I used:</p>
  <pre><code>#!/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)
  </code></pre>
  <p>Any help, explanation or like a formula to calculate the real resistance would be very appreciated.</p>
  
Tags: <ev3><programming><electronics><micropython><pybricks>
Title: EV3 not recognizing resistance correctly (MicroPython)
UserDisplayName: C-Brick
ThreadText: # EV3 not recognizing resistance correctly (MicroPython)
  
  (Asked by: username_0 on 2021-07-24)
  
  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.
  
  **Tags:** ev3, programming, electronics, micropython, pybricks
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-07-24. Score: 8 | Accepted answer
  
  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](https://i.sstatic.net/T52bm.png)](https://i.sstatic.net/T52bm.png)
  
  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](https://en.wikipedia.org/wiki/Voltage_divider):
  
  [![schematic of equivalent circuit](https://i.sstatic.net/olvfX.png)](https://i.sstatic.net/olvfX.png)
  
  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.
  
  
  ---
  
  