from pcp_api import PCP_over_USB, PulsarActuator
from time import sleep, time
import csv
Common code¶
Most of the setup is shared with the other examples. The cells below include the required adapter and actuator initialization so this notebook can run on its own.
port = PCP_over_USB.get_port() # auto-detect
# port = "COM1"
print(f"Connecting to {port}")
adapter = PCP_over_USB(port)
actuator = PulsarActuator(adapter, 0)
if not actuator.connect():
print(f"Could not connect to the actuator {actuator.address}")
adapter.close()
raise SystemExit(1)
print(f"Connected to the actuator {actuator.address} (model: {actuator.model}, firmware: {actuator.firmware_version})")
Select the items to log¶
You can put the items to log from the actuator in a list. The items are defined in PulsarActuator.PCP_Items. You can choose from items like POSITION_FB, TORQUE_SENS, SPEED_FB, and more. In this example, we log the current in the three motor phases: IA, IB, and IC.
itemsToLog = [
PulsarActuator.PCP_Items.IA,
PulsarActuator.PCP_Items.IB,
PulsarActuator.PCP_Items.IC,
# add more items to log
]
Prepare CSV logging¶
This opens a CSV file for writing. The key thing is to order the items in the same way they will be logged. Because the items are defined in an enum, you can sort them by name to ensure a consistent column order.
file = open("log.csv", "w")
csv_writer = csv.writer(file, lineterminator="\n")
# add header
header = ["Timestamp"]
header.extend(sorted([item.name for item in itemsToLog])) # sorted by name for consistent order
csv_writer.writerow(header)
Callback function for feedback¶
Instead of showing the feedback in real time, like the other examples, this callback writes directly to the CSV file, which allows for higher rates. The feedback data is a dictionary where the keys are PulsarActuator.PCP_Items and the values are the corresponding readings. Again, we sort the keys by name to ensure a consistent order.
def actuator_feedback(address: int, feedback: dict):
line = [time()] # timestamp
line.extend([feedback[k] for k in sorted(feedback.keys(), key=lambda x: x.name)]) # sorted by enum name for consistent order
csv_writer.writerow(line)
Configure the feedback rates¶
We are going to use only high-frequency feedback at 1 kHz.
actuator.set_feedback_items(itemsToLog)
actuator.set_feedback_rate(actuator.Rates.RATE_1KHZ)
Start the actuator and clean up¶
Like in the other examples, you can choose the control mode, setpoint, and other parameters. In this example, we let it spin in SPEED mode for 3 seconds, then disconnect the actuator and close the adapter and CSV file.
try:
actuator.change_mode(PulsarActuator.Mode.SPEED)
actuator.change_setpoint(1.0) # rad/s
actuator.start()
actuator.set_feedback_callback(actuator_feedback)
sleep(3) # actuator_feedback() should be triggered during this time
except KeyboardInterrupt:
pass
finally:
actuator.disconnect() # also stops the actuator
sleep(0.1)
adapter.close()
file.close()
Example output¶
This code generates a CSV file named log.csv with the logged data. The first column is the timestamp, and the subsequent columns are the values of the items you logged.
| Timestamp | IA | IB | IC |
|---|---|---|---|
| 1642780800.123 | 0.15 | -0.08 | 0.12 |
| 1642780800.124 | 0.16 | -0.09 | 0.13 |
| 1642780800.125 | 0.17 | -0.10 | 0.14 |