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


    BushPilotWannabe's Avatar
    Join Date
    Jan 2014
    Location
    Alberta, Canada
    Posts
    153
    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

    /*
    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) pulls a data byte or null character from the download
    stack and fires the packet at the deputy (Pro Mini). The one or two byte 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.

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

    In the 59 or so milliseconds until the next transmission, the main board is running King KFC 225_ish full function autopilot
    and King KN 62A_ish DME as well as process traffic both ways for the flap indicator and gear lamps. The
    SimConnect codes from the USB are squeezed into a switch identifier byte and a data byte then tossed onto the download
    stack. Any incoming bytes from the deputy MCU are transcribed into SimConnect imputs and kicked up the USB to
    FSX.

    Maximum time measured is just under 2 milliseconds to transmit two bytes in both directions.
    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 MCU I2C controller
    - add elements from part 3 'switch() and case statements as required

    BushPilotWannabe
    May 2017
    */

    #include

    volatile bool receive_acknol;

    long scheduleTimer1;
    long scheduleTimer2;

    //byte switchPanel_data;
    byte transmit_last;
    byte transmit_buffer[30];
    long transmit_timer;
    byte transmit_byte1;
    byte transmit_byte2;
    bool transmit_twoBytes;

    //download stack
    bool stack_enabled;
    long stack_slot;

    //DEMO
    int demo_counter = 100;
    int demo_counter1 = 15;

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

    void setup() {
    Wire.begin(0); // join i2c bus -- address must be defined when using Wire.onReceive() -- enven it is '0'
    Wire.onReceive(RECEIVE_EVENT);
    Serial.begin(115200);
    transmit_buffer[0] = 255;
    }// end setup

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

    void loop() {

    //Send the processed data to Deputy MCU and schedule preparation for the next transmission
    if (millis() > transmit_timer){
    TRANSMIT();
    stack_enabled = true; stack_slot = millis() + 50;
    transmit_timer = millis() + 60;
    }// close if millis() > transmit_timer

    //Generate simulated data
    DEMO();

    //Call STACK()
    if ((stack_enabled == true) && (millis() > stack_slot)) {STACK();}

    //Receive incoming two bytes from Deputy MCU
    if (receive_acknol == true){PROCESS_RECEIVED(); receive_acknol = false;}
    }// 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;
    while (Wire.available()) {
    c = Wire.read();
    if (c == 254) {c = Wire.read(); Serial.println(c); }
    if (c == 253) {c = Wire.read(); Serial.print(" "); Serial.println(c);}
    }// close while

    //Schedule call to prepare next batch of outgoing data
    stack_slot = millis() + 50;
    }// 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;
    }
    else Wire.write(255);
    Wire.endTransmission();
    }// end TRANSMIT()


    void STACK(){

    //Prepare TRANSMIT() for default one byte packet -- this is changed inside the for loop
    transmit_twoBytes = false;
    if (transmit_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 < transmit_last; inner++){
    transmit_buffer[inner] = transmit_buffer[inner + 1];}
    transmit_buffer[transmit_last] = 255;
    transmit_last--;
    }// close for int outer = 0 ....
    transmit_twoBytes = true;
    }// close if transmit_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
    if (millis() > scheduleTimer1){
    transmit_last++;
    transmit_buffer[transmit_last] = 253;
    transmit_last++;
    transmit_buffer[transmit_last] = demo_counter;
    demo_counter++;
    if (demo_counter == 150) demo_counter = 100;
    scheduleTimer1 = millis() + 100;
    }
    if (millis() > scheduleTimer2){
    transmit_last++;
    transmit_buffer[transmit_last] = 254;
    transmit_last++;
    transmit_buffer[transmit_last] = demo_counter1;
    demo_counter1++;
    if (demo_counter1 == 50) demo_counter1 = 1;
    scheduleTimer2 = millis() + 200;
    }
    }// end DEMO()

    Last edited by BushPilotWannabe; 05-20-2017 at 01:18 PM. Reason: correct the auto format
    ---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
    153
    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

    /*
    Two_Way_Deputy_I2C_Controller

    General Aviation Lower Switch Panel In A Can

    Now on to the Pro Mini deputy MCU. The arriving transmission from Main is used to synchronize all functions. At zero
    plus 10 ms a 74xx595 parallel out register is loaded to update the landing gear lights. At zero plus 20 ms, two analog
    pins checks the magneto switch and flap switch for movement. Any change goes onto the upload stack. At zero plus 30 ms,
    two 74xx165 serial out shift registers add any changes in scanned toggle switch status to the stack. Finally at zero
    plus 50, two bottom bytes of the stack is passed to variables, ready when loop() enables the I2C transmission function
    following the arrival of the next packet from the Main Arduino.

    Most of this sketch is an adaptation of the Main I2C sketch. Use comments from there.

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

    BushPilotWannabe
    May 2017
    */

    #include

    //************************************************************************************************
    // This is required to set the length of stack_pinRegister[]
    // CHANGE 'reg165_chipCount' TO DECLARE NUMBER OF SHIFT REGISTERS
    //************************************************************************************************

    const byte reg165_chipCount = 2;
    const byte register_bitCount = reg165_chipCount * 8;

    volatile bool receive_acknol;

    long scheduleTimer1;
    long scheduleTimer2;
    byte reset_counter; // controls progress of coordinating hard switches and fsx switches on start up

    byte i2c_out; // byte to pass on to master mcu
    byte i2c_count; // used after reset -- reset_counter is incremented after i2c 'counts out' at 15
    bool i2c_Transmit_enabled;

    byte stack_pinRegister[reg165_chipCount]; // all flags of register are initiated low
    byte stack[register_bitCount]; //output buffer - holds switch number or (switch number + 100) if switch was opened
    bool stack_enabled;
    long stack_slot;
    int stack_last; // last element of stack[] stack

    byte transmit_last;
    byte transmit_buffer[30];
    long transmit_slot;
    byte transmit_byte1;
    byte transmit_byte2;
    bool transmit_twoBytes;
    bool transmit_enabled;

    int demo_counter = 100;
    int demo_counter1 = 15;

    // *******************
    // 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 MCU
    // 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);

    // and the serial bus -- not needed when operational -- all references to 'Serial....' may be placed behind // marks
    Serial.begin(115200);
    }// end setup()

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

    void loop() {
    if (receive_acknol == true) {
    transmit_slot = millis();
    receive_acknol = false;
    PROCESS_RECEIVED();
    stack_enabled = true; stack_slot = millis() + 50;
    }// close if receive_acknol = true

    DEMO();

    if (millis() > transmit_slot) {
    TRANSMIT();
    transmit_slot = millis() + 10000;
    }// close if millis() > transmit_timer

    if (millis() > stack_slot){
    STACK();
    stack_slot = millis() + 10000;
    }// close if millis() > stack_slot
    }// end loop()

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

    void TRANSMIT(){
    Wire.beginTransmission(0); // to Main MCU
    if (transmit_twoBytes == true){
    Wire.write(transmit_byte1);
    Wire.write(transmit_byte2);
    transmit_twoBytes = false;
    }// close if transmit_twoBytes = true
    else Wire.write(255);
    Wire.endTransmission();
    }// end TRANSMIT()


    void RECEIVE_EVENT(int howMany){
    receive_acknol = true;
    }// end RECEIVE_EVENT()


    void PROCESS_RECEIVED(){

    byte c;
    while (Wire.available()) {
    c = Wire.read();
    if (c == 254) {c = Wire.read(); Serial.println(c);}
    if (c == 253) {c = Wire.read(); Serial.print(" "); Serial.println(c);}
    }// close while
    transmit_slot = millis(); transmit_enabled = true;
    stack_slot = millis() + 50;
    }// end PROCESS_RECEIVED()

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

    void STACK(){
    transmit_twoBytes = false;
    if (transmit_last > 0){
    transmit_byte1 = transmit_buffer[1];
    transmit_byte2 = transmit_buffer[2];
    for (int outer = 0; outer <2; outer++){
    for (int inner = 0; inner < transmit_last; inner++){
    transmit_buffer[inner] = transmit_buffer[inner + 1];}
    transmit_buffer[transmit_last] = 255;
    transmit_last--;
    }// close inner for loop
    transmit_twoBytes = true;
    }// close outer for loop
    stack_slot = millis() + 10000;
    }// end STACK()

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

    void DEMO(){

    if (millis() > scheduleTimer1){
    transmit_last++;
    transmit_buffer[transmit_last] = 253;
    transmit_last++;
    transmit_buffer[transmit_last] = demo_counter;
    demo_counter++;
    if (demo_counter == 201) demo_counter = 150;
    scheduleTimer1 = millis() + 381;
    }// close if millis() > scheduleTimer1
    if (millis() > scheduleTimer2){
    transmit_last++;
    transmit_buffer[transmit_last] = 254;
    transmit_last++;
    transmit_buffer[transmit_last] = demo_counter1;
    demo_counter1++;
    if (demo_counter1 == 101) demo_counter1 = 50;
    scheduleTimer2 = millis() + 85;
    }// close if millis() > scheduleTimer2
    }// end DEMO()
    ---CYXD ----- TWR --- GND ------ Closed
    ILS-- NDB -- 119.1 -- 121.9 ---- 11/2013