[{"data":1,"prerenderedAt":731},["ShallowReactive",2],{"article-737max-electronics":3},{"id":4,"title":5,"body":6,"description":722,"downloads":723,"extension":724,"lastUpdated":725,"meta":726,"navigation":190,"path":727,"readingTime":403,"seo":728,"stem":729,"__hash__":730},"projectArticles\u002Fprojects\u002F737max\u002Felectronics.md","Electronics & Microcontrollers",{"type":7,"value":8,"toc":705},"minimark",[9,14,18,29,32,35,39,46,49,127,130,132,136,141,148,154,157,161,164,228,237,241,248,278,285,287,291,295,298,314,321,430,442,446,449,455,462,464,468,475,481,484,589,591,595,643,650,658,660,664,671,673,677,683,689,695,701],[10,11,13],"h2",{"id":12},"architecture-overview","Architecture Overview",[15,16,17],"p",{},"Every input in this cockpit connects through a chain of ESP32 hardware, MobiFlight firmware, and SimConnect events:",[19,20,25],"pre",{"className":21,"code":23,"language":24},[22],"language-text","Physical Input\n  → ESP32\n    → USB HID \u002F Serial\n      → MobiFlight Connector (PC)\n        → SimConnect API\n          → MSFS 2024\n","text",[26,27,23],"code",{"__ignoreMap":28},"",[15,30,31],{},"Outputs (LED states, display values) flow in reverse — the simulator writes variables, MobiFlight reads them, and Arduinos drive the LEDs or displays accordingly.",[33,34],"hr",{},[10,36,38],{"id":37},"arduino-selection","Arduino Selection",[15,40,41,45],{},[42,43,44],"strong",{},"Arduino Mega 2560"," is the workhorse of this build. Each MCP, overhead panel zone, and pedestal section gets its own Mega.",[15,47,48],{},"Why Mega over Uno or Nano:",[50,51,52,68],"table",{},[53,54,55],"thead",{},[56,57,58,62,65],"tr",{},[59,60,61],"th",{},"Feature",[59,63,64],{},"Arduino Uno",[59,66,67],{},"Arduino Mega",[69,70,71,83,94,105,116],"tbody",{},[56,72,73,77,80],{},[74,75,76],"td",{},"Digital I\u002FO pins",[74,78,79],{},"14",[74,81,82],{},"54",[56,84,85,88,91],{},[74,86,87],{},"Analog inputs",[74,89,90],{},"6",[74,92,93],{},"16",[56,95,96,99,102],{},[74,97,98],{},"Hardware serial ports",[74,100,101],{},"1",[74,103,104],{},"4",[56,106,107,110,113],{},[74,108,109],{},"Flash memory",[74,111,112],{},"32 KB",[74,114,115],{},"256 KB",[56,117,118,121,124],{},[74,119,120],{},"Cost (AliExpress)",[74,122,123],{},"~€3",[74,125,126],{},"~€7",[15,128,129],{},"With 54 digital I\u002FO pins, a single Mega can handle an entire panel zone without the complexity of I²C multiplexers (though those are used for the overhead panel — see below).",[33,131],{},[10,133,135],{"id":134},"mcp-wiring","MCP Wiring",[137,138,140],"h3",{"id":139},"switch-matrix","Switch Matrix",[15,142,143,144,147],{},"Toggle switches and momentary buttons are wired in a ",[42,145,146],{},"matrix"," to save pins. A 6×8 matrix handles 48 switches using only 14 pins.",[19,149,152],{"className":150,"code":151,"language":24},[22],"      C0    C1    C2    C3    C4    C5    C6    C7\nR0  [SW1] [SW2] [SW3] [SW4] [SW5] [SW6] [SW7] [SW8]\nR1  [SW9] ...\nR2  ...\nR3  ...\nR4  ...\nR5  ...\n",[26,153,151],{"__ignoreMap":28},[15,155,156],{},"MobiFlight handles matrix scanning natively — configure it in the firmware editor, no custom code needed.",[137,158,160],{"id":159},"rotary-encoders","Rotary Encoders",[15,162,163],{},"Encoders (Bourns PEC11R) use 2 digital pins each plus a common ground. For the MCP, 6 encoders are wired to pins 22–33 on the Mega:",[19,165,169],{"className":166,"code":167,"language":168,"meta":28,"style":28},"language-cpp shiki shiki-themes github-light github-dark","\u002F\u002F MobiFlight encoder pin assignment (MCP)\n\u002F\u002F Defined in MobiFlight firmware config, not in sketch directly\n\n\u002F\u002F HDG encoder  → pins 22, 23\n\u002F\u002F SPD encoder  → pins 24, 25\n\u002F\u002F ALT encoder  → pins 26, 27\n\u002F\u002F VS  encoder  → pins 28, 29\n\u002F\u002F CRS1 encoder → pins 30, 31\n\u002F\u002F CRS2 encoder → pins 32, 33\n","cpp",[26,170,171,179,185,192,198,204,210,216,222],{"__ignoreMap":28},[172,173,176],"span",{"class":174,"line":175},"line",1,[172,177,178],{},"\u002F\u002F MobiFlight encoder pin assignment (MCP)\n",[172,180,182],{"class":174,"line":181},2,[172,183,184],{},"\u002F\u002F Defined in MobiFlight firmware config, not in sketch directly\n",[172,186,188],{"class":174,"line":187},3,[172,189,191],{"emptyLinePlaceholder":190},true,"\n",[172,193,195],{"class":174,"line":194},4,[172,196,197],{},"\u002F\u002F HDG encoder  → pins 22, 23\n",[172,199,201],{"class":174,"line":200},5,[172,202,203],{},"\u002F\u002F SPD encoder  → pins 24, 25\n",[172,205,207],{"class":174,"line":206},6,[172,208,209],{},"\u002F\u002F ALT encoder  → pins 26, 27\n",[172,211,213],{"class":174,"line":212},7,[172,214,215],{},"\u002F\u002F VS  encoder  → pins 28, 29\n",[172,217,219],{"class":174,"line":218},8,[172,220,221],{},"\u002F\u002F CRS1 encoder → pins 30, 31\n",[172,223,225],{"class":174,"line":224},9,[172,226,227],{},"\u002F\u002F CRS2 encoder → pins 32, 33\n",[229,230,231],"blockquote",{},[15,232,233,236],{},[42,234,235],{},"Debouncing:"," MobiFlight handles software debouncing. For electrically noisy environments, add a 100nF capacitor between each encoder pin and GND.",[137,238,240],{"id":239},"_7-segment-displays","7-Segment Displays",[15,242,243,244,247],{},"The MCP altitude, speed, heading, and VS readouts use ",[42,245,246],{},"TM1637"," 4-digit displays:",[19,249,251],{"className":166,"code":250,"language":168,"meta":28,"style":28},"\u002F\u002F TM1637 display wiring (MCP altitude display)\n\u002F\u002F CLK → Pin 40\n\u002F\u002F DIO → Pin 41\n\u002F\u002F VCC → 5V\n\u002F\u002F GND → GND\n",[26,252,253,258,263,268,273],{"__ignoreMap":28},[172,254,255],{"class":174,"line":175},[172,256,257],{},"\u002F\u002F TM1637 display wiring (MCP altitude display)\n",[172,259,260],{"class":174,"line":181},[172,261,262],{},"\u002F\u002F CLK → Pin 40\n",[172,264,265],{"class":174,"line":187},[172,266,267],{},"\u002F\u002F DIO → Pin 41\n",[172,269,270],{"class":174,"line":194},[172,271,272],{},"\u002F\u002F VCC → 5V\n",[172,274,275],{"class":174,"line":200},[172,276,277],{},"\u002F\u002F GND → GND\n",[15,279,280,281,284],{},"MobiFlight supports TM1637 natively — add it as an output device and bind it to ",[26,282,283],{},"AUTOPILOT_ALTITUDE_LOCK_VAR",".",[33,286],{},[10,288,290],{"id":289},"backlighting-system","Backlighting System",[137,292,294],{"id":293},"led-architecture","LED Architecture",[15,296,297],{},"The backlight system uses two types of LEDs:",[299,300,301,308],"ol",{},[302,303,304,307],"li",{},[42,305,306],{},"WS2812B addressable LEDs"," — for panel flood lighting and RGB annunciators",[302,309,310,313],{},[42,311,312],{},"Individual 3mm warm-white LEDs"," — for through-legend backlighting on the acrylic overlay",[15,315,316,317,320],{},"WS2812B strips are driven by a single data pin using the FastLED library. All strips are on a ",[42,318,319],{},"shared 5V \u002F 3A supply",", separate from the Arduino's USB power.",[19,322,324],{"className":166,"code":323,"language":168,"meta":28,"style":28},"\u002F\u002F FastLED setup (panel backlight)\n#include \u003CFastLED.h>\n\n#define LED_PIN     6\n#define NUM_LEDS    48\n#define BRIGHTNESS  80      \u002F\u002F 0–255, tune for panel brightness\n#define LED_TYPE    WS2812B\n#define COLOR_ORDER GRB\n\nCRGB leds[NUM_LEDS];\n\nvoid setup() {\n  FastLED.addLeds\u003CLED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);\n  FastLED.setBrightness(BRIGHTNESS);\n\n  \u002F\u002F Warm white for instrument panel feel\n  fill_solid(leds, NUM_LEDS, CRGB(255, 200, 120));\n  FastLED.show();\n}\n",[26,325,326,331,336,340,345,350,358,363,368,372,378,383,389,395,401,406,412,418,424],{"__ignoreMap":28},[172,327,328],{"class":174,"line":175},[172,329,330],{},"\u002F\u002F FastLED setup (panel backlight)\n",[172,332,333],{"class":174,"line":181},[172,334,335],{},"#include \u003CFastLED.h>\n",[172,337,338],{"class":174,"line":187},[172,339,191],{"emptyLinePlaceholder":190},[172,341,342],{"class":174,"line":194},[172,343,344],{},"#define LED_PIN     6\n",[172,346,347],{"class":174,"line":200},[172,348,349],{},"#define NUM_LEDS    48\n",[172,351,352,355],{"class":174,"line":206},[172,353,354],{},"#define BRIGHTNESS  80",[172,356,357],{},"      \u002F\u002F 0–255, tune for panel brightness\n",[172,359,360],{"class":174,"line":212},[172,361,362],{},"#define LED_TYPE    WS2812B\n",[172,364,365],{"class":174,"line":218},[172,366,367],{},"#define COLOR_ORDER GRB\n",[172,369,370],{"class":174,"line":224},[172,371,191],{"emptyLinePlaceholder":190},[172,373,375],{"class":174,"line":374},10,[172,376,377],{},"CRGB leds[NUM_LEDS];\n",[172,379,381],{"class":174,"line":380},11,[172,382,191],{"emptyLinePlaceholder":190},[172,384,386],{"class":174,"line":385},12,[172,387,388],{},"void setup() {\n",[172,390,392],{"class":174,"line":391},13,[172,393,394],{},"  FastLED.addLeds\u003CLED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);\n",[172,396,398],{"class":174,"line":397},14,[172,399,400],{},"  FastLED.setBrightness(BRIGHTNESS);\n",[172,402,404],{"class":174,"line":403},15,[172,405,191],{"emptyLinePlaceholder":190},[172,407,409],{"class":174,"line":408},16,[172,410,411],{},"  \u002F\u002F Warm white for instrument panel feel\n",[172,413,415],{"class":174,"line":414},17,[172,416,417],{},"  fill_solid(leds, NUM_LEDS, CRGB(255, 200, 120));\n",[172,419,421],{"class":174,"line":420},18,[172,422,423],{},"  FastLED.show();\n",[172,425,427],{"class":174,"line":426},19,[172,428,429],{},"}\n",[229,431,432],{},[15,433,434,437,438,441],{},[42,435,436],{},"Tip:"," Real 737 MAX panel lighting is a warm amber-white at around 2700K. ",[26,439,440],{},"CRGB(255, 200, 120)"," is a close approximation with WS2812B LEDs.",[137,443,445],{"id":444},"annunciator-leds","Annunciator LEDs",[15,447,448],{},"Warning and status annunciators use individual 3mm LEDs wired through 330Ω current-limiting resistors:",[19,450,453],{"className":451,"code":452,"language":24},[22],"Arduino Pin → 330Ω Resistor → LED Anode → LED Cathode → GND\n",[26,454,452],{"__ignoreMap":28},[15,456,457,458,461],{},"MobiFlight reads ",[26,459,460],{},"AUTOPILOT_MASTER"," and similar variables and writes HIGH\u002FLOW to the corresponding LED pin.",[33,463],{},[10,465,467],{"id":466},"overhead-panel-ic-multiplexing","Overhead Panel — I²C Multiplexing",[15,469,470,471,474],{},"The overhead panel has over 200 switches — far too many for a single Mega. The solution is ",[42,472,473],{},"PCF8574 I²C GPIO expanders",", each adding 8 inputs on a shared 2-wire bus.",[19,476,479],{"className":477,"code":478,"language":24},[22],"Arduino Mega SDA (pin 20) ─────┬──────────────────────\nArduino Mega SCL (pin 21) ─────┼─┬────────────────────\n                               │ │\n                         PCF8574 #1 (addr 0x20) → 8 switches\n                         PCF8574 #2 (addr 0x21) → 8 switches\n                         PCF8574 #3 (addr 0x22) → 8 switches\n                         ... up to 8 expanders per bus\n",[26,480,478],{"__ignoreMap":28},[15,482,483],{},"Each expander has 3 address pins (A0, A1, A2), giving 8 unique addresses (0x20–0x27) per I²C bus. The Mega has 4 hardware serial ports and supports a second I²C bus via the Wire1 library for additional expanders.",[19,485,487],{"className":166,"code":486,"language":168,"meta":28,"style":28},"#include \u003CWire.h>\n#include \u003CPCF8574.h>\n\nPCF8574 expander1(0x20);\nPCF8574 expander2(0x21);\n\nvoid setup() {\n  Wire.begin();\n  expander1.begin();\n  expander2.begin();\n}\n\nvoid loop() {\n  \u002F\u002F Read all 8 pins of expander 1\n  uint8_t state = expander1.read8();\n\n  \u002F\u002F Check individual pin\n  bool sw1 = expander1.read(0);  \u002F\u002F pin P0\n  bool sw2 = expander1.read(1);  \u002F\u002F pin P1\n  \u002F\u002F ...\n}\n",[26,488,489,494,499,503,508,513,517,521,526,531,536,540,544,549,554,559,563,568,573,578,584],{"__ignoreMap":28},[172,490,491],{"class":174,"line":175},[172,492,493],{},"#include \u003CWire.h>\n",[172,495,496],{"class":174,"line":181},[172,497,498],{},"#include \u003CPCF8574.h>\n",[172,500,501],{"class":174,"line":187},[172,502,191],{"emptyLinePlaceholder":190},[172,504,505],{"class":174,"line":194},[172,506,507],{},"PCF8574 expander1(0x20);\n",[172,509,510],{"class":174,"line":200},[172,511,512],{},"PCF8574 expander2(0x21);\n",[172,514,515],{"class":174,"line":206},[172,516,191],{"emptyLinePlaceholder":190},[172,518,519],{"class":174,"line":212},[172,520,388],{},[172,522,523],{"class":174,"line":218},[172,524,525],{},"  Wire.begin();\n",[172,527,528],{"class":174,"line":224},[172,529,530],{},"  expander1.begin();\n",[172,532,533],{"class":174,"line":374},[172,534,535],{},"  expander2.begin();\n",[172,537,538],{"class":174,"line":380},[172,539,429],{},[172,541,542],{"class":174,"line":385},[172,543,191],{"emptyLinePlaceholder":190},[172,545,546],{"class":174,"line":391},[172,547,548],{},"void loop() {\n",[172,550,551],{"class":174,"line":397},[172,552,553],{},"  \u002F\u002F Read all 8 pins of expander 1\n",[172,555,556],{"class":174,"line":403},[172,557,558],{},"  uint8_t state = expander1.read8();\n",[172,560,561],{"class":174,"line":408},[172,562,191],{"emptyLinePlaceholder":190},[172,564,565],{"class":174,"line":414},[172,566,567],{},"  \u002F\u002F Check individual pin\n",[172,569,570],{"class":174,"line":420},[172,571,572],{},"  bool sw1 = expander1.read(0);  \u002F\u002F pin P0\n",[172,574,575],{"class":174,"line":426},[172,576,577],{},"  bool sw2 = expander1.read(1);  \u002F\u002F pin P1\n",[172,579,581],{"class":174,"line":580},20,[172,582,583],{},"  \u002F\u002F ...\n",[172,585,587],{"class":174,"line":586},21,[172,588,429],{},[33,590],{},[10,592,594],{"id":593},"power-supply","Power Supply",[50,596,597,613],{},[53,598,599],{},[56,600,601,604,607,610],{},[59,602,603],{},"Rail",[59,605,606],{},"Voltage",[59,608,609],{},"Current",[59,611,612],{},"Powers",[69,614,615,629],{},[56,616,617,620,623,626],{},[74,618,619],{},"PSU 5V",[74,621,622],{},"5V DC",[74,624,625],{},"5A",[74,627,628],{},"Arduinos, WS2812B strips, logic",[56,630,631,634,637,640],{},[74,632,633],{},"PSU 12V",[74,635,636],{},"12V DC",[74,638,639],{},"2A",[74,641,642],{},"Future: stepper motors (trim wheel)",[15,644,645,646,649],{},"All Arduinos share a common ",[42,647,648],{},"5V \u002F GND bus"," from a single ATX power supply (silent fan, repurposed from a PC). USB connections to the PC are data-only — the Arduinos are powered by the ATX supply, not USB.",[229,651,652],{},[15,653,654,657],{},[42,655,656],{},"Critical:"," Always connect all GNDs together — Arduino GND, LED strip GND, and PSU GND must share a common reference or the WS2812B LEDs will flicker or behave erratically.",[33,659],{},[10,661,663],{"id":662},"full-wiring-diagram","Full Wiring Diagram",[665,666],"content-image",{"alt":667,"caption":668,"src":669,"width":670},"MCP wiring schematic","Complete MCP wiring schematic — click to enlarge","\u002Fimages\u002Fmcp-wiring-diagram.jpg","full",[33,672],{},[10,674,676],{"id":675},"troubleshooting","Troubleshooting",[15,678,679,682],{},[42,680,681],{},"Encoder skips steps or double-triggers","\n→ Add 100nF caps between encoder pins and GND. Check MobiFlight debounce setting (increase to 5–10ms).",[15,684,685,688],{},[42,686,687],{},"WS2812B LEDs flash white on startup","\n→ Add a 300–500Ω resistor on the data line and a 1000µF cap across VCC\u002FGND near the strip.",[15,690,691,694],{},[42,692,693],{},"MobiFlight doesn't detect Arduino","\n→ Check COM port in Device Manager. Ensure CH340 driver is installed (common on AliExpress Mega clones). Try a different USB cable (data-capable, not charge-only).",[15,696,697,700],{},[42,698,699],{},"SimConnect events not firing","\n→ Confirm MSFS is running before starting MobiFlight Connector. Check that the aircraft supports the event (some third-party aircraft use custom events).",[702,703,704],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":28,"searchDepth":181,"depth":181,"links":706},[707,708,709,714,718,719,720,721],{"id":12,"depth":181,"text":13},{"id":37,"depth":181,"text":38},{"id":134,"depth":181,"text":135,"children":710},[711,712,713],{"id":139,"depth":187,"text":140},{"id":159,"depth":187,"text":160},{"id":239,"depth":187,"text":240},{"id":289,"depth":181,"text":290,"children":715},[716,717],{"id":293,"depth":187,"text":294},{"id":444,"depth":187,"text":445},{"id":466,"depth":181,"text":467},{"id":593,"depth":181,"text":594},{"id":662,"depth":181,"text":663},{"id":675,"depth":181,"text":676},"Full electronics documentation for the 737 MAX build — ESP32 wiring, encoder debouncing, LED backlighting, and simulator integration.",null,"md","2026-03",{},"\u002Fprojects\u002F737max\u002Felectronics",{"title":5,"description":722},"projects\u002F737max\u002Felectronics","ZPHdBWMtpL_GHEvlNSUtn6VDgZJZRBCz1QaMKoktbgE",1781294860588]