|
@@ -36,7 +36,7 @@ class LoaderSystem:
|
|
|
|
|
|
|
|
self.pump_controller = PumpController(self.config, self.gpio)
|
|
self.pump_controller = PumpController(self.config, self.gpio)
|
|
|
|
|
|
|
|
- self.feeder_prepared = False
|
|
|
|
|
|
|
+ self.next_cell_id = ""
|
|
|
|
|
|
|
|
async def run(self):
|
|
async def run(self):
|
|
|
await self.controller.connect()
|
|
await self.controller.connect()
|
|
@@ -75,6 +75,39 @@ class LoaderSystem:
|
|
|
self.logger.info(f"Cell {cell_id_str} voltage({voltage}) is good")
|
|
self.logger.info(f"Cell {cell_id_str} voltage({voltage}) is good")
|
|
|
return True
|
|
return True
|
|
|
|
|
|
|
|
|
|
+ async def _prepare_feeder_cell(self) -> None:
|
|
|
|
|
+ """
|
|
|
|
|
+ Handles the process of preparing a cell in the feeder. Loops until a suitable cell is found or no cell is detected.
|
|
|
|
|
+ Returns the cell_id_str if a cell is prepared, otherwise an empty string.
|
|
|
|
|
+ """
|
|
|
|
|
+ io_conf = self.config.gpio
|
|
|
|
|
+ while not self.next_cell_id:
|
|
|
|
|
+ self.next_cell_id = self.vision.read_datamatrix()
|
|
|
|
|
+ if not self.next_cell_id:
|
|
|
|
|
+ self.logger.debug("No cell detected")
|
|
|
|
|
+ return # No cell detected
|
|
|
|
|
+
|
|
|
|
|
+ self.gpio.set_pin(io_conf.probe_pin, 1)
|
|
|
|
|
+ await asyncio.sleep(0.1) # Wait for probe to deploy
|
|
|
|
|
+ cell_v = await self.i2c.read_channel(1) # Measure cell voltage
|
|
|
|
|
+ self.gpio.set_pin(io_conf.probe_pin, 0)
|
|
|
|
|
+ self.logger.debug(f"Cell voltage: {cell_v}")
|
|
|
|
|
+
|
|
|
|
|
+ if self.check_cell_voltage(cell_v, self.next_cell_id):
|
|
|
|
|
+ return # Desired case!
|
|
|
|
|
+
|
|
|
|
|
+ # Discard cell directly from feeder
|
|
|
|
|
+ self.logger.info(f"Cell {self.next_cell_id} voltage({cell_v}) is bad, discarding cell")
|
|
|
|
|
+ self.gpio.do_step(io_conf.measure_dir_pin, io_conf.measure_step_pin, 1600, 200) # Exactly half a turn
|
|
|
|
|
+ await asyncio.sleep(1) # Wait for cell to be ejected
|
|
|
|
|
+ try:
|
|
|
|
|
+ self.next_cell_id = ""
|
|
|
|
|
+ await self.controller.pick_cell_from_feeder()
|
|
|
|
|
+ await self.controller.dropoff_cell()
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ self.logger.error(f"Failed to process cell {self.next_cell_id}: {str(e)}")
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
async def _loader_loop(self):
|
|
async def _loader_loop(self):
|
|
|
"""
|
|
"""
|
|
|
Main loop for the loader system.
|
|
Main loop for the loader system.
|
|
@@ -88,49 +121,22 @@ class LoaderSystem:
|
|
|
|
|
|
|
|
# Check for free slots loop
|
|
# Check for free slots loop
|
|
|
while True:
|
|
while True:
|
|
|
- cell_id_str = ""
|
|
|
|
|
- # Discard cells until acceptable cell is found
|
|
|
|
|
- while not self.feeder_prepared:
|
|
|
|
|
- # Check if cell is present in feeder
|
|
|
|
|
- cell_id_str = self.vision.read_datamatrix()
|
|
|
|
|
- if not cell_id_str:
|
|
|
|
|
- self.logger.debug("No cell detected")
|
|
|
|
|
- break # No cell detected
|
|
|
|
|
-
|
|
|
|
|
- # Measure cell voltage with probe
|
|
|
|
|
- io_conf = self.config.gpio
|
|
|
|
|
- self.gpio.set_pin(io_conf.probe_pin, 1)
|
|
|
|
|
- await asyncio.sleep(0.1) # Wait for probe to deploy
|
|
|
|
|
- cell_v = await self.i2c.read_channel(1) # Measure cell voltage
|
|
|
|
|
- self.gpio.set_pin(io_conf.probe_pin, 0)
|
|
|
|
|
- self.logger.debug(f"Cell voltage: {cell_v}")
|
|
|
|
|
-
|
|
|
|
|
- if self.check_cell_voltage(cell_v, cell_id_str):
|
|
|
|
|
- self.feeder_prepared = True
|
|
|
|
|
- break # Desired case!
|
|
|
|
|
-
|
|
|
|
|
- # Discard cell directly from feeder
|
|
|
|
|
- self.logger.info(f"Cell {cell_id_str} voltage({cell_v}) is bad, discarding cell")
|
|
|
|
|
- self.gpio.do_step(io_conf.measure_dir_pin, io_conf.measure_step_pin, 1600, 200) # Exactly half a turn
|
|
|
|
|
- await asyncio.sleep(1) # Wait for cell to be ejected
|
|
|
|
|
- try:
|
|
|
|
|
- await self.controller.pick_cell_from_feeder()
|
|
|
|
|
- await self.controller.dropoff_cell()
|
|
|
|
|
- except Exception as e:
|
|
|
|
|
- self.logger.error(f"Failed to process cell {cell_id}: {str(e)}")
|
|
|
|
|
- break
|
|
|
|
|
|
|
+ # Discard cells until acceptable cell is found as next_cell_id
|
|
|
|
|
+ if not self.next_cell_id:
|
|
|
|
|
+ await self._prepare_feeder_cell()
|
|
|
|
|
|
|
|
slot = self.controller.get_next_free_slot()
|
|
slot = self.controller.get_next_free_slot()
|
|
|
if not slot:
|
|
if not slot:
|
|
|
break # No free slots available
|
|
break # No free slots available
|
|
|
|
|
|
|
|
- if not cell_id_str:
|
|
|
|
|
- break
|
|
|
|
|
|
|
+ if not self.next_cell_id:
|
|
|
|
|
+ break # Continue with process_finished_measurement
|
|
|
|
|
|
|
|
# Pick and place new cell
|
|
# Pick and place new cell
|
|
|
- cell_id = int(cell_id_str)
|
|
|
|
|
|
|
+ cell_id = int(self.next_cell_id)
|
|
|
self.logger.info(f"Processing cell {cell_id}")
|
|
self.logger.info(f"Processing cell {cell_id}")
|
|
|
cell = self.controller.add_cell(cell_id)
|
|
cell = self.controller.add_cell(cell_id)
|
|
|
|
|
+ io_conf = self.config.gpio
|
|
|
try:
|
|
try:
|
|
|
self.gpio.do_step(io_conf.measure_dir_pin, io_conf.measure_step_pin, 1600, 200) # Exactly half a turn
|
|
self.gpio.do_step(io_conf.measure_dir_pin, io_conf.measure_step_pin, 1600, 200) # Exactly half a turn
|
|
|
await asyncio.sleep(1) # Wait for cell to be ejected
|
|
await asyncio.sleep(1) # Wait for cell to be ejected
|