Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help needed to encode parameters to measure flux linkage. #35

Open
eliashauksson opened this issue Sep 10, 2024 · 1 comment
Open

Help needed to encode parameters to measure flux linkage. #35

eliashauksson opened this issue Sep 10, 2024 · 1 comment

Comments

@eliashauksson
Copy link

I'm encountering difficulties with encoding parameters for the flux linkage measurement, and would appreciate some guidance.

The issue is that unlike other measurement done with this library the flux linkage (COMM_DETECT_MOTOR_FLUX_LINKAGE) needs parameters to perform the test (current, min_rpm, duty and internal resistance) (as seen in the firmware source code)

Now my question is how is it intended to encode input parameters for the measurement using the VESCMessage?

If I try to do this the usual style, recommended by the docs, I don't know how to add the parameters:

class GetFluxMeasurement(metaclass=pyvesc.VESCMessage):
    id = VedderCmd.COMM_DETECT_MOTOR_FLUX_LINKAGE
    fields = [("foc_motor_flux_linkage", "i", 1)]

fluxRequest = pyvesc.encode_request(GetFluxMeasurment)
fluxResponse = self.writeRead(fluxRequest) # self.writeRead is a function that sends the request and listens to the result

This doesn't perform the measurement, since the parameters are not encoded.

Here's what I have tried instead:

class GetFluxMeasurement(metaclass=pyvesc.VESCMessage):
    id = VedderCmd.COMM_DETECT_MOTOR_FLUX_LINKAGE
    fields = [
        ("current", "i", 1),
        ("min_rpm", "i", 1),
        ("duty", "i", 1),
        ("resistance", "i", 1),
        ("inductance", "i", 1),
    ]

    def setParameters(self, current, minRpm, duty, resistance, inductance):
        self.current = current
        self.min_rpm = minRpm
        self.duty = duty
        self.resistance = resistance
        self.inductance = inductance

fluxMeasurement = GetFluxMeasurement()
fluxMeasurement.setParameters(
    current=20000,
    minRpm=2000000,
    duty=300,
    resistance=int(self.VESCData["foc_motor_r"] * 1e3), # internal resistance from previous measurement.
    inductance=int(self.VESCData["foc_motor_l"] * 1e2), # internal inductance from previous measurement.
)
fluxRequest = pyvesc.encode_request(fluxMeasurement, header_only=False)
fluxResponse = self.writeRead(fluxRequest, timeout=15)

Note: I changed the encode_request() (here) so it would allow for header_only=False.

This code encodes the data into the following request: \x02\x15\x1a\x00\x00\x4e\x20\x00\x1e\x84\x80\x00\x00\x01\x2c\x00\x00\x77\x7f\x00\x00\x0b\x21\x0c\x0d\x03
compared to the request that gets sent using the vesc tool (recorded with wireshark): \x02\x15\x39\x00\x00\x4e\x20\x00\x1e\x84\x80\x00\x00\x01\x2c\x00\x00\x78\xe6\x00\x00\x0b\x2f\xc5\xb6\x03

Analysis:

  • \x02: Start of message (same for both)
  • \x15: Length of message (same for both)
  • \x1a vs. \x39: This one I don't really know how it gets defined.
  • \x00\x00\x4e\x20: Current parameter (20A) (same for both)
  • \x00\x1e\x84\x80: Min rpm parameter (2000ERPM/s) (same for both)
  • \x00\x00\x01\x2c: Duty parameter (0.3) (same for both)
  • \x00\x00\x77\x7f: Resistance parameter (30.59mΩ) (slightly different but that's expected)
  • \x00\x00\x0b\x21: Inductance parameter (28.49µH) (slightly different but that's expected), This parameter I'm not sure if I need to encode since the firmware source code doesn't seem to read it. But the request sent out by the vesc tool included those bytes and they match perfectly with the measured inductance value, so I assumed it's that.
  • \x0c\0d vs. \xc5\xb6: checksum created here, I assume this work correctly
  • \x03: End of message (same for both)

My request makes the motor spin (rather fast, and not accelerating smoothly as it does with the vesc tool), and then the response gives an error while decoding: Decoding error: unpack_from requires a buffer of at least 21 bytes for unpacking 20 bytes at offset 1 (actual buffer size is 5). I think this is because the vesc returns some flux linkage measurement (1 result) while the VESCMessage expects 5 results, since I defined 5 parameters in fields.

Any suggestions or guidance on how to properly encode parameters for the flux linkage measurement, and what might be causing the discrepancies in the encoded request, would be greatly appreciated!

@eliashauksson
Copy link
Author

I found a fix for the problem. It's definitely not the way it was intended to work but it works for me. The questions still stands on how to properly encode input parameters.

What I did is I made some variations in how the data is encoded and decoded:

def encodeFluxRequest(self, data):
    payload = pyvesc.protocol.base.VESCMessage.pack(data, header_only=False)
    payloadArray = bytearray(payload)
    payloadArray[0] = 0x39
    payload = bytes(payloadArray)
    packet = pyvesc.protocol.packet.codec.frame(payload)
    return packet

def decodeFluxResponse(self, response):
    try:
        fluxBytes = response[3:7]
        fluxValue = int.from_bytes(fluxBytes, byteorder="big", signed=False) * 1e-4
        return type("FluxResponse", (object,), {"foc_motor_flux_linkage": fluxValue}), 4
    
    except Exception as e:
        MessageHandler().columnPrint(f"Error decoding flux response: {e}")
        return None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant