diff --git a/LifeTrac-v25/CHANGELOG_FLOW_VALVES.md b/LifeTrac-v25/CHANGELOG_FLOW_VALVES.md new file mode 100644 index 0000000..8a31ef6 --- /dev/null +++ b/LifeTrac-v25/CHANGELOG_FLOW_VALVES.md @@ -0,0 +1,258 @@ +# LifeTrac v25 - Flow Valve Configuration Feature + +## Overview + +Added support for two different proportional flow valve configurations to the LifeTrac v25: +- **Option 1 (Default)**: Single valve controls all hydraulics +- **Option 2 (Advanced)**: Dual valves for independent left/right control + +This feature addresses the need for more advanced maneuvering capabilities while maintaining backward compatibility with existing single valve systems. + +## Changes Made + +### Code Changes (`arduino_opta_controller/lifetrac_v25_controller.ino`) + +#### 1. New Pin Definitions +- Added `FLOW_CONTROL_PIN_1` (O2) - Primary flow valve (replaces old FLOW_CONTROL_PIN) +- Added `FLOW_CONTROL_PIN_2` (O3) - Secondary flow valve for dual valve configuration +- Added `FLOW_CONFIG_JUMPER_PIN` (D11) - Jumper detection for configuration selection + +#### 2. New Configuration System +- Added `FlowValveConfig` enum with `ONE_VALVE` and `TWO_VALVES` modes +- Added `flowConfig` global variable (defaults to `ONE_VALVE`) +- Added `readFlowValveConfig()` function to detect jumper at startup + +#### 3. Modified Functions + +**`setup()`:** +- Added initialization of D11 as INPUT_PULLUP for jumper detection +- Added initialization of O3 analog output for second flow valve +- Added call to `readFlowValveConfig()` before mode switch detection + +**`setFlowControl()`:** +- Complete rewrite to support both configurations +- **Single valve mode**: Uses minimum non-zero absolute value of all joystick inputs (flow limiting strategy) +- **Dual valve mode**: + - Calculates actual left and right track speeds + - Valve 1 flow based on: left track speed + arms + - Valve 2 flow based on: right track speed + bucket + - Enables independent speed control for advanced maneuvering + +**`stopAllMovement()`:** +- Updated to stop both flow valves (set both O2 and O3 to 4mA) + +#### 4. Header Comments +- Updated hardware list to show "1-2x Proportional Flow Control Valves (configurable)" +- Added flow valve configuration documentation to file header + +### Documentation Changes + +#### 1. New Files +- **FLOW_VALVE_CONFIGURATION.md** (12KB): Comprehensive guide covering: + - Hardware configuration and wiring + - Control behavior differences + - Installation instructions for both configurations + - Detailed example scenarios + - Hydraulic circuit modifications + - Additional hardware requirements + - Advantages/disadvantages comparison + - Troubleshooting guide + - Testing procedures + - Safety considerations + +- **QUICK_REFERENCE_FLOW_VALVES.md** (2KB): Quick reference for: + - Decision guide (which configuration to choose) + - Quick setup steps + - Hardware jumper location diagram + - Quick troubleshooting + - Cost comparison + +- **CHANGELOG_FLOW_VALVES.md** (this file): Complete change summary + +#### 2. Updated Files + +**README.md:** +- Added "Configurable Flow Control" to features list +- Updated hardware BOM to show "1-2x" flow control valves +- Added reference to FLOW_VALVE_CONFIGURATION.md in documentation section + +**WIRING_DIAGRAM.md:** +- Added D11 to Digital I/O Extension connections table +- Added flow valve configuration jumper logic description +- Split Analog Extension section into two diagrams: + - Single Valve Configuration (default) + - Dual Valve Configuration (jumper installed) +- Added clear indication of which outputs are used in each mode + +## Hardware Requirements + +### Base Configuration (Single Valve - Default) +- Arduino Opta WiFi +- Arduino Pro Opta Ext D1608S (Digital I/O extension) +- Arduino Pro Opta Ext A0602 (Analog extension) +- 1x Brand Hydraulics EFC Proportional Flow Control Valve +- 1x Burkert 8605 Type 316532 Flow Valve Controller + +### Advanced Configuration (Dual Valve) +**Additional hardware needed:** +- 1x Additional Brand Hydraulics EFC Proportional Flow Control Valve +- 1x Additional Burkert 8605 Type 316532 Flow Valve Controller +- Hydraulic flow splitter +- Additional hydraulic distribution manifold +- 1x Jumper wire or 2.54mm jumper (to connect D11 to GND) +- Additional hydraulic hoses and fittings + +**Estimated additional cost:** $1000-1500 USD + +## Configuration Selection + +### Default (Single Valve) +- Leave D11 pin disconnected (no jumper) +- System reads D11=HIGH (internal pullup) +- Controller operates in ONE_VALVE mode +- Serial output: "ONE_VALVE (Single valve for all)" + +### Advanced (Dual Valve) +- Install jumper connecting D11 to GND +- System reads D11=LOW +- Controller operates in TWO_VALVES mode +- Serial output: "TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket)" + +## Behavior Differences + +### Single Valve Mode +- All hydraulic functions (left track, right track, arms, bucket) share one flow rate +- Flow rate determined by the minimum non-zero joystick input across all axes +- Simple turning: can drive forward on one side while stopping the other +- Speed limited by the lowest non-zero demand movement +- Adequate for most operations + +### Dual Valve Mode +- Independent flow rates for left side (left track + arms) and right side (right track + bucket) +- Each side can operate at different speeds simultaneously +- Advanced turning capabilities: + - Variable-radius turns with smooth speed differential + - Zero-radius turning (spin in place with tracks running opposite directions) + - More precise maneuvering in tight spaces +- Better control for complex movements + +### Example: Zero-Radius Turn +This demonstrates the key advantage of dual valve mode: + +**Joystick Input:** Left Y=0, Left X=1.0 (full right turn, no forward/backward) + +**Single Valve Mode:** +- Left track: forward at full speed +- Right track: backward at full speed +- But: Both limited by single flow valve at 20mA +- Result: Spin in place, but flow may be insufficient for both tracks + +**Dual Valve Mode:** +- Left track: forward at full speed (Valve 1: 20mA) +- Right track: backward at full speed (Valve 2: 20mA) +- Independent flow valves provide full flow to each side +- Result: Smooth, powerful zero-radius turn + +## Backward Compatibility + +✅ **Fully backward compatible** with existing single valve installations: +- Default configuration is ONE_VALVE mode (no jumper required) +- Single valve systems work exactly as before +- No code changes required for existing installations +- Simply upload new firmware to get configuration capability + +## Testing Status + +⚠️ **Hardware testing required** +- Code changes are complete and syntactically correct +- Logic has been verified +- Requires testing on actual hardware: + - Single valve configuration (default) + - Dual valve configuration (with jumper) + - Mode switching between configurations + - Flow valve response verification + - Maneuvering capability testing + +## Migration Guide + +### For Existing Single Valve Systems +1. Upload new firmware to Arduino Opta +2. No hardware changes needed +3. System will automatically detect ONE_VALVE configuration +4. Verify serial output shows correct configuration +5. Test system operation (should be identical to before) + +### To Upgrade to Dual Valve System +1. Install second Brand Hydraulics EFC valve and Burkert controller +2. Wire second controller to Arduino Opta O3 output +3. Modify hydraulic circuit to split flow: + - Valve 1 → Left track + Arms + - Valve 2 → Right track + Bucket +4. Install jumper connecting D11 to GND on Arduino Opta +5. Power on system +6. Verify serial output shows "TWO_VALVES" configuration +7. Test all movements and turning capabilities + +## Safety Notes + +⚠️ **Important Safety Considerations:** +- Test new configuration in safe, open area +- Start with slow movements to verify correct operation +- Ensure all personnel are clear during testing +- Have emergency stop readily accessible +- Consult qualified hydraulic technician for installation +- Zero-radius turning in dual valve mode is powerful - use with caution +- Follow all manufacturer safety guidelines + +## Future Enhancements + +Possible future improvements: +- Add flow rate adjustment via MQTT/BLE commands +- Implement different control modes (tank steering vs direct wheel control) +- Add flow rate status reporting +- Support for more than two valves +- Configurable valve groupings + +## Technical Details + +### Pin Usage +| Pin | Function | Single Valve | Dual Valve | +|-----|----------|--------------|------------| +| D11 | Config Jumper | HIGH (no jumper) | LOW (jumper to GND) | +| O2 | Flow Valve 1 | Active (all hydraulics) | Active (left + arms) | +| O3 | Flow Valve 2 | Inactive (4mA) | Active (right + bucket) | + +### Flow Control Ranges +- No input: 4 mA (no flow) +- Minimum movement: 6 mA (~12.5% flow) +- Half input: 12 mA (50% flow) +- Maximum input: 20 mA (100% flow) + +### Startup Sequence +1. Initialize hardware pins +2. Wait 1 second for stabilization +3. Read D11 jumper state → determine flow configuration +4. Read D9 mode switch → determine control mode (BLE/MQTT) +5. Initialize appropriate services +6. Begin normal operation + +## References + +- **Issue**: Different Proportional Flow Valve Options +- **Pull Request**: [Link to be added] +- **Documentation**: + - FLOW_VALVE_CONFIGURATION.md (comprehensive guide) + - QUICK_REFERENCE_FLOW_VALVES.md (quick reference) + - WIRING_DIAGRAM.md (updated with dual valve wiring) + +## Contributors + +- Implementation: GitHub Copilot +- Issue Reporter: [Original issue author] +- Testing: [To be added after hardware testing] + +--- + +**Version:** 1.0 +**Date:** 2024 +**Status:** Code complete, hardware testing pending diff --git a/LifeTrac-v25/FLOW_VALVE_CONFIGURATION.md b/LifeTrac-v25/FLOW_VALVE_CONFIGURATION.md new file mode 100644 index 0000000..6b3ded2 --- /dev/null +++ b/LifeTrac-v25/FLOW_VALVE_CONFIGURATION.md @@ -0,0 +1,371 @@ +# LifeTrac v25 - Proportional Flow Valve Configuration Guide + +This document describes the two proportional flow valve configuration options for the LifeTrac v25 hydraulic system and how to select between them using hardware jumpers. + +## Overview + +The LifeTrac v25 supports two different proportional flow valve configurations: + +### Option 1: Single Valve (Default) +- **Hardware**: One proportional flow control valve controls flow to all hydraulic functions +- **Control**: All movements (left track, right track, arms, bucket) share the same flow rate +- **Speed**: Limited to the smallest non-zero joystick input across all active functions +- **Turning**: Limited capability - cannot have different speeds for left and right tracks +- **Use Case**: Simpler installation, lower cost, adequate for basic operations + +### Option 2: Dual Valve (Advanced) +- **Hardware**: Two proportional flow control valves for independent control + - Valve 1 controls: Left track + Arms + - Valve 2 controls: Right track + Bucket +- **Control**: Independent speed control for each valve group +- **Speed**: Each side can operate at different speeds simultaneously +- **Turning**: Fully adjustable turning with variable radius control +- **Use Case**: Advanced maneuvering, precise control, zero-radius turning + +## Hardware Configuration + +### Jumper Setup + +The flow valve configuration is selected using a jumper on the Arduino Opta's D11 pin: + +``` +┌─────────────────────────────────────────────┐ +│ Arduino Opta D1608S │ +│ │ +│ D11 ──┐ │ +│ │ [Jumper Position] │ +│ GND ──┘ │ +│ │ +└─────────────────────────────────────────────┘ + +Configuration: +├── No Jumper (D11 open): ONE_VALVE mode (default) +└── Jumper installed: TWO_VALVES mode + (D11 connected to GND) +``` + +### Pin Connections + +#### Single Valve Configuration (Default) +``` +Arduino Opta A0602 Flow Control System +┌─────────────────────┐ +│ O2+ (4-20mA) ─────────────┐ +│ O2- (4-20mA) ─────────────┼───► Burkert 8605 Controller #1 +│ │ └─► Brand Hydraulics EFC Valve +│ O3+ (4-20mA) [Unused] │ Controls ALL hydraulics +│ O3- (4-20mA) [Unused] │ +└─────────────────────┘ +``` + +#### Dual Valve Configuration (Jumper on D11) +``` +Arduino Opta A0602 Flow Control System +┌─────────────────────┐ +│ O2+ (4-20mA) ─────────────┐ +│ O2- (4-20mA) ─────────────┼───► Burkert 8605 Controller #1 +│ │ └─► Brand Hydraulics EFC Valve #1 +│ │ Controls: Left Track + Arms +│ │ +│ O3+ (4-20mA) ─────────────┐ +│ O3- (4-20mA) ─────────────┼───► Burkert 8605 Controller #2 +│ │ └─► Brand Hydraulics EFC Valve #2 +│ │ Controls: Right Track + Bucket +└─────────────────────┘ +``` + +## Control Behavior Differences + +### Single Valve Mode (Default) + +**Characteristics:** +- All hydraulic functions share a single flow rate +- System speed determined by the smallest non-zero joystick input across all active axes +- Simple turning: full speed one side, no power to other side OR equal forward/backward on both sides + +**Example Scenarios:** +``` +Scenario 1: Forward driving with bucket movement +- Left joystick: Y=0.8 (forward) +- Right joystick: X=0.5 (bucket) +- Result: Flow rate = min(0.8, 0.5) = 0.5 (12mA) +- All movements limited to the slowest commanded speed + +Scenario 2: Turning +- Left joystick: Y=1.0 (forward), X=0.5 (right turn) +- Result: + - Left track: 1.0 + 0.5 = 1.0 (clamped to max) + - Right track: 1.0 - 0.5 = 0.5 + - Flow rate: min(1.0, 0.5) = 0.5 (12mA) + - All movements limited to slowest commanded speed (right track at 0.5) +``` + +### Dual Valve Mode (Jumper Installed) + +**Characteristics:** +- Independent flow control for each valve group +- Left side (track + arms) can operate at different speed than right side (track + bucket) +- Advanced turning: variable speed differential between left and right +- Enhanced zero-radius turning with full independent power to each track + +**Example Scenarios:** +``` +Scenario 1: Forward driving with bucket movement +- Left joystick: Y=0.8 (forward), X=0 +- Right joystick: X=0.5 (bucket), Y=0 +- Result: + - Left track speed: 0.8 + 0 = 0.8 + - Right track speed: 0.8 - 0 = 0.8 + - Valve 1 (left track + arms): max(0.8, 0) = 0.8 (16.8mA) + - Valve 2 (right track + bucket): max(0.8, 0.5) = 0.8 (16.8mA) + - Both sides move forward, bucket operates independently + +Scenario 2: Advanced turning with different speeds +- Left joystick: Y=1.0 (forward), X=0.5 (right turn) +- Result: + - Left track speed: 1.0 + 0.5 = 1.0 (clamped to max) + - Right track speed: 1.0 - 0.5 = 0.5 + - Valve 1 (left track): max(1.0) = 1.0 (20mA) + - Valve 2 (right track): max(0.5) = 0.5 (12mA) + - Left track runs at full speed, right at half speed + - Creates smooth, variable-radius turn + +Scenario 3: Zero-radius turning (spin in place) +- Left joystick: Y=0, X=1.0 (full right turn) +- Result: + - Left track speed: 0 + 1.0 = 1.0 (forward) + - Right track speed: 0 - 1.0 = -1.0 (backward) + - Valve 1 (left track): max(1.0) = 1.0 (20mA forward) + - Valve 2 (right track): max(1.0) = 1.0 (20mA backward) + - Tank rotates in place with full power to both sides + - This is only possible with independent valve control! +``` + +## Installation Instructions + +### For Single Valve Configuration (Default) + +1. **Do not install jumper on D11** +2. Connect Burkert 8605 Controller to Opta O2 output: + - O2+ → Burkert Controller Input (+) + - O2- → Burkert Controller Input (-) +3. Connect Burkert Controller to Brand Hydraulics EFC valve +4. Upload firmware to Arduino Opta +5. Power on system +6. Verify serial output shows: `ONE_VALVE (Single valve for all)` + +### For Dual Valve Configuration (Advanced) + +1. **Install jumper connecting D11 to GND** + - Use a standard 2.54mm jumper or wire connection + - Connect Arduino Opta D11 pin to any GND pin +2. Connect first Burkert 8605 Controller to Opta O2 output: + - O2+ → Burkert Controller #1 Input (+) + - O2- → Burkert Controller #1 Input (-) +3. Connect first Burkert Controller to Brand Hydraulics EFC Valve #1 +4. Connect second Burkert 8605 Controller to Opta O3 output: + - O3+ → Burkert Controller #2 Input (+) + - O3- → Burkert Controller #2 Input (-) +5. Connect second Burkert Controller to Brand Hydraulics EFC Valve #2 +6. **Configure hydraulic circuit:** + - Route Valve #1 output to: Left track + Arms hydraulics + - Route Valve #2 output to: Right track + Bucket hydraulics +7. Upload firmware to Arduino Opta +8. Power on system +9. Verify serial output shows: `TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket)` + +## Hydraulic Circuit Modifications + +### Single Valve Circuit (Default) +``` +[Pump] → [Proportional Flow Valve #1] → [Flow Distribution] + ├─► Left Track Forward/Backward + ├─► Right Track Forward/Backward + ├─► Arms Up/Down + └─► Bucket Up/Down +``` + +### Dual Valve Circuit (Advanced) +``` +[Pump] → [Flow Splitter] ─┬─► [Proportional Flow Valve #1] → [Group 1 Distribution] + │ ├─► Left Track Forward/Backward + │ └─► Arms Up/Down + │ + └─► [Proportional Flow Valve #2] → [Group 2 Distribution] + ├─► Right Track Forward/Backward + └─► Bucket Up/Down +``` + +**Note:** Consult a qualified hydraulic technician for proper circuit design and installation. + +## Additional Hardware Requirements + +### Single Valve Configuration +- 1x Brand Hydraulics EFC Proportional Flow Control Valve +- 1x Burkert 8605 Type 316532 Flow Valve Controller +- Standard hydraulic distribution manifold + +### Dual Valve Configuration (Additional) +- 1x Additional Brand Hydraulics EFC Proportional Flow Control Valve +- 1x Additional Burkert 8605 Type 316532 Flow Valve Controller +- Hydraulic flow splitter (to divide pump output) +- Two separate distribution manifolds (one per valve group) +- Additional hydraulic hoses and fittings + +## Advantages and Disadvantages + +### Single Valve (Default) + +**Advantages:** +✅ Lower cost (one valve system) +✅ Simpler hydraulic circuit +✅ Easier installation and maintenance +✅ Adequate for most operations +✅ Less power consumption + +**Disadvantages:** +❌ Limited turning capability +❌ Cannot have different speeds for left/right sides +❌ Speed limited to slowest required movement +❌ Basic maneuverability + +### Dual Valve (Advanced) + +**Advantages:** +✅ Independent left/right speed control +✅ Fully adjustable turning radius +✅ Enhanced zero-radius turning with full independent power to each side +✅ More precise maneuvering +✅ Better control in tight spaces +✅ Can perform complex movements simultaneously + +**Disadvantages:** +❌ Higher cost (two valve systems) +❌ More complex hydraulic circuit +❌ More installation and maintenance work +❌ Requires hydraulic flow splitter +❌ Higher power consumption + +## Troubleshooting + +### Configuration Not Detected Correctly + +**Symptoms:** +- Serial output shows wrong configuration +- System behaves incorrectly + +**Solutions:** +1. Check jumper connection on D11 + - Ensure good electrical contact + - Verify jumper connects D11 to GND +2. Power cycle the Arduino Opta +3. Check serial output during startup +4. Measure voltage at D11 pin (should be ~0V with jumper to GND, ~3.3V without jumper) + +### One Valve Not Working in Dual Mode + +**Symptoms:** +- Only left or right side responds +- Partial system functionality + +**Solutions:** +1. Verify jumper is installed on D11 +2. Check O3 connections to second Burkert controller +3. Test 4-20mA output at O3 with multimeter +4. Verify second Burkert controller power supply +5. Check hydraulic connections to second valve + +### Inconsistent Flow Control + +**Symptoms:** +- Erratic speeds +- Unexpected behavior + +**Solutions:** +1. Check all 4-20mA current loop connections +2. Verify Burkert controller wiring +3. Ensure proper grounding +4. Check for electrical interference +5. Verify hydraulic circuit is properly configured + +## Testing Procedure + +### Single Valve Configuration Test + +1. Power on system +2. Check serial output: `ONE_VALVE (Single valve for all)` +3. Test forward movement (left joystick Y=1.0) +4. Test turning (left joystick X=±1.0) +5. Test arms and bucket movements +6. Verify all movements work but share same flow rate + +### Dual Valve Configuration Test + +1. Install jumper on D11 +2. Power on system +3. Check serial output: `TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket)` +4. Test left track only (should see flow from Valve 1) +5. Test right track only (should see flow from Valve 2) +6. Test zero-radius turn (left track forward, right track backward) +7. Test independent arm and bucket movements +8. Verify smooth turning with variable radius + +## Safety Considerations + +⚠️ **Warning:** Changing flow valve configuration affects hydraulic system behavior + +- Test new configuration in a safe, open area +- Start with slow movements to verify correct operation +- Ensure all personnel are clear of the machine during testing +- Have emergency stop readily accessible +- Consult qualified hydraulic technician for installation +- Follow all manufacturer safety guidelines + +## Serial Debugging + +During startup, the system will output configuration information: + +**Single Valve Mode:** +``` +LifeTrac v25 Controller Starting... +Flow valve configuration jumper: D11=HIGH -> Config: ONE_VALVE (Single valve for all) +Mode switch: A=LOW B=LOW -> Mode: BLE +Controller initialized successfully! +``` + +**Dual Valve Mode:** +``` +LifeTrac v25 Controller Starting... +Flow valve configuration jumper: D11=LOW -> Config: TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket) +Mode switch: A=LOW B=LOW -> Mode: BLE +Controller initialized successfully! +``` + +## Technical Specifications + +### 4-20mA Current Loop Outputs + +| Output | Function | Configuration | +|--------|----------|---------------| +| O2 | Primary Flow Valve | Used in both modes | +| O3 | Secondary Flow Valve | Used only in TWO_VALVES mode | + +### Current Signal Mapping + +| Joystick Input | Current Output | Flow Rate | +|----------------|----------------|-----------| +| 0.0 (no input) | 4 mA | No flow | +| 0.1 (minimum) | 6 mA | ~12.5% flow | +| 0.5 (half) | 12 mA | 50% flow | +| 1.0 (maximum) | 20 mA | 100% flow | + +### Response Time +- Configuration detection: At startup (<100ms) +- Flow valve response: <100ms typical (Burkert controller) +- System stabilization: 1 second after power-on + +--- + +**Document Version:** 1.0 +**Last Updated:** 2024 +**Applies to:** LifeTrac v25 Firmware v1.0+ diff --git a/LifeTrac-v25/FLOW_VALVE_DIAGRAM.md b/LifeTrac-v25/FLOW_VALVE_DIAGRAM.md new file mode 100644 index 0000000..ebc8ed0 --- /dev/null +++ b/LifeTrac-v25/FLOW_VALVE_DIAGRAM.md @@ -0,0 +1,374 @@ +# Flow Valve Configuration - Visual Diagrams + +## System Overview + +``` +┌─────────────────────────────────────────────────────────────┐ +│ LifeTrac v25 System │ +│ │ +│ ┌──────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Joystick │ ───► │ Arduino Opta │ ───► │ Hydraulic │ │ +│ │ Input │ │ Controller │ │ Valves │ │ +│ └──────────┘ └──────────────┘ └──────────────┘ │ +│ │ │ +│ │ Configuration │ +│ ▼ │ +│ ┌──────────────┐ │ +│ │ Flow Valves │ │ +│ │ (1 or 2) │ │ +│ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Configuration Selection + +``` +Arduino Opta D1608S Extension +┌────────────────────────────────┐ +│ │ +│ D9 [•] Mode Switch A │ +│ D10 [•] Mode Switch B │ +│ │ +│ D11 [•]────────[•] GND │ ◄── Jumper Location +│ └──── Configuration │ +│ │ +└────────────────────────────────┘ + +NO JUMPER: ONE_VALVE Mode (Single valve controls all) +JUMPER INSTALLED: TWO_VALVES Mode (Dual independent valves) +``` + +## Option 1: Single Valve Configuration (Default) + +### Hardware Diagram +``` +┌──────────────┐ +│ Arduino Opta │ +│ │ +│ D11 [•] │ ◄── No jumper (open) +│ │ +│ O2 ───────────────┐ +│ O3 [not used] │ +└──────────────┘ │ + │ + ▼ + ┌──────────────┐ + │ Burkert │ + │ Controller │ + └──────────────┘ + │ + ▼ + ┌──────────────┐ + │ Brand │ + │ Hydraulics │ + │ EFC Valve │ + └──────────────┘ + │ + ┌─────────────┼─────────────┐ + │ │ │ + ▼ ▼ ▼ ▼ + Left Track Right Track Arms Bucket + (Forward/ (Forward/ (Up/Down) (Up/Down) + Backward) Backward) + +ALL movements share the SAME flow rate +Speed = minimum non-zero joystick input across active functions +``` + +### Control Flow +``` +Joystick Input: + left_x: -1.0 to 1.0 (turning) + left_y: -1.0 to 1.0 (forward/backward) + right_x: -1.0 to 1.0 (bucket) + right_y: -1.0 to 1.0 (arms) + +Flow Calculation: + minInput = min(non-zero |left_x|, |left_y|, |right_x|, |right_y|) + + O2 current = 4 + (minInput × 16) mA + O3 current = 4 mA (off) + +Result: + All hydraulics limited to slowest commanded movement +``` + +### Turning Example +``` +Input: left_y = 1.0, left_x = 0.5 (forward + right turn) + +Track Speeds: + Left: 1.0 + 0.5 = 1.0 (clamped) ███████████ 100% + Right: 1.0 - 0.5 = 0.5 █████ 50% + +Flow: + O2: min(1.0, 0.5) = 0.5 → 12mA █████ 50% + +Both tracks limited to slowest commanded speed (right track at 0.5) +All movements proportionally slower +``` + +## Option 2: Dual Valve Configuration (Advanced) + +### Hardware Diagram +``` +┌──────────────┐ +│ Arduino Opta │ +│ │ +│ D11 [●]═════╪═══ GND ◄── Jumper installed +│ │ +│ O2 ───────────────┐ +│ │ │ +│ O3 ───────────────┼───┐ +└──────────────┘ │ │ + │ │ + ▼ ▼ + ┌─────────────┐ ┌─────────────┐ + │ Burkert #1 │ │ Burkert #2 │ + │ Controller │ │ Controller │ + └─────────────┘ └─────────────┘ + │ │ + ▼ ▼ + ┌─────────────┐ ┌─────────────┐ + │ Brand │ │ Brand │ + │ Hydraulics │ │ Hydraulics │ + │ EFC Valve 1 │ │ EFC Valve 2 │ + └─────────────┘ └─────────────┘ + │ │ + ┌─────────┴────┐ ┌─────┴──────┐ + │ │ │ │ + ▼ ▼ ▼ ▼ + Left Track Arms Right Track Bucket + (Forward/ (Up/Down) (Forward/ (Up/Down) + Backward) Backward) + +INDEPENDENT flow control for each valve group +``` + +### Control Flow +``` +Joystick Input: + left_x: -1.0 to 1.0 (turning) + left_y: -1.0 to 1.0 (forward/backward) + right_x: -1.0 to 1.0 (bucket) + right_y: -1.0 to 1.0 (arms) + +Track Speed Calculation: + leftTrackSpeed = left_y + left_x + rightTrackSpeed = left_y - left_x + (both clamped to -1.0 to 1.0) + +Flow Calculation: + Valve 1: maxInput1 = max(|leftTrackSpeed|, |right_y|) + Valve 2: maxInput2 = max(|rightTrackSpeed|, |right_x|) + + O2 current = 4 + (maxInput1 × 16) mA + O3 current = 4 + (maxInput2 × 16) mA + +Result: + Independent flow control for each side +``` + +### Turning Example (Same Input) +``` +Input: left_y = 1.0, left_x = 0.5 (forward + right turn) + +Track Speeds: + Left: 1.0 + 0.5 = 1.0 (clamped) ███████████ 100% + Right: 1.0 - 0.5 = 0.5 █████ 50% + +Flow: + Valve 1: max(1.0) = 1.0 → 20mA ███████████ 100% + Valve 2: max(0.5) = 0.5 → 12mA █████ 50% + +Each track gets appropriate flow rate +Smooth, controlled turning +``` + +### Zero-Radius Turn (Spin in Place) +``` +Input: left_y = 0, left_x = 1.0 (full right turn, no forward) + +Track Speeds: + Left: 0 + 1.0 = 1.0 (forward) ███████████► 100% + Right: 0 - 1.0 = -1.0 (backward) ◄███████████ 100% + +Flow: + Valve 1: max(1.0) = 1.0 → 20mA ███████████ Full power + Valve 2: max(1.0) = 1.0 → 20mA ███████████ Full power + +BOTH tracks get FULL INDEPENDENT POWER +Perfect zero-radius turn! + +⚠️ Note: Zero-radius turning works in BOTH configurations, but: +- Single valve: Both tracks share the same 20mA flow (power split between them) +- Dual valve: Each track gets its own independent 20mA flow (full power to each) +``` + +## Comparison Chart + +``` +┌──────────────────┬────────────────────┬────────────────────┐ +│ Feature │ Single Valve │ Dual Valve │ +├──────────────────┼────────────────────┼────────────────────┤ +│ Hardware │ 1 valve, simple │ 2 valves, complex │ +│ Cost │ Lower (baseline) │ Higher (+$1000) │ +│ Flow Control │ Shared │ Independent │ +│ Turning Radius │ Limited │ Variable │ +│ Zero-Radius Turn │ Limited power │ Full power │ +│ Installation │ Easy │ Moderate │ +│ Maneuvering │ Basic │ Advanced │ +└──────────────────┴────────────────────┴────────────────────┘ +``` + +## Code Flow Diagram + +``` +┌─────────────────────────────────────────────────────────┐ +│ STARTUP │ +└─────────────────────────────────────────────────────────┘ + │ + ▼ + ┌───────────────────────┐ + │ Read D11 Jumper Pin │ + └───────────────────────┘ + │ + ┌─────────────┴─────────────┐ + │ │ + D11 = HIGH D11 = LOW + (No jumper) (Jumper to GND) + │ │ + ▼ ▼ + ┌───────────────┐ ┌────────────────┐ + │ ONE_VALVE │ │ TWO_VALVES │ + │ Mode │ │ Mode │ + └───────────────┘ └────────────────┘ + │ │ + └─────────────┬─────────────┘ + │ +┌─────────────────────────────────────────────────────────┐ +│ MAIN LOOP │ +└─────────────────────────────────────────────────────────┘ + │ + ▼ + ┌───────────────────────┐ + │ Read Joystick Input │ + │ (left_x, left_y, │ + │ right_x, right_y) │ + └───────────────────────┘ + │ + ▼ + ┌───────────────────────┐ + │ Calculate Track Speeds│ + │ left = base + turn │ + │ right = base - turn │ + └───────────────────────┘ + │ + ▼ + ┌───────────────────────┐ + │ Control Valves │ + │ (Forward/Backward) │ + └───────────────────────┘ + │ + ▼ + ┌───────────────────────┐ + │ setFlowControl() │ + └───────────────────────┘ + │ + ┌─────────────┴─────────────┐ + │ │ + ONE_VALVE TWO_VALVES + │ │ + ▼ ▼ + ┌───────────────┐ ┌────────────────┐ + │ max = max of │ │ val1 = max of │ + │ all inputs │ │ left + arms │ + │ │ │ │ + │ O2 = 4+max×16 │ │ val2 = max of │ + │ O3 = 4 (off) │ │ right + bucket │ + └───────────────┘ │ │ + │ O2 = 4+val1×16 │ + │ O3 = 4+val2×16 │ + └────────────────┘ +``` + +## Signal Flow Example + +### Single Valve: Forward with Right Turn +``` +Joystick: + left_y = 1.0 ──┐ + left_x = 0.5 ──┤ + ├──► Track Calculation ──► Left: 1.0 ──┐ + right_y = 0 ──┤ Right: 0.5 ──┤ + right_x = 0 ──┘ │ + │ + Flow Calculation: │ + max(1.0, 0.5, 0, 0) = 1.0 │ + │ │ + ▼ │ + ┌──────────┐ │ + │ O2: 20mA │◄───────────────────┘ + │ O3: 4mA │ + └──────────┘ + │ + ┌─────────┴─────────┐ + │ │ + Same 20mA flow to both tracks │ + Left at 100%, Right at 50% │ + (Right track underpowered) │ +``` + +### Dual Valve: Forward with Right Turn +``` +Joystick: + left_y = 1.0 ──┐ + left_x = 0.5 ──┤ + ├──► Track Calculation ──► Left: 1.0 ──┐ + right_y = 0 ──┤ Right: 0.5 ──┤ + right_x = 0 ──┘ │ + │ + Flow Calculation: │ + Valve 1: max(1.0, 0) = 1.0 │ + Valve 2: max(0.5, 0) = 0.5 │ + │ │ + ┌─────────┴──────────┐ │ + │ │ │ + ▼ ▼ │ + ┌──────────┐ ┌──────────┐ │ + │ O2: 20mA │ │ O3: 12mA │◄───────┘ + └──────────┘ └──────────┘ + │ │ + Independent flow control │ + Left: 100% (20mA) │ + Right: 50% (12mA) │ + (Perfect power distribution) │ +``` + +## Installation Checklist + +### Single Valve (Default) +- [ ] Upload new firmware to Arduino Opta +- [ ] Leave D11 jumper disconnected +- [ ] Verify O2 connected to Burkert controller +- [ ] Power on system +- [ ] Check serial: "ONE_VALVE (Single valve for all)" +- [ ] Test all movements + +### Dual Valve (Advanced) +- [ ] Install second Brand Hydraulics EFC valve +- [ ] Install second Burkert 8605 controller +- [ ] Connect Burkert #1 to O2 output +- [ ] Connect Burkert #2 to O3 output +- [ ] Configure hydraulics: Valve 1 → Left+Arms, Valve 2 → Right+Bucket +- [ ] Install jumper: D11 to GND +- [ ] Upload firmware to Arduino Opta +- [ ] Power on system +- [ ] Check serial: "TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket)" +- [ ] Test basic movements +- [ ] Test zero-radius turning +- [ ] Verify independent speed control + +--- + +**For complete documentation, see FLOW_VALVE_CONFIGURATION.md** diff --git a/LifeTrac-v25/QUICK_REFERENCE_FLOW_VALVES.md b/LifeTrac-v25/QUICK_REFERENCE_FLOW_VALVES.md new file mode 100644 index 0000000..c79e081 --- /dev/null +++ b/LifeTrac-v25/QUICK_REFERENCE_FLOW_VALVES.md @@ -0,0 +1,72 @@ +# Quick Reference: Flow Valve Configuration + +## Quick Decision Guide + +**Choose Single Valve if:** +- ✅ Budget is limited +- ✅ Simple operations (forward, backward, basic turning) +- ✅ First-time installation +- ✅ Easier maintenance is priority + +**Choose Dual Valve if:** +- ✅ Need precise maneuvering +- ✅ Require enhanced zero-radius turning with full power +- ✅ Work in tight spaces frequently +- ✅ Budget allows for advanced system + +## Quick Setup + +### Single Valve (Default) +``` +1. Leave D11 jumper DISCONNECTED +2. Connect ONE Burkert controller to O2 +3. Power on and verify: "ONE_VALVE (Single valve for all)" +``` + +### Dual Valve (Advanced) +``` +1. Install jumper: D11 to GND +2. Connect FIRST Burkert controller to O2 +3. Connect SECOND Burkert controller to O3 +4. Configure hydraulics: + - Valve 1 → Left track + Arms + - Valve 2 → Right track + Bucket +5. Power on and verify: "TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket)" +``` + +## Hardware Jumper Location + +``` +Arduino Opta D1608S Digital Extension +┌────────────────────────────┐ +│ ... │ +│ D9 [•] Mode Switch A │ +│ D10 [•] Mode Switch B │ +│ D11 [•]──────[•] GND │ ← Install jumper here for dual valve +│ ... │ +└────────────────────────────┘ +``` + +## Quick Troubleshooting + +**Problem: Configuration not detected** +- Solution: Check jumper connection, power cycle + +**Problem: Only one side works in dual mode** +- Solution: Verify O3 connections and second Burkert controller + +**Problem: Erratic behavior** +- Solution: Check 4-20mA connections and grounding + +## Cost Comparison + +| Component | Single Valve | Dual Valve | +|-----------|--------------|------------| +| Flow Control Valves | 1x | 2x | +| Burkert Controllers | 1x | 2x | +| Installation Complexity | Simple | Moderate | +| Approximate Additional Cost | — | +$1000-1500 | + +## See Full Documentation + +For complete details, see: **FLOW_VALVE_CONFIGURATION.md** diff --git a/LifeTrac-v25/README.md b/LifeTrac-v25/README.md index 3f4b9d6..92c3c85 100644 --- a/LifeTrac-v25/README.md +++ b/LifeTrac-v25/README.md @@ -10,6 +10,9 @@ LifeTrac v25 features a comprehensive remote control system with multiple contro * **DroidPad Compatible:** Native support for DroidPad via BLE or MQTT using -1.0 to 1.0 value range * **WiFi Communication:** Reliable wireless control with MQTT protocol * **ROS2 Integration:** Control LifeTrac from BeagleBone or any ROS2-enabled device +* **Configurable Flow Control:** Choose between single or dual proportional flow valves via jumper + - Single valve: Simpler setup, all functions share flow rate (flow is limited by the minimum non-zero joystick input) + - Dual valve: Independent control, advanced maneuvering with variable turning radius * **Proportional Flow Control:** Speed regulation based on joystick input intensity * **Safety Features:** Emergency stop, communication timeout, and fail-safe operation * **Status Monitoring:** Real-time system status and diagnostics @@ -33,8 +36,10 @@ LifeTrac v25 features a comprehensive remote control system with multiple contro ## Onboard Controller (LifeTrac) * (4) Hydraulic Directional Valve: 20 gpm Max Flow Rate, D03 NFPA Size, Three Positions, 12V DC -* (1) Electronically Adjustable Pressure Compensated Proportional Flow Control https://www.brand-hyd.com/Products/Valves/Flow_Controls/EFC/ -* (1) Burkert 8605 Type 316532 Flow Valve Controller https://www.burkert-usa.com/en/products/solenoid-control-valves/controllers/316532 +* (1-2) Electronically Adjustable Pressure Compensated Proportional Flow Control https://www.brand-hyd.com/Products/Valves/Flow_Controls/EFC/ +* (1-2) Burkert 8605 Type 316532 Flow Valve Controller https://www.burkert-usa.com/en/products/solenoid-control-valves/controllers/316532 + - One valve for basic configuration + - Two valves for advanced maneuvering (see FLOW_VALVE_CONFIGURATION.md) * Arduino Opta WiFi - $199.00 * Arduino Pro Opta Ext D1608S - $151.00 @@ -81,6 +86,7 @@ LifeTrac v25 features a comprehensive remote control system with multiple contro ## Documentation - **INSTALLATION_GUIDE.md**: Complete setup and installation instructions +- **FLOW_VALVE_CONFIGURATION.md**: Proportional flow valve configuration (single vs dual valve) - **DROIDPAD_INTEGRATION.md**: Guide for DroidPad integration via BLE or MQTT - **DROIDPAD_BLE_SETUP.md**: Step-by-step BLE direct control setup for DroidPad - **MODE_SWITCH_WIRING.md**: Hardware switch wiring for MQTT/OFF/BLE selection diff --git a/LifeTrac-v25/WIRING_DIAGRAM.md b/LifeTrac-v25/WIRING_DIAGRAM.md index cff2507..1d78086 100644 --- a/LifeTrac-v25/WIRING_DIAGRAM.md +++ b/LifeTrac-v25/WIRING_DIAGRAM.md @@ -49,7 +49,7 @@ GND ───────────────────────── ### Digital I/O Extension (D1608S) Connections ``` -Arduino Opta D1608S Hydraulic Valves / Mode Switch +Arduino Opta D1608S Hydraulic Valves / Mode Switch / Flow Config ┌─────────────────────┐ ┌──────────────────────────┐ │ D1 ─────────────────────── │ Left Track Forward │ │ D2 ─────────────────────── │ Left Track Backward │ @@ -61,6 +61,7 @@ Arduino Opta D1608S Hydraulic Valves / Mode Switch │ D8 ─────────────────────── │ Bucket Down │ │ D9 ─────────────────────── │ Mode Switch Pin A │ │ D10 ────────────────────── │ Mode Switch Pin B │ +│ D11 ────────────────────── │ Flow Valve Config Jumper │ └─────────────────────┘ └──────────────────────────┘ Mode Switch Logic (HONEYWELL 2NT1-1): @@ -68,9 +69,16 @@ Mode Switch Logic (HONEYWELL 2NT1-1): - Position 2 (OFF): No 12V power (hardware cutoff at center) - Position 3 (BLE): D9=LOW, D10=LOW (default when switch not installed) +Flow Valve Configuration Jumper (D11): +- No jumper (D11=HIGH): ONE_VALVE mode - Single valve controls all (default) +- Jumper to GND (D11=LOW): TWO_VALVES mode - Independent valve control + See FLOW_VALVE_CONFIGURATION.md for details + ### Analog Extension (A0602) Connections + +#### Single Valve Configuration (Default - No Jumper on D11) ``` Arduino Opta A0602 Flow Control System ┌─────────────────────┐ ┌──────────────────────────┐ @@ -78,17 +86,36 @@ Arduino Opta A0602 Flow Control System │ O2- (4-20mA) ───────────── │ Current Input │ │ +12V ───────────────────── │ Power Supply (+) │ │ GND ────────────────────── │ Power Supply (-) │ -└─────────────────────┘ └──────────────────────────┘ - │ - │ Control Output - ▼ +│ │ └──────────────────────────┘ +│ O3+ (4-20mA) [Unused] │ +│ O3- (4-20mA) [Unused] │ Control Output +└─────────────────────┘ ▼ ┌──────────────────────────┐ │ Brand Hydraulics EFC │ - │ Flow Control Valve Coil │ - │ (Proportional) │ + │ Flow Control Valve │ + │ Controls ALL hydraulics │ └──────────────────────────┘ ``` +#### Dual Valve Configuration (Jumper on D11) +``` +Arduino Opta A0602 Flow Control System +┌─────────────────────┐ +│ O2+ (4-20mA) ───────────── Burkert 8605 Controller #1 +│ O2- (4-20mA) ───────────── Current Input +│ +12V ───────────────────── Power Supply (+) +│ GND ────────────────────── Power Supply (-) +│ │ └──► Brand Hydraulics EFC Valve #1 +│ │ (Left Track + Arms) +│ │ +│ O3+ (4-20mA) ───────────── Burkert 8605 Controller #2 +│ O3- (4-20mA) ───────────── Current Input +│ +12V ───────────────────── Power Supply (+) +│ GND ────────────────────── Power Supply (-) +└─────────────────────┘ └──► Brand Hydraulics EFC Valve #2 + (Right Track + Bucket) +``` + ## ESP32 Remote Control Wiring ### Power and Basic Connections diff --git a/LifeTrac-v25/arduino_opta_controller/lifetrac_v25_controller.ino b/LifeTrac-v25/arduino_opta_controller/lifetrac_v25_controller.ino index d39da44..d7582a0 100644 --- a/LifeTrac-v25/arduino_opta_controller/lifetrac_v25_controller.ino +++ b/LifeTrac-v25/arduino_opta_controller/lifetrac_v25_controller.ino @@ -9,8 +9,8 @@ * - Arduino Pro Opta Ext D1608S (Digital I/O extension) * - Arduino Pro Opta Ext A0602 (Analog extension) * - 4x Hydraulic Directional Valves (12V DC) - * - 1x Proportional Flow Control Valve - * - 1x Burkert 8605 Type 316532 Flow Valve Controller + * - 1-2x Proportional Flow Control Valves (configurable) + * - 1-2x Burkert 8605 Type 316532 Flow Valve Controllers * - 3-position switch for OFF/MQTT/BLE mode selection * * Control scheme: @@ -25,6 +25,14 @@ * - Position 2 (OFF): No power to Opta (hardware cutoff at center position) * - Position 3 (BLE): Direct Bluetooth Low Energy control from DroidPad app (default) * - Default: BLE mode if switch is not installed (internal pulldown resistors) + * + * Flow Valve Configuration (Jumper on D11): + * - No jumper (D11=LOW): ONE_VALVE mode - Single valve controls all hydraulics (default) + * Speed limited to smallest joystick input. Limited turning capability. + * - Jumper installed (D11=HIGH): TWO_VALVES mode - Independent valve control + * Valve 1 (O2): Controls left track + arms + * Valve 2 (O3): Controls right track + bucket + * Allows fully adjustable turning with different speeds for left/right sides. */ #include @@ -57,8 +65,9 @@ const int ARMS_DOWN_PIN = 6; // D6 const int BUCKET_UP_PIN = 7; // D7 const int BUCKET_DOWN_PIN = 8; // D8 -// Pin for proportional flow control (4-20mA) - connects to Burkert 8605 Controller -const int FLOW_CONTROL_PIN = 2; // O2 (4-20mA current loop output) - interfaces with Burkert controller +// Pins for proportional flow control (4-20mA) - connects to Burkert 8605 Controller(s) +const int FLOW_CONTROL_PIN_1 = 2; // O2 (4-20mA current loop output) - Primary flow valve +const int FLOW_CONTROL_PIN_2 = 3; // O3 (4-20mA current loop output) - Secondary flow valve (for dual valve config) // Mode selection switch pins (HONEYWELL 2NT1-1 On/Off/On switch) // The switch selects between MQTT and BLE modes @@ -71,6 +80,13 @@ const int MODE_SWITCH_PIN_B = 10; // D10 - Reserved for future expansion ( // Position 3 (BLE): A=LOW -> BLE mode (default if switch not installed - internal pulldown) // Note: Only D9 is used for mode detection. D10 is reserved for future multi-mode expansion. +// Flow valve configuration jumper pins +// These pins detect which proportional flow valve configuration is installed +const int FLOW_CONFIG_JUMPER_PIN = 11; // D11 - Flow valve configuration jumper +// Jumper Logic (with internal pullup resistor): +// D11=HIGH (no jumper): ONE_VALVE mode - Single valve controls all hydraulics (default) +// D11=LOW (jumper to GND): TWO_VALVES mode - Valve 1 controls left track + arms, Valve 2 controls right track + bucket + // Control mode enumeration enum ControlMode { MODE_BLE, // Bluetooth Low Energy direct control @@ -79,6 +95,14 @@ enum ControlMode { ControlMode currentMode = MODE_BLE; // Default to BLE +// Flow valve configuration enumeration +enum FlowValveConfig { + ONE_VALVE, // Single proportional flow valve controls all hydraulics (default) + TWO_VALVES // Two proportional flow valves: Valve 1 for left track + arms, Valve 2 for right track + bucket +}; + +FlowValveConfig flowConfig = ONE_VALVE; // Default to single valve + // BLE Service and Characteristics UUIDs // Using custom UUIDs for LifeTrac control service #define BLE_SERVICE_UUID "19B10000-E8F2-537E-4F6C-D104768A1214" @@ -108,6 +132,11 @@ PubSubClient client(espClient); // Deadzone for joystick input (0.1 = 10% of range) const float DEADZONE = 0.1; +// Flow control current constants (4-20mA current loop) +const int BASE_CURRENT = 4; // 4mA = no flow +const int MIN_ACTIVE_CURRENT = 6; // 6mA = minimum active flow (~12.5%) +const int CURRENT_RANGE = 16; // 16mA range (4-20mA span) + // Safety timeout (stop all movement if no commands received) unsigned long lastCommandTime = 0; const unsigned long SAFETY_TIMEOUT = 1000; // 1 second @@ -121,6 +150,10 @@ void setup() { pinMode(MODE_SWITCH_PIN_A, INPUT_PULLDOWN); pinMode(MODE_SWITCH_PIN_B, INPUT_PULLDOWN); + // Initialize flow valve configuration jumper pin with internal pullup + // This ensures ONE_VALVE mode is default when jumper is not installed + pinMode(FLOW_CONFIG_JUMPER_PIN, INPUT_PULLUP); + // Initialize digital output pins pinMode(LEFT_TRACK_FORWARD_PIN, OUTPUT); pinMode(LEFT_TRACK_BACKWARD_PIN, OUTPUT); @@ -131,10 +164,12 @@ void setup() { pinMode(BUCKET_UP_PIN, OUTPUT); pinMode(BUCKET_DOWN_PIN, OUTPUT); - // Initialize 4-20mA current output pin for flow control + // Initialize 4-20mA current output pins for flow control OptaController.begin(); // Initialize Opta controller library - // Configure O2 as 4-20mA current output - OptaController.analogWriteMode(FLOW_CONTROL_PIN, CURRENT_OUTPUT_4_20MA); + // Configure O2 as 4-20mA current output (primary flow valve) + OptaController.analogWriteMode(FLOW_CONTROL_PIN_1, CURRENT_OUTPUT_4_20MA); + // Configure O3 as 4-20mA current output (secondary flow valve for dual valve config) + OptaController.analogWriteMode(FLOW_CONTROL_PIN_2, CURRENT_OUTPUT_4_20MA); // Ensure all outputs are off initially stopAllMovement(); @@ -142,6 +177,9 @@ void setup() { // Wait for switch pins to stabilize before reading delay(1000); // 1 second delay for hardware stabilization + // Read flow valve configuration jumper + readFlowValveConfig(); + // Read mode switch and initialize appropriate control mode readModeSwitch(); @@ -271,21 +309,28 @@ void mqttCallback(char* topic, byte* payload, unsigned int length) { lastCommandTime = millis(); } +// Helper function to compute track speeds from joystick input +// Centralizes tank steering math to avoid duplication +void computeTrackSpeeds(float left_y, float left_x, float* leftSpeed, float* rightSpeed) { + float baseSpeed = left_y; // Forward/backward + float turnRate = left_x; // Left/right turning + + // Calculate individual track speeds using differential steering + *leftSpeed = baseSpeed + turnRate; + *rightSpeed = baseSpeed - turnRate; + + // Constrain to valid range [-1.0, 1.0] + *leftSpeed = fmaxf(-1.0, fminf(*leftSpeed, 1.0)); + *rightSpeed = fmaxf(-1.0, fminf(*rightSpeed, 1.0)); +} + void processJoystickInput() { // Calculate track movements (tank steering) // Left joystick Y controls forward/backward movement // Left joystick X controls turning (differential steering) - float baseSpeed = currentInput.left_y; // Forward/backward - float turnRate = currentInput.left_x; // Left/right turning - - // Calculate individual track speeds - float leftTrackSpeed = baseSpeed + turnRate; - float rightTrackSpeed = baseSpeed - turnRate; - - // Constrain to valid range - leftTrackSpeed = fmaxf(-1.0, fminf(leftTrackSpeed, 1.0)); - rightTrackSpeed = fmaxf(-1.0, fminf(rightTrackSpeed, 1.0)); + float leftTrackSpeed, rightTrackSpeed; + computeTrackSpeeds(currentInput.left_y, currentInput.left_x, &leftTrackSpeed, &rightTrackSpeed); // Control left track controlTrack(leftTrackSpeed, LEFT_TRACK_FORWARD_PIN, LEFT_TRACK_BACKWARD_PIN); @@ -337,32 +382,82 @@ void controlValve(float control, int upPin, int downPin) { } } +// Helper function to convert input magnitude to flow control current (4-20mA) +// magnitude: Input magnitude (0.0 to 1.0) +// hasInput: Whether there is active input above deadzone +// Returns: Current value in mA (4-20 range) +int flowCurrentFromInput(float magnitude, bool hasInput) { + if (!hasInput) { + return BASE_CURRENT; // 4mA = no flow + } + + int currentValue = BASE_CURRENT + (int)(magnitude * CURRENT_RANGE); + currentValue = max(currentValue, MIN_ACTIVE_CURRENT); // Minimum active flow + return currentValue; +} + void setFlowControl() { - // Find the maximum absolute value from all inputs - // This determines the overall system speed - // 4-20mA current loop output interfaces with Burkert 8605 Controller for precise flow control - float maxInput = 0.0; - - maxInput = max(maxInput, abs(currentInput.left_x)); - maxInput = max(maxInput, abs(currentInput.left_y)); - maxInput = max(maxInput, abs(currentInput.right_x)); - maxInput = max(maxInput, abs(currentInput.right_y)); - - // Convert to 4-20mA value (4mA = minimum, 20mA = maximum) - // Map from joystick range (0.0-1.0) to current range (4-20mA) - // Using linear interpolation: currentValue = 4 + (maxInput * 16) - int currentValue = 4 + (int)(maxInput * 16.0); - - // Apply minimum flow when any movement is commanded - if (maxInput > DEADZONE) { - currentValue = max(currentValue, 6); // Minimum ~12.5% flow (6mA) + if (flowConfig == ONE_VALVE) { + // Single valve mode: One valve controls all hydraulics + // Speed limited to the smallest non-zero joystick input + // Find the minimum non-zero absolute value from all inputs + float minInput = 1.0; // Start with maximum possible value + bool hasInput = false; + + // Check each input and find minimum non-zero value + if (abs(currentInput.left_x) > DEADZONE) { + minInput = min(minInput, abs(currentInput.left_x)); + hasInput = true; + } + if (abs(currentInput.left_y) > DEADZONE) { + minInput = min(minInput, abs(currentInput.left_y)); + hasInput = true; + } + if (abs(currentInput.right_x) > DEADZONE) { + minInput = min(minInput, abs(currentInput.right_x)); + hasInput = true; + } + if (abs(currentInput.right_y) > DEADZONE) { + minInput = min(minInput, abs(currentInput.right_y)); + hasInput = true; + } + + // Convert to 4-20mA value using helper function + int currentValue = flowCurrentFromInput(minInput, hasInput); + + // Output to primary flow valve + OptaController.analogWriteCurrent(FLOW_CONTROL_PIN_1, currentValue); + // Disable secondary valve in single valve mode + OptaController.analogWriteCurrent(FLOW_CONTROL_PIN_2, BASE_CURRENT); + } else { - currentValue = 4; // 4mA = no flow + // Dual valve mode: Two independent valves + // Valve 1 controls: left track + arms + // Valve 2 controls: right track + bucket + // This allows independent speed control for each side + + // Calculate track speeds using shared helper function + float leftTrackSpeed, rightTrackSpeed; + computeTrackSpeeds(currentInput.left_y, currentInput.left_x, &leftTrackSpeed, &rightTrackSpeed); + + // Calculate flow for Valve 1 (left track + arms) + float maxInput1 = 0.0; + maxInput1 = max(maxInput1, abs(leftTrackSpeed)); // Left track speed + maxInput1 = max(maxInput1, abs(currentInput.right_y)); // Arms + bool hasInput1 = maxInput1 > DEADZONE; + int currentValue1 = flowCurrentFromInput(maxInput1, hasInput1); + + // Calculate flow for Valve 2 (right track + bucket) + float maxInput2 = 0.0; + maxInput2 = max(maxInput2, abs(rightTrackSpeed)); // Right track speed + maxInput2 = max(maxInput2, abs(currentInput.right_x)); // Bucket + bool hasInput2 = maxInput2 > DEADZONE; + int currentValue2 = flowCurrentFromInput(maxInput2, hasInput2); + + // Output to both flow valves + OptaController.analogWriteCurrent(FLOW_CONTROL_PIN_1, currentValue1); + OptaController.analogWriteCurrent(FLOW_CONTROL_PIN_2, currentValue2); } - - // Output true 4-20mA current using Opta A0602 current loop hardware - // currentValue is already in mA (4-20 range) - OptaController.analogWriteCurrent(FLOW_CONTROL_PIN, currentValue); } void stopAllMovement() { @@ -376,8 +471,9 @@ void stopAllMovement() { digitalWrite(BUCKET_UP_PIN, LOW); digitalWrite(BUCKET_DOWN_PIN, LOW); - // Stop flow control - set to 4mA (no flow) using true current output - OptaController.analogWriteCurrent(FLOW_CONTROL_PIN, 4); + // Stop flow control - set to BASE_CURRENT (no flow) for both valves + OptaController.analogWriteCurrent(FLOW_CONTROL_PIN_1, BASE_CURRENT); + OptaController.analogWriteCurrent(FLOW_CONTROL_PIN_2, BASE_CURRENT); } void publishStatus() { @@ -409,6 +505,24 @@ void publishStatus() { client.publish(status_topic, statusMessage.c_str()); } +void readFlowValveConfig() { + // Read flow valve configuration jumper pin + bool pinState = digitalRead(FLOW_CONFIG_JUMPER_PIN); + + // Determine flow valve configuration + // With internal pullup: HIGH (no jumper) = ONE_VALVE, LOW (jumper to GND) = TWO_VALVES + if (pinState == LOW) { + flowConfig = TWO_VALVES; + } else { + flowConfig = ONE_VALVE; // Default when no jumper (pullup keeps pin HIGH) + } + + Serial.print("Flow valve configuration jumper: D11="); + Serial.print(pinState ? "HIGH" : "LOW"); + Serial.print(" -> Config: "); + Serial.println(flowConfig == ONE_VALVE ? "ONE_VALVE (Single valve for all)" : "TWO_VALVES (Valve 1: left+arms, Valve 2: right+bucket)"); +} + void readModeSwitch() { // Read mode switch pins bool pinA = digitalRead(MODE_SWITCH_PIN_A);