-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcomprehensive_test_controller.ino
More file actions
373 lines (308 loc) · 14.7 KB
/
comprehensive_test_controller.ino
File metadata and controls
373 lines (308 loc) · 14.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
===============================================================================
X-Plane Dataref Bridge - Comprehensive Test Controller for ESP32-S2
===============================================================================
PURPOSE:
This sketch creates a comprehensive test controller that repeatedly changes values for
various X-Plane datarefs with different behaviors:
1. Toggles sim/lights/beacon_lights_toggle on/off every 500ms
2. Gradually changes sim/flightmodel/controls/parkbrake from 0 to 1 and back
3. Gradually changes sim/cockpit2/radios/actuators/com1_frequency_Mhz from 118 to 136
4. Changes sim/aircraft/view/acf_ICAO from C152 to C1522 repeatedly every 1 sec
5. Reads and prints the current value of sim/aircraft/view/acf_ICAO
REQUIRED HARDWARE:
- ESP32-S2 development board
- USB cable for programming and communication
COMMANDS USED:
- DREF for writing numeric/string datarefs
- INPUT for requesting dataref values from X-Plane (requires OUTPUT_ID mapping in bridge)
- SET for receiving dataref values from bridge
FEATURES:
- Multiple simultaneous dataref changes
- Reading dataref values from X-Plane
- Proper handshake protocol with X-Plane Dataref Bridge
- Configurable timing for different dataref types
- Error handling and bounds checking
TROUBLESHOOTING:
- No communication? Verify 115200 baud rate in Serial Monitor
- Wrong values? Check if datarefs are writable in X-Plane
- ESP32-S2 not detected? Verify correct board selected in Arduino IDE
===============================================================================
*/
/* ==========================================================================
DEVICE IDENTIFICATION SECTION
These constants identify your device to bridge application
========================================================================== */
const char* DEVICE_NAME = "ComprehensiveTestController"; // Human-readable name for your device
const char* FIRMWARE_VERSION = "1.0"; // Version number for updates/tracking
const char* BOARD_TYPE = "ESP32-S2"; // ESP32-S2 board type
/* ==========================================================================
DATAREF DEFINITIONS SECTION
These define the datarefs we'll write to directly in X-Plane
========================================================================== */
const char* DATAREF_BEACON = "sim/lights/beacon_lights_toggle";
const char* DATAREF_PARKBRAKE = "sim/flightmodel/controls/parkbrake";
const char* DATAREF_COM_FREQ = "sim/cockpit2/radios/actuators/com1_frequency_Mhz";
const char* DATAREF_AIRCRAFT_ICAO = "sim/aircraft/view/acf_ICAO";
/* ==========================================================================
OUTPUT_ID DEFINITIONS SECTION
These are friendly names we'll use for receiving data from X-Plane
NOTE: These must be mapped in the Bridge application
========================================================================== */
const char* OUTPUT_ID_CURRENT_ICAO = "CURRENT_ICAO"; // For receiving current ICAO code
/* ==========================================================================
TIMING VARIABLES SECTION
Variables to control timing for different dataref updates
========================================================================== */
unsigned long lastBeaconUpdate = 0; // Timestamp of last beacon update
const unsigned long BEACON_INTERVAL = 500; // Update beacon every 500ms
bool beaconState = false; // Current beacon state (true=on, false=off)
unsigned long lastParkBrakeUpdate = 0; // Timestamp of last park brake update
const unsigned long PARKBRAKE_INTERVAL = 100; // Update park brake every 100ms for gradual change
float parkBrakeValue = 0.0; // Current park brake value (0.0 to 1.0)
float parkBrakeDirection = 0.01; // Direction and increment for gradual change
unsigned long lastComFreqUpdate = 0; // Timestamp of last COM frequency update
const unsigned long COM_FREQ_INTERVAL = 500; // Update COM frequency every 500ms
float comFrequency = 118.0; // Current COM frequency (118.0 to 136.0)
float comFreqDirection = 0.1; // Direction and increment for gradual change
unsigned long lastIcaoUpdate = 0; // Timestamp of last ICAO update
const unsigned long ICAO_INTERVAL = 1000; // Update ICAO every 1000ms (1 second)
bool icaoState = false; // Current ICAO state (false=C152, true=C1522)
unsigned long lastIcaoRead = 0; // Timestamp of last ICAO read request
const unsigned long ICAO_READ_INTERVAL = 2000; // Read ICAO every 2000ms (2 seconds)
String currentIcaoValue = "UNKNOWN"; // Current ICAO value received from X-Plane
/* ==========================================================================
SERIAL COMMUNICATION SECTION
Buffer for building messages from PC character by character
========================================================================== */
String inputBuffer = ""; // Storage for incoming serial messages
/* ==========================================================================
SETUP FUNCTION
This runs once when ESP32-S2 boots up - initializes all hardware and settings
========================================================================== */
void setup() {
// --- Initialize Serial Communication ---
// Start serial communication at 115200 baud (bits per second)
// This is the speed required by X-Plane Dataref Bridge
Serial.begin(115200);
// --- Wait for Serial Connection ---
// ESP32-S2 needs time to establish serial connection
// This waits up to 5 seconds for serial to be ready
while (!Serial && millis() < 5000) {
delay(10); // Small delay to prevent overwhelming the processor
}
// --- Send Startup Messages ---
// These messages help with debugging and confirm device is working
Serial.println("// Comprehensive Test Controller Started"); // Startup confirmation
Serial.print("// Device: ");
Serial.println(DEVICE_NAME); // Send device name
Serial.println("// Testing: beacon, parkbrake, com_freq, aircraft_icao, read_icao"); // Function guide
// Initialize timing
lastBeaconUpdate = millis();
lastParkBrakeUpdate = millis();
lastComFreqUpdate = millis();
lastIcaoUpdate = millis();
lastIcaoRead = millis();
}
/* ==========================================================================
MAIN LOOP FUNCTION
This runs continuously after setup() - handles communication and value updates
========================================================================== */
void loop() {
checkSerial(); // Listen for commands from bridge application
updateBeacon(); // Update beacon light toggle
updateParkBrake(); // Update park brake gradually
updateComFrequency(); // Update COM frequency gradually
updateIcaoCode(); // Update aircraft ICAO code
readCurrentIcao(); // Read current ICAO value from X-Plane
delay(10); // Small delay to prevent overwhelming processor
}
/* ==========================================================================
SERIAL COMMUNICATION HANDLER
Processes incoming messages from X-Plane Dataref Bridge using correct protocol
========================================================================== */
void checkSerial() {
// Check if any data is available to read from serial port
while (Serial.available() > 0) {
// Read one character at a time
char c = (char)Serial.read();
// If we receive a newline character, the message is complete
if (c == '\n') {
processLine(inputBuffer); // Process the complete message
inputBuffer = ""; // Clear buffer for next message
}
// Ignore carriage return characters (Windows sometimes sends them)
else if (c != '\r') {
inputBuffer += c; // Add character to buffer
}
}
}
/* ==========================================================================
MESSAGE PROCESSING FUNCTION
Decodes and handles messages received from the bridge application
========================================================================== */
void processLine(String line) {
line.trim(); // Remove any whitespace from beginning and end
// --- Handle Handshake Request ---
// Bridge sends "HELLO" to check if device is responding
if (line == "HELLO") {
// Respond with device information in the exact expected format
Serial.print("XPDR;fw=");
Serial.print(FIRMWARE_VERSION); // Send firmware version
Serial.print(";board=");
Serial.print(BOARD_TYPE); // Send board type
Serial.print(";name=");
Serial.println(DEVICE_NAME); // Send device name
// Visual feedback - blink built-in LED to show connection established
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
#endif
}
// --- Handle SET Commands (values from X-Plane) ---
// Bridge sends "SET <KEY> <VALUE>" when X-Plane dataref changes
else if (line.startsWith("SET ")) {
// Parse format: "SET CURRENT_ICAO C172"
int firstSpace = line.indexOf(' '); // Find first space
int secondSpace = line.lastIndexOf(' '); // Find last space
if (firstSpace > 0 && secondSpace > firstSpace) {
String key = line.substring(firstSpace + 1, secondSpace); // Extract the OUTPUT_ID
String valueStr = line.substring(secondSpace + 1); // Extract the value
// Handle the SET command based on the key
handleSetCommand(key, valueStr);
}
}
}
/* ==========================================================================
SET COMMAND HANDLER
Processes SET commands and sends ACK responses for debugging
========================================================================== */
void handleSetCommand(String key, String value) {
if (key == OUTPUT_ID_CURRENT_ICAO) {
currentIcaoValue = value; // Store current ICAO value
Serial.print("// Received current ICAO: ");
Serial.println(currentIcaoValue);
}
// Send acknowledgment for debugging (optional but helpful)
Serial.print("ACK ");
Serial.print(key);
Serial.print(" ");
Serial.println(value);
}
/* ==========================================================================
BEACON LIGHT UPDATE FUNCTION
Updates beacon light state every 500ms, toggling between on and off
========================================================================== */
void updateBeacon() {
if (millis() - lastBeaconUpdate > BEACON_INTERVAL) {
// Toggle beacon state
beaconState = !beaconState;
// Send CMD command to X-Plane to toggle beacon light
// This is a command dataref, not a value dataref
Serial.print("CMD ");
Serial.println(DATAREF_BEACON);
Serial.print("// Beacon command sent: ");
Serial.println(beaconState ? "ON" : "OFF");
// Update the timestamp
lastBeaconUpdate = millis();
}
}
/* ==========================================================================
PARK BRAKE UPDATE FUNCTION
Gradually changes park brake value from 0 to 1 and back
========================================================================== */
void updateParkBrake() {
if (millis() - lastParkBrakeUpdate > PARKBRAKE_INTERVAL) {
// Update park brake value gradually
parkBrakeValue += parkBrakeDirection;
// Reverse direction if we hit the limits
if (parkBrakeValue >= 1.0) {
parkBrakeValue = 1.0;
parkBrakeDirection = -0.01; // Start decreasing
} else if (parkBrakeValue <= 0.0) {
parkBrakeValue = 0.0;
parkBrakeDirection = 0.01; // Start increasing
}
// Send DREF command to X-Plane to set park brake value
Serial.print("DREF ");
Serial.print(DATAREF_PARKBRAKE);
Serial.print(" ");
Serial.println(parkBrakeValue, 4); // Send value with 4 decimal places
Serial.print("// Park brake value: ");
Serial.println(parkBrakeValue, 4);
// Update the timestamp
lastParkBrakeUpdate = millis();
}
}
/* ==========================================================================
COM FREQUENCY UPDATE FUNCTION
Gradually changes COM frequency from 118 to 136 MHz
========================================================================== */
void updateComFrequency() {
if (millis() - lastComFreqUpdate > COM_FREQ_INTERVAL) {
// Update COM frequency gradually
comFrequency += comFreqDirection;
// Reverse direction if we hit the limits
if (comFrequency >= 136.0) {
comFrequency = 136.0;
comFreqDirection = -0.1; // Start decreasing
} else if (comFrequency <= 118.0) {
comFrequency = 118.0;
comFreqDirection = 0.1; // Start increasing
}
// Send DREF command to X-Plane to set COM frequency
Serial.print("DREF ");
Serial.print(DATAREF_COM_FREQ);
Serial.print(" ");
Serial.println(comFrequency, 2); // Send value with 2 decimal places
Serial.print("// COM frequency: ");
Serial.print(comFrequency, 2);
Serial.println(" MHz");
// Update the timestamp
lastComFreqUpdate = millis();
}
}
/* ==========================================================================
AIRCRAFT ICAO CODE UPDATE FUNCTION
Changes aircraft ICAO code from C152 to C1522 every second
========================================================================== */
void updateIcaoCode() {
if (millis() - lastIcaoUpdate > ICAO_INTERVAL) {
// Toggle ICAO code
icaoState = !icaoState;
// Send STRING command to X-Plane to set aircraft ICAO code
Serial.print("STRING ");
Serial.print(DATAREF_AIRCRAFT_ICAO);
Serial.print(" ");
if (icaoState) {
Serial.println("C1522"); // Send C1522 when state is true
} else {
Serial.println("C152"); // Send C152 when state is false
}
Serial.print("// Aircraft ICAO: ");
Serial.println(icaoState ? "C1522" : "C152");
// Update the timestamp
lastIcaoUpdate = millis();
}
}
/* ==========================================================================
READ CURRENT ICAO FUNCTION
This function doesn't actively read the ICAO value from X-Plane.
Instead, it just displays the last received value.
To receive values from X-Plane, you must configure the bridge to
subscribe to the dataref and map it to the OUTPUT_ID.
========================================================================== */
void readCurrentIcao() {
if (millis() - lastIcaoRead > ICAO_READ_INTERVAL) {
// Just display the last received ICAO value
Serial.print("// Current ICAO value: ");
Serial.println(currentIcaoValue);
// Update the timestamp
lastIcaoRead = millis();
}
}
/* ==========================================================================
END OF SKETCH
Congratulations! You now have a comprehensive test controller with multiple dataref types.
========================================================================== */