|
|
@@ -3,6 +3,7 @@ import serial_asyncio
|
|
|
from typing import List
|
|
|
from utils.logging import LoggerSingleton
|
|
|
import datetime
|
|
|
+import collections
|
|
|
|
|
|
MOVE_RATE = 50
|
|
|
APPROACHE_RATE = 10
|
|
|
@@ -29,23 +30,23 @@ class GRBLHandler:
|
|
|
return
|
|
|
|
|
|
logger.info("Connecting to GRBL...")
|
|
|
- try:
|
|
|
- self.reader, self.writer = await serial_asyncio.open_serial_connection(
|
|
|
- url = self.port,
|
|
|
- baudrate = self.baudrate
|
|
|
- )
|
|
|
- for _ in range(3):
|
|
|
- await self._process_response()
|
|
|
- logger.info("GRBL connected.")
|
|
|
- # Enable homing ($22=1)
|
|
|
- # Run homing cycle ($H)
|
|
|
- # Set absolute positioning mode (G90)
|
|
|
- # Set units to millimeters (G21)
|
|
|
- await self.send_gcode(['$22=1', '$H', 'G90', 'G21'])
|
|
|
- # await self.send_gcode(['$22=1', '$X', 'G90', 'G21'])
|
|
|
- except Exception as e:
|
|
|
- logger.error(f"Failed to connect to GRBL: {e}")
|
|
|
- raise
|
|
|
+ self.reader, self.writer = await serial_asyncio.open_serial_connection(
|
|
|
+ url = self.port,
|
|
|
+ baudrate = self.baudrate
|
|
|
+ )
|
|
|
+ init_response = []
|
|
|
+ for _ in range(3): # Flush initial responses
|
|
|
+ init_response.append(await self._process_response())
|
|
|
+ if not any(isinstance(response, collections.Iterable) and "Grbl" in response for response in init_response):
|
|
|
+ raise RuntimeError("Failed to connect to GRBL")
|
|
|
+
|
|
|
+ logger.info("GRBL connected.")
|
|
|
+ # Enable homing ($22=1)
|
|
|
+ # Run homing cycle ($H)
|
|
|
+ # Set absolute positioning mode (G90)
|
|
|
+ # Set units to millimeters (G21)
|
|
|
+ # await self.send_gcode(['$22=1', '$H', 'G90', 'G21'])
|
|
|
+ await self.send_gcode(['$22=1', '$X', 'G90', 'G21']) # This skips homing
|
|
|
|
|
|
async def send_gcode(self, commands: List[str]):
|
|
|
"""Send GCODE commands"""
|
|
|
@@ -60,12 +61,15 @@ class GRBLHandler:
|
|
|
self.writer.write(f"{cmd}\n".encode())
|
|
|
await self.writer.drain()
|
|
|
await self._process_response()
|
|
|
+ except RuntimeError as e:
|
|
|
+ logger.error(f"Failed to send G-Code commands: {str(e)}")
|
|
|
finally:
|
|
|
self.controller_active.clear()
|
|
|
|
|
|
async def wait_until_idle(self, timeout_s):
|
|
|
"""Wait until GRBL reports idle status"""
|
|
|
if self.debug:
|
|
|
+ asyncio.sleep(1)
|
|
|
return
|
|
|
|
|
|
start = datetime.datetime.now()
|
|
|
@@ -95,7 +99,7 @@ class GRBLHandler:
|
|
|
"""Process GRBL responses"""
|
|
|
if self.reader:
|
|
|
try:
|
|
|
- response = await asyncio.wait_for(self.reader.readline(), timeout=2.0) # 2 second timeout
|
|
|
+ response = await asyncio.wait_for(self.reader.readuntil(), timeout=4.0) # 2 second timeout
|
|
|
decoded = response.strip().decode("utf-8")
|
|
|
logger.debug(f"G-Code response: {decoded}")
|
|
|
|
|
|
@@ -112,10 +116,8 @@ class GRBLHandler:
|
|
|
return decoded
|
|
|
except asyncio.TimeoutError as e:
|
|
|
logger.warning("Timeout waiting for GRBL response")
|
|
|
- raise e
|
|
|
except Exception as e:
|
|
|
- logger.error(f"Failed to parse response: {e}")
|
|
|
- raise e
|
|
|
+ raise RuntimeError(f"Failed to process response: {e}")
|
|
|
|
|
|
def register_position_callback(self, callback):
|
|
|
"""Register callback for position updates
|