Results 1 to 6 of 6
  1. #1
    150+ Forum Groupie


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    164
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    General Aviation Lower Switch Panel In A Can

    // General Aviation Lower Switch Panel In A Can

    /*
    Two_Way_Main_I2C_Controller.ino

    General Aviation Lower Switch Panel In A Can

    My thanks as always to the mycockpit.org community, the arduino.cc community and especially jim for www.jimspage.co.nz

    This sketch is a combination of many posts on the web. My thanks to the authors and the organizations.
    https://www.arduino.cc/en/Tutorial/MasterWriter
    https://michael.bouvy.net/blog/en/20...to-master-i2c/ Master #2 sketch

    Its ugly but it works. Why not use an Arduino Mega and pull the wires from the flap switch with stepper motor and driver, 16 or more toggle switches, landing gear switch and indicator leds to one location? Not to mention the circuitry needed by the pricipal use for the board. Given the choice between spaghetti code and spaghetti circuitry, I will choose the code every time. I hope that this has been brought down to a level that somebody can build this on a breadboard and adapt the circuit to their needs.

    A poor man's I2C copy of the SPI protocol is at the centre of the project. The two way transfer is not instantaneous, but it is coordinated. Every 60 milliseconds the Main board - Nano, Uno, or Mega - pulls either two bytes from the download stack or a single null character and fires the packet at the Deputy (Pro Mini). The data byte from the packet is stored in a variable and the Deputy in turn, pulls a data byte or null character from its upload stack and fires that off to the Main board. The Main board monitors the downloads from Link2FS and the Deputy board monitors the switch panel hardware.

    To do this both boards must act as both controller and controllee. This is possible in this bare bones form because the Main board transmission triggers the transmission from the Deputy board. Any communication with other I2C devices on the circuit should use the more traditional 'transmit' and 'requestFrom' procedures with the Main board as master.

    In the 59 or so milliseconds until the next transmission, my Main board will be running King KFC 225_ish full function autopilot and King KN 62A_ish DME as well as processing traffic both ways for the flap indicator and gear lamps. Maximum time to transmit two bytes in both directions is just under 2 milliseconds. Transmission of the single null byte is faster. In future parts, I will see if eliminating the return transmission of the null byte is beneficial.

    DEMO setup: Any two Arduino boards connect SDA to SDA and SCL to SCL. GND to GND, and 5V to 5V. Get specific pins for your board from a pinout .jpeg. This DEMO does not require pullup resistors for SDA and SCL.

    part 1. Main board I2C controller. This is the core sketch. Other posts will add user functions as equipment is added.
    - add code for Link2FS extractions and inputs as required.

    BushPilotWannabe
    May 2017
    */

    #include "Wire.h"

    volatile bool receive_acknol;

    byte transmit_buffer[20]; // holds ten 2 byte data packets (source identifier and data byte)
    long transmit_slot; // time in milliseconds for the next transmission to the Deputy board
    byte transmit_byte1; // source identifier -- magneto, flap, parallel out shift register to start with
    byte transmit_byte2; // data - switch position
    bool transmit_twoBytes; // switch between transmit one byte or two

    //download stack
    byte stack_last; // last occupied level on the stack
    long stack_slot; // time in milliseconds for the next call to STACK() function


    // *******************
    // VOID SETUP() **********************************************************************************
    // *******************

    void setup() {
    Wire.begin(0); // join i2c bus -- Wire begin() will not work when using Wire.onReceive() -- must have a device code
    Wire.onReceive(RECEIVE_EVENT);
    Serial.begin(115200);
    transmit_buffer[0] = 255;
    }// end setup

    // *******************
    // VOID LOOP() *********************************************************************************
    // *******************

    void loop() {

    //Receive incoming two bytes from Deputy board
    if (receive_acknol == true) {PROCESS_RECEIVED(); receive_acknol = false;}

    //Prepare the next packet for transmission -- millis() + 10000 stops repeats until reset by PROCESS_RECEIVED()
    if (millis() > stack_slot) {STACK(); stack_slot = millis() + 10000;}

    //Send the processed data to the Deputy board and schedule timed operations
    if (millis() > transmit_slot) {
    TRANSMIT();
    stack_slot = millis() + 50;
    transmit_slot = millis() + 60;
    }// close if millis() > transmit_slot

    //Generate simulated data
    DEMO();

    }// end loop()


    // ***************************
    // I2C TRANSMIT & RECEIVE *************************************************************************
    // ***************************

    void RECEIVE_EVENT(int howMany) {
    //Process everything outside the ISR

    receive_acknol = true;
    }// end RECEIVE_EVENT()


    void PROCESS_RECEIVED() {
    //We will process incoming data here

    //Display incoming data
    byte c;
    if (Wire.available()) {
    c = Wire.read();
    // if (c == 255) Serial.println(c);
    if (c == 254) {
    c = Wire.read();
    Serial.println(c);
    }
    if (c == 253) {
    c = Wire.read();
    Serial.print(" "); Serial.println(c);
    }
    }// close if Wire.available()
    }// end PROCESS_RECEIVED()


    void TRANSMIT() {
    //Start communication, download bytes of data or null message, and end communication

    Wire.beginTransmission(8 ) ; // to device #8
    if (transmit_twoBytes == true) {
    Wire.write(transmit_byte1);
    Wire.write(transmit_byte2);
    transmit_twoBytes = false;
    //Serial.println(transmit_byte1);
    //Serial.println(transmit_byte2);
    }
    else Wire.write(255);
    Wire.endTransmission();
    }// end TRANSMIT()




    // ********************************
    // GENERATE OUTGOING DEMO DATA ************************************************************************
    // ********************************


    void STACK() {
    //Prepare TRANSMIT() for default one byte packet

    transmit_twoBytes = false;
    if (stack_last > 0) {

    //Transfer bottom two bytes of the stack to variables and freeze their value until transmission
    transmit_byte1 = transmit_buffer[1];
    transmit_byte2 = transmit_buffer[2];

    //Remove bottom two bytes from the stack
    for (int outer = 0; outer < 2; outer++) {
    for (int inner = 0; inner < stack_last; inner++) {
    transmit_buffer[inner] = transmit_buffer[inner + 1];
    }
    transmit_buffer[stack_last] = 255;
    stack_last--;
    }// close for int outer = 0 ....
    transmit_twoBytes = true;
    }// close if stack_last > 0

    //Lock out call to STACK() until loop() updates stack_slot
    stack_slot = millis() + 10000;
    }// end STACK()

    void DEMO() {
    //Supply two different series of numbers to the download stack at different rates
    static int demo_counter = 115;
    static int demo_counter1 = 15;
    static long scheduleTimer1;
    static long scheduleTimer2;

    if ((millis() > scheduleTimer1) && (stack_last < 17)){ // stack size is 20 -- anything over will corrupt other data
    stack_last++;
    transmit_buffer[stack_last] = 253;
    stack_last++;
    transmit_buffer[stack_last] = demo_counter;
    demo_counter++;
    if (demo_counter == 151) demo_counter = 101;
    scheduleTimer1 = millis() + 100;
    }// close if millis() > scheduleTimer1
    if ((millis() > scheduleTimer2) && (stack_last < 17)) { // ditto
    stack_last++;
    transmit_buffer[stack_last] = 254;
    stack_last++;
    transmit_buffer[stack_last] = demo_counter1;
    demo_counter1++;
    if (demo_counter1 == 51) demo_counter1 = 1;
    scheduleTimer2 = millis() + 200;
    }// close if millis() > scheduleTimer2
    }// end DEMO()
    Last edited by BushPilotWannabe; 06-15-2017 at 07:24 PM. Reason: small changes to facilitate adding later components
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013

  2. #2
    150+ Forum Groupie


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    164
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: General Aviation Lower Switch Panel In A Can

    /*Re: General Aviation Lower Switch Panel In A Can

    Two_Way_Deputy_I2C_Controller

    General Aviation Lower Switch Panel In A Can

    Now on to the Pro Mini Deputy board. When complete the arriving transmission from Main is used to synchronize all functions. At zero ms, the outgoing packet is transmitted and the incoming packet updates the flap indicator and gear position lights (servo or stepper motor and parallel out shift register). At plus 30 ms, analog pins A6 and A7 are checked for movement of the magneto switch and flap switch and any changes to the stack. At plus 40 ms two 74xx165 serial out shift registers add any changes in scanned toggle switch status to the stack. Finally at plus 50, two bottom bytes of the stack are passed to variables; ready when loop() enables the I2C transmission function following the arrival of the next packet from the Main board.

    Most of this DEMO is a copy of the Main I2C sketch. Use comments from there.

    part 2. Deputy board I2C controller
    - the other half of main board I2C controller part 1.
    - add code for shift registers, stepper motors etc. as required

    BushPilotWannabe
    May 2017
    */

    #include "Wire.h"

    volatile bool receive_acknol;

    byte transmit_buffer[20]; // holds ten 2 byte data packets (source identifier and data byte)
    long transmit_slot; // time in milliseconds for the next transmission to the Deputy board
    byte transmit_byte1; // source identifier -- magneto, flap, parallel out shift register to start with
    byte transmit_byte2; // data - switch position
    bool transmit_twoBytes; // switch between transmit one byte or two

    //download stack
    byte stack_last; // last occupied level on the stack
    long stack_slot; // time in milliseconds for the next call to STACK() function


    // *******************
    // VOID SETUP ***************************************************************************************
    // ******************

    void setup() {
    // SN2003 pins 2 to 5
    // 74xx595 pins 6 to 9
    // 74xx165 pins 10 to 12
    // Hall effect sensor pin 13 -- calibrate the flap indicator -- requires removal of the blink diode from the board
    // pins 14 to 17 (A0 to A3) still available
    // ANALOG (4) I2C SDA
    // ANALOG (5) I2C SCL
    // ANALOG (6) MAGNETO SWITCH // analog input only pin -- use it or lose it
    // ANALOG (7) FLAP SWITCH

    Wire.begin(8 ); // join i2c bus with address #8
    Wire.onReceive(RECEIVE_EVENT);
    Serial.begin(115200); // only required for the DEMO and programming later additions
    }// end setup()

    // *************
    // VOID LOOP ***************************************************************************************
    // *************

    void loop() {
    if (receive_acknol == true) {PROCESS_RECEIVED(); receive_acknol = false;}

    //Prepare the next packet for transmission -- millis() + 10000 stops repeats until reset by PROCESS_RECEIVED()
    if (millis() > stack_slot) {STACK(); stack_slot = millis() + 10000;}

    //Send the processed data to the Deputy board and schedule timed operations
    if (millis() > transmit_slot) {TRANSMIT(); transmit_slot = millis() + 10000;}

    //Generate simulated data
    DEMO();

    }// end loop()

    // ***************************
    // I2C TRANSMIT & RECEIVE ***************************************************************************************
    // ***************************

    void RECEIVE_EVENT(int howMany) {
    //Process everything outside the ISR

    receive_acknol = true;
    }// end RECEIVE_EVENT())


    void PROCESS_RECEIVED() {
    //We will process incoming data here

    //Display incoming data
    byte c;
    if (Wire.available()) {
    c = Wire.read();
    // if (c == 255) Serial.println(c);
    if (c == 254) {
    c = Wire.read();
    Serial.println(c);
    }
    if (c == 253) {
    c = Wire.read();
    Serial.print(" "); Serial.println(c);
    }
    }// close if Wire.available()

    // schedule calls by void loop() to other functions
    transmit_slot = millis();
    stack_slot = millis() + 50;
    }// end PROCESS_RECEIVED()

    void TRANSMIT() {
    //Start communication, download bytes of data or null message, and end communication

    Wire.beginTransmission(0) ; // to Main board device #0
    if (transmit_twoBytes == true) {
    Wire.write(transmit_byte1);
    Wire.write(transmit_byte2);
    transmit_twoBytes = false;
    //Serial.println(transmit_byte1);
    //Serial.println(transmit_byte2);
    }
    else Wire.write(255);
    Wire.endTransmission();
    }// end TRANSMIT()


    // *****************************
    // MANIPULATE OUTGOING DATA ***************************************************************************************
    // *****************************

    void STACK() {
    //Prepare TRANSMIT() for default one byte packet

    transmit_twoBytes = false;
    if (stack_last > 0) {

    //Transfer bottom two bytes of the stack to variables and freeze their value until transmission
    transmit_byte1 = transmit_buffer[1];
    transmit_byte2 = transmit_buffer[2];

    //Remove bottom two bytes from the stack
    for (int outer = 0; outer < 2; outer++) {
    for (int inner = 0; inner < stack_last; inner++) {
    transmit_buffer[inner] = transmit_buffer[inner + 1];
    }
    transmit_buffer[stack_last] = 255;
    stack_last--;
    }// close for int outer = 0 ....
    transmit_twoBytes = true;
    }// close if stack_last > 0

    //Lock out call to STACK() until loop() updates stack_slot
    stack_slot = millis() + 10000;
    }// end STACK()

    // ********************************
    // GENERATE OUTGOING DEMO DATA ***************************************************************************************
    // ********************************

    void DEMO() {
    //Supply two different series of numbers to the download stack at different rates
    static long scheduleTimer1;
    static long scheduleTimer2;
    static int demo_counter = 160;
    static int demo_counter1 = 60;

    if ((millis() > scheduleTimer1) && (stack_last < 17)){ // stack size is 20 -- anything over will corrupt other data
    stack_last++;
    transmit_buffer[stack_last] = 253;
    stack_last++;
    transmit_buffer[stack_last] = demo_counter;
    demo_counter++;
    if (demo_counter == 201) demo_counter = 151;
    scheduleTimer1 = millis() + 381;
    //Serial.println(stack_last);
    //Serial.println(demo_counter1);
    }// close if millis() > scheduleTimer1
    if ((millis() > scheduleTimer2) && (stack_last < 17)){ // ditto
    stack_last++;
    transmit_buffer[stack_last] = 254;
    stack_last++;
    transmit_buffer[stack_last] = demo_counter1;
    demo_counter1++;
    if (demo_counter1 == 101) demo_counter1 = 51;
    scheduleTimer2 = millis() + 85;

    }// close if millis() > scheduleTimer2

    }// end DEMO()
    Last edited by BushPilotWannabe; 06-15-2017 at 07:27 PM. Reason: small changes to facilitate adding later components
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013

  3. #3
    150+ Forum Groupie


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    164
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: General Aviation Lower Switch Panel In A Can

    General Aviation Lower Switch Panel In A Can part 3. Two_Way_Main_Analog_Devices

    My thanks as always to the mycockpit.org community, the arduino.cc community and especially Jim for www.jimspage.co.nz

    This is beginning to look like a hard way of doing Jim's Multi Annunciator Panel -- http://www.jimspage.co.nz/Multi_Annunciators.htm
    We have the Main and Deputy boards communicating in parts 1 & 2. Parts 3 & 4 handle the analog inputs ie. magneto switch and flaps and continue to employ common components. Everybody has at least two Arduino boards, one 12 pos. rotary switch and one or two linear 50k pots, right?

    Part 3 expands on the post Two_Way_Main_I2C_Controller.ino, receiving two bytes of data from the Deputy board and then package this into Jim’s SimConnect inputs for uploading to Link2FS and FSX. This sketch is set up as a stand alone demo. The main objective is to add these functions to an existing sketch of your radio stack or other aircraft sytem using only the two I2C pins and a small amount of program space.


    *** Load your existing 'Two_Way_Main_I2C_Controller.ino' and save the file as "Two_Way_Main_Analog_Devices"


    *** Remove any of the preamble that only applies to the demo sketch.


    *** Delete two lines in void loop()
    //Generate simulated data
    DEMO();

    *** Delete the entire user function void DEMO().


    *** REPLACE THE OLD void PROCESS_RECEIVED() user function' with

    void PROCESS_RECEIVED(){
    //We will process incoming I2C data here
    byte c;

    //Process system identifier
    if (Wire.available()) {
    c = Wire.read(); // process system identifier
    //Serial.println(c);

    //Process flaps
    if (c == 210){
    c = Wire.read();

    //Convert flap switch byte into Link2FS SimConnect Input code
    // format is 'C17' then 3 digit value 0 --> 100 %. 100% is 90 degrees of flap extension. -- That's more than a DHC-3 Otter
    byte tempByte = c;
    String tempString = String(tempByte);
    while (tempString.length() < 3){tempString = '0' + tempString;}
    Serial.println("C17" + tempString);
    }// close if c = 210

    //Process magnetos
    if (c == 220){
    c = Wire.read(); // get the data byte

    //Convert magneto switch byte into Link2FS SimConnect Input code
    switch(c){
    // mags off
    case 0: {Serial.println("E11");} break;
    // mags left
    case 1: {Serial.println("E12");} break;
    // mags right
    case 2: {Serial.println("E13");} break;
    // mags both
    case 3: {Serial.println("E14");} break;
    // starter
    case 4: {Serial.println("E42");} break; // if you have Carenado’s C182RG add-on use "E35"
    }// close switch(c)
    }// // close if c = 220


    }// close if Wire.available()

    //Schedule call to prepare next batch of outgoing data
    stack_slot = millis() + 50;
    }// end PROCESS_RECEIVED()


    *** You can slow the output to the serial monitor for debugging by changing the line in void loop() from transmit_timer = millis() + 60; to transmit_timer = millis() + 1000; . I have had trouble with stack overflow if BOTH DEMO() functions were not removed. Go back to transmit_timer = millis() + 60; when you are are ready to run at full speed.

    Hugh
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013

  4. #4
    150+ Forum Groupie


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    164
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: General Aviation Lower Switch Panel In A Can

    General Aviation Lower Switch Panel In A Can part 4. Two_Way_Deputy_Analog_Devices

    My thanks as always to the mycockpit.org community, the arduino.cc community and especially Jim for www.jimspage.co.nz

    Part 4 does not leave much of the earlier part 2 behind. Later parts will add a few lines in Global Variable Declarations area, and maybe two new user functions

    The flap switch uses a different approach to decoding from that of the magneto switch function. The Link2FS SimConnect Inputs may update FSX with the angle of the flaps as a percentage of rotation from zero to ninety degrees, and lets FSX select the nearest notch on the lever. Zero % deflection is flaps up and 100 % deflection is straight down. Aircraft have different flap settings so if a panel mounted lever is used, you may require flap lever stop plates for aircraft with differring numbers of flap positions. So far construction is limited to a knob with a flat top. The flap lever is bolted to the top surface. Check out this web posting. http://azziagiuseppe.blogspot.ca/201...gn-part-2.html . The switch is a beautiful design and the use of gears simplifies mounting the flap lever to a potentiometer knob. I hope that it can be modified to provide room for a stepper motor and a hall effect transistor calibration point. Great idea using gear ratios to increase or decrease shaft rotation to maximize resolution of the device. Nice work.

    If an add-on aircraft requires an instruction to move the flaps to an upper or lower position. Copy and adapt the code for the magneto switch. Think of the flap switch as a magneto switch turned sideways.

    The magneto switch may be either a rotary switch with an analog decoded resistor loadder per schematic http://www.mycockpit.org/forums/show...740&highlight= post #3 or a high ohm potentiometer (10k or greater). MAGNETO_SWITCH() works with both devices. Unlike the sketch in the above URL, this post uses ball park figures to determine position. Place the switch pointer somewhere between the switch index midpoints and you have created the desired output. Instructions for each device are found in the comments of each function.

    BushPilotWannabe
    June 2017


    *** Load Two_Way_Deputy_I2C_Controller and save the file as Two_Way_Deputy_Analog_Devices

    *** Replace any of the preamble that only applies to the demo sketch with the above.

    *** Add the following to Global Varialbles Section
    //analog pin processed switches
    long analogSwitch_slot; // time in milliseconds for the next call to MAGNETO_SWITCH_ANALOG() & FLAP_SWITCH_ANALOG()
    int flap_oldCode = 255; // last flap setting -- triggers switch output after startup
    byte Magneto_oldCode = 255; //last magneto setting -- ditto

    *** In void loop() replace the lines
    //Generate simulated data
    DEMO();
    with
    //Process magneto and flap switches
    if (millis() > analogSwitch_slot) {MAGNETO_SWITCH_ANALOG(); FLAP_SWITCH_ANALOG(); analogSwitch_slot = millis() + 10000;}

    *** Replace the entire user function PROCESS RECEIVED() with

    void PROCESS_RECEIVED() {
    //We will process incoming data here

    //Display incoming data
    byte c;
    if (Wire.available()) {
    c = Wire.read();
    // if (c == 255) Serial.println(c);
    }// close if Wire.available()

    // schedule calls by void loop() to other functions
    transmit_slot = millis();
    analogSwitch_slot = millis() + 20;
    stack_slot = millis() + 50;
    }// end PROCESS_RECEIVED()

    *** Circuit setup

    Analog Flap Switch
    Connect the potentiometer outside terminals to 5V or GND, and the wiper terminal to Pro Mini pin A6. Reverse the 5V and GND leads if the analogRead level does not increase as the pot is turned anticlockwise. For now, turn the potentiometer knob clockwise and position the knob until it is pointing to ten-thirty o’clock and the analogRead level is zero. Divide the space between ten-thirty o’clock and seven-thirty o’clock into the aircraft flap settings with aircraft full flap extention at the seven-thirty. Adjust global variable flap_adjust until analogFlap_code at full flap setting is equal to the aircraft maximum flap setting * 100 / 90.

    Magneto Switch
    A wiring diagram and a parts layout for a rotary switch mounted PCB is shown on http://www.mycockpit.org/forums/showthread.php? t=28740&highlight= post #3. Connect the 'A' terminal to pin A7 of the Pro MIni. Each circuit has slightly different inputs. . Follow the instruction in the remarks at the top of _MAG_SWITCH_ANALOG().

    *** Replace the entire user function void DEMO(){

    with

    // **************************
    // ANALOG FLAP SWITCH *************************************************************************
    // **************************

    void FLAP_SWITCH_ANALOG(){


    //ADJUST 'flap_adjust' until the flap lever sets the flaps when moved onto your 'flap lever stops' in all positions
    float flap_adjust = 675;
    byte flap_pin = 6;
    int flap_code;


    // PLACE "//" IN FRONT OF the next line after recording your flap_pin outputs.
    Serial.println(analogRead(flap_pin));

    // Gatekeeper -- return to the calling function if the analog pin reading is not stable
    // increase '< & >' values if the flap does not move within one or two calls to the function
    int firstRead = analogRead(flap_pin);
    int secondRead = analogRead(flap_pin);
    if ((firstRead + 3 < secondRead) || (firstRead - 3 > secondRead)) return;

    //RETURN CHANGE in flap lever's position as a percentage of the flap movement (0 to 90 degrees)
    //Flap lever moved to 30 degree flap extension may show up as flap_code equals 50 or higher.
    flap_code = byte(map(firstRead, 0, flap_adjust, 0, 100));

    // Return to calling function when the switch has not moved OR induced voltage at analog pin creates change in output
    if (((flap_code +2) > flap_oldCode) && ((flap_code - 2) < flap_oldCode)) return;

    // OR pile the fresh data bytes on top of the stack
    else {
    stack_last++; transmit_buffer[stack_last] = 210;
    stack_last++; transmit_buffer[stack_last] = flap_code;
    // Serial.println( flap_code);
    flap_oldCode = flap_code;
    }// close else if flap_code + 2 ....
    }// end FLAP_SWITCH_ANALOG()


    // ****************************
    // ANALOG MAGNETO SWITCH ******************************************************************
    // ****************************

    void MAGNETO_SWITCH_ANALOG(){
    byte Magneto_pin = 7;
    int Magneto_code;

    // PLACE "//" IN FRONT OF the next line after recording your analog pin outputs for the rotary switch positions.
    Serial.println(analogRead(Magneto_pin));

    // CALCULATE the mid points
    // Rotary switch calculate mid point between ajacent switch contacts and replace '42' below with your numbers
    // Potentiometer draw radii from the pot 30 degrees apart magneto switch labels. Point the knob between magneto labels and replace ‘42’ with your values.
    int midPoint_0 = 42; // mid point between 'Off' and 'Left'
    int midPoint_1 = 42; // mid point between ‘Left’ and ‘Right’
    int midPoint_2 = 42; // mid point between ‘Right’ and ‘Both’
    int midPoint_3 = 42; // mid point between ‘Both’ and ‘Start’
    // For rotary switch - or just a jumper tapping a resister node - analogRead level of last rotary switch position ‘Start’.
    // For potentiometers, point the knob to clockwise edge of the ‘Start’ segment on the dial and add 20.
    int start = 42;

    // Gatekeeper -- return to void loop() if the analog pin reading is not stable
    int firstRead = analogRead(Magneto_pin);
    int secondRead = analogRead(Magneto_pin);
    // increase '< & >' values if FSX magneto does not change within one or two calls to the function
    if ((firstRead + 3 < secondRead) || (firstRead - 3 > secondRead)) return;

    //PROCESS MAGNETO SWITCH SETTINGS
    // Match analog reading to the switch position
    byte switchPosition = 0;
    if (firstRead < midPoint_0) Magneto_code = 0; // off
    if ((firstRead > midPoint_0) && (firstRead < midPoint_1)) Magneto_code = 1; // left
    if ((firstRead > midPoint_1) && (firstRead < midPoint_2)) Magneto_code = 2; // right
    if ((firstRead > midPoint_2) && (firstRead < midPoint_3)) Magneto_code = 3; // both
    if ((firstRead > midPoint_3) && (firstRead < start)) Magneto_code = 4; // start

    //Return to calling function when switch has not moved
    //OR put fresh data bytes on top of the stack
    if (Magneto_code == Magneto_oldCode) return;
    else {
    stack_last++;
    transmit_buffer[stack_last] = 220;
    stack_last++;
    transmit_buffer[stack_last] = Magneto_code;
    Magneto_oldCode = Magneto_code;
    //Serial.println( Magneto_code);
    }// close else if Magneto_code ....
    }// end MAGNETO_SWITCH_ANALOG()
    Last edited by BushPilotWannabe; 07-10-2017 at 09:53 PM. Reason: remove the Arduino IDE formatting from the preamble.
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013

  5. #5
    150+ Forum Groupie


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    164
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: General Aviation Lower Switch Panel In A Can

    General Aviation Lower Switch Panel In A Can
    part 5. Two_Way_Main_XX595_Shift_Register

    My thanks as always to the mycockpit.org community, the arduino.cc community and especially Jim for www.jimspage.co.nz

    Posts #5 and #6 add landing gear indicator lights to the panel. No two aircraft have the same condiguration, so I am going with an inverted 'V' of three dual colour lights using 5mm red green or red green blue LEDs inside 5mm bezels from eBay. There are two unused pins on the XX595 chip for future development and the ability to daily chain additional XX595 chips. If you are building a DC3 cockpit with one gear light, skip the construction and drive the one LED directly from the Pro Mini. Salvage what code you can, gear down is '222', and anything else is lamp off - gear not safe.

    BushPilotWannabe
    July 2017
    */

    // *************************************************** PROJECT WIDE CHANGE *********************************************
    To begin, transmit_buffer[20] is a queue not a stack. To reflect this fact, change 'transmit_buffer[20]' in post #3 to dnLdQueue[20]. Change transmit_buffer[20] in post #4 to upLdQueue[20]. Replace any instance of 'stack_' in posts #3 & #4 with 'queue_'. Replace any instance of 'STACK(' in posts #3 & #4 with 'QUEUE('. In any comments newdata goes to the rear of the queue and data to be transmitted is taken from the front of the queue.
    // ************************************************** END CHANGE ***********************************************************


    // ************************************************ ADD TO LIBRARY INCLUSIONS *****************************************
    // next two lines enable use of F( macro. Stores lcd.print(F(" ")) or Serial.println(F(" ")) Strings in program memory. Does not copy to ram.
    #include
    #define F(string_literal) (reinterpret_cast(PSTR(string_literal)))
    // **************************************************** END ADD *************************************************************


    // ************************************************* ADD TO GLOBAL VARIABLES *********************************************
    //system
    byte system_busVoltage;
    byte system_gearStatus;
    byte system_flapPosition;
    // **************************************************** END ADD ***************************************************************

    //********************************************* ADD TO void loop() *********************************************
    // The intention of the project is to add the lower switch panel to an existing sketch which may using Link2FS.
    // Add any parts of the the following that are not already included in your sketch.

    char serial_codeIn;
    if (Serial.available()){ // now lets check the serial buffer for any input data
    serial_codeIn = getChar();

    if (serial_codeIn == '?') {QUESTION();}// The first identifier is "?"
    }// close if (Serial.available()
    //********************************************END ADD TO void loop() *******************************************



    // ****************************************** ADD SERIAL FUNCTIONS *************************************

    // *********************
    // Serial Streaming *************************************************************************
    // *********************

    char getChar(){ // Get a character from the serial buffer
    while(Serial.available() == 0);// wait for data
    return((char)Serial.read());// Thanks Doug
    }// end getchar()


    void QUESTION(){ // The first identifier was "?"
    char serial_codeIn = getChar(); // Get another character
    //Serial.println(serial_codeIn);
    switch(serial_codeIn){ // Now lets find what to do with it - like convert it to an integer

    case 'K':{
    // Main Bus Voltage -- Indicates whether there is power on the main bus to drive electrical devices. To be true, battery switch must be on or alternator switch must be on and the engine turning - either running or with the prop windmilling.

    system_busVoltage = ((getChar() - '0') > 0);
    queue_last++; dnLdQueue[queue_last] = 206;
    queue_last++; dnLdQueue[queue_last] = system_busVoltage;
    for (byte x = 0; x < 3; x++) getChar(); // only first digit is required to show any voltage -- remove the remainder
    }// close case 'K'
    break;

    case 'Y':{ //Gear Position (Nose, L, R)
    system_gearStatus = 0;
    system_gearStatus += (byte(getChar()-'0'))*100;
    system_gearStatus += byte((getChar()-'0'))*10;
    system_gearStatus += byte(getChar()-'0');
    queue_last++; dnLdQueue[queue_last] = 200;
    queue_last++; dnLdQueue[queue_last] = system_gearStatus;
    //Serial.println(tempByte);
    }// close case 'Y':
    break ;


    }// close switch
    }// end QUESTION()

    //***************************************** END ADD SERIAL FUNCTIONS ************************************
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013

  6. #6
    150+ Forum Groupie


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    164
    Contribute If you enjoy reading the
    content here, click the below
    image to support MyCockpit site.
    Click Here To Contribute To Our Site

    Re: General Aviation Lower Switch Panel In A Can

    /*
    General Aviation Lower Switch Panel In A Can
    part 6. Two_Way_Deputy_XX595_Shift_Register

    I used a SN74HC595N 16 pin DIP parallel out shift register for this project. All pin names and variables names are taken from the manufacture's data sheet. Many chips will work, I recommend that you change the pin names used in the sketch to those specific to your chip and the data sheet used. Pin 13 OE (active low) of the 16 pin DIP package is hardwired to GND, and pin 10 SRCLR (active low) is hardwired to VCC keeping the the LEDs always active. They may not be turned on but they are not disabled. Run a power lead from VCC to all anodes, and ground the LEDs though the chip outputs. Raising the voltage of 74HC595 outputs HIGH turns the LED off. The same LOW or HIGH works for chips with open output registers.
    The code itself for XX595REG_OUT() is simple, single purpose output. No libraries are used. Start with all bits of the assembly byte HIGH. If an LED is to be illuminated, set the corresponding bit LOW, and shift the assembly byte into the XX595 shift register.
    The easiest to use and cheapest source for the chip would be a 74HC595 breakout board available on line. Dress up the project and use angle pin headers between the Pro Mini and the breakout boards. Hopefully all components can be found locally or in a single online store.
    The build so far puts the three red/green 5mm LEDs on a scrap of two sided proto board using point to point wiring to join the wire harness headers to the voltage takeup resistors to the LEDs. Would you believe a 5.6k ohm resistor for red cathodes and a 56k ohm resistor for green cathodes to get a nice glow. More than half the jumpers used so far are VCC and GND pulled back to the mini breadboard mounted Pro Mini. Could be time to run a VCC bus and a GND bus across the panel.

    Bushpilotwannbe
    July 2017

    // *************************
    // UPDATE QUEUE as per instructions at the top of Post #5
    // **************************

    // *********************************** ADD before #include "Wire.h" leave the comment marks in place **************************
    /*
    user functions finder -- this sketch could run 500 lines
    highlight the function, press + , then punch 'FIND' twice
    RECEIVE_EVENT(int howMany) {
    PROCESS_RECEIVED() {
    TRANSMIT() {
    QUEUE() {
    FLAP_SWITCH_ANALOG() {
    MAGNETO_SWITCH_ANALOG() {
    // STEPPER_MOTOR() { // coming soon
    // XX165REG_IN() { // coming soon
    XX595REG_OUT() {
    */
    // ******************************************************* END ADD *********************************************************************

    // ****************************************** ADD TO GLOBAL VARIABLES *******************************************
    //XX595 PARALLEL OUT REGISTER
    byte RCLK = 10; // chip pin # 12 -- Transfers Serial Register to Output Buffer when LOW goes HIGH (edge triggered)
    byte SER = 11; // chip pin # 14 -- Shift Register input pin
    byte SRCLK = 12; // chip pin # 11 -- Copies bit to store when LOW and enabled -- Shifts bit sideways when LOW goes HIGH
    byte XX595Reg_received; // data byte downloaded from the Main board
    long XX595Reg_slot; // scheduled time to call XX595REG_OUT()

    //System
    bool system_busPowered;
    // *************************************************** END ADD *******************************************************

    // ***************************
    // REPLACE VOID SETUP -- a good place to document what is going on ********************************************
    // ***************************

    void setup() {
    // SN2003 pins 2 to 5
    // 74XX165 pins 6 to 9
    // 74xx595 pins 10 to 12
    pinMode(RCLK, OUTPUT); // pin 10
    pinMode(SER, OUTPUT); // pin 11
    pinMode(SRCLK, OUTPUT);// pin 12
    // pin 13 still available
    // pins 14 to 17 (A0 to A3) still available
    // ANALOG (4) I2C SDA
    // ANALOG (5) I2C SCL
    // ANALOG (6) FLAP SWITCH -- analog input only pin -- use it or lose it
    // ANALOG (7) MAGNETO SWITCH -- ditto
    Wire.begin(8 ); // join i2c bus with address #8
    Wire.onReceive(RECEIVE_EVENT);
    Serial.begin(115200); // only required for the DEMO and programming later additions
    }// end setup()
    // ************************************************** END REPLACE **********************************************

    // *********************** ADD TO loop() after the line starting 'if (millis() > transmit_slot) ******************
    //Display changes to LED Array
    if (millis() > XX595Reg_slot) {XX595REG_OUT(XX595Reg_received); XX595Reg_slot = millis() + 10000;}
    // **************************************************** END ADD **************************************************


    //**************************************** CHANGE PROCESS RECEIVED ************************************
    // ************************** Replace 'Serial.println(c); with ***************************************
    // if (c == 255) Serial.println(c); // look for and display a null byte coming in from the Main board

    // ******************* ADD TO PROCESS RECEIVED () following the last replace ***************
    //Process wire data (undercarriage)
    if (c == 200) {
    XX595Reg_received = Wire.read();
    XX595Reg_slot = millis() + 2;
    }// close if c = 200

    //Process wire data (power bus) -- anything affected will be continue when power is restored
    if (c == 206) {
    byte tempByte = Wire.read();
    Serial.println(tempByte);
    system_busPowered = (tempByte == 1);
    //if (tempByte == 1) {system_busPowered = true;}
    //else system_busPowered = false;
    //Update LED register time slot
    XX595Reg_slot = millis() + 10;
    }// close if c = 206
    // **** ************************************* END PROCESS RECEIVED() ***********************************

    //*************************************** ADD USER FUNCTION TO SKETCH *******************************

    // *********************************
    // PARALLEL SHIFT OUT SN74HC595N ***************************************************************************************
    // *********************************

    void XX595REG_OUT(int dataByte) {
    //DISPLAY GEAR LEDS
    //Serial.println("xx595");
    //Serial.println(dataByte, BIN);

    //SET UP LED REGISTER with all bits high -- cleared bits will illuminate LEDs
    byte shiftOutByte = 255;

    // PROCESS NOSE GEAR -- bit 6 GREEN -- bit 1 RED -- chip pins 6 and 1
    if (dataByte >= 200) {bitClear(shiftOutByte, 6); dataByte -=200;} // green
    else if (dataByte >= 100) {bitClear(shiftOutByte, 1); dataByte -=100;} // red
    //Serial.println(dataByte);

    // PROCESS LEFT GEAR -- bit 2 GREEN -- bit 3 RED -- chip pins 2 and 3
    if (dataByte >= 20) {bitClear(shiftOutByte, 2); dataByte -=20;} // green
    else if (dataByte >= 10) {bitClear(shiftOutByte, 3); dataByte -=10;} // red
    //Serial.println(dataByte);

    // PROCESS RIGHT GEAR -- bit 5 GREEN -- bit 4 RED -- chip pins 5 and 4
    if (dataByte >= 2) {bitClear(shiftOutByte, 5);} // green
    else if (dataByte >= 1) {bitClear(shiftOutByte, 4);} // red
    //Serial.println(dataByte);
    //Serial.println(shiftOutByte, BIN);

    //DRIVE THE SHIFT REGISTER CLOCK LOW to enable edge triggered 'RCLK' when it is driven high
    //TRANSFER EIGHT BITS OF DATA INTO THE SERIAL REGISTER -- use down counter to process the MSB first
    //DRIVE THE SERIAL REGISTER CLOCK LOW;
    //DRIVE SER HIGH OR LOW TO MATCH THE BIT IN 'shiftOutByte' TO BE TRANSFERED TO SERIAL REGISTER
    //DRIVE SERIAL REGISTER CLOCK HIGH TO STORE VOLTAGE LEVEL ON 'SER IN' PIN ON THE SERIAL REGISTER
    //DRIVE THE REGISTER CLOCK HIGH TO TRANSFER 8 BITS INTO THE OUTPUT BUFFERS

    digitalWrite(RCLK, LOW);

    for (int shiftCounter = 7; shiftCounter > -1; shiftCounter--){
    digitalWrite(SRCLK, LOW);
    digitalWrite(SER, bitRead(shiftOutByte, shiftCounter));
    digitalWrite (SRCLK, HIGH);
    }// close for int shiftCounter = 7 ....

    digitalWrite(RCLK,HIGH);

    // THAT'S IT. When you can see what is going on. It is easier to understand what is happening.
    }// end XX595REG_OUT()
    // ********************************************************** END ADD *****************************************************************
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013