Skip to content

Inconsistent Mid-Level Channel Behavior When Using is_active=False in MidLevelChannelConfiguration (P24 Stimulator) #19

@geroratto

Description

@geroratto

I'm working with the P24 Stimulator and the science_mode_4 library using the mid-level API. In my system, I have a main FES thread that maintains a list of 8 MidLevelChannelConfiguration objects. Each of these corresponds to one channel (1–8) and can be enabled/disabled from separate channel threads.

Initialization:

for c in CHANNELS:
    setattr(self, f'channel_{c}', Channel(self.__ctrl, c))
    self.channels.append(getattr(self, f'channel_{c}'))
    dummy_point = ChannelPoint(200, 0)  # 200 µs, 0 mA
    self.config_list.append(MidLevelChannelConfiguration(False, 0, 1000, [dummy_point]))

Each channel thread updates its corresponding config when stimulation conditions are met:

# Enabling stimulation
fes.config_list[self.__channel_number-1] = MidLevelChannelConfiguration(
    True, MAX_STEPS, self.__stimulation_period, self.__wave)

# Disabling stimulation
fes.config_list[self.__channel_number-1] = MidLevelChannelConfiguration(
    False, MAX_STEPS, self.__stimulation_period, self.__wave)

fes.update_config.set()

The FES thread sends the full 8-channel config to the device:

if self.update_config.is_set():
    await self.__mid_level_layer.update(self.config_list)
    ...
    self.channel_stimulation_states = await self.__mid_level_layer.get_current_data()

Problem

When enabling stimulation for channels 1, 2, and 5, only channels 1 and 2 visibly activate on the tester (e.g., LED indicators). Channel 5 shows no output, despite get_current_data() returning True for all three.
When channel 1 is disabled, channel 5 starts activating (visibly), and channel 2 stops — but get_current_data() still reports all three channels as active.
Finally, when channel 5 is disabled, channel 2 still reports active in get_current_data(), even though it's clearly off.

Workaround

I've found that if I keep all is_active=True and instead set current to zero to "disable" stimulation, the issue disappears:

# Disabling stimulation safely
fes.config_list[self.__channel_number] = MidLevelChannelConfiguration(
    True, 0, 1000, [dummy_point])  # is_active stays True, current = 0

Besides, I'm initializing each channel with the is_active Flag to True:

for c in CHANNELS:
    setattr(self, f'channel_{c}', Channel(self.__ctrl, c))
    self.channels.append(getattr(self, f'channel_{c}'))
    dummy_point = ChannelPoint(200, 0)  # 200 µs, 0 mA
    self.config_list.append(MidLevelChannelConfiguration(True, 0, 1000, [dummy_point]))

Root Cause Hypothesis

It seems that setting is_active=False causes the device to expect a reduced list of channel configurations (only active ones), but I’m still sending 8. This mismatch may cause internal reordering or misalignment of configs.
Keeping is_active=True for all channels maintains the bitmask, preventing channel misalignment. Disabling stimulation by using zero current instead avoids this issue.

Request

Please investigate and resolve this issue. This behavior is not intuitive and can lead to unsafe stimulation mismatches.

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions