From 1346356d3cf95691ea0e3e87be335659d5513ec8 Mon Sep 17 00:00:00 2001 From: Anashuman Singh Date: Sun, 15 Jun 2025 14:26:07 +0530 Subject: [PATCH 1/6] fix: UART passthrough --- pslab/sciencelab.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pslab/sciencelab.py b/pslab/sciencelab.py index bf4b16f..1cbc81e 100644 --- a/pslab/sciencelab.py +++ b/pslab/sciencelab.py @@ -36,6 +36,7 @@ class ScienceLab: def __init__(self, device: ConnectionHandler | None = None): self.device = device if device is not None else autoconnect() + self.firmware = self.device.get_firmware_version() self.logic_analyzer = LogicAnalyzer(device=self.device) self.oscilloscope = Oscilloscope(device=self.device) self.waveform_generator = WaveformGenerator(device=self.device) @@ -293,7 +294,7 @@ def _uart_passthrough(self, baudrate: int) -> None: self.device.send_byte(CP.PASSTHROUGHS) self.device.send_byte(CP.PASS_UART) self.device.send_int(self._get_brgval(baudrate)) - self.device.interface.baudrate = baudrate + self.device.baudrate = baudrate def _uart_passthrough_legacy(self, baudrate: int) -> None: self.device.send_byte(CP.PASSTHROUGHS_LEGACY) From bc6b868c7a8dc9c480295a0a2d3c981daaf4746e Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 16 Jun 2025 14:35:46 +0200 Subject: [PATCH 2/6] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0f4a94..c3de7b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [4.0.1] - 2025-06-16 + +### Fixed + +Fix UART passthrough ([`1346356`](https://github.com/fossasia/pslab-python/commit/1346356d3cf95691ea0e3e87be335659d5513ec8)) (Anashuman Singh) + ## [4.0.0] - 2025-02-19 ### Changed @@ -41,6 +47,7 @@ _Changelog added in following release._ +[4.0.1]: https://github.com/fossasia/pslab-python/releases/tag/4.0.1 [4.0.0]: https://github.com/fossasia/pslab-python/releases/tag/4.0.0 [3.1.1]: https://github.com/fossasia/pslab-python/releases/tag/3.1.1 [3.1.0]: https://github.com/fossasia/pslab-python/releases/tag/3.1.0 From 1c5d19cfa394a71b3b66e7c9e12aa2580763c2db Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 16 Jun 2025 14:36:31 +0200 Subject: [PATCH 3/6] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3de7b0..5b7b312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixed -Fix UART passthrough ([`1346356`](https://github.com/fossasia/pslab-python/commit/1346356d3cf95691ea0e3e87be335659d5513ec8)) (Anashuman Singh) +- Fix UART passthrough ([`1346356`](https://github.com/fossasia/pslab-python/commit/1346356d3cf95691ea0e3e87be335659d5513ec8)) (Anashuman Singh) ## [4.0.0] - 2025-02-19 From c12fb51136c077400bd2f5fb1e0184a6b9dd6b6e Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 16 Jun 2025 14:39:53 +0200 Subject: [PATCH 4/6] Release 4.0.1 --- pslab/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pslab/__init__.py b/pslab/__init__.py index 174ca77..fde015c 100644 --- a/pslab/__init__.py +++ b/pslab/__init__.py @@ -17,4 +17,4 @@ "ScienceLab", ) -__version__ = "4.0.0" +__version__ = "4.0.1" From b97ee9a506ecbbeca8132e52b63bbf96c672890b Mon Sep 17 00:00:00 2001 From: Rahul Das Date: Tue, 15 Jul 2025 16:58:21 +0530 Subject: [PATCH 5/6] feat: Added RoboticArm (#255) --- pslab/external/motor.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index 71cff0c..f6caee1 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -7,6 +7,8 @@ >>> servo.angle = 30 # Turn motor to 30 degrees position. """ +import time +from typing import List from typing import Union from pslab.instrument.waveform_generator import PWMGenerator @@ -70,3 +72,40 @@ def _get_duty_cycle(self, angle): angle *= self._max_angle_pulse - self._min_angle_pulse # Scale angle += self._min_angle_pulse # Offset return angle / (self._frequency**-1 * MICROSECONDS) + + +class RoboticArm: + """Robotic arm controller for up to 4 servos.""" + + MAX_SERVOS = 4 + + def __init__(self, servos: List[Servo]) -> None: + if len(servos) > RoboticArm.MAX_SERVOS: + raise ValueError( + f"At most {RoboticArm.MAX_SERVOS} servos can be used, got {len(servos)}" + ) + self.servos = servos + + def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> None: + """Run a time-based schedule to move servos. + + Parameters + ---------- + timeline : List[List[int]] + A list of timesteps,where each sublist represents one timestep, + with angles corresponding to each servo. + + time_step : float, optional + Delay in seconds between each timestep. Default is 1.0. + """ + if len(timeline[0]) != len(self.servos): + raise ValueError("Each timestep must specify an angle for every servo") + + tl_len = len(timeline[0]) + if not all(len(tl) == tl_len for tl in timeline): + raise ValueError("All timeline entries must have the same length") + + for tl in timeline: + for i, s in enumerate(self.servos): + s.angle = tl[i] + time.sleep(time_step) From 8ae580effcddaf4d341e66098a96beab77f86b3d Mon Sep 17 00:00:00 2001 From: Rahul Das Date: Fri, 18 Jul 2025 03:09:34 +0530 Subject: [PATCH 6/6] feat: RoboticArm CSV import/export (#256) --- pslab/external/motor.py | 62 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/pslab/external/motor.py b/pslab/external/motor.py index f6caee1..1fba065 100644 --- a/pslab/external/motor.py +++ b/pslab/external/motor.py @@ -10,8 +10,11 @@ import time from typing import List from typing import Union +import csv +import os from pslab.instrument.waveform_generator import PWMGenerator +from datetime import datetime MICROSECONDS = 1e6 @@ -96,7 +99,7 @@ def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> Non with angles corresponding to each servo. time_step : float, optional - Delay in seconds between each timestep. Default is 1.0. + Delay in seconds between each timestep. Default is 1.0. """ if len(timeline[0]) != len(self.servos): raise ValueError("Each timestep must specify an angle for every servo") @@ -107,5 +110,60 @@ def run_schedule(self, timeline: List[List[int]], time_step: float = 1.0) -> Non for tl in timeline: for i, s in enumerate(self.servos): - s.angle = tl[i] + if tl[i] is not None: + s.angle = tl[i] time.sleep(time_step) + + def import_timeline_from_csv(self, filepath: str) -> List[List[int]]: + """Import timeline from a CSV file. + + Parameters + ---------- + filepath : str + Absolute or relative path to the CSV file to be read. + + Returns + ------- + List[List[int]] + A timeline consisting of servo angle values per timestep. + """ + timeline = [] + + with open(filepath, mode="r", newline="") as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + angles = [] + for key in ["Servo1", "Servo2", "Servo3", "Servo4"]: + value = row[key] + if value == "null": + angles.append(None) + else: + angles.append(int(value)) + timeline.append(angles) + + return timeline + + def export_timeline_to_csv( + self, timeline: List[List[Union[int, None]]], folderpath: str + ) -> None: + """Export timeline to a CSV file. + + Parameters + ---------- + timeline : List[List[Union[int, None]]] + A list of timesteps where each sublist contains servo angles. + + folderpath : str + Directory path where the CSV file will be saved. The filename + will include a timestamp to ensure uniqueness. + """ + timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + filename = f"Robotic_Arm{timestamp}.csv" + filepath = os.path.join(folderpath, filename) + + with open(filepath, mode="w", newline="") as csvfile: + writer = csv.writer(csvfile) + writer.writerow(["Timestep", "Servo1", "Servo2", "Servo3", "Servo4"]) + for i, row in enumerate(timeline): + pos = ["null" if val is None else val for val in row] + writer.writerow([i] + pos) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy