From a5202496da4b59139a0536acf12b305d7a90ace2 Mon Sep 17 00:00:00 2001 From: "mostafa.safaie" Date: Thu, 17 Jun 2021 17:35:11 +0100 Subject: [PATCH 1/5] prevent the out-of-range problem caused by mouse sensor data --- com/data_logger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com/data_logger.py b/com/data_logger.py index 484457f9..48bef927 100755 --- a/com/data_logger.py +++ b/com/data_logger.py @@ -111,5 +111,5 @@ def save_analog_chunk(self, ID, sampling_rate, timestamp, data_array): for i, x in enumerate(data_array): t = int(timestamp + i*ms_per_sample) self.analog_files[ID].write(t.to_bytes(4,'little', signed=True)) - self.analog_files[ID].write(x.to_bytes(4,'little', signed=True)) + self.analog_files[ID].write(x.to_bytes(4,'little', signed=False)) self.analog_files[ID].flush() \ No newline at end of file From a8c99f1dc8187301477b03a63bfcfea2338d6a4c Mon Sep 17 00:00:00 2001 From: "mostafa.safaie" Date: Mon, 28 Jun 2021 13:10:55 +0100 Subject: [PATCH 2/5] 0 --- com/data_logger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com/data_logger.py b/com/data_logger.py index 48bef927..484457f9 100755 --- a/com/data_logger.py +++ b/com/data_logger.py @@ -111,5 +111,5 @@ def save_analog_chunk(self, ID, sampling_rate, timestamp, data_array): for i, x in enumerate(data_array): t = int(timestamp + i*ms_per_sample) self.analog_files[ID].write(t.to_bytes(4,'little', signed=True)) - self.analog_files[ID].write(x.to_bytes(4,'little', signed=False)) + self.analog_files[ID].write(x.to_bytes(4,'little', signed=True)) self.analog_files[ID].flush() \ No newline at end of file From ec7a0036b09913d02ec3973df190eadbf1559c82 Mon Sep 17 00:00:00 2001 From: AtMostafa Date: Mon, 28 Jun 2021 08:58:40 -0700 Subject: [PATCH 3/5] add env file --- env.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 env.yml diff --git a/env.yml b/env.yml new file mode 100644 index 00000000..e630b7ff --- /dev/null +++ b/env.yml @@ -0,0 +1,14 @@ +#To install the environment, run in a terminal: conda env create -f env.yml +name: pycontrol +dependencies: + - python=3.* + - pyserial + - numpy + - notebook + - matplotlib=3.* + - jupyterlab=1.* + - scikit-learn=0.21.* + - pip=19.* + - pip: + - pyqt5 + - pyqtgraph From 9a923f654bee7a7a744de2f9cabcc678b5126b43 Mon Sep 17 00:00:00 2001 From: Mostafa Safaie Date: Wed, 16 Oct 2024 15:51:43 +0100 Subject: [PATCH 4/5] Delete hardware_definition.py to allow merging with the tasks repo --- config/hardware_definition.py | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 config/hardware_definition.py diff --git a/config/hardware_definition.py b/config/hardware_definition.py deleted file mode 100644 index 85340216..00000000 --- a/config/hardware_definition.py +++ /dev/null @@ -1,16 +0,0 @@ -# This hardware definition specifies that 3 pokes are plugged into ports 1-3 and a speaker into -# port 4 of breakout board version 1.2. The houselight is plugged into the center pokes solenoid socket. - -from devices import * - -board = Breakout_1_2() - -# Instantiate Devices. -left_poke = Poke(board.port_1, rising_event = 'left_poke' , falling_event = 'left_poke_out' ) -center_poke = Poke(board.port_2, rising_event = 'center_poke', falling_event = 'center_poke_out') -right_poke = Poke(board.port_3, rising_event = 'right_poke' , falling_event = 'right_poke_out') - -speaker = Audio_board(board.port_4) - -# Aliases -houselight = center_poke.SOL \ No newline at end of file From 463605a5887c8feb50eac24be3b61173a82c839d Mon Sep 17 00:00:00 2001 From: Mostafa Safaie Date: Wed, 16 Oct 2024 15:56:13 +0100 Subject: [PATCH 5/5] update devices dir --- devices/{more devices => }/_audio_player.py | 78 ++++++++--------- devices/{ => more devices}/_LED_driver.py | 8 +- devices/{ => more devices}/_audio_board.py | 26 +++--- devices/{ => more devices}/_breakout_1_2.py | 48 +++++------ devices/{ => more devices}/_poke.py | 44 +++++----- devices/{ => more devices}/_rotary_encoder.py | 86 +++++++++---------- devices/{ => more devices}/_stepper_motor.py | 38 ++++---- 7 files changed, 164 insertions(+), 164 deletions(-) rename devices/{more devices => }/_audio_player.py (96%) rename devices/{ => more devices}/_LED_driver.py (97%) rename devices/{ => more devices}/_audio_board.py (97%) rename devices/{ => more devices}/_breakout_1_2.py (97%) rename devices/{ => more devices}/_poke.py (97%) rename devices/{ => more devices}/_rotary_encoder.py (98%) rename devices/{ => more devices}/_stepper_motor.py (97%) diff --git a/devices/more devices/_audio_player.py b/devices/_audio_player.py similarity index 96% rename from devices/more devices/_audio_player.py rename to devices/_audio_player.py index 21fc8171..9a14618f 100644 --- a/devices/more devices/_audio_player.py +++ b/devices/_audio_player.py @@ -1,39 +1,39 @@ -from machine import UART -from array import array -import pyb - -class Dfplayer(): - - def __init__(self, uart=1, timeout=1): - self.uart = UART(uart, 9600) - self.uart.init(9600, bits=8, parity=None, stop=1, timeout=timeout) - self.cmd_bytes = array('B', [0x7E, 0xFF, 0x06, 0, 0, 0, 0, 0, 0, 0xEF]) - self.command(0x3F) # Initialisation. - - def command(self, cmd, param_1=0, param_2=0): - self.cmd_bytes[3] = cmd - self.cmd_bytes[5] = param_1 - self.cmd_bytes[6] = param_2 - self.cmd_bytes[7:9] = (-sum(self.cmd_bytes[1:7])).to_bytes(2,'big') # checksum - self.uart.write(self.cmd_bytes) - - def play(self, folder_num, file_num): - self.command(0x0F, folder_num, file_num) - - def stop(self): - self.command(0x16) - - def set_volume(self, volume): # Between 1 - 30 - self.command(0x06, 0, volume) - -class Audio_player(Dfplayer): - - def __init__(self, port): - self._enable_L = pyb.Pin(port.POW_A, pyb.Pin.OUT) - self._enable_R = pyb.Pin(port.POW_B, pyb.Pin.OUT) - self.set_enabled(True, True) - super().__init__(port.UART) - - def set_enabled(self, left=True, right=True): - self._enable_L.value(bool(left)) - self._enable_R.value(bool(right)) +from machine import UART +from array import array +import pyb + +class Dfplayer(): + + def __init__(self, uart=1, timeout=1): + self.uart = UART(uart, 9600) + self.uart.init(9600, bits=8, parity=None, stop=1, timeout=timeout) + self.cmd_bytes = array('B', [0x7E, 0xFF, 0x06, 0, 0, 0, 0, 0, 0, 0xEF]) + self.command(0x3F) # Initialisation. + + def command(self, cmd, param_1=0, param_2=0): + self.cmd_bytes[3] = cmd + self.cmd_bytes[5] = param_1 + self.cmd_bytes[6] = param_2 + self.cmd_bytes[7:9] = (-sum(self.cmd_bytes[1:7])).to_bytes(2,'big') # checksum + self.uart.write(self.cmd_bytes) + + def play(self, folder_num, file_num): + self.command(0x0F, folder_num, file_num) + + def stop(self): + self.command(0x16) + + def set_volume(self, volume): # Between 1 - 30 + self.command(0x06, 0, volume) + +class Audio_player(Dfplayer): + + def __init__(self, port): + self._enable_L = pyb.Pin(port.POW_A, pyb.Pin.OUT) + self._enable_R = pyb.Pin(port.POW_B, pyb.Pin.OUT) + self.set_enabled(True, True) + super().__init__(port.UART) + + def set_enabled(self, left=True, right=True): + self._enable_L.value(bool(left)) + self._enable_R.value(bool(right)) diff --git a/devices/_LED_driver.py b/devices/more devices/_LED_driver.py similarity index 97% rename from devices/_LED_driver.py rename to devices/more devices/_LED_driver.py index 3eb018c9..856fbe29 100644 --- a/devices/_LED_driver.py +++ b/devices/more devices/_LED_driver.py @@ -1,5 +1,5 @@ -import pyControl.hardware as _h - -class LED_driver(_h.Digital_output): - def __init__(self, port): +import pyControl.hardware as _h + +class LED_driver(_h.Digital_output): + def __init__(self, port): super().__init__(port.DIO_A, pulse_enabled=True) \ No newline at end of file diff --git a/devices/_audio_board.py b/devices/more devices/_audio_board.py similarity index 97% rename from devices/_audio_board.py rename to devices/more devices/_audio_board.py index 004b57ba..b028396f 100644 --- a/devices/_audio_board.py +++ b/devices/more devices/_audio_board.py @@ -1,14 +1,14 @@ -import pyb -import pyControl.audio as _a - -class Audio_board(_a.Audio_output): - - def __init__(self, port): - assert port.DAC is not None, '! Audio board needs port with DAC.' - assert port.I2C is not None, '! Audio board needs port with I2C.' - self.I2C = pyb.I2C(port.I2C) - self.I2C.init(pyb.I2C.MASTER) - super().__init__(port.DAC) - - def set_volume(self, V): # Set volume of audio output, range 0 - 127 +import pyb +import pyControl.audio as _a + +class Audio_board(_a.Audio_output): + + def __init__(self, port): + assert port.DAC is not None, '! Audio board needs port with DAC.' + assert port.I2C is not None, '! Audio board needs port with I2C.' + self.I2C = pyb.I2C(port.I2C) + self.I2C.init(pyb.I2C.MASTER) + super().__init__(port.DAC) + + def set_volume(self, V): # Set volume of audio output, range 0 - 127 self.I2C.mem_write(int(V), 46, 0) \ No newline at end of file diff --git a/devices/_breakout_1_2.py b/devices/more devices/_breakout_1_2.py similarity index 97% rename from devices/_breakout_1_2.py rename to devices/more devices/_breakout_1_2.py index 5540a65a..4dff2b99 100644 --- a/devices/_breakout_1_2.py +++ b/devices/more devices/_breakout_1_2.py @@ -1,25 +1,25 @@ -import pyControl.hardware as _h - -class Breakout_1_2(_h.Mainboard): - def __init__(self): - # Inputs and outputs. - self.port_1 = _h.Port(DIO_A='X1', DIO_B='X2' , POW_A='Y7' , POW_B='Y8' , POW_C='Y11', UART=4) - self.port_2 = _h.Port(DIO_A='Y3', DIO_B='Y4' , POW_A='X4' , POW_B='X18', POW_C='Y12') - self.port_3 = _h.Port(DIO_A='X9', DIO_B='X10', POW_A='X7' , POW_B='X19', - DIO_C='X5', DAC=1 , I2C=1, UART=1) - self.port_4 = _h.Port(DIO_A='Y9', DIO_B='Y10', POW_A='X8' , POW_B='X20', - DIO_C='X6', DAC=2 , I2C=2, UART=3) - self.port_5 = _h.Port(DIO_A='Y5', DIO_B='Y6' , POW_A='X21', POW_B='X22') - self.port_6 = _h.Port(DIO_A='X3', DIO_B='X11' , POW_A='Y1' , POW_B='Y2') - self.BNC_1 = 'X12' - self.BNC_2 = 'X11' - self.DAC_1 = 'X5' - self.DAC_2 = 'X6' - self.button = 'X17' - - -class Devboard_1_2(Breakout_1_2): - def __init__(self): - self.set_pull_updown({'down':['X1','X2','Y3','Y4','X9','X10', - 'Y9','Y10','Y5','Y6','Y1','X3']}) +import pyControl.hardware as _h + +class Breakout_1_2(_h.Mainboard): + def __init__(self): + # Inputs and outputs. + self.port_1 = _h.Port(DIO_A='X1', DIO_B='X2' , POW_A='Y7' , POW_B='Y8' , POW_C='Y11', UART=4) + self.port_2 = _h.Port(DIO_A='Y3', DIO_B='Y4' , POW_A='X4' , POW_B='X18', POW_C='Y12') + self.port_3 = _h.Port(DIO_A='X9', DIO_B='X10', POW_A='X7' , POW_B='X19', + DIO_C='X5', DAC=1 , I2C=1, UART=1) + self.port_4 = _h.Port(DIO_A='Y9', DIO_B='Y10', POW_A='X8' , POW_B='X20', + DIO_C='X6', DAC=2 , I2C=2, UART=3) + self.port_5 = _h.Port(DIO_A='Y5', DIO_B='Y6' , POW_A='X21', POW_B='X22') + self.port_6 = _h.Port(DIO_A='X3', DIO_B='X11' , POW_A='Y1' , POW_B='Y2') + self.BNC_1 = 'X12' + self.BNC_2 = 'X11' + self.DAC_1 = 'X5' + self.DAC_2 = 'X6' + self.button = 'X17' + + +class Devboard_1_2(Breakout_1_2): + def __init__(self): + self.set_pull_updown({'down':['X1','X2','Y3','Y4','X9','X10', + 'Y9','Y10','Y5','Y6','Y1','X3']}) super().__init__() \ No newline at end of file diff --git a/devices/_poke.py b/devices/more devices/_poke.py similarity index 97% rename from devices/_poke.py rename to devices/more devices/_poke.py index f3060ce9..774fb2ea 100644 --- a/devices/_poke.py +++ b/devices/more devices/_poke.py @@ -1,23 +1,23 @@ -import pyControl.hardware as _h - -class Poke(): - # Single IR beam, LED and Solenoid. - def __init__(self, port, rising_event = None, falling_event = None, debounce = 5): - self.input = _h.Digital_input(port.DIO_A, rising_event, falling_event, debounce) - self.LED = _h.Digital_output(port.POW_A) - self.SOL = _h.Digital_output(port.POW_B) - if port.POW_C is not None: - self.POW_C = _h.Digital_output(port.POW_C) - - def value(self): - return self.input.value() - - -class _Poke(): - # Poke class used in multi-poke devices. - def __init__(self, input_pin, LED_pin, rising_event, falling_event, debounce): - self.input = _h.Digital_input(input_pin, rising_event, falling_event, debounce) - if LED_pin: self.LED = _h.Digital_output(LED_pin) - - def value(self): +import pyControl.hardware as _h + +class Poke(): + # Single IR beam, LED and Solenoid. + def __init__(self, port, rising_event = None, falling_event = None, debounce = 5): + self.input = _h.Digital_input(port.DIO_A, rising_event, falling_event, debounce) + self.LED = _h.Digital_output(port.POW_A) + self.SOL = _h.Digital_output(port.POW_B) + if port.POW_C is not None: + self.POW_C = _h.Digital_output(port.POW_C) + + def value(self): + return self.input.value() + + +class _Poke(): + # Poke class used in multi-poke devices. + def __init__(self, input_pin, LED_pin, rising_event, falling_event, debounce): + self.input = _h.Digital_input(input_pin, rising_event, falling_event, debounce) + if LED_pin: self.LED = _h.Digital_output(LED_pin) + + def value(self): return self.input.value() \ No newline at end of file diff --git a/devices/_rotary_encoder.py b/devices/more devices/_rotary_encoder.py similarity index 98% rename from devices/_rotary_encoder.py rename to devices/more devices/_rotary_encoder.py index a189ed26..7ba751a5 100644 --- a/devices/_rotary_encoder.py +++ b/devices/more devices/_rotary_encoder.py @@ -1,44 +1,44 @@ -import pyb -from pyControl.hardware import Analog_input - -class Rotary_encoder(Analog_input): - # Quadrature output rotary encoder. - def __init__(self, name, sampling_rate, output='velocity', threshold=None, - rising_event=None, falling_event=None, bytes_per_sample=2, reverse=False): - assert output in ('velocity', 'position'), 'ouput argument must be \'velocity\' or \'position\'.' - assert bytes_per_sample in (2,4), 'bytes_per_sample must be 2 or 4' - self.output_velocity = output == 'velocity' - self.reverse = reverse - self.pin_a = pyb.Pin('X1', pyb.Pin.AF_PP, pull=pyb.Pin.PULL_NONE, af=pyb.Pin.AF1_TIM2) - self.pin_b = pyb.Pin('X2', pyb.Pin.AF_PP, pull=pyb.Pin.PULL_NONE, af=pyb.Pin.AF1_TIM2) - self.counter_max_value = 0xffff - self.counter_half_max_value = self.counter_max_value // 2 - self.enc_timer = pyb.Timer(2, prescaler=1, period=self.counter_max_value) - self.enc_channel = self.enc_timer.channel(1, pyb.Timer.ENC_AB) - self.position = 0 - self.velocity = 0 - Analog_input.__init__(self, None, name, int(sampling_rate), threshold, rising_event, - falling_event, data_type={2:'h',4:'l'}[bytes_per_sample]) - - def read_sample(self): - # Read value of encoder counter, correct for rollover, return position or velocity. - new_counter_value = self.enc_timer.counter() - counter_change = new_counter_value - self.counter_value - self.counter_value = new_counter_value - if counter_change > self.counter_half_max_value: # Backward counter rollover. - counter_change = counter_change - self.counter_max_value - elif counter_change < -self.counter_half_max_value: # Forward counter rollover. - counter_change = counter_change & self.counter_max_value - if self.reverse: - counter_change = -counter_change - self.position += counter_change - self.velocity = counter_change * self.sampling_rate - if self.output_velocity: - return self.velocity - else: - return self.position - - def _start_acquisition(self): - # Start sampling analog input values. - self.counter_value = self.enc_timer.counter() +import pyb +from pyControl.hardware import Analog_input + +class Rotary_encoder(Analog_input): + # Quadrature output rotary encoder. + def __init__(self, name, sampling_rate, output='velocity', threshold=None, + rising_event=None, falling_event=None, bytes_per_sample=2, reverse=False): + assert output in ('velocity', 'position'), 'ouput argument must be \'velocity\' or \'position\'.' + assert bytes_per_sample in (2,4), 'bytes_per_sample must be 2 or 4' + self.output_velocity = output == 'velocity' + self.reverse = reverse + self.pin_a = pyb.Pin('X1', pyb.Pin.AF_PP, pull=pyb.Pin.PULL_NONE, af=pyb.Pin.AF1_TIM2) + self.pin_b = pyb.Pin('X2', pyb.Pin.AF_PP, pull=pyb.Pin.PULL_NONE, af=pyb.Pin.AF1_TIM2) + self.counter_max_value = 0xffff + self.counter_half_max_value = self.counter_max_value // 2 + self.enc_timer = pyb.Timer(2, prescaler=1, period=self.counter_max_value) + self.enc_channel = self.enc_timer.channel(1, pyb.Timer.ENC_AB) + self.position = 0 + self.velocity = 0 + Analog_input.__init__(self, None, name, int(sampling_rate), threshold, rising_event, + falling_event, data_type={2:'h',4:'l'}[bytes_per_sample]) + + def read_sample(self): + # Read value of encoder counter, correct for rollover, return position or velocity. + new_counter_value = self.enc_timer.counter() + counter_change = new_counter_value - self.counter_value + self.counter_value = new_counter_value + if counter_change > self.counter_half_max_value: # Backward counter rollover. + counter_change = counter_change - self.counter_max_value + elif counter_change < -self.counter_half_max_value: # Forward counter rollover. + counter_change = counter_change & self.counter_max_value + if self.reverse: + counter_change = -counter_change + self.position += counter_change + self.velocity = counter_change * self.sampling_rate + if self.output_velocity: + return self.velocity + else: + return self.position + + def _start_acquisition(self): + # Start sampling analog input values. + self.counter_value = self.enc_timer.counter() Analog_input._start_acquisition(self) \ No newline at end of file diff --git a/devices/_stepper_motor.py b/devices/more devices/_stepper_motor.py similarity index 97% rename from devices/_stepper_motor.py rename to devices/more devices/_stepper_motor.py index 0fd30fe2..e4e2bc2b 100644 --- a/devices/_stepper_motor.py +++ b/devices/more devices/_stepper_motor.py @@ -1,20 +1,20 @@ -import pyControl.hardware as _h - -class Stepper_motor(): - def __init__(self, port=None, direction_pin=None, step_pin=None): - if port: - direction_pin = port.DIO_A - step_pin = port.DIO_B - self._direction = _h.Digital_output(direction_pin) - self._step = _h.Digital_output(step_pin, pulse_enabled=True) - - def forward(self, step_rate, n_steps=False): - self._direction.off() #set direction forward - self._step.pulse(step_rate, n_pulses=n_steps) - - def backward(self, step_rate, n_steps=False): - self._direction.on() #set direction back - self._step.pulse(step_rate, n_pulses=n_steps) - - def stop(self): +import pyControl.hardware as _h + +class Stepper_motor(): + def __init__(self, port=None, direction_pin=None, step_pin=None): + if port: + direction_pin = port.DIO_A + step_pin = port.DIO_B + self._direction = _h.Digital_output(direction_pin) + self._step = _h.Digital_output(step_pin, pulse_enabled=True) + + def forward(self, step_rate, n_steps=False): + self._direction.off() #set direction forward + self._step.pulse(step_rate, n_pulses=n_steps) + + def backward(self, step_rate, n_steps=False): + self._direction.on() #set direction back + self._step.pulse(step_rate, n_pulses=n_steps) + + def stop(self): self._step.off() \ No newline at end of file