Using Yoctopuce modules with the iRacing game

Using Yoctopuce modules with the iRacing game

IRacing is a racing game simulation with realistic physics. To test this simulation, we dusted off an old racing wheel Logitec G25 that still works very well, but doesn't have LEDs or a display that can be controlled by the game. So we thought this was a good opportunity to add these features by using Yoctopuce modules. And as we'll see, it's not very complicated.




The first step is to look at what information we can get from the game. By browsing the iRacing forums, we discovered that there is an SDK that allows us to easily retrieve all the car's telemetry information (speed, lap count, gear engaged, and son on). Someone has even written a Python library that makes it possible to easily interface with this SDK: Python iRacing SDK

We install this library as well as our Python library with the pip install command.

pip install pyirsdk yoctopuce



After installing the libraries, we check that we have obtained the active gear.

#!python3
import irsdk
ir = irsdk.IRSDK()
ir.startup()
print(ir['Gear'])



The code works, but only when the game is started and it only displays the gear on the computer terminal.

Based on the available examples, we create a code that checks whether the game is running and calls the refresh method 60 times per second if a game is in progress. In this code, we also add the calls to YAPI.RegisterHub, YAPI.RegisterDeviceArrivalCallback, YAPI.RegisterDeviceRemovalCallback and YAPI.UpdateDeviceList which enables us to correctly manage the hotplug of Yoctopuce modules.

If you are not familiar with these functions, we have a post that explains how they work.

def deviceArrival(self, m: YModule):
  serial = m.get_serialNumber()
  if m.get_productName().startswith("Yocto-MaxiDisplay"):
    self.display = YDisplay.FindDisplay(serial + ".display")
    self.configure_display()

def deviceRemoval(self, m):
  serial = m.get_serialNumber()
  if self.display is not None and serial == self.display.get_serialNumber():
    self.display = None

def loop(self):
  self.ir = irsdk.IRSDK()
  errmsg = YRefParam()
    err = YAPI.RegisterHub(hub, errmsg)
    if err != YAPI.SUCCESS:
      sys.exit("Unable to register " + hub + " : " + errmsg.value)
  YAPI.RegisterDeviceArrivalCallback(self.deviceArrival)
  YAPI.RegisterDeviceRemovalCallback(self.deviceRemoval)
  # infinite loop
  while True:
    # check if we are connected to iracing
    if self.ir_connected
           and not (self.ir.is_initialized and self.ir.is_connected):
        self.ir_connected = False
        self.last_car_setup_tick = -1
        self.ir.shutdown()
        print('irsdk disconnected')
    elif not self.ir_connected and self.ir.startup()
            and self.ir.is_initialized and self.ir.is_connected:
        self.ir_connected = True
        print('irsdk connected')
    if self.ir_connected:
        self.refresh()
    # Check for Yoctopuce devices arrival or removal
    YAPI.UpdateDeviceList()
    # sleep ~1/60s
    YAPI.Sleep(16)

def configure_display(self):
 ...

def refresh(self):
 ...



The configure_display method is called when a Yocto-MaxiDisplay is connected to the USB port. This function cleans the screen and stores some values, such as the screen dimensions, in variables.

def configure_display(self):
    # display clean up
    self.display.resetAll()
    # retrieve the display size
    self.display_w = self.display.get_displayWidth()
    self.display_h = self.display.get_displayHeight()
    # retrieve the first layer
    self.layer0 = self.display.get_displayLayer(0)



As we have seen above, the refresh method is called only when iRacing is launched. This method reads the gear engaged thanks to the"Gear" attribute of the IRSDK object. The value -1 corresponds to the reverse gear, 0 corresponds to the neutral point and the positive values indicate the engaged gear. If the gear has changed, the Yocto-MaxiDisplay screen is updated using the drawText method.

def refresh(self):
    if self.display is not None:
        gear_char = 'X'
        gear = self.ir['Gear']
        if gear < 0:
            gear_char = 'R'
        elif gear == 0:
            gear_char = 'N'
        else:
            gear_char = '%d' % gear
        if gear_char != self.lastGear:
            self.layer0.clear()
            self.layer0.selectFont("Large.yfm")
            self.layer0.drawText(self.display_w / 2, self.display_h / 2, YDisplayLayer.ALIGN.CENTER, gear_char)
            self.lastGear = gear_char



All that's left to do is to attach the Yocto-MaxiDisplay to the base of the steering wheel and that's it!

Yocto-MaxiDisplay displays the engaged gear
Yocto-MaxiDisplay displays the engaged gear




As we took care to correctly manage the hot-plug of Yoctopuce modules and the connection with iRacing, you can launch this program during a game or on the contrary before starting the game. The same goes for the Yoctopuce modules, it is possible to plug and unplug them at any time.

As usual the complete source code is available on GitHub:
https://github.com/yoctopuce-examples/yocto_iracing_info.

In order to keep this post quite concise, we limited ourselves to explaining how to display the engaged gear, but the SDK publishes a lot of information and it is very easy to modify the code to display other information. By the way, the version available on GitHub includes a few extra features...

For example, if you plugged in a Yocto-Color-V2, the LEDs are used as shift-light.

Yocto-Color-V2 is used as shift-light
Yocto-Color-V2 is used as shift-light


Add a comment No comment yet Back to blog












Yoctopuce, get your stuff connected.