LDU Rotor Temperature Monitor

Toyota Rav4 EV Forum

Help Support Toyota Rav4 EV Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.


Well-known member
Supporting Member
Aug 7, 2017
Oak Harbor, Wash.
After modifying my LDU to no longer circulate liquid coolant through the rotor, I would like to know just how hot this rotor is getting. I figure that it now can't dissipate much heat anywhere except to the stator, and to the rotor bearings, and I'm a bit worried about the latter; I think the rating for the bearings' grease is only 160°C, according to Howard.

Data! I don't have "before modification" temperatures, which is a shame, but I'm working on "after" temp data now.

So far I have:
  • Installed a Melexis MLX90614 IR temperature sensor in the rotor end cap, pointed to the edge of the rotor.
  • Test connected it to an Arduino Pro Mini microcontroller
  • Test connected it to a OLED display, 0.91"
  • Assembled code to initialize and read the sensor data, display the result on the OLED, in either °C or °F, updated once per second
  • Ruined my lab power supply by using it more than its rated service life of 6 hours per 23 months.
It's working on the bench, and the sensor is now installed in my RAV4; I have yet to build the "extension harness" that allows me to put the display inside the car, but the sensor and display/microcontroller/DC-DC converter can plug together without the extension harness, so it's tested and ready for install. I just need more time, lol.


The MLX90614 can read up to 380°C (720°F), and I sure hope that the rotor isn't going to get hotter than that.

This is an early pic, but I don't have an updated one available. Trust me that the spacing has been corrected:
IMG_7933.jpg IMG_7945.jpg

The silver box is a 12v->5v DC-DC Converter with an input range to 30v, so safe for automotive "12v".
The blue circuit board is the Arduino Pro Mini, which measures ~3/4" (19mm) x 1.25" (32mm).
The harness connector is Deutsch DTM04-4P.

All connections off-board are crimped.

It's wired something like this:

The specific variety of MLX906014 is MLX90614ESF-ACF-000-SP, which works well with 5V, has a relatively narrow 10° field of view, and does internal gradient compensation. Importantly, this version is fairly long, which worked into my mounting idea at the time.

(cont'd next msg.)
Last edited:
How to mount an IR sensor such that it can see the rotor, and be also be serviced? I chose a location, and a mounting technique that I'm not 100% happy with, but will serve as a first-pass attempt.


Prepping the rotor cap housing, I removed part of an internal rib, and drilled/tapped for 3/8" NPT.

I used a 3/8" MNPT x 1/8" FNPT reducing bushing to form a mount for the sensor.
The IR sensor is ~9mm OD (.199"), I used drill 'T' (.201"). 23/64" (.203") would probably work as well. As you're drilling a threaded surface, the bit wanders a little and the actual hole size is a bit larger than you'd expect from looking at those figures, but as the epoxy used to fix the sensor to the bushing needs some space, this worked out well.

Sensor epoxied in the bushing, leads soldered:
IMG_7894.jpg IMG_7893.jpg

(cont'd next msg.)
Last edited:
I potted the leads with a different epoxy, using a copper reducer 1/2" x 3/8":

I first used RTV very sparingly at the outside of the base:

Then, the next day, I poured epoxy from the top to pot the leads:

After that set up, I carefully ground off flats on the reducer, to allow an open-end wrench to access the bushing later. The OD of the base of the reducer was just slightly larger than the hex bushing across the flats.

I attached a Deutsh plug connector to the sensor's leads:


The aim of the sensor is not ideal, but this location was the best I could locate.

(cont'd next msg)
IR sensors work via . . . IR radiation ;) An ideal black body emits the most IR per unit of temperature. Shiny surfaces emit the least. Emissivity is measured on a scale of [0..1], with 1 being "ideal" (I am simplifying, and I also wasn't a physics major).

Copper of average polish has an emissivity index of around 0.05: not very good. I sprayed the end of my rotor with high-temp oil-based paint, flat black, which has an emissivity of 0.94:

Next was wiring the mess up. It looks simple, right?
Here's a reference for the microcontroller. Bear in mind that I'm only using FIVE of the solder pads (plus six for programming only):
Arduino Pro Mini,  ATmega328, 16MHz,  5V.png

There was a time when my dining room could have theoretically been used for . . . dining . . . but that was only a passing fantasy:

After beating on the code for a few hours, and learning the hard way the difference between Serial.print("foo"); and Serial.print(F("foo"));, the code is reliable enough to disconnect the FTDI adapter and package the wiring (see in the first post but repeated here):

I put a layer of clear-ish RTV on the DC-DC, then after that set up firm I strapped the Arduino to it.

It works on the bench.
Working code is here. Of note, the emissivity index, and temperature scale of °C or °F can be configured in code at the top, without fussing with anything else. If you change the emissivity, it's written to the sensor's EEPROM, and the sensor has to be powered down to use the new index. I tried out code that was suggested to reboot the Arduino and it didn't appear to work, and I gave up on that feature for now.

I consider this a fairly amateurish project, but I have little experience with these tiny things; my background is in servicing stuff that better engineers defined. I'm sure that you can do better, and if I ever do this again I'm going to improve that IR sensor mount, it's too fragile. And my coding skills are appalling and way out of date; try not to judge me based on what you read.

But it works.

Current spreadsheet on this project (including some extra Deutsch terminals that won't be used here):

Very useful guide on Pro Mini & MLX90614, including a good code skeleton (though loaded with Serialprint() functions which store strings in SRAM (2k) instead of Flash RAM (32k), which is a serious problem if you use many of them, as I did).
Pinout of bare sensor is incorrect, though, don't use it.

Melexis MLX90614 datasheet. Correct pinout of bare sensor is on pg. 8.

Project overview using IR sensor with an Uno
Shows the 10k pull-up resistors for use with 5V! [see later in this thread, where it was shown that 10k is too high for longer sensor harness lengths.]

Arduino Pro Mini 328 - 5V/16MHz DEV-11113 $11 overview & some specs

Mostly about their breakout board, not all that useful
I'll post more on this when I get the non-sensor stuff stuffed into the car; the weather has turned and this is outdoor work for me.
Last edited:
I do not like running wiring from the engine compartment into the passenger area on modern cars, so I've been putting it off, but today was the day . . .

The firewall wiring bundle on the passenger (right) side has an oversized grommet with a pre-molded empty nipple. I cut the end of the nipple off and routed my four-conductor cable through it. It looks simple, but I explored several different locations before deciding on this route.

Similarly, I took off the plastic cowl to see if removing the metal "shelf" on the engine bay side was reasonable. I decided that it would have to be re-sealed upon reinstallation and I was able to work my arm close enough to the firewall wiring grommet (from the engine bay side) to feed the cable via Braille. To be clear, it is not necessary to remove the cowl/wiper arms etc. to access this grommet, but I didn't know the answer when I began.

From the engine bay side (plastic cowl removed: not necessary):

IMG_8031.jpg IMG_8033.jpg

IMG_8041.jpg IMG_8044.jpg

Feeding the cable in, you will want the person with the smallest forearms; mine aren't quite small enough:


But don't even think of trying to push cable through that nipple until you cut the end of it off, from the passenger compartment side of the firewall.

From the interior, I removed the glovebox (as if changing the cabin filter), then I had to remove around five modules from behind the glovebox, in order to see what I was doing. If you are young/limber/dexterous, you might be able to cut the nipple's end off without removing the modules; it might be possible. But you'd never be able to see it clearly enough to know what it is, without the modules out of the way.



I snipped the end off of this nipple:

I can't fix the focus; the phone refuses to do far focus if there's something in the foreground, but here's the 4-conductor cable installed through the grommet. This cable is ~5mm dia and fits, though larger would not fit nearly so well.


  • IMG_8033.jpg
    1.8 MB · Views: 1
Last edited:
I do not like running wiring from the engine compartment into the passenger area on modern cars, so I've been putting it off, but today was the day . . .

The firewall wiring bundle on the passenger (right) side has an oversized grommet with a pre-molded empty nipple. I cut the end of the nipple off and routed my four-conductor cable through it. It looks simple, but I explored several different locations before deciding on this route.
It will be quite curious to know the temperature of the rotor when the stator temperature reaches 170°F ÷190°F.

Temperature of inverter, stator and HV battery current while driving RAV4EV
Last edited:
It works on the bench.
Update: while the Deutsch-wired sensor plugged into the Arduino/DC-DC/Display worked on the diningroom table, it does not work when installed with the extension harness in the car (~8' of the same 4-conductor cable I'd been using for the sensor), and the symptom I'm seeing:
  • Display works OK until the sensor is plugged in;
  • Sensor will sometimes initialze when plugged in, but I²C bus jams afterward
. . . is the same symptom I'd received earlier when I lacked pullup resistors on the I²C lines, so I need to look at this further. I'm awaiting more Deutsch connectors (bought an assortment this time!) because I want to extend that harness further and try to put everything over on the left, next to the headlight leveling wheel, and possibly float the DC-DC outside the box, put everything else in a single smaller box . . . and like that.

Next week at the soonest, probably.
Last edited:
Is it possible to compare with the oscillogram of signals from SCL and SDA pins on the input pins of the arduino board with short wires and with elongated wires*?

You may need to use twisted pair or shielded wires. I do not rule out the need to use additional ceramic capacitors (0.1÷1.0 microF 104÷105) in the power supply circuit of the sensor and Arduino for filtering/protection from high-frequency interference...

Does the temperature display system work when the rotor is stationary?
What (photo) does the screen currently show in this situation?


  • IMG_20240522_135857.png
    854.2 KB · Views: 0
Last edited:
Yeah, 8' is a long distance for I2C. Twisted pairs won't help much since you don't have differential signals. You might try lowering the data rate drastically. Bandwidth shouldn't be much of a concern.

Are the display and the sensor both on the same I2C bus? You might try separating them using a separate set of Arduino pins for each device.

Another idea would be to put the Arduino close to the sensor, then use a display that can be interfaced over RS-422 (asynch serial) which can use twisted pair wire for the longer run to the dashboard.
Sorry Al, 8' likely isn't going to work for i2c. Tyr Wire.setClock(10000) to force low speed mode. If that doesn't work, I would suggest moving your microcontroller close to the sensor and then either use a long USB cable to laptop to display the temp via serial monitor, or establish a RS232 link to a second Arduino module in the vehicle which reads the data in over serial and shows it on your local i2c display.
From what I'm reading, I²C should be able to handle 12'. I had used 10k pullups on SDA & SCL (because of this), and according to the man who wrote I²C for the wire.h library, I should be using either 4k7 or 2k pullups. Nice waveforms there, from 2011.


I used Wire.setClock(10000)* in setup() but measured frequency appears to be close to the 400kHz "fast mode" -- the clock line does not run continuously, so the measured freq. is a bit lower -- and this is without the IR sensor plugged in (only the OLED display is on the I²C). Truly awful rise time, though the OLED display gets along just fine with it:


So, two things to investigate: lower value pullups (or move to a real current source instead), and slow down the I²C bus. It may be being overridden in one of the libraries' setups for the sensor or the display. This is kind of a stretch for me, but I'll do the easy thing first and swap out the pullups for something shorter, and then see if I can figure out how to get keep the I²C speed down to 100kHz or lower.

* = According to the documentation, setClock() has no return value. IDK how you can tell if the function has succeeded. Who writes this stuff?

The Adafruit_SSD1306 (OLED display) library has a couple of params (line 151) to set the I2C bus speed during and after this library is using I²C, and it looks like I will be trying them out. Tomorrow is a "lumber" day and I don't expect to get any "computer" time in.

Hmph. I paid over $2,000 for this TDS 210 new -- around 1998 -- and now you can buy them all day long on eBay for a tenth of that. I did recently buy the USB and FFT add-in aftermarket card for it. No more GPIB/Centronics/RS232 on this rig!
Last edited:
Can you use the sensor's PWM output to input information into the Arduino?
Last edited:
After some Googling, I have seen some posts that say setClock() should be after Wire.begin(), and at least one person who said it should be in loop() and not setup(). Maybe try moving it's location around and seeing if there's any effect?
10k pullups, 400k I2C rate (1μs time scale):

4k7 pullups, 100k I2C rate (2.5μs time scale):

Same, with 8' of harness + MLX sensor connected:

It's now working as intended.

Beside the pullup resistor changes, I changed one line in the program, adding two parameters to constructor:

#define SCREEN_WIDTH 128    // OLED display width, in pixels
#define SCREEN_HEIGHT 64    // OLED display height, in pixels
#define OLED_RESET -1       // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET, 100000, 100000); // Last two params set the I2C bus speed during and after this driver uses the bus. See Adafruit_SSD1306.cpp #151-166 .


This tells the SSD1306 library to use 100k I2C bus speed during and after it writes.

In the car, and connected to the sensor in the LDU (~8' of harness):


In about a week I'll receive more Deutsch connectors, and try to get this mounted somewhere. It's running off a power tool 19.2v battery right now, and just draped on the passenger seat, glovebox is still out, etc. Lots of cleanup and repacking to do.
Ecellent results!
What was the stator temperature at this time?
I assume that the measurement results shown are quite reliable.

Can I use your results and illustrations to promote this project of yours to a Russian-speaking audience?
Of course, with your copyright indicated.
Last edited:
Unfortunately, this was a rushed trial run to take a friend to a ferry -- which we almost missed -- and I was not able to juggle the laptop at the same time as watch the monitor; this is very early stages and things are taped down to the console, clip leads to the battery, etc. So, I have no stator temps to compare. Next week, this will be installed much better.

Everything posted publicly is public; feel free to re-post wherever you like. I do not retain copyright, but due credit is always appreciated and professional. "I am an amateur, this is a hobby, at your own risk" etc. . . .

The microcontroller stopped updating several times during the 30 mile drive. This OLED display will maintain and show the "last data received" as long as power is applied, so with the current code it's not obvious when the code dies; I noticed a lack up updates several times, I cycled the power each time, and it always restarted well. I will add a "heartbeat" indicator on the display at a minimum, and I will have to look into possible cause(s), but for now it is not stable as-is. However, it is working well enough to provide some data for the moment.

I will move to a shielded harness first, but the microcontroller lockup did not seem related to throttle movement, and frankly the HV components are quite well shielded from EMC from Tesla. Changing to shielded cabling is just good practice though, and I don't know why I didn't do that the first time, it seems a simple oversight.
Last edited:
After some Googling, I have seen some posts that say setClock() should be after Wire.begin(), and at least one person who said it should be in loop() and not setup().
There's no Wire.begin() in my code -- none of the example code I stole used it for this combination of sensor and display -- and I'm getting the impression that while the Adafruit_SSD1306 display driver library is built on top of or inherits Wire.h, it doesn't use all its functions directly, and may be bypassing that one.

I hate the idea of setting the I²C bus speed in loop(), but that does look like a possible workaround.

The Adafruit_SSD1306 display driver library interacts with the I²C bus speeds too often for Wire.setClock() to be functional, from my testing. And, the optional params only work down to 31k [later: 30304hz] and no further. I'm probably missing some info, but that's where I am right now.

I have a "hearbeat" working on the display now, and it's stable in the driveway with I²C @ 31kHz. I'll do on-the-road testing tomorrow, probably.
Last edited: