Skip to content

Commit

Permalink
maint and comments
Browse files Browse the repository at this point in the history
  • Loading branch information
FilipDominec committed Nov 29, 2024
1 parent 3c5c785 commit 131100a
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 26 deletions.
3 changes: 2 additions & 1 deletion c_code_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def generate_command_binary_interface():
# Append extracted docstring to the overall API reference
markdown_docs += f"\n\n## {command_name}\n\n{raw_docstring}\n\n"
markdown_docs += f"__Call signature:__\n\n`{command_name}({exec_header} _callback=None)`\n\n"
markdown_docs += f"__Parameters__:\n\n{param_docstring}\n"
markdown_docs += f"__Command parameters__:\n\n{param_docstring}\n"
#markdown_docs += f"__Report object's attributes__:\n\n{param_docstring}\n"
#markdown_docs += f"{raw_docstring}\n\n#### Arguments:"

# TODO once 16-bit msglen enabled: cmd_length will go +3, and 1st struct Byte must change to Half-int
Expand Down
40 changes: 22 additions & 18 deletions docs/PYTHON_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ Returns the digital state of a gpio pin.

Typically used when the pin is set to high-z or pull-up/down.

> [!CAUTION]
> The maximum allowed voltage at any pin is 3.3V.
__This command results in single near-immediate report.__

__Call signature:__
Expand Down Expand Up @@ -117,7 +120,7 @@ __Call signature:__

__Parameters__:

* channel_mask : Masks 0x01, 0x02, 0x04 are GPIO26, 27, 28; mask 0x08 internal reference, 0x10 temperature sensor
* channel_mask : Bits 0x01, 0x02, 0x04 are GPIO26, 27, 28; mask 0x08 internal reference, 0x10 temperature sensor
* blocksize : Number of sample points until a report is sent
* infinite : Disables blocks_to_send countdown; reports will keep coming until stopped by adc(blocks_to_send=0)
* blocks_to_send : Limits the number of reports to be sent (if the 'infinite' option is not set)
Expand Down Expand Up @@ -209,9 +212,9 @@ The "inertia" parameter allows for smooth ac-/de-celeration of the stepper,
preventing it from losing steps at startup even at high rotation speeds. The
default value is usually OK unless the stepper moves some heavy mass.

> [!WARNING]
> Never disconnect a stepper from its driver when powered; this results in burning
> the A4988 chip.
> [!CAUTION]
> Never disconnect a stepper from Stepstick when powered. Interrupting the
> current in its coils results in a voltage spike that may burn the driver chip.

__Call signature:__
Expand Down Expand Up @@ -263,13 +266,14 @@ Starts stepping motor movement from current position towards the new position gi
motor has to be initialized by stepper_init first (please refer to this command for more details on
stepper control).

The units of position are nanosteps, i.e., 1/256 of a microstep. So typically if you have a motor
with 200 steps per turn and your A4988-compatible driver is hard-wired for 16 microsteps/step, it takes
about a million (200x256x16 = 819200) nanosteps per turn.

The "speed" is in nanosteps per 0.1 ms update cycle; thus setting speed=82 turns the motor in
the above example once in second. Setting minimal speed=1 gives 0.732 RPM. Note most stepper motors
won't be able to turn much faster than 600 RPM.
> [!TIP]
> The units of position are nanosteps, i.e., 1/256 of a microstep. So typically if you have a motor
> with 200 steps per turn and your A4988-compatible driver is hard-wired for 16 microsteps/step, it takes
> about a million (200x256x16 = 819200) nanosteps per turn.
>
> The "speed" is in nanosteps per 0.1 ms update cycle; thus setting speed=82 turns the motor in
> the above example once in second. Setting minimal speed=1 gives 0.732 RPM. Note most stepper motors
> won't be able to turn much faster than 600 RPM.
The "endswitch_sensitive_down" option is by default set to 1, i.e., the motor will immediately stop its
movement towards more negative target positions when the end switch pin gets connected to zero.
Expand All @@ -284,12 +288,12 @@ Alternately, one can swap these two options if the endswitch is mounted on the h
of the range. Or one can use different settings before/after the first calibration to allow the motor
going beyond the end-switch(es) - if this is safe.

"reset_nanopos_at_endswitch" will reset the position only if endswitch triggers the end of the
movement. This is the recommended option for easy calibration of position at the endswitch.

"reset_nanopos_first" will reset the position before movement, so the target nanopos value given is
taken as relative to the actual position.
"reset_nanopos_at_endswitch" will reset the position if endswitch triggers the end of the
movement. This is a convenience option for easy calibration of position using the endswitch.
Note that the nanopos can also be manually reset by re-issuing the `stepper_init()` function.

"relative" if set to true, rp2daq will add the `to` value to current nanopos; movement
then becomes relative to the position of the motor when the command is issued.

When no callback is provided, this command blocks your program until the movement is finished.
Using asychronous commands one can easily make multiple steppers move at once.
Expand All @@ -303,7 +307,7 @@ or delayed by seconds, minutes or hours, depending on distance and speed. __

__Call signature:__

`stepper_move(stepper_number, to, speed, endswitch_sensitive_up=0, endswitch_sensitive_down=1, reset_nanopos_first=0, reset_nanopos_at_endswitch=0, _callback=None)`
`stepper_move(stepper_number, to, speed, endswitch_sensitive_up=0, endswitch_sensitive_down=1, relative=0, reset_nanopos_at_endswitch=0, _callback=None)`

__Parameters__:

Expand All @@ -312,7 +316,7 @@ __Parameters__:
* speed
* endswitch_sensitive_up
* endswitch_sensitive_down
* reset_nanopos_first
* relative
* reset_nanopos_at_endswitch
* _callback: optional report handling function; if set, makes this command asynchronous so it does not wait for report

Expand Down
2 changes: 1 addition & 1 deletion example_ADC_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
## User options
ADC_channel_names = {0:"GPIO 26", 1:"GPIO 27", 2:"GPIO 28", 3:"ref V", 4:"builtin thermo"}

channels = [1,2] # 0,1,2 are GPIOs 26-28; 3 is V_ref and 4 is internal thermometer
channels = [0,1] # 0,1,2 are GPIOs 26-28; 3 is V_ref and 4 is internal thermometer
#kSPS_total = 500 # note there is only one multiplexed ADC
kSPS_total = 50 # note there is only one multiplexed ADC

Expand Down
10 changes: 5 additions & 5 deletions include/stepper.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

struct __attribute__((packed)) {
uint8_t report_code;
int32_t initial_nanopos;
int32_t initial_nanopos; // This is the nanoposition the stepper was initialized to; always 0 in current firmware.
} stepper_init_report;

void stepper_init() {
Expand Down Expand Up @@ -38,10 +38,10 @@ void stepper_init() {
*
*/
struct __attribute__((packed)) {
uint8_t stepper_number; // min=0 max=15
uint8_t dir_gpio; // min=0 max=24
uint8_t step_gpio; // min=0 max=24
int8_t endswitch_gpio; // min=-1 max=24 default=-1
uint8_t stepper_number; // min=0 max=15 The ID of the stepper to be configured.
uint8_t dir_gpio; // min=0 max=24 Direction-controlling output pin.
uint8_t step_gpio; // min=0 max=24 Microstep-advancing output pin.
int8_t endswitch_gpio; // min=-1 max=24 default=-1 Optionally, this pin gets shorted at end switch.
int8_t disable_gpio; // min=-1 max=25 default=-1
uint32_t inertia; // min=0 max=10000 default=30
} * args = (void*)(command_buffer+1);
Expand Down
10 changes: 9 additions & 1 deletion usb_backend_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

import multiprocessing as mp

# This is a unique (?) trick to prevent the multiprocessing module from launching
# a "spawn bomb", without one having to annoyingly put the "if __name__ == '__main__'"
# guard into every script that imports this code.
# We just need to monkey-patch the start() method of mp.Process class so that it runs this
# file in the new process, instead of re-running the whole original program. The deadly
# recursion is thus avoided and no functionality is apparently harmed.
# Maybe this feature should become available in the official multiprocessing module, too.
class PatchedProcess(mp.Process):
def start(self, *args):
import sys
Expand All @@ -23,7 +30,8 @@ def usb_backend(report_queue, command_queue, terminate_queue, port_name):
"""
Default Python interpreter has a Global Interpreter Lock, due to which a high CPU load
in the user script can halt USB data reception, leading to USB buffer overflow and
corrupted reports.
corrupted reports. This was confirmed both on Linux and Windows, although they behave a bit
different.
Relegating the raw data handling to this separate process resolves the problem with GIL.
To keep the communication fluent without a tight busy loop in this process, USB input and
Expand Down

0 comments on commit 131100a

Please sign in to comment.