Coder Social home page Coder Social logo

adafruit / adafruit_circuitpython_motor Goto Github PK

View Code? Open in Web Editor NEW
61.0 22.0 39.0 211 KB

Helpers for controlling PWM based motors and servos

License: MIT License

Python 100.00%
circuitpython servo servo-motor continuous-servo dc-motor stepper-motor hacktoberfest

adafruit_circuitpython_motor's Introduction

Introduction

Documentation Status

Discord

Build Status

Code Style: Black

This helper library provides higher level objects to control motors and servos based on one or more PWM outputs.

The PWM outputs can be any object that have a 16-bit duty_cycle attribute. Its assumed that the frequency has already been configured appropriately. (Typically 50hz for servos and 1600hz for motors.)

Dependencies

This driver depends on:

Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading the Adafruit library and driver bundle.

Installing from PyPI

On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally from PyPI. To install for current user:

pip3 install adafruit-circuitpython-motor

To install system-wide (this may be required in some cases):

sudo pip3 install adafruit-circuitpython-motor

To install in a virtual environment in your current project:

mkdir project-name && cd project-name
python3 -m venv .venv
source .venv/bin/activate
pip3 install adafruit-circuitpython-motor

Documentation

API documentation for this library can be found on Read the Docs.

For information on building library documentation, please check out this guide.

Contributing

Contributions are welcome! Please read our Code of Conduct before contributing to help this project stay welcoming.

adafruit_circuitpython_motor's People

Contributors

allplamp avatar brennen avatar caternuson avatar cedargrovestudios avatar deanm1278 avatar dhalbert avatar evaherrada avatar foamyguy avatar jedgarpark avatar jposada202020 avatar kattni avatar ladyada avatar makermelissa avatar siddacious avatar sommersoft avatar tannewt avatar tekktrik avatar tgs avatar williamlai2 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

Watchers

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

adafruit_circuitpython_motor's Issues

ServoKit problem on Jetson Nano

Hi,

While using the PCA9685 board with NVIDIA Jetson Nano through I2C I get a mysterious error while trying to run a simple example:

import busio
import board
from adafruit_servokit import ServoKit

i2c_bus0=(busio.I2C(board.SCL_1, board.SDA_1))
kit = ServoKit(channels=16, i2c=i2c_bus0)

kit.servo[0].angle = 180

Running this code leads to the following error:

Traceback (most recent call last):
  File "servo_test.py", line 10, in <module>
    kit.servo[0].angle = 180
  File "/home/belovictor/.local/lib/python3.6/site-packages/adafruit_servokit.py", line 140, in __getitem__
    import adafruit_motor.servo  # pylint: disable=import-outside-toplevel
  File "/home/belovictor/.local/lib/python3.6/site-packages/adafruit_motor/servo.py", line 18, in <module>
    from pwmio import PWMOut
  File "/home/belovictor/.local/lib/python3.6/site-packages/pwmio.py", line 45, in <module>
    raise NotImplementedError("pwmio not supported for this board.")
NotImplementedError: pwmio not supported for this board.
Exiting... 
Cleaning up pins

This looks weird as it should not depend on the availability of PWM pins on the Jetson board?
I have the following versions of Adafruit libraries installed on Jetson, all installed through pip:
adafruit-circuitpython-servokit (1.3.6)
adafruit-circuitpython-pca9685 (3.3.9)
adafruit-circuitpython-motor (3.3.2)
Adafruit-Blinka (6.15.0)

Thanks in advance

provide a way to turn off stepper

I can't find away to release the coils on a stepper in motor_featherwing. Could this be added to the library? Similar to release() in Adafruit_MotorShield. Thanks!

Incorporate DC Motor Characteristics as Optional Parameters

  1. Abstracting duty cycle to a -1.0 to +1.0 motor speed parameter could be improved to match actual motor speed by including the spin threshold voltage of the target DC motor. Since a DC motor's spin threshold voltage can be 10% to 20% of the DC motor's voltage range (1 to 2 volts for a 6-volt motor), a noticeable dead zone exists as the speed parameter value approaches zero. For example, the motor may stop spinning when the PWM duty cycle is less than 20%. The spin threshold is motor dependent and can be derived from the motor datasheet or through experimentation. Incorporating spin threshold would require that the motor controller's supply voltage be known by the driver.
  2. Limiting maximum duty cycle to match the DC motor's maximum voltage would allow the use of motors with maximum ratings lower than the motor controller's power source, while maintaining a full -1.0 to +1.0 motor speed parameter range. When powering a 3-volt motor from a 5-volt power source, for example, the speed parameter value for maximum speed would be +1.0 for the forward direction. This would also prevent overdriving the motor and/or motor controller board. The maximum voltage is motor dependent and can be derived from the motor datasheet or through experimentation. Incorporating a maximum voltage limit would require that the motor controller's supply voltage be known by the driver.

Motor kit / motor issues

Rather strange problem: Feather can't seem to process "from adafruit_motorkit import MotorKit". So far I have checked file names, versions, reinstalled motorkit and motor libraries, ensured they are in the right destination, and tried calling them with "import adafruit_motor" and "import adafruit_motorkit", both of which worked properly. Had little to no trouble getting files for the OLED to work and I followed the same steps, as well as closely following the guide: https://learn.adafruit.com/adafruit-stepper-dc-motor-featherwing/circuitpython. Needless to say this is preventing me from running the stepper motor I'm working with.

Stepper motor assumes PWM pins are variable frequency

When initializing a stepper with PWM pins, the stepper attempts to raise the PWM frequency to 2000 Hz if it is set to below 1500 Hz. This happens frequently as PWMOut pins default to 500 Hz. However, the stepper doesn't check that these values are writable (that the PWM pin's vairable_frequency is True) before writing, resulting in a very vague AttributeError when initialized with a default PWMOut. This should be pretty easy thing to check and throw a more descriptive error. The error happens on line 117 in stepper.py.

l293

How do you hook up an L293D? it needs 4 pins for directions and uses the 2 enable pin as pwd.

Servo motors are not disabling/releasing after setting angle to None

I'm using a Raspberry Pi 4 to control the PCA9685. I have generic MG996R-style servos connected (2 different brands). When I set the servo.angle = None, the servos just hold their current position without releasing.

I'm using servokit 1.3.13, pca9685 3.4.6, and motor 3.4.5

(I do have a version on a different raspberry pi that is running servokit 1.3.6, pca9685 3.39 and motor 3.3.2 that does work correctly, though it uses a different brand of servo).

I am not quite sure if this is due to a regression or certain brands of servos not recognizing the angle = None.

Any insight would be appreciated. I may try to upgrade the second raspberry pi and see if those servos get the issue. That would help narrow down if this is a per-servo-brand bug or a regression.

Add Micro Servo (#169) to servo_sweep.py example

It would be very useful for the min_pulse and max_pulse parameters for the TowerPro SG92R Micro Servo (PID# 169) to be included in the servo_sweep.py example. The following values were determined through experimentation with two servos purchased more than 12 months apart. Here's a suggested addition for the example:

# This is an example for the Micro servo - TowerPro SG-92R:
#   https://www.adafruit.com/product/169
# servo7 = servo.Servo(pca.channels[7], min_pulse=500, max_pulse=2400)

The current product page lists the values incorrectly as min_pulse=1000usec and max_pulse=2000us. I will submit a correction via the forums.

Missing Type Annotations

There are missing type annotations for some functions in this library.

The typing module does not exist on CircuitPython devices so the import needs to be wrapped in try/except to catch the error for missing import. There is an example of how that is done here:

try:
    from typing import List, Tuple
except ImportError:
    pass

Once imported the typing annotations for the argument type(s), and return type(s) can be added to the function signature. Here is an example of a function that has had this done already:

def wrap_text_to_pixels(
    string: str, max_width: int, font=None, indent0: str = "", indent1: str = ""
) -> List[str]:

If you are new to Git or Github we have a guide about contributing to our projects here: https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github

There is also a guide that covers our CI utilities and how to run them locally to ensure they will pass in Github Actions here: https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/check-your-code In particular the pages: Sharing docs on ReadTheDocs and Check your code with pre-commit contain the tools to install and commands to run locally to run the checks.

If you are attempting to resolve this issue and need help, you can post a comment on this issue and tag both @FoamyGuy and @kattni or reach out to us on Discord: https://adafru.it/discord in the #circuitpython-dev channel.

The following locations are reported by mypy to be missing type annotations:

  • adafruit_motor/servo.py:27
  • adafruit_motor/servo.py:31
  • adafruit_motor/servo.py:48
  • adafruit_motor/servo.py:88
  • adafruit_motor/servo.py:103
  • adafruit_motor/servo.py:126
  • adafruit_motor/servo.py:136
  • adafruit_motor/motor.py:51
  • adafruit_motor/motor.py:66
  • adafruit_motor/motor.py:101
  • adafruit_motor/motor.py:112
  • adafruit_motor/stepper.py:82
  • adafruit_motor/stepper.py:110
  • adafruit_motor/stepper.py:156

PWM output low average voltage problem with Servo motor

We have an MG996R model Servo motor.
The PWM output from the Coral is only 2.5V peak, and not very strong. We are using the HC4049 model buffer for this. But this doesn't work. We couldn't run our servo motor. Previously we have Raspberry PI 3 Model B and it was working smoothly.

We are following this article.
https://learn.adafruit.com/circuitpython-on-google-coral-linux-blinka/pwm-outputs-servos
We tried the codes in the "Servo Control" section.
Didn't get errors but nothing happened.
This doesn't work for me.
Do you have an idea to increase the power of the PWM output?
Thanks.

Minor: print statements in Example code fail on motor4.throttle

In my test environment "motor4.throttle" fails.
examples/dc_motor.py: line 35
print("throttle:", motor4.throttle)
Looks like the getter (@properties) code isn't working as expected

Thanks for maintaining excellent demo code!

My environment:
Adafruit HUZZAH
CircuitPython version: adafruit-circuitpython-feather_huzzah-2.3.1.bin
Bundle: adafruit-circuitpython-bundle-2.3.1-mpy-20180630.zip

Bundle downloaded by ampy ... put lib

Remove methods on DCMotor and ContinuousServo

DCMotor and ContinuousServo, but not regular Servo, provide a deinit() operation that sets .throttle to 0. However, they don't actually deinit anything: you could change the speed again in the future.

I'm not sure why they were added (they were in from the start). I think we could just delete them.

Came up while @caternuson was recoding an Arduino example (see #17), but this is a separate issue.

Tagging @tannewt for any comment.

Add method to manually set pulse width

On the Arduino, the writeMicroseconds method of the Servo class is useful for calibrating servos that don't align directly with the 1-2ms range. An equivalent function or field in the servo class would be more convenient than setting the pulse width range to a wide value and calculating the actual limits.

Naming and defaults for steppers could be changed

Hi!
I ran into some confusing when trying to work with the stepper library.
I found the naming of the different drive methods to be confusing. I had assumed SINGLE, the default option would be full-step drive (the motor moves a single step), but instead it's what most other references calls "wave drive" (see https://en.wikipedia.org/wiki/Stepper_motor, http://www.ti.com/lit/an/slva767a/slva767a.pdf). What most other references call full-step, the library calls DOUBLE. Additionally, that cited app note also mentions that:

The Wave Drive mode of operation is typically considered to be the most simple way of driving a stepper motor, but is also the least common mode of stepper motor driving, due to its shortfalls relative to Full-Step (torque) and Half-step (precision) patterns

I did notice much higher vibration and higher precision waveforms were needed when trying to drive motors this way.

My proposed solution to improve the library and cut down on confusion would be to rename DOUBLE to FULL_STEP and make this the default, then rename SINGLE to WAVE and INTERLEAVE to HALF_STEP.

Get Angle

Hi,

I would like to know if there is a way to query the current position (angle) of a servo. I can see there is a setter and a property but no getter. Is there another way to get this information ?

Thank you in advance
Arnaud

Does this library work with raspberry pi?

Hi, this is more a question than an issue but I think this should be documented.
Does this library work with vanilla python on a raspberry pi? If I understand, it does not because
I need to install this Circuit Python which is a completely separate operating system for the rasberry.
Am I right?

Recommend adding DCMotor controller decay mode getter/setter

Thanks to a wonderful question/assertion from @ZodiusInfuser (thank you), I experimented with a change of DCMotor's default "coasting" (fast) decay mode to "braking" (slow) decay mode. The result was even more significant than adjusting PWM frequencies for expanding the controllable motor speed range. Braking mode also linearized the relationship between throttle and motor speed as well as reducing sensitivity to higher (>500Hz) PWM frequencies. When coupled with a lower PWM frequency such as 25Hz, braking mode increased torque at low motor speeds and contributed to a very low spin threshold.

The braking mode change was successfully tested with TB6612 and DRV8833-based motor controllers (Crickit, MotorWing, and various breakouts), but hasn't been tested on the entire range of Adafruit motor controller boards and discrete h-bridge ICs -- issues aren't anticipated. I placed an order to obtain the rest of the Adafruit motor controller inventory and plan to complete the tests when the devices arrive late next week.

I expect to submit a PR to add a getter/setter to DCMotor to allow switching between braking and coasting modes on a motor-by-motor basis, keeping coasting as the default for compatibility with existing projects. Would like to have a discussion about the UI for the controller decay mode parameter. During testing I've been using:

motor1.decay_mode = 0  # Coasting mode
motor1.decay_mode = 1  # Braking mode

image
Result of mode comparison test at 25Hz. Note the improved spin threshold (speed = red line) and overall linearity of speed versus throttle (shown as PWM Equivalent Voltage).

provide a way to turn off a Servo

Servo doesn't have a way of setting the duty cycle to zero, so that the servo becomes unpowered completely. In Arduino land, detach() does that, because it removes the connection to the (hidden) pwm object (if I understand correctly).

@caternuson was trying to translate the first example here: https://learn.adafruit.com/analog-feedback-servos/servos-as-input-devices and encountered the API differences.

Proposal: add a turn_off() method, which sets the PWMOut duty cycle to zero. Setting the .fraction to any value after that will repower the servo to some non-zero duty cycle.

Tagging @tannewt, @TheKitty, and @ladyada here for any comments they may have.

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.