Results 1 to 5 of 5
  1. #1
    25+ Posting Member
    Join Date
    Apr 2010
    Location
    BLR
    Posts
    34
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    SimCheck A300B4 MCP and Link2fs Multi (Experts)

    Hi everyone,

    Continuing my project to create as many different MCP's as I can for civil airliners in FSX, using Arduino for the outputs (and BU0836X for the inputs), the SimCheck A300 presented a challenge in that the offsets for the switch states (lighted LED annunciators) are not available. But thankfully, this aircraft uses standard SimConnect variables / FSUIPC offsets to store values for the numeric displays of NAV1, CRS1, SPD, V/S (non-numeric), HDG, ALT, NAV2 and CRS2, so reading them with Link2fs and sending them to seven cascaded 8-digit 7-segment LED modules was easy.

    I requested the developer of this exquisitely-modelled airliner (via the forum) to provide me with the offsets for the MCP switch states, but I got no response, so I tried this "back-door" method and it worked!

    (1) located a pixel in the centre of each MCP switch on screen, and used an autoit script to detect and record its pixel colour when the switch light comes on (record as a decimal value with x,y coordinates)
    (2) wrote an autoit script that continuously checks (every 100 msec) these pixel coordinates for color changes like this:
    Code:
    If PixelGetColor (2281, 149) = 13041540 Then
        local $ispd = 1
      Else
            $ispd = 0
    EndIf
    and on that basis writes the switch states to a text file. The output to this text file might look like this:
    Code:
    spd=0,enwun=0,ias=0,nav=0,land=0,appr=0,vorloc=0,hdgsel=1,alt=0,vspd=1,fdone=1,fdtwo=0,altacq=1,apone=1,aptwo=0

    This file is updated every 100 msec.
    (3) wrote a lua plugin which opens this file every 100 msec, reads the switch states and writes them to FSUIPC 'user' offsets starting at 0x66C0. I had 15 such switch states and so I used 15 of the 16 available offsets.
    (4) then got Link2fs to read those offsets and on that basis operate the led's off my Mega pins.

    The LED's operate with very little lag (say 250 msec at most) from their on-screen 'parents'.Of course, this method works only as long as you can have a working screen displaying the FS panels that you want to read the pixels from.

    I have attached screenshots of the SimCheck A300 MCP and the Link2fs pages, a photo of my test-setup showing the 7 cascaded LED modules and LED switch annunciator lights, as well as the .ino I have written. I would be happy to share the lua plugin as well as the autoit scripts if anyone is interested.

    Code:
    //for SimCheck A300B4-203
    //this .ino manages all OUTPUTS for central MCP numeric displays & led annunciators (in illuminated mode select switches)
    //display units used here are 7 cascaded 8-digit 7-segment LED modules driven by MAX7219
    //by Chakko Kovoor, with thanks to Jim for Link2fs, and Fess_ter for his code examples
    
    #include 
    
    LedControl led_Display_1 = LedControl(12,10,11,7);   // 7 modules 
    
    int CodeIn;        // used on all serial reads from Jim's code
    String Digit;      //
    int Count;         // This variable used in loops in the EQUALS() function
    
    int MCP_IAS_set[3];
    int MCP_Heading_set[3];
    char MCP_VertSpeed_minus;
    int MCP_VertSpeed_set[4];
    int MCP_Altitude_set[5];
    int MCP_NAV1freq[5];
    int MCP_NAV1Crs[3];
    int MCP_NAV2freq[5];
    int MCP_NAV2Crs[3];
    
    byte annunSPD;
    byte annunN1;
    byte annunIAS;
    byte annunNAV;
    byte annunLAND;
    byte annunAPPR; 
    byte annunVORLOC; 
    byte annunHDG; 
    byte annunALT; 
    byte annunVSPD; 
    byte annunFD1; 
    byte annunFD2; 
    byte annunALTACQ;
    byte annunAP1; 
    byte annunAP2; 
    
    // **************************************************************************************************
    
    void setup() 
    {
      // The MAX72XX is in power-saving mode on startup, we have to do a wakeup call
      delay (500);
      led_Display_1.shutdown(0,false);      
      delay (500);                          
      led_Display_1.shutdown(1,false);
      delay (500);                          
      led_Display_1.shutdown(2,false);
      delay (500);                          
      led_Display_1.shutdown(3,false);  
      delay (500);                          
      led_Display_1.shutdown(4,false);
       delay (500);                          
      led_Display_1.shutdown(5,false);
       delay (500);                          
      led_Display_1.shutdown(6,false);
      
      // Set the brightness to a lower than medium values 
      led_Display_1.setIntensity(0,4);
      led_Display_1.setIntensity(1,4);
      led_Display_1.setIntensity(2,4);
      led_Display_1.setIntensity(3,4);
      led_Display_1.setIntensity(4,4);
      led_Display_1.setIntensity(5,4);
      led_Display_1.setIntensity(6,4);
      
      // and clear the display 
      led_Display_1.clearDisplay(0);
      led_Display_1.clearDisplay(1);
      led_Display_1.clearDisplay(2);
      led_Display_1.clearDisplay(3);
      led_Display_1.clearDisplay(4);
      led_Display_1.clearDisplay(5);
      led_Display_1.clearDisplay(6);
      
      // Get all the "project" OUTPUT pins ready
      for (int PinNo = 2; PinNo <= 9; PinNo++)  
      {pinMode(PinNo, OUTPUT);}
      for (int PinNo = 21; PinNo <= 52; PinNo++)
      {pinMode(PinNo, OUTPUT);}
        
      Serial.begin(115200);   
    }//end of setup
    
    //*******************************************
    
    void loop() 
    {if (Serial.available()) 
      { CodeIn = getChar();
        if (CodeIn == '#') 
        {
         POUND();              // The first identifier is "#"
        }
      }
    }
    
    //*********************************************************
    
    char getChar()// Get a character from the serial buffer
    {
      while(Serial.available() == 0);   // wait for data
      return((char)Serial.read());      
    }                  
         
    //*********************************************************
    
    void POUND(){      // The first identifier was "#"
    
            CodeIn = getChar(); // Get another character
            switch(CodeIn) {// Now lets find what to do with it
          
         case 'b':    //  MCP_IASMach set
            Count = 0;
            while (Count < 3)
            {Digit = "";
            Digit += getChar();
            MCP_IAS_set[Count] = Digit.toInt();
            Count++;}
            
            {led_Display_1.setChar(2,7,' ',false);
            led_Display_1.setDigit(2,6,MCP_IAS_set[0],false);
            led_Display_1.setDigit(2,5,MCP_IAS_set[1],false);
            led_Display_1.setDigit(2,4,MCP_IAS_set[2],false);}
            
         break;
           
           
          
         case 'a':    //  MCP_Heading set
              Count = 0;
              while (Count < 3)
              {Digit = "";
              Digit += getChar();
              MCP_Heading_set[Count] = Digit.toInt();
              Count++;}
              
              led_Display_1.setDigit(2,3,' ',false);
              led_Display_1.setDigit(2,2,MCP_Heading_set[0],false);
              led_Display_1.setDigit(2,1,MCP_Heading_set[1],false);
              led_Display_1.setDigit(2,0,MCP_Heading_set[2],false);
         break;
        
        
         case 'e':    //  MCP_VertSpeed set with minus 
              Count = 0;
              while (Count < 4)
              {Digit = "";
              Digit += getChar();
                  if (Count == 0)
                  {if (Digit == "-")
                  {MCP_VertSpeed_minus = '-';
                  Digit = "";
                  Digit += getChar();}
                  else 
                  {MCP_VertSpeed_minus = ' ';}}                     
              MCP_VertSpeed_set[Count] = Digit.toInt();
              Count++;}
              
              {led_Display_1.setChar(3,7,' ',false);
              led_Display_1.setChar(3,6,' ',false);
              led_Display_1.setChar(3,5,' ',false);
              led_Display_1.setChar(3,4,MCP_VertSpeed_minus,false);
              led_Display_1.setDigit(3,3,MCP_VertSpeed_set[0],false);
              led_Display_1.setDigit(3,2,MCP_VertSpeed_set[1],false);
              led_Display_1.setDigit(3,1,MCP_VertSpeed_set[2],false);
              led_Display_1.setDigit(3,0,MCP_VertSpeed_set[3],false);}
              
          break;
          
        
          case 'd':    //  MCP_Altitude set
              Count = 0;
              while (Count < 5)
              {Digit = "";
              Digit += getChar();
              MCP_Altitude_set[Count] = Digit.toInt();
              Count++;}
              
              {led_Display_1.setDigit(4,7,' ',false);
              led_Display_1.setDigit(4,6,' ',false);
              led_Display_1.setDigit(4,5,' ',false);
              led_Display_1.setDigit(4,4,MCP_Altitude_set[0],false);
              led_Display_1.setDigit(4,3,MCP_Altitude_set[1],false); 
              led_Display_1.setDigit(4,2,MCP_Altitude_set[2],false);
              led_Display_1.setDigit(4,1,MCP_Altitude_set[3],false);
              led_Display_1.setDigit(4,0,MCP_Altitude_set[4],false);}
          break;
          
          case 'f':    //  MCP_NAV1_Freq set (fsuipc offset NAV1 freq 0x0350)
              Count = 0;
              while (Count < 5)
              {Digit = "";
              Digit += getChar();
              MCP_NAV1freq[Count] = Digit.toInt();
              Count++;}
              
              {led_Display_1.setChar(0,7,MCP_NAV1freq[0],false);
              led_Display_1.setChar(0,6,MCP_NAV1freq[1],false); 
              led_Display_1.setChar(0,5,MCP_NAV1freq[2],true); // activate dp
              led_Display_1.setChar(0,4,MCP_NAV1freq[3],false);
              led_Display_1.setChar(0,3,MCP_NAV1freq[4],false);}
          break;
        
          
          case 'g':    //  Pedestal_ILS_Course set (fsuipc offset NAV1 OBS 0x0C4E)
              Count = 0;
              while (Count < 3)
              {Digit = "";
              Digit += getChar();
              MCP_NAV1Crs[Count] = Digit.toInt();
              Count++;}
              
              led_Display_1.setDigit(1,7,MCP_NAV1Crs[0],false);
              led_Display_1.setDigit(1,6,MCP_NAV1Crs[1],false);
              led_Display_1.setDigit(1,5,MCP_NAV1Crs[2],false);
           break;
           
           
           case 'h':    //  MCP_NAV2_Freq set (fsuipc offset NAV2 freq  )
              Count = 0;
              while (Count < 5)
              {Digit = "";
              Digit += getChar();
              MCP_NAV2freq[Count] = Digit.toInt();
              Count++;}
              
              {led_Display_1.setChar(5,7,MCP_NAV2freq[0],false);
              led_Display_1.setChar(5,6,MCP_NAV2freq[1],false); 
              led_Display_1.setChar(5,5,MCP_NAV2freq[2],true); // activate dp
              led_Display_1.setChar(5,4,MCP_NAV2freq[3],false);
              led_Display_1.setChar(5,3,MCP_NAV2freq[4],false);}
          break;
        
          
          case 'i':    //  Pedestal_ILS_Course set (fsuipc offset NAV2 OBS  )
              Count = 0;
              while (Count < 3)
              {Digit = "";
              Digit += getChar();
              MCP_NAV2Crs[Count] = Digit.toInt();
              Count++;}
              
              led_Display_1.setDigit(6,7,MCP_NAV2Crs[0],false);
              led_Display_1.setDigit(6,6,MCP_NAV2Crs[1],false);
              led_Display_1.setDigit(6,5,MCP_NAV2Crs[2],false);
           break;
          
          
          case 'j':    //  MCP_annunSPD set
            Digit = "";
            Digit += getChar();
            annunSPD = Digit.toInt();
            if (annunSPD == 1) {digitalWrite (9, HIGH);}
            else if (annunSPD == 0) {digitalWrite (9, LOW);}
        break;
        
          case 'k':    //  MCP_annunN1 set
            Digit = "";
            Digit += getChar();
            annunN1 = Digit.toInt();
            if (annunN1 == 1) {digitalWrite (8, HIGH);}
            else if (annunN1 == 0) {digitalWrite (8, LOW);}
        break;
        
          case 'l':    //  MCP_annunIAS set
            Digit = "";
            Digit += getChar();
            annunIAS = Digit.toInt();
            if (annunIAS == 1) {digitalWrite (7, HIGH);}
            else if (annunIAS == 0) {digitalWrite (7, LOW);}
        break;
        
        
         case 'm':    //  MCP_NAV set
            Digit = "";
            Digit += getChar();
            annunNAV = Digit.toInt();
            if (annunNAV == 1) {digitalWrite (6, HIGH);}
            else if (annunNAV == 0) {digitalWrite (6, LOW);}
        break;
        
          case 'n':    //  MCP_LAND set
            Digit = "";
            Digit += getChar();
            annunLAND = Digit.toInt();
            if (annunLAND == 1) {digitalWrite (5, HIGH);}
            else if (annunLAND == 0) {digitalWrite (5, LOW);}
        break;
        
          case 'o':    //  MCP_APPR set
            Digit = "";
            Digit += getChar();
            annunAPPR = Digit.toInt();
            if (annunAPPR == 1) {digitalWrite (4, HIGH);}
            else if (annunAPPR == 0) {digitalWrite (4, LOW);}
        break;
        
          case 'p':    //  MCP_VORLOC set
            Digit = "";
            Digit += getChar();
            annunVORLOC = Digit.toInt();
            if (annunVORLOC == 1) {digitalWrite (3, HIGH);}
            else if (annunVORLOC == 0) {digitalWrite (3, LOW);}
        break;
        
        
          case 'q':    //  MCP_annunHDGSEL set
            Digit = "";
            Digit += getChar();
            annunHDG = Digit.toInt();
            if (annunHDG == 1) {digitalWrite (2, HIGH);}
            else if (annunHDG == 0) {digitalWrite (2, LOW);}
        break;
        
          case 'r':    //  MCP_annunALT set
            Digit = "";
            Digit += getChar();
            annunALT = Digit.toInt();
            if (annunALT == 1) {digitalWrite (22, HIGH);}
            else if (annunALT == 0) {digitalWrite (22, LOW);}
        break;
       
       
         case 's':    //  MCP_VSPD set
            Digit = "";
            Digit += getChar();
            annunVSPD = Digit.toInt();
            if (annunVSPD == 1) {digitalWrite (23, HIGH);}
            else if (annunNAV == 0) {digitalWrite (23, LOW);}
        break;
        
          case 't':    //  MCP_FD1 set
            Digit = "";
            Digit += getChar();
            annunFD1 = Digit.toInt();
            if (annunFD1 == 1) {digitalWrite (24, HIGH);}
            else if (annunFD1 == 0) {digitalWrite (24, LOW);}
        break;
        
          case 'u':    //  MCP_FD2 set
            Digit = "";
            Digit += getChar();
            annunFD2 = Digit.toInt();
            if (annunFD2 == 1) {digitalWrite (25, HIGH);}
            else if (annunFD2 == 0) {digitalWrite (25, LOW);}
        break;
        
        
          case 'v':    //  MCP_ALTACQ set
            Digit = "";
            Digit += getChar();
            annunALTACQ = Digit.toInt();
            if (annunALTACQ == 1) {digitalWrite (26, HIGH);}
            else if (annunALTACQ == 0) {digitalWrite (26, LOW);}
        break;
        
        
          case 'w':    //  MCP_AP1 set
            Digit = "";
            Digit += getChar();
            annunAP1 = Digit.toInt();
            if (annunAP1 == 1) {digitalWrite (27, HIGH);}
            else if (annunAP1 == 0) {digitalWrite (27, LOW);}
        break;
        
          case 'x':    //  MCP_AP2 set
            Digit = "";
            Digit += getChar();
            annunAP2 = Digit.toInt();
            if (annunAP2 == 1) {digitalWrite (28, HIGH);}
            else if (annunAP2 == 0) {digitalWrite (28, LOW);}
        break;
           
        }  // end of switch
    } // end of void pound
    I invite your comments on this method.

    I am considering requesting Pete Dowson to include lua facilities in FSUIPC for reading pixel data on screens displaying FS, as that would obviate the need for external programs (like autoit) to do this work; also as FSUIPC lua has a COM library, that pixel data could be analyzed in lua and then transmitted to Arduino. Alternatively, Jim might want to consider adding such functionality to Link2fs itself: I mean the ability to read pixel data from areas of the FS screen in order to transmit this information to the Arduino, directly, even without the use of FSUIPC user offsets (which are limited in number).

    I am now experimenting with reading pixels from digital numeric displays on FS screens and analyzing them to find the values of the various AP parameters (ALT, HDG, V/S etc). This would be of help in cases like the PMDG MD-11 where virtually no information about these can be extracted for lack of published or 'discovered' offsets.

    Thank you and Regards,

    Chakko.
    Attached Images Attached Images

  2. Thanks bizjet999, bsmart thanked for this post
    Likes bsmart liked this post
  3. #2
    25+ Posting Member
    Join Date
    Apr 2010
    Location
    BLR
    Posts
    34
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: SimCheck A300B4 MCP and Link2fs Multi (Experts)

    Hi,

    My experiments with reading numeric displays off the PMDG MD-11 MCP were successful, and discussion of the method can be found at the FSUIPC forum:

    http://forum.simflight.com/topic/78417-lua-for-pixel-analysis/


    Thanks,

    Chakko.

  4. #3
    300+ Forum Addict Avro748's Avatar
    Join Date
    Dec 2012
    Location
    At the Controls
    Posts
    359
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: SimCheck A300B4 MCP and Link2fs Multi (Experts)

    I'm surprised this isn't getting more attention. I've had to do all kinds of crazy xml editing and lua scripting to convert LVars into offsets for the annunciators to work on my build, and even then, they don't always work correctly. Your idea could really revolutionize cockpit building, maybe even allowing for something other than 737s to show up.

  5. #4
    25+ Posting Member
    Join Date
    Apr 2010
    Location
    BLR
    Posts
    34
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: SimCheck A300B4 MCP and Link2fs Multi (Experts)

    I am happy that at least a few people here think this will be useful. Thank you, Avro748, for saying so!

  6. #5
    Our new friend needs to reach 10 posts to get to the next flight level
    Join Date
    Nov 2014
    Location
    India
    Posts
    6
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: SimCheck A300B4 MCP and Link2fs Multi (Experts)

    Quote Originally Posted by tomahawk66 View Post
    I am happy that at least a few people here think this will be useful. Thank you, Avro748, for saying so!
    Thanks for the code will work on it and post details.! can you please share how you wired setup? like a sketch would love to see it.
    Last edited by Charan; 03-04-2015 at 12:26 PM. Reason: doubt on wiring.