Jelajahi Sumber

fix reverse

tuanchris 3 bulan lalu
induk
melakukan
f63589c30a
3 mengubah file dengan 67 tambahan dan 6 penghapusan
  1. 26 5
      main.py
  2. 8 1
      modules/led/ball_tracking_manager.py
  3. 33 0
      static/js/settings.js

+ 26 - 5
main.py

@@ -1974,15 +1974,22 @@ async def dw_leds_get_idle_timeout():
 async def set_ball_tracking_config(request: dict):
 async def set_ball_tracking_config(request: dict):
     """Update ball tracking configuration"""
     """Update ball tracking configuration"""
     try:
     try:
+        logger.info(f"=== Ball Tracking Config Update ===")
+        logger.info(f"Received request: {request}")
+
         # Update state variables
         # Update state variables
         if "enabled" in request:
         if "enabled" in request:
             state.ball_tracking_enabled = request["enabled"]
             state.ball_tracking_enabled = request["enabled"]
+            logger.info(f"Set enabled: {request['enabled']}")
         if "mode" in request:
         if "mode" in request:
             state.ball_tracking_mode = request["mode"]
             state.ball_tracking_mode = request["mode"]
+            logger.info(f"Set mode: {request['mode']}")
         if "led_offset" in request:
         if "led_offset" in request:
             state.ball_tracking_led_offset = request["led_offset"]
             state.ball_tracking_led_offset = request["led_offset"]
+            logger.info(f"Set led_offset: {request['led_offset']}")
         if "reversed" in request:
         if "reversed" in request:
             state.ball_tracking_reversed = request["reversed"]
             state.ball_tracking_reversed = request["reversed"]
+            logger.info(f"Set reversed: {request['reversed']}")
         if "spread" in request:
         if "spread" in request:
             state.ball_tracking_spread = max(1, min(10, request["spread"]))
             state.ball_tracking_spread = max(1, min(10, request["spread"]))
         if "lookback" in request:
         if "lookback" in request:
@@ -1998,6 +2005,7 @@ async def set_ball_tracking_config(request: dict):
 
 
         # Save to state.json
         # Save to state.json
         state.save()
         state.save()
+        logger.info(f"Saved to state.json - reversed is now: {state.ball_tracking_reversed}")
 
 
         # Update manager config if it exists
         # Update manager config if it exists
         if state.ball_tracking_manager:
         if state.ball_tracking_manager:
@@ -2090,10 +2098,15 @@ async def test_led_for_calibration(request: dict):
 
 
         controller = state.led_controller.get_controller()
         controller = state.led_controller.get_controller()
 
 
-        # Clear all LEDs
-        controller.clear_all_leds()
+        # Ensure power is off so effect loop doesn't interfere
+        # (calling set_power(0) is safe even if already off)
+        controller.set_power(0)
 
 
-        # Light up only the selected LED in white
+        # Brief pause to ensure effect loop has stopped
+        await asyncio.sleep(0.05)
+
+        # Clear all LEDs and light only the selected one
+        controller.clear_all_leds()
         controller.set_single_led(led_index, (255, 255, 255), 0.5)
         controller.set_single_led(led_index, (255, 255, 255), 0.5)
 
 
         if controller._pixels:
         if controller._pixels:
@@ -2130,12 +2143,20 @@ async def calibrate_ball_tracking():
         # Turn off all LEDs except LED 0 to show reference
         # Turn off all LEDs except LED 0 to show reference
         try:
         try:
             controller = state.led_controller.get_controller()
             controller = state.led_controller.get_controller()
+
+            # First, power off to stop the effect loop from overwriting our manual commands
+            controller.set_power(0)
+
+            # Wait a moment for effect loop to stop
+            await asyncio.sleep(0.1)
+
+            # Now set LED 0 manually (power is off so effect loop won't interfere)
             controller.clear_all_leds()
             controller.clear_all_leds()
-            # Light up only LED 0 in white
             controller.set_single_led(0, (255, 255, 255), 0.5)
             controller.set_single_led(0, (255, 255, 255), 0.5)
             if controller._pixels:
             if controller._pixels:
                 controller._pixels.show()
                 controller._pixels.show()
-            logger.info("LED 0 illuminated as reference")
+
+            logger.info("LED 0 illuminated as reference (effect loop paused)")
         except Exception as e:
         except Exception as e:
             logger.warning(f"Failed to set reference LED: {e}")
             logger.warning(f"Failed to set reference LED: {e}")
 
 

+ 8 - 1
modules/led/ball_tracking_manager.py

@@ -143,14 +143,20 @@ class BallTrackingManager:
 
 
         # Calculate LED index (0° = LED 0 before offset)
         # Calculate LED index (0° = LED 0 before offset)
         led_index = int((theta / 360.0) * self.num_leds)
         led_index = int((theta / 360.0) * self.num_leds)
+        original_index = led_index
 
 
         # Apply user-defined offset
         # Apply user-defined offset
         offset = self.config.get("led_offset", 0)
         offset = self.config.get("led_offset", 0)
         led_index = (led_index + offset) % self.num_leds
         led_index = (led_index + offset) % self.num_leds
 
 
         # Reverse direction if needed
         # Reverse direction if needed
-        if self.config.get("reversed", False):
+        is_reversed = self.config.get("reversed", False)
+        if is_reversed:
+            led_index_before_reverse = led_index
             led_index = (self.num_leds - led_index) % self.num_leds
             led_index = (self.num_leds - led_index) % self.num_leds
+            logger.debug(f"Theta={theta:.1f}° -> LED {original_index} + offset {offset} = {led_index_before_reverse} -> REVERSED to {led_index}")
+        else:
+            logger.debug(f"Theta={theta:.1f}° -> LED {original_index} + offset {offset} = {led_index}")
 
 
         return led_index
         return led_index
 
 
@@ -201,6 +207,7 @@ class BallTrackingManager:
         """Update configuration at runtime"""
         """Update configuration at runtime"""
         self.config.update(config)
         self.config.update(config)
         logger.info(f"Ball tracking config updated: {config}")
         logger.info(f"Ball tracking config updated: {config}")
+        logger.info(f"Current reversed setting: {self.config.get('reversed', False)}")
 
 
     def get_status(self) -> Dict:
     def get_status(self) -> Dict:
         """Get current tracking status"""
         """Get current tracking status"""

+ 33 - 0
static/js/settings.js

@@ -1906,6 +1906,31 @@ function initCalibrationWizard() {
     // Reverse direction toggle
     // Reverse direction toggle
     reverseDirectionToggle.addEventListener('change', () => {
     reverseDirectionToggle.addEventListener('change', () => {
         reversed = reverseDirectionToggle.checked;
         reversed = reverseDirectionToggle.checked;
+        console.log('Toggle changed! Reversed:', reversed);
+
+        // Visual feedback - find the <p> element more robustly
+        const container = reverseDirectionToggle.closest('.flex');
+        console.log('Found container:', container);
+
+        if (container) {
+            const directionLabel = container.querySelector('p');
+            console.log('Found label:', directionLabel);
+
+            if (directionLabel) {
+                if (reversed) {
+                    directionLabel.textContent = 'LED strip runs counter-clockwise (REVERSED)';
+                    directionLabel.classList.add('font-semibold', 'text-orange-600');
+                } else {
+                    directionLabel.textContent = 'Enable if your LED strip runs counter-clockwise';
+                    directionLabel.classList.remove('font-semibold', 'text-orange-600');
+                }
+                console.log('Label updated successfully');
+            } else {
+                console.error('Could not find label element');
+            }
+        } else {
+            console.error('Could not find container element');
+        }
     });
     });
 
 
     // Confirm calibration
     // Confirm calibration
@@ -1922,6 +1947,12 @@ function initCalibrationWizard() {
                 reversed: reversed
                 reversed: reversed
             };
             };
 
 
+            console.log('=== CALIBRATION COMPLETION ===');
+            console.log('Current LED:', currentLed);
+            console.log('Reversed flag:', reversed);
+            console.log('Toggle checked state:', reverseDirectionToggle.checked);
+            console.log('Sending config:', JSON.stringify(config));
+
             const response = await fetch('/api/ball_tracking/config', {
             const response = await fetch('/api/ball_tracking/config', {
                 method: 'POST',
                 method: 'POST',
                 headers: {'Content-Type': 'application/json'},
                 headers: {'Content-Type': 'application/json'},
@@ -1929,6 +1960,8 @@ function initCalibrationWizard() {
             });
             });
 
 
             const data = await response.json();
             const data = await response.json();
+            console.log('Backend response:', data);
+            console.log('=== END CALIBRATION ===');
 
 
             if (data.success) {
             if (data.success) {
                 // Show completion
                 // Show completion