Skip to content

A python library that provides non-blocking, timed transitions from one value to another. For example, it is useful for projects that use servos, LEDs, graphics and other things that need to move more naturally.

License

Notifications You must be signed in to change notification settings

pvanallen/VarSpeedPython

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VarSpeedPython library

Description

This Python library is descended from the VarspeedServo library (https://github.com/netlabtoolkit/VarSpeedServo), originally written for the Arduino in C++ (which was itself built on an early Arduino servo library). Unlike the old Arduino library, VarSpeedPython is not tied to servos, and can be used more generally for timed moves from one value to another. It is also not bound to any processor architecture with hardware interrupts etc.

The library is designed for projects that need to control values over time. For example: setting the new angle of a servo in 3.0 seconds; setting the brightness of an LED by fading up in 2.5 seconds; or moving a graphic on a screen. You can set the amount of time for a change in value, and apply easing to each move to make it seem more natural.

It also provides a function for running sequences of moves (that can be looped or repeated if desired), where each move in the sequence has a new position and speed. More than one move or sequence can be run at the same time.

VarSpeedPython objects are designed to be called repeatedly from within an event loop and do not block execution.

Circuit Python Setup

To set up on a CircuitPython hardware device:

  • Put varspeed/varspeed.py in the lib directory on CIRCUITPY
  • Put varspeed/easing_functions.py in the lib directory on CIRCUITPY
  • Copy the python code from any of the examples/ into code.py or main.py at the top of CIRCUITPY

Code Examples - non-CircuitPython

  • move_simple.py — a non-CircuitPython dependent example that can be run in any Python environment
  • sequence_simple.py — a non-CircuitPython dependent example that can be run in any Python environment

Code Examples - CircuitPython

Easing Types

For any move (even within a sequence), you can set an easing function using the following classic Robert Penner easing types. For an animated and graphed visualization of each easing type, see https://easings.net. For an explanation of the use of easing, see this article: Animation Principles in UI Design: Understanding Easing

Warning

The names on https://easings.net do not reflect the names used in the easing_functions.py file. The names used in this project start with the type of easing used by the function (e.g Linear, Quad, Circular) followed by the word Ease and finally whether it's "In", "Out" or "InOut". For example: the function listed on the website as easeInOutCubic is called CubicEaseInOut in this library. The reason behind this naming scheme is to be consistent with python classes naming conventions. The list with all this library's easing functions with the correct names are listed below. Note also that the new gamma functions are not listed on the easings.net page

  • LinearInOut (essentially no easing)

  • QuadEaseInOut, QuadEaseIn, QuadEaseOut

  • CubicEaseIn, CubicEaseOut, CubicEaseInOut

  • QuarticEaseIn, QuarticEaseOut, QuarticEaseInOut

  • QuinticEaseIn, QuinticEaseOut, QuinticEaseInOut

  • SineEaseIn, SineEaseOut, SineEaseInOut

  • CircularEaseIn, CircularEaseOut, CircularEaseInOut

  • ExponentialEaseIn, ExponentialEaseOut, ExponentialEaseInOut

  • ElasticEaseIn, ElasticEaseOut, ElasticEaseInOut

  • BackEaseIn, BackEaseOut, BackEaseInOut

  • BounceEaseIn, BounceEaseOut, BounceEaseInOut

  • GammaEaseIn, GammaEaseOut, GammaEaseInOut

  • NEW: GAMMA EASING - provides gamma correction of 2.8 for dimming LEDs and other lighting to match human vision characteristics. EXPLANATION of gamma correction: https://www.advateklighting.com/blog/guides/dithering-and-gamma-correction

CLASS: Vspeed

class Vspeed():

Provides a non-blocking object that can be called repeatedly from an event loop with the move() and sequence() functions to generate a timed series of values from a current position to a new position(s)

init

def __init__(self, init_position = 0, result = "int", debug = False):

Creates and initializes a Vspeed object.

Args

  • init_position (int/float) : sets the initial position of the object.
  • result (string = "int" or "float") : sets the type of the returned position.
  • debug (True/False) : sets debugging mode on or off, resulting in prints on or off.

Returns

  • object : returns a Vspeed object

move

def move(self, new_position = 0, time_secs = 2.0, steps = 20, easing = "LinearInOut", delay_start = 0.0):

Generates a series of values that transition from the current position to a new_position.

Args

  • new_position (float or int) : position output will change to over time_secs
  • time_secs (int) : time for the transition to the new_position
  • steps (int) : number of steps to change from the start position to the new_position
  • easing (string) : the easing function to use for the transition
  • delay_start (float) : the number of seconds to delay the start of the move - this helps when putting several moves together in a sequence so there can be pauses between moves

Returns

  • position (int or float) : each new position, marked by changed being True
  • running (Boolean) : if true there are more steps to go in the transition/move
  • changed (Boolean) : indicates if the latest value is different from the previous value

sequence

def sequence(self, sequence, loop_max = 1):

Creates a series of values in a sequence of moves as specified in the sequence array.

Args

  • sequence (array of tuples) : perform a sequence of moves (position,time,steps,easing,delay_start[optiona]) in the array.
  • loop_max (int) : how many times to loop the sequence, zero means loop forever.

Returns

  • position (int or float) : each new position, marked by changed being True
  • running (Boolean) : if true there are more steps to go in the transition/move
  • changed (Boolean) : indicates if the latest position value is different from the previous value

sequence_change_seq_num

def sequence_change_seq_num(self, seq_position = 0):

Sets the current sequence number.

Args

  • seq_position (int) : jump to the element in the sequence[seq_position] array.

Returns

nothing

sequence_run

def sequence_run(self, value = True):

Pauses or unpauses a running sequence.

Args

  • value (Boolean) : pauses (False) or unpauses (True) the run of the sequence.

Returns

nothing

set_position

def set_position(self, position = 0):

Sets the current position from which the next move will proceed

Args

  • position (int or float) : sets the current position of the object

Returns

nothing

set_bounds

def set_bounds(self, lower_bound = 0, upper_bound = 1000, bounded=True):

Sets the lower and upper bounds of values returned by a move or sequence

Args

  • lower_bound (int) : sets the lower allowed bound of the output of a move or sequnce
  • upper_bound (int) : sets the upper allowed bound of the output of a move or sequnce
  • bounded (Boolean) : turns bounds checking on (True - Default) or off (False)

Returns

nothing

About

A python library that provides non-blocking, timed transitions from one value to another. For example, it is useful for projects that use servos, LEDs, graphics and other things that need to move more naturally.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages