Coder Social home page Coder Social logo

liambindle / pyvesc Goto Github PK

View Code? Open in Web Editor NEW
68.0 8.0 52.0 104 KB

PyVESC is an easy to use and robust Python implementation of the VESC - Open Source ESC communication protocol

Home Page: https://pyvesc.readthedocs.io/en/latest/

License: Creative Commons Attribution 4.0 International

Python 100.00%
vesc motor-controller robust python

pyvesc's Introduction

PyVESC Build Status Documentation Status

PyVESC is aimed at being a easy to use and robust python implementation of the communication protocol used by the VESC - Open Source ESC by Benjamin Vedder. Its a great project with a really great community and I'd urge anyone interested in motor controllers to take a look at it.

That being said, if you're here you probably already know about it. This small project was written by Liam Bindle for the University of Saskatchewan Space Design Team as our primary language for non-embedded system is Python. You might wonder why you might need a library to handling packing and parsing VESC messages since Pythons standard struct module is great for almost exaclty this. PyVESC's usefulness comes from the fact that PyVESC is:

  • Well tested
  • Robust in handling corrupt packets in a buffer
  • Messages are easily extensible so that PyVESC can be used as a generic message/codec protocol (ie. at the USST we use PyVESC for sending messages to all of our embedded systems)
  • Implements a number of common-error catching exceptions to speed up your development

Documentation

For the latest version of PyVESC's documentation Read The Docs

Contributing

Obviously this is just a quick and dirty project; however, if you have any ideas, critiques or changes just let me know or submit a pull request.

License

Just like VESC, PyVESC is distributed under a Creative Commons ShareALike 4.0 International License.

pyvesc's People

Contributors

ausshir avatar cactode avatar groybe avatar jk213509 avatar liambindle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyvesc's Issues

Checksum should be CRCCCITT

While Carl was testing today we found that the checksum used by VESC appears to be CCITT. This should be an easy CRTL-H fix.

Setup motor foc

Hello, I would like to know if it is possible with your library to make a setup motor foc as in vesc tool.
If possible, do you have an example?
Thanks in advance,
Vincent LAMBERT.

error: missing attribute 'can_id'

Background:

  • I've got a logging script that I'm updating to work with the current version of pyvesc.
  • I pulled pyvesc as a folder within my logger repo, since PyPI still has an old version of pyvesc.

When I try to encode a GetValues request, I get an exception:

type object 'GetValues' has no attribute 'can_id'
Traceback (most recent call last):
  File "logger.py", line 102, in log_vesc
    send_packet = pyvesc.encode_request(GetValues)
  File "./pyvesc\pyvesc\protocol\interface.py", line 51, in encode_request
    msg_payload = pyvesc.protocol.base.VESCMessage.pack(msg_cls, header_only=True)
  File "./pyvesc\pyvesc\protocol\base.py", line 104, in pack
    if instance.can_id is not None:
AttributeError: type object 'GetValues' has no attribute 'can_id'

I was able to avoid this error by modifying VESCMessage in protocol\base.py.
I added this line to the VESCMessage constructor:
cls.can_id = None

With that change, pyvesc is working and I get correct data with GetValues.

Connection problems

hello everyone.

My name is Yonatan. My team and I are making an AUV and we're using the VESC 75/300 in order to control our main motor.
We do most of our coding in oython and we make use of ROS2 in order to manage the communication between different modules.

While workshopping in the lab, we had little to no connection problems with the VESC. For some reason, after transportting the AUV and locking it up, we cant seem to reach serial connection. Moreover, our computer doesn't even see anything connected to the port where we connect our VESC.

Our connection method:

image

We have a rules.d file that sends '/dev/jet' to '/dev/ttyACM0'

We're using a USB cable to connect the VESC to an UP board (https://up-board.org/wp-content/uploads/datasheets/UPDatasheetV8.5.pdf). While in transit, the VESC is powered and physically connected to the UP board, but the UP board itself is turned off. We started thinking this might be one of the reasons for our trouble but we're unable to confirm this yet.

Has anyone used the python PyVESC module and had a similar problem?

Thanks in advance,

Yonatan.

trouble with set_rpm()

I tried implementing a very basic code using PyVESC in order to get the motor running at certain RPM's.
For some reason any time I use the set_rpm() method I get a serious spike in the rpm and the measurement reads the RPM at -22389 or a number around that area.
I'd really appreciate any help with this.
Thanks in advance to any helpers.

P.S.
I'm using the Trampa VESC 75/300 controller and the TP power TP100 brushless motor.

How to determine sensor_mode of foc

My goal is to create a Python script with the same functionality as the VESCTOOL setupwizardfoc. I am using the Pyvesc library to encode and decode messages for the VESC. I send the COMM_DETECT_APPLY_ALL_FOC message, the motor runs correctly, and I receive a response corresponding to the COMM_GET_MCCONF message. So far, I am following the same logic that I observed in the VESCTOOL source code.

What I do not understand is the logic VESCTOOL uses to analyze the mcconf of the VESC and deduce the foc_sensor_mode. In the COMM_GET_MCCONF message that I receive, there are many parameters, as you can see in the text below. However, the only parameter whose value changes depending on the Sensor mode in the FOC tab of VESCTOOL is the following:

foc_duty_dowmramp_ki: 0.0 in sensorless
foc_duty_dowmramp_ki: 2.802596928649634e-45 in hall sensor
foc_duty_dowmramp_ki: 1.401298464324817e-45 in encoder

Message sent by the VESC in response to COMM_DETECT_APPLY_ALL_FOC:

pwm_mode: 131.0
comm_mode: 214.0
motor_type: 32.0
sensor_mode: 122.0
l_current_max: 2.351132194607322e-38
l_current_min: 38.619998931884766
l_in_current_max: -38.619998931884766
l_in_current_min: 99.0
l_abs_current_max: -60.0
l_min_erpm: 150.0
l_max_erpm: -100000.0
l_erpm_start: 100000.0
l_max_erpm_fbrake: 0.800000011920929
l_max_erpm_fbrake_cc: 300.0
l_min_vin: 1500.0
l_max_vin: 8.0
l_battery_cut_start: 57.0
l_battery_cut_end: 10.199999809265137
l_slow_abs_current: 65.0
l_temp_fet_start: 2.5243551976337916e-29
l_temp_fet_end: 85.0
l_temp_motor_start: 100.0
l_temp_motor_end: 85.0
l_temp_accel_dec: 100.0
l_min_duty: 0.15000000596046448
l_max_duty: 0.004999999888241291
l_watt_max: 0.949999988079071
l_watt_min: 1500000.0
sl_min_erpm: -1500000.0
sl_min_erpm_cycle_int_limit: 1.0
sl_max_fullbreak_current_dir_change: 1.0
sl_cycle_int_limit: 1.0
sl_phase_advance_at_br: 150.0
sl_cycle_int_rpm_br: 1100.0
sl_bemf_coupling_k: 10.0
hall_table_0: 66.0
hall_table_1: 120.0
hall_table_2: 0.0
hall_table_3: 0.0
hall_table_4: 63.0
hall_table_5: 76.0
hall_table_6: -52.0
hall_table_7: -51.0
hall_sl_erpm: 80000.0
foc_current_kp: 600.0
foc_current_ki: -1.7148602891164896e+38
foc_f_sw: 6.301567357904227e-36
foc_dt_us: 2000.0
foc_encoder_inverted: 61.0
foc_encoder_offset: 1.396456972987105e-20
foc_encoder_ratio: -4.076628851033237e-19
foc_sensor_mode: 195.0
foc_pll_kp: 8606176256.0
foc_pll_ki: -71.5005111694336
foc_motor_l: 1.1921019904548302e-07
foc_motor_r: -3.68937652243493e+19
foc_motor_flux_linkage: -8.828180325246348e-44
foc_observer_gain: -8.828180325246348e-44
foc_observer_gain_slow: -769658912768.0
foc_duty_dowmramp_kp: -769658912768.0
foc_duty_dowmramp_ki: 0.0
foc_openloop_rpm: 2000.0
foc_sl_openloop_hyst: 30000.0
foc_sl_openloop_time: 3.867000123136677e-05
foc_sl_d_current_duty: 0.0
foc_sl_d_current_factor: 0.08049999922513962
foc_hall_table_0: 59.0
foc_hall_table_1: 250.0
foc_hall_table_2: 105.0
foc_hall_table_3: 190.0
foc_hall_table_4: 75.0
foc_hall_table_5: 130.0
foc_hall_table_6: 157.0
foc_hall_table_7: 128.0
foc_sl_erpm: 0.05000000074505806
foc_sample_v0_v7: 65.0
foc_sample_high_current: 32.0
foc_sat_comp: 2.413596474953065e-41
foc_temp_comp: 0.0
foc_temp_comp_base_temp: 6.261674161866159e-39
s_pid_kp: 8.828180325246348e-44
s_pid_ki: 2.7200758163159178e+23
s_pid_kd: 107374592.0
s_pid_min_erpm: 6.162975822039155e-33
s_pid_allow_braking: 10.0
p_pid_kp: 5.507985782829056e-40
p_pid_ki: 9.925151316279335e-27
p_pid_kd: -1.1886727691035048e-07
p_pid_ang_div: 2.4923494486481196e-41
cc_startup_boost_duty: 0.0
cc_min_current: 1.2611686178923354e-44
cc_gain: -759.199951171875
cc_ramp_step_max: -136315920.0
m_fault_stop_time_ms: -1610612672.0
m_duty_ramp_step: -9.10844001811131e-44
m_current_backoff_gain: 1.0842109612795128e-19
m_encoder_counts: 4194304000.0
m_sensor_port_mode: 65.0
m_invert_direction: 58.0
m_drv8301_oc_mode: 131.0
m_drv8301_oc_adj: 18.0
m_bldc_f_sw_min: 3.992451074025009e+28
m_bldc_f_sw_max: 2.2168541705618606e-41
m_dc_f_sw: -107603880.0
m_ntc_motor_beta: -71.62945556640625

Struct error when reading firmware

I am using an Enertion Focbox 1.2. When I run the motor_example.py script I get this error:

Traceback (most recent call last):
  File "C:\Users\mgagv\OneDrive\Documents\Senior_Research\VESC\PyVESC\pyvesc\examples\motor_example.py", line 45, in <module>
    run_motor_using_with()
  File "C:\Users\mgagv\OneDrive\Documents\Senior_Research\VESC\PyVESC\pyvesc\examples\motor_example.py", line 10, in run_motor_using_with
    with VESC(serial_port=serial_port) as motor:
  File "c:\users\mgagv\onedrive\documents\senior_research\vesc\pyvesc\pyvesc\VESC\VESC.py", line 38, in __init__
    version = self.get_firmware_version()
  File "c:\users\mgagv\onedrive\documents\senior_research\vesc\pyvesc\pyvesc\VESC\VESC.py", line 127, in get_firmware_version
    return str(self.write(encode_request(msg), num_read_bytes=msg._full_msg_size))       
  File "c:\users\mgagv\onedrive\documents\senior_research\vesc\pyvesc\pyvesc\VESC\VESC.py", line 91, in write
    response, consumed = decode(self.serial_port.read(self.serial_port.in_waiting))      
  File "c:\users\mgagv\onedrive\documents\senior_research\vesc\pyvesc\pyvesc\protocol\interface.py", line 18, in decode
    return pyvesc.protocol.base.VESCMessage.unpack(msg_payload), consumed
  File "c:\users\mgagv\onedrive\documents\senior_research\vesc\pyvesc\pyvesc\protocol\base.py", line 85, in unpack
    data = list(struct.unpack_from(VESCMessage._endian_fmt + msg_type._fmt_fields, msg_bytes, 1))
struct.error: unpack_from requires a buffer of at least 4 bytes for unpacking 3 bytes at 
offset 1 (actual buffer size is 3)

I have verified I'm using the correct serial port. Any ideas as to why this is happening @LiamBindle?

how to DETECT_MOTOR_FLUX_LINKAGE

i use this code
class DetectMotorFluxLinkage(metaclass=VESCMessage):
""" Detects the motor flux linkage value.
"""
id = VedderCmd.COMM_DETECT_MOTOR_FLUX_LINKAGE

fields = [
    ('flux_linkage', 'i', 1000)# Adjust the scale as needed for the result
]

but it won't give the correct answer which was given in the vesctool but the same method is working for DETECT_MOTOR_R_L

MESSAGE_GET_VALUES Getter (and Setter?)

There is a need to read the MESSAGE_GET_VALUES messages as it gives all the RPM, Current, Power, Position etc. information.

The get-values branch contains the start of this work

As a first step, something like this should work:

def decode_test():
    buf_test = b'\x028\x04\x01\x14\x01\x14\x01\x14\x01\x14\x01\x14\x01\x14\x01\x14\x00\x00\x00\x18\x00\x00\x00\x06\x01\x10\x00\x00$u\x00\xef\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x01\t\x00\x00\x00\x00\x00\x00\xec\xbf\x00\x00\xec\xbf\x00\xa7g\x03'
    (a,b) = pyvesc.decode(buf_test)
    print(a, b)

Where buf_test represents the raw data coming off the serial port. This data is retreived by sending a blank message with id=4 (length=1), which also presents a challenge of having two message types with the same id.

A useful reference would be the VESC code in commands.c
https://github.com/vedderb/bldc/blob/master/commands.c#L162

Cannot import name 'VESC' from 'pyvesc'

Hi, I'm trying to run your motor_example.py, but I 'm getting the error "cannot import name 'VESC' from 'pyvesc'." Any idea why this may be? I believe I'm working in python 3, but I'm new to coding in Python. Thanks!

error: missing attribute 'can_id'

Background:

  • I've got a logging script that I'm updating to work with the current version of pyvesc.
  • I pulled pyvesc as a folder within my logger repo, since PyPI still has an old version of pyvesc.

When I try to encode a GetValues request, I get an exception:

type object 'GetValues' has no attribute 'can_id'
Traceback (most recent call last):
  File "logger.py", line 102, in log_vesc
    send_packet = pyvesc.encode_request(GetValues)
  File "./pyvesc\pyvesc\protocol\interface.py", line 51, in encode_request
    msg_payload = pyvesc.protocol.base.VESCMessage.pack(msg_cls, header_only=True)
  File "./pyvesc\pyvesc\protocol\base.py", line 104, in pack
    if instance.can_id is not None:
AttributeError: type object 'GetValues' has no attribute 'can_id'

I was able to avoid this error by modifying VESCMessage in protocol\base.py.
I added this line to the VESCMessage constructor:
cls.can_id = None

With that change, pyvesc is working and I get correct data with GetValues.

Does this work at all with VESC FW6 / FW5.03?

The code in this library predates these versions by many years, yet I see fairly recent commits and a lot of forks. One fork appears to target FW 3.x. Is there a newer version of this library that supports recent firmware versions, that I missed perhaps?

I want to get VESC 6 UART working with python, but I don't see any documentation / description on what the UART protocol actually is. Do such docs exist? For comparison, I currently use APD ESCs, and their UART protocol is described here.

UART only or CAN BUS compatible?

hi,
using the vesc tool and looking for a python CAN-BUS lib.
I didn't see anywhere the CAN Communication.
Do you know if this works with CAN as well, if so, have you tried it?

Protocol out of date

Hello and thank you for the excellent work you have done with PyVESC.

I am using PyVESC for a data logging script. When I got the script running, I noticed that some of the values from the GetValues message response were incorrect.

Here is a thread by another user who discovered the same problem: https://vesc-project.com/node/281

It seems that the new firmware (probably since version 3.xx) provides different values for the GetValues response. I modified my copy of messages/getters.py, replacing the fields in the GetValues class with the following:

fields = [
        ('temp_fet', 'h', 10),
        ('temp_motor', 'h', 10),
        ('current_motor', 'i', 100),
        ('current_in', 'i', 100),
        ('avg_id', 'i', 100),
        ('avg_iq', 'i', 100),
        ('duty_now', 'h', 1000),
        ('rpm', 'i', 1),
        ('v_in', 'h', 10),
        ('amp_hours', 'i', 10000),
        ('amp_hours_charged', 'i', 10000),
        ('watt_hours', 'i', 10000),
        ('watt_hours_charged', 'i', 10000),
        ('tachometer', 'i', 1),
        ('tachometer_abs', 'i', 1),
        ('mc_fault_code', 'c'),
        ('unknown', 'i', 1)            
]

Now I am getting proper values in my GetValues response. Other messages may also have been changed, but I haven't used the other messages for my application.

Error running documentation sample code

I am using this code :
import pyvesc
my_msg = pyvesc.SetDutyCycle(255)
print(my_msg.duty_cycle)
my_packet = pyvesc.encode(my_msg)

Traceback (most recent call last):
File "pyvesctest.py", line 1, in
import pyvesc
File "/usr/local/lib/python2.7/dist-packages/pyvesc/init.py", line 1, in
from pyvesc.interface import *
File "/usr/local/lib/python2.7/dist-packages/pyvesc/interface.py", line 1, in
import pyvesc.messages.base
File "/usr/local/lib/python2.7/dist-packages/pyvesc/messages/init.py", line 2, in
from pyvesc.messages.getters import *
File "/usr/local/lib/python2.7/dist-packages/pyvesc/messages/getters.py", line 3
class GetValues(metaclass=VESCMessage):
^
SyntaxError: invalid syntax

CAN Bus Forwarding

Nice work, everyone. Was wondering if you have considered integrating the ability to forward messages over CAN (e.g., using the COMM_FORWARD_CAN byte) for communication with multiple VESCs. Or is this something I missed?

can forward example and change of value?

Hello all and thanks for your work!

I have been trying to work out how the can forwarding is working but to no avail! Also, sniffing around the code trying to make the can forwarding work I have notices that in the base.py the _comm_forward_can is set to 33 whereas in the Vedder_BLDC_Commands.py this is 34.

For the testing, I have tried both of the above values and manually changing in base.py the cls.can_id = None to 1 - which is the id of the slave vesc and then just run a bare minimum script sending the rpm values.

In both cases, only the master led lights up and only the master motor is spinning.
I can verify that when manually changing the cls.can_id to something other than None, it goes into the
def pack(instance, header_only=None):
if header_only:
if instance.can_id is not None:

Shall I send the command from my script differently?
Current way:
ser.write(pyvesc.encode(SetRPM(7500)))
as in the example.

Are there any examples on how to actually can forward the messages?
Am i missing something?

Thank you very much for your time!

Best,

Mike

Needed example or docs for standard procedure on multiple getters

When using more than one getter the incoming buffer can get a bit messy, and simply decoding it directly and naively doesn't always get the intended message.

This applies specifically to turning on the encoder output (which is a periodic message) as well as requesting values (which is a triggered message).

Potentially, this could be a new feature - or it could be already implemented in a non-obvious way that I'm not seeing!

''None'' response.

I am trying to read the rpm of motor, which is actually connected to VESC 4 on firmware version 5. Hereby I am using PyVESC method to send the message from Jetson to VESC. With PyVESC, it send the message to VESC, which RPM or/and Current it should give to the VESC in order to get the desired rpm from the motor. Below you can see this in the code. But, i am not able to read the return value which gives motor. Here, I get "None".

import pyvesc
import serial
import time
import datetime
from pyvesc import GetValues, SetRPM, SetCurrent, SetRotorPositionMode, GetRotorPosition

port_object = serial.Serial("/dev/ttyACM0",115200, timeout=0.1)


message = pyvesc.SetRPM(10000)
cumessage = pyvesc.SetCurrent(10000)
packet = pyvesc.encode(message)
cupacket = pyvesc.encode(cumessage)


while True:
    data = ''
    port_object.write(packet)
    port_object.write(cupacket)
    print("data; ", port_object.in_waiting)
    #data = port_object.read(5)
    #print(data)
    port_object.write(pyvesc.encode_request(GetValues))
    #print(port_object.in_waiting)
                # Check if there is enough data back for a measurement
    if port_object.in_waiting > 78:
        (response, consumed) = pyvesc.decode(78)

        #packets = []
        #now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
        print("response: ",response)
        print("consumed: ", consumed)
        """for sensor, value in response.__dict__.items():
            data = {}
            data['measurement'] = sensor
            data['tags'] = {}
            data['tags']['source'] = 'vesc'
            data['time'] = now
            data['fields'] = {}
            data['fields']['value'] = value
            packets.append(data)"""
            #print(data)

      
#port_object.flush()
#VESCMessage = pyvesc.GetVaĺues()
#packet = pyvesc.decode(VESCMessage)
#print(pa)

this is the result:

data;  2681
response:  None
consumed:  0
data;  2620
response:  None
consumed:  18
data;  2559
response:  None
consumed:  36
data;  2498
response:  None
consumed:  40
data;  2437
response:  None
consumed:  47
data;  2376
response:  None
consumed:  23

Does anyone know what is the problem here, why it gets none? what could be the best solutions? Would be really great! Thanks in Advance.

No module named 'PyCRC'

Hi Liam Bindle
I am using /examples/get- values.py. The terminal told me this error:

from PyCRC . CRCCCITT import CRCCCITT

ModuleNot FoundError :No module named ' PyCRC '

Sent from PPHub

VESC uses big endian

This should be a fairly easy fix however test.py will need to be updates (specifically in the corruption testing) to account for the endian switch.

Documentation missing type information.

I am having trouble with SetCurrent and I noticed it didn't mention what the units or data types are. It throws an error when I try to use a float, but float is what I would want to use. Integer values don't seem to work either.

I noticed on dutycycle the example shows a value of 255, which makes me wonder if that is a 0-255 type of value rather than the float the docs suggest.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.