Welcome to Cockpitbuilders.com. Please login or sign up.

March 28, 2024, 02:58:57 AM

Login with username, password and session length

PROUDLY ENDORSING


Fly Elise-ng
126 Guests, 0 Users
Members
Stats
  • Total Posts: 59,639
  • Total Topics: 7,853
  • Online today: 130
  • Online ever: 582
  • (January 22, 2020, 08:44:01 AM)
Users Online
Users: 0
Guests: 126
Total: 126

COUNTDOWN TO WF2022


WORLDFLIGHT TEAM USA

Will Depart in...

Recent

Welcome

Narco DME 195 interface discussion

Started by ame, May 12, 2020, 05:53:21 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ame

This is a topic to discuss the development of the Narco DME 195 display driver.

In this topic we can discuss the details of the project. The results of the discussion will be posted in the Tutorial forum:
https://www.cockpitbuilders.com/index.php?topic=7962.msg57246

Thank you.

ame

For completeness, here are some observations made during PM sessions.

Arturo's DME 195 had a 7808 regulator inside. This is odd because the schematic shows a 7V supply and a 7805 regulator. The 7V supply feeds the incandescent display modules (through an emitter follower acting as a dimmer) and also feeds the 7805 regulator to power the logic chips at 5V.

The 7808 was tested and:
with 12v, it outputs 8v
with 5v, it outputs 3.6v
So, it is possible that with 7v power supply (which I did not test because I don't have one), it outputs about 5v. But it is a little strange to use a 7808, and use a 7v to get 5v output. But it works.

Arturo's hardware changes were:
- remove the 7808 and use 5v for logic part.
- remove the Darlington driver and use 5v for bulbs.
- read the dimmer pot with Arduino, and use a driver to power the bulbs. I send the power depending on pot value.
- To read the switch (1, 2, hold) position, you need to deal with pins 10 and 22. As the voltage is variable depending on the dimmer, you need to make something to read the high and low states of the pins. Because they are not high/low, but analogue. It can be done in several ways, but as I had the unit open, I removed the CR101 CR102 CR103 diodes, and used the upper side of the terminals to drive the LEDs through a ULN2803a, and the down side of the terminals to read the switch position.

I propose an LM2596 voltage regulator module, which will accept up to 40V and deliver a pre-set voltage up to 3A. The module should be set to 7V, which will power the DME 195, and pin 5 on the regulator should be lifted so that the output state of the regulator can be controlled externally.

Inside the DME 195 the power is controlled by S101 which has an external connection from J101-24&12 (and GND). When the switch is "ON" it is connected to GND. You can see the switch function in section 3.7.15, on page 3-79 of the manual (page 147 of the PDF). The switch drives a relay, the relay provides power to the Narco DME 195 system.

Arturo says this could be done through the Arduino if you want to simulate avionics bus voltage. If you don't switch on avionics switch (and master, and there is enough battery voltage), then when you switch on DME it should not power up. I have this simulated.

I think the display unit will not be damaged if power is applied and no other signals are connected. Arturo agrees.

If power is applied then the display will be blank or will show BAR (I'm not sure), and DECIMAL (DS111) will be on, and one of the NAV1 NAV2 or HOLD indicators will be on. DIM (R105) should work, and PUSH TEST S103.

Arturo says, in the unit I interfaced, it displayed some random numbers if only powered up without signals.
In my software, I put "Low" state on BAR (activate the bar). Then, when data is available, I write the data and later put BAR High.
DECIMAL is always on. Nav1/Nav2 or Hold are on, depending switch position, and dimmed with the digits. DIM works and PUSH TEST too.
The HUNDREDS pin has to be driven manually, because "signal function" or "MPX" do not drive it.

I wired the R NAV function to my Arduino. When Low, green light is on and Speed and Time are hidden.

To send data to displays:
-Hundred has to be driven manually
-Distance has its own Data and Clock lines, so can be driven easily.
-Speed and Time share clock and data lines. You must first select which one are you writing to, with the VThead and VTclocking pins.

Some other interesting things to make it real, that can be found in manuals:
-Distance range: 0 to 199.9 nm
-Speed range:  10 to 400 kts
-Time: 0 to 89 minutes. Blank display if more than 89 minutes.

Data is only updated every 15 seconds.
I am using mine with 5 seconds rate update. But the real unit was 15 seconds.
As the shift registers are non-latched, you have to write the data on "live mode", so you see some blink with any data update.
It would not be comfortable to the eyes with a high refresh rate. I like 5 seconds. But can be chosen by the final user.

v0.3 Schematic:
I updated the schematic to allow the Arduino to control the power. The ON/OFF switch is detected by A7- yes, it's analog only, but I ran out of digital pins.

The regulator is controlled by D10. So the Arduino can control the DME power with the simulator power status. The Arduino is powered all the time, but if the simulated aircraft power is off, then the Arduino can turn off the regulator and ignore the state of the front panel ON/OFF switch.

_alioth_

#2
I have built a prototype with my second DME unit. This unit is damage inside. It seems it got water inside or something like that and it does not work properly.

My first unit was modified so I can't not test as is with this diagram.
But I have manage to test everything. Things with the first unit, things with the second.

My first unit had a 7808 (8v) regulator as you can see in the added pic.
The second unit has a 7622 05VC that regulates to 5v (Tested).

I have built the diagram v3, except the power on function and ident.

Everything works fine.
The A7 pin for ON-OFF can be read with analogRead, and it will say near 0 and near 1024 in on and off positions. So can be added to the code really easy.

Here is the code:

Quote#define MAX_STRING_LEN 32
#include <string.h>

String cadenaCharEntrada = "";
char vectorChar[32];
bool finCadena = false;

char buf[50];
int CodeIn;

// --------------------------------------------------------------- DME

int powerValue = 1;
int DMEfirstRunWhenON = 0;

int DMEswitchAPIN = 2;
int DMEswitchBPIN = 3;
int DMEonoffPIN = A7;

int DMEselectorPosition = 0 ;
int DMEselectorPositionOLD = 1;

int DMEhundredPIN = A3;
int DMEsignalPIN = A1;
int DMEmpxPIN = A2;
int DMErnavPIN = 7;

int distClockPin = A0; 
int distDataPin = 8;   

int vtClockPin = 6;
int vtDataPin = 9;
int clockingPIN = 5;
int controlheadPIN = 4;

int DMEdistanceNav1 = 0;
int DMEdistanceNav2 = 0;
int DMEdistanceHold = 0;
int DMEspeedNav1 = 0;
int DMEspeedNav2 = 0;
int DMEspeedHold = 0;
int DMEtimeNav1 = 0;
int DMEtimeNav2 = 0;
int DMEtimeHold = 0;

int DMEupdate = 1;
int firstHold = 0;

unsigned long DMErefreshtime = 0;
const long DMErefresintervalo = 5000;

byte digit[11] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xF};



void setup() {                                               //////////////////////// SETUP


  cadenaCharEntrada.reserve(20);

  Serial.begin(115200);


  //DME

  //pinMode (DMEpowerPIN, OUTPUT);

  pinMode (DMEswitchAPIN, INPUT_PULLUP);
  pinMode (DMEswitchBPIN, INPUT_PULLUP);
  pinMode (DMEonoffPIN, INPUT_PULLUP);

  pinMode (DMEhundredPIN, OUTPUT);
  pinMode (DMEsignalPIN, OUTPUT);
  pinMode (DMErnavPIN, OUTPUT);
  pinMode (DMEmpxPIN, OUTPUT);
  digitalWrite (DMEhundredPIN, HIGH);
  digitalWrite (DMEsignalPIN, HIGH);
  digitalWrite (DMErnavPIN, HIGH);
  digitalWrite (DMEmpxPIN, HIGH);

  pinMode(distClockPin, OUTPUT);
  pinMode(distDataPin, OUTPUT);

  pinMode (vtClockPin, OUTPUT);
  pinMode (vtDataPin, OUTPUT);

  pinMode (clockingPIN, OUTPUT);
  pinMode (controlheadPIN, OUTPUT);


}




void loop() {                                     /////////////////////////////////////////////////////////// loop ////////////////////

  if (finCadena) {                             //Serial 0
    finCadena = false;
    cadenaCharEntrada.toCharArray(vectorChar, 80);
    String key = subStr(vectorChar, "=", 1);
    int value = atoi(subStr(vectorChar, "=", 2));
    int value2 = atoi(subStr(vectorChar, "=", 3));
    cadenaCharEntrada = "";
    if (key == "d1") {
      DMEdistanceNav1 = value;
      DMEspeedNav1 = value2;
      DMEtimeNav1 = 60 * (DMEdistanceNav1 * 0.1 ) / DMEspeedNav1;
      //Serial.println (value);
      //Serial.println (value2);
    }
    if (key == "d2") {
      DMEdistanceNav2 = value;
      DMEspeedNav2 = value2;
      DMEtimeNav2 = 60 * (DMEdistanceNav2 * 0.1 ) / DMEspeedNav2;
    }
    if (key == "d3") {
      DMEupdate = 1;
      DMEdistanceHold = value;
      DMEspeedHold = value2;
      DMEtimeHold = 60 * (DMEdistanceHold * 0.1 ) / DMEspeedHold;
    }
    if (key == "R") {
      digitalWrite(DMErnavPIN, value);
    }
    if (key == "M") {
      digitalWrite(DMEmpxPIN, value);
    }
  }

  ///---------------------------------------------------------------------     DME


  if (DMEfirstRunWhenON == 1) {                   
    DMEfirstRunWhenON = 0;
    DMEdistanceNav1 = 0;
    DMEspeedNav1 =  0;
    DMEtimeNav1 =  0;
    DMEdistanceNav2 = 0;
    DMEspeedNav2 =  0;
    DMEtimeNav2 =  0;
  }

  if (millis() - DMErefreshtime > DMErefresintervalo) {   
    DMErefreshtime = millis();
    DMEupdate = 1;
  }

  int DMEselector = 0;
  DMEselector = digitalRead (DMEswitchAPIN) + 10 * digitalRead (DMEswitchBPIN);

  if (DMEselector != 0) DMEselectorPosition = DMEselector;
  if (DMEselectorPosition != DMEselectorPositionOLD) {
    DMEselectorPositionOLD = DMEselectorPosition;
    DMEupdate = 1;
  }

  if (DMEupdate) {
    DMEupdate = 0;

    if (DMEtimeNav1 > 89 || DMEspeedNav1 == 0 ) DMEtimeNav1 = 89;
    if (DMEtimeNav2 > 89 || DMEspeedNav2 == 0) DMEtimeNav2 = 89;

    if (DMEselectorPosition == 10) {                       // pos nav 1
      if (DMEdistanceNav1 == 0) {
        digitalWrite (DMEsignalPIN, LOW);
        showDistance(0);
      } else {
        digitalWrite (DMEsignalPIN, HIGH);
        //delay(50);
        showDistance(DMEdistanceNav1);
        showSpeed(DMEspeedNav1);
        showTime (DMEtimeNav1);
      }
    } else if (DMEselectorPosition == 1) {                  //pos nav 2

      if (DMEdistanceNav2 == 0) {
        digitalWrite (DMEsignalPIN, LOW);
        showDistance(0);
      } else {
        digitalWrite (DMEsignalPIN, HIGH);
        showDistance(DMEdistanceNav2);
        showSpeed(DMEspeedNav2);
        showTime (DMEtimeNav2);
      }
    } else  {                                          // pos hold
      if (DMEdistanceHold == 0) {
        digitalWrite (DMEsignalPIN, LOW);
        showDistance(0);
      } else {
        digitalWrite (DMEsignalPIN, HIGH);
        delay(5);
        showDistance(DMEdistanceHold);
        showSpeed(DMEspeedHold);
        showTime (DMEtimeHold);
      }
    }
    DMEselectorPositionOLD = DMEselectorPosition;
  }

}    /////////////////////////////////////////////////////////////////////////////////////////////////// fin del loop


void showDistance( int valor) {
  int datos = valor;
  digitalWrite(DMEhundredPIN, HIGH);
  if (datos >= 1000) {
    digitalWrite(DMEhundredPIN, LOW);
    datos = datos - 1000;
  }
  int centena = datos / 100;
  int decena = (datos - centena * 100) / 10;
  int unidad = (datos - centena * 100 - decena * 10);
  if (centena == 0 && valor < 1000) centena = 10;
  shift4bits(distDataPin, distClockPin, MSBFIRST, ~digit[centena]);
  shift4bits(distDataPin, distClockPin, MSBFIRST, ~digit[decena]);
  shift4bits(distDataPin, distClockPin, MSBFIRST, ~digit[unidad]);
}

void showSpeed( int valor) {
  digitalWrite(clockingPIN, LOW);
  digitalWrite(controlheadPIN, HIGH);
  digitalWrite(clockingPIN, HIGH);
  int datos = valor;
  int centena = datos / 100;
  int decena = (datos - centena * 100) / 10;
  int unidad = (datos - centena * 100 - decena * 10);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[centena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[decena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[unidad]);
}

void showTime (int valor) {
  //Serial.println(valor);
  digitalWrite(clockingPIN, LOW);
  digitalWrite(controlheadPIN, LOW);
  digitalWrite(clockingPIN, HIGH);
  int datos = valor;
  int centena = datos / 100;
  int decena = (datos - centena * 100) / 10;
  int unidad = (datos - centena * 100 - decena * 10);
  //unidad = 10;
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[centena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[decena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[unidad]);
}


void shift4bits(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
{
  int i;
  for (i = 0; i < 4; i++)  {
    if (bitOrder == LSBFIRST) {
      digitalWrite(dataPin,  1 - !!(val & (1 << i)));
    } else {
      digitalWrite(dataPin,  1 - !!(val & (1 << (3 - i))));
    }
    digitalWrite(clockPin, HIGH);
    digitalWrite(clockPin, LOW);
  }
}



void serialEvent() {
  while (Serial.available()) {             
    char CaracterEntrada = Serial.read();   
    cadenaCharEntrada += CaracterEntrada;   
    if (CaracterEntrada == '\n') {         
      finCadena = true;                 
    }
  }
}

char* subStr (char* str, char *delim, int index) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;

  // Since strtok consumes the first arg, make a copy
  strcpy(copy, str);

  for (i = 1, act = copy; i <= index; i++, act = NULL) {
    sub = strtok_r(act, delim, &ptr);
    if (sub == NULL) break;
  }
  return sub;
}


It works through serial port.
You can send in the Arduino console to test:

Rnav function:
R=0 or  R=1  to activate/deactivate
MPX funtion:
M=0 or  M=1
To send data, distance and speed, use:
d1=1234=136   sends 123.4mn and 136kts for Nav1 switch postition. The time is computed. You don't have to send it.
d2=0=0 sends no signal in nav2 switch position.
d3... sends data to hold position. But his function is not coded here. I have coded the function outside (fsuipc luascript) and sends the data to arduino.

I am not good at electronics nor coding...  It works. But I know it can be done better.

Arturo.


ame

Crikey! That was quick!

And it works? Even better!

Great job!

_alioth_

#4
Quote from: ame on May 13, 2020, 04:15:26 PMI presume you don't want to change any pins? Shall we use v0.3 of the schematic as the final version?


Schematic is fine.
Just to say:

Pins 13 and 25 are grounded inside the unit. So it is not needed to ground them outside.
About pin changes, as I define them in the beginning of the code it is easy to change if someone use other controller or just don't need to use I2C, for example.

I don't understand the mpx function. It seems to do the same as BAR (function). I did not drive it in my first unit. Now I have wired but... it seems to do the same as BAR. If it wouldn't be needed, it can be driven high and use this pin (A2) as a standard digital pin for the on/off switch.
Can you tell me the difference? I don't understand this part of the diagram.

I don't use the ident function because p3d has no volume for it. I use the ident button in the audio panel. But I suppose it is fine to have the function just in case simulators use the volume ident function in future. I don't know how xplane works with this.

As my second unit is damaged (Distance shifter registers don't work, hundred digit is different and it does not work... The flexible board of the dme195 is quite fragile and the box has big holes to dissipate heat, so it it is not stored with care the dme can be damage.

I think I will rebuilt my first unit with the 7805 and dimmer and use the second for repair parts.
The first one had a segment in a digit burnt (I put this digit in the hundred because this segment is not needed in this digit). So, with both I can make a complete working unit and use the second for replacement digits etc.

The two heatsinks get very hot. Not warm but hot.
The voltage is setup to exact 7.00v. After several minutes of use, I can not touch the heatsinks with the fingers. I will try to measure the exact temp. I don't like it, but I supose it is fine.

Arturo.

ame

Great! Although I am sorry to hear the second display was damaged internally.

I have some suggestions for the code, but I have not finished yet (and I can't test it).

I don't know how hot the hardware should get. If it's too hot then you could add more metal and make a bigger heatsink? Or install a small PC fan (they are very cheap)?

The technology is old, and the incandescent displays use a lot of current, and the Darlington driver is inefficient. If you remove it and use PWM then it will be cooler (as you know), but... you have to open the case and make modifications.

I am looking at MPX and BAR. In the manual there is some information on page 3-57 (PDF page 125), but I haven't found any more yet. Basically, you get a bar display (---) if MPX BLANKING is low, or BAR is low, or R NAV is low.

Something in the control box will drive MPX BLANKING, but it could be an unrelated function. So, for simulation purposes it might not be necessary.

However, the pin must be connected to something. You can't leave the input to U112B unconnected (or 'floating'). You can't connect it to ground (because it will display '---'). You could connect it to Arduino +5V. Or an Arduino pin. :)

_alioth_


QuoteI am looking at MPX and BAR. In the manual there is some information on page 3-57 (PDF page 125), but I haven't found any more yet. Basically, you get a bar display (---) if MPX BLANKING is low, or BAR is low, or R NAV is low.

yes, I saw it. The difference with Rnav is that Rnav going Low cleans Speed and Time displays and switch on Rnav light and it does not show the bar. It shows the distance.

But Bar and Mpx I think it is the same (or similar), at simulator porpose with arduino. So I think it can be driven HIGH and we have a free pin.

Driving BAR or MPX LOW do not clean the hundred digit. this is the reason I send a "showDistance(0)" in the code when there is no "valid signal". It clears the hundred digit.

AsI think I will redone the first unit as its original state, I can test the code if you make improvements in it.

Thanks
Arturo.

_alioth_

#7
I have rebuilt my first unit to its original state (using a 7805 regulator).
I have added the power PIN to switch on/off the LM2596.

Max temps I have measured in heatsinks are 75ÂșC. Datasheet says is safe.

I have made changes in code:
Header define min/max speed. Real values are 10-400
Header define data refresh time. 150000 miliseconds in real unit.
Now if time is longer than 89 then displays nothing in speed. As the real unit.

Now send P=1 to power the unit or P=0 to cut power.
Send data in format dx=yyyy=zzz
x= 1 for nav1, 2 for nav2, 3 for hold
yyyy= distance in MN*10
zzz= speed in knots.
arduino will sends a code when selecting HOLD:
H=00001 if you come from nav2
H=00010 if you come from nav1
This is used for external script so it can send correct Hold data.

Quote// NARCO DME 195 INTERFACE
// ARDUINO NANO
// Arturo Moreno. 


#define MAX_STRING_LEN 32
#include <string.h>

#define MAX_SPEED 400       //real narco 195 value is 400
#define MIN_SPEED 10        //real narco 195 value is 10
int refreshTime = 5000;   // miliseconds.  15000 in real unit

String cadenaCharEntrada = "";
char vectorChar[32];
bool finCadena = false;

char buf[50];
int CodeIn;

int DMEswitchAPIN = 2;
int DMEswitchBPIN = 3;
int DMEonoffPIN = A7;
int DMEpowerPIN = 10;

int DMEonoffValue = 0;
int DMEpowerValue = 0;
int DMEpowerState = 0;
int DMEpowerStateOLD = 0;

int DMEselectorPosition = 0 ;
int DMEselectorPositionOLD = 1;

int DMEhundredPIN = A3;
int DMEsignalPIN = A1;
int DMEmpxPIN = A2;
int DMErnavPIN = 7;

int distClockPin = A0;
int distDataPin = 8;

int vtClockPin = 6;
int vtDataPin = 9;
int clockingPIN = 5;
int controlheadPIN = 4;

int DMEdistanceNav1 = 0;
int DMEdistanceNav2 = 0;
int DMEdistanceHold = 0;
int DMEspeedNav1 = 0;
int DMEspeedNav2 = 0;
int DMEspeedHold = 0;
int DMEtimeNav1 = 0;
int DMEtimeNav2 = 0;
int DMEtimeHold = 0;

int DMEupdate = 1;
int firstHold = 0;

unsigned long DMErefreshtime = 0;

byte digit[11] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xF};



void setup() {                               ////////////////// SETUP  /////////////////

  cadenaCharEntrada.reserve(32);

  Serial.begin(115200);

  pinMode (DMEswitchAPIN, INPUT_PULLUP);
  pinMode (DMEswitchBPIN, INPUT_PULLUP);
  pinMode (DMEonoffPIN, INPUT_PULLUP);
  pinMode (DMEpowerPIN, OUTPUT);
  digitalWrite (DMEpowerPIN, HIGH);

  pinMode (DMEhundredPIN, OUTPUT);
  pinMode (DMEsignalPIN, OUTPUT);
  pinMode (DMErnavPIN, OUTPUT);
  pinMode (DMEmpxPIN, OUTPUT);
  digitalWrite (DMEhundredPIN, HIGH);
  digitalWrite (DMEsignalPIN, LOW);
  digitalWrite (DMErnavPIN, LOW);
  digitalWrite (DMEmpxPIN, HIGH);

  pinMode(distClockPin, OUTPUT);
  pinMode(distDataPin, OUTPUT);

  pinMode (vtClockPin, OUTPUT);
  pinMode (vtDataPin, OUTPUT);

  pinMode (clockingPIN, OUTPUT);
  pinMode (controlheadPIN, OUTPUT);

}




void loop() {                      ////////////////////   LOOP   /////////////////////

  if (finCadena) {                             
    finCadena = false;
    cadenaCharEntrada.toCharArray(vectorChar, 80);
    String key = subStr(vectorChar, "=", 1);
    int value = atoi(subStr(vectorChar, "=", 2));
    int value2 = atoi(subStr(vectorChar, "=", 3));
    cadenaCharEntrada = "";
    if (key == "d1") {
      DMEdistanceNav1 = value;
      DMEspeedNav1 = value2;
      DMEtimeNav1 = 60 * (DMEdistanceNav1 * 0.1 ) / DMEspeedNav1;
    }
    if (key == "d2") {
      DMEdistanceNav2 = value;
      DMEspeedNav2 = value2;
      DMEtimeNav2 = 60 * (DMEdistanceNav2 * 0.1 ) / DMEspeedNav2;
    }
    if (key == "d3") {
      DMEupdate = 1;
      DMEdistanceHold = value;
      DMEspeedHold = value2;
      DMEtimeHold = 60 * (DMEdistanceHold * 0.1 ) / DMEspeedHold;
    }
    if (key == "R")digitalWrite(DMErnavPIN, value);
    if (key == "M")digitalWrite(DMEmpxPIN, value);
    if (key == "P") DMEpowerValue = value;

  }


  //---- TIME UPDATE
  if (millis() - DMErefreshtime > refreshTime) {   
    DMErefreshtime = millis();
    DMEupdate = 1;
  }

  //---- POWER BASED IN SIMULATOR VOLTAGE AND SWITCH POSITION
  DMEpowerState = 0;             
  if  (analogRead ( DMEonoffPIN) < 100 && DMEpowerValue == 1) DMEpowerState = 1;
  if (DMEpowerState != DMEpowerStateOLD) {
    DMEpowerStateOLD = DMEpowerState;
    if (DMEpowerState) {
      digitalWrite (DMEpowerPIN, LOW);
      digitalWrite(DMErnavPIN, HIGH);
      DMEdistanceNav1 = 0;
      DMEspeedNav1 =  0;
      DMEtimeNav1 =  0;
      DMEdistanceNav2 = 0;
      DMEspeedNav2 =  0;
      DMEtimeNav2 =  0;
      DMEdistanceHold = 0;
      DMEspeedHold =  0;
      DMEtimeHold =  0;
    } else {
      digitalWrite (DMEpowerPIN, HIGH);
      digitalWrite (DMEsignalPIN, LOW);
      digitalWrite(DMErnavPIN, LOW);
    }
  }

  //---  NAV1 HOLD NAV2 SELECTOR
  DMEselectorPosition = digitalRead (DMEswitchAPIN) + 10 * digitalRead (DMEswitchBPIN);
  if (DMEselectorPosition != DMEselectorPositionOLD){
    delay (20); // anti bounce
    if (DMEselectorPosition == 11){
        sprintf (buf, "H=%05d", DMEselectorPositionOLD);
        Serial.println (buf);
    }
    DMEselectorPositionOLD = DMEselectorPosition;
    DMEupdate = 1;
  }

  if (DMEupdate) {
    DMEupdate = 0;

    if (DMEselectorPosition == 10) {                       // pos nav 1
      if (DMEdistanceNav1 == 0) {
        digitalWrite (DMEsignalPIN, LOW);
        showDistance(0);
      } else {
        digitalWrite (DMEsignalPIN, HIGH);
        showDistance(DMEdistanceNav1);
        showSpeed(DMEspeedNav1);
        showTime (DMEtimeNav1);
      }
    } else if (DMEselectorPosition == 1) {                  //pos nav 2

      if (DMEdistanceNav2 == 0) {
        digitalWrite (DMEsignalPIN, LOW);
        showDistance(0);
      } else {
        digitalWrite (DMEsignalPIN, HIGH);
        showDistance(DMEdistanceNav2);
        showSpeed(DMEspeedNav2);
        showTime (DMEtimeNav2);
      }
    } else  {                                          // pos hold
      if (DMEdistanceHold == 0) {
        digitalWrite (DMEsignalPIN, LOW);
        showDistance(0);
      } else {
        digitalWrite (DMEsignalPIN, HIGH);
        showDistance(DMEdistanceHold);
        showSpeed(DMEspeedHold);
        showTime (DMEtimeHold);
      }
    }
    DMEselectorPositionOLD = DMEselectorPosition;
  }

}                     /////////////////  LOOP  END   ////////////////////////////////


void showDistance( int valor) {
  int datos = constrain (valor, 0, 1999);
  digitalWrite(DMEhundredPIN, HIGH);
  if (datos >= 1000) {
    digitalWrite(DMEhundredPIN, LOW);
    datos = datos - 1000;
  }
  int centena = datos / 100;
  int decena = (datos - centena * 100) / 10;
  int unidad = (datos - centena * 100 - decena * 10);
  if (centena == 0 && valor < 1000) centena = 10;
  shift4bits(distDataPin, distClockPin, MSBFIRST, ~digit[centena]);
  shift4bits(distDataPin, distClockPin, MSBFIRST, ~digit[decena]);
  shift4bits(distDataPin, distClockPin, MSBFIRST, ~digit[unidad]);
}

void showSpeed( int valor) {
  valor = constrain (valor, MIN_SPEED, MAX_SPEED);
  digitalWrite(clockingPIN, LOW);
  digitalWrite(controlheadPIN, HIGH);
  digitalWrite(clockingPIN, HIGH);
  int datos = valor;
  int centena = datos / 100;
  int decena = (datos - centena * 100) / 10;
  int unidad = (datos - centena * 100 - decena * 10);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[centena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[decena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[unidad]);
}

void showTime (int value) {
  digitalWrite(clockingPIN, LOW);
  digitalWrite(controlheadPIN, LOW);
  digitalWrite(clockingPIN, HIGH);
  int centena = 0;
  int decena = value / 10;
  int unidad = (value - decena * 10);
  if (value > 89){
    centena = 10;
    decena = 10;
    unidad = 10;
  }
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[centena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[decena]);
  shift4bits(vtDataPin, vtClockPin, MSBFIRST, ~digit[unidad]);
}


void shift4bits(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
{
  int i;
  for (i = 0; i < 4; i++)  {
    if (bitOrder == LSBFIRST) {
      digitalWrite(dataPin,  1 - !!(val & (1 << i)));
    } else {
      digitalWrite(dataPin,  1 - !!(val & (1 << (3 - i))));
    }
    digitalWrite(clockPin, HIGH);
    digitalWrite(clockPin, LOW);
  }
}


void serialEvent() {
  while (Serial.available()) {
    char CaracterEntrada = Serial.read();
    cadenaCharEntrada += CaracterEntrada;
    if (CaracterEntrada == '\n') {
      finCadena = true;
    }
  }
}

char* subStr (char* str, char *delim, int index) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;

  // Since strtok consumes the first arg, make a copy
  strcpy(copy, str);

  for (i = 1, act = copy; i <= index; i++, act = NULL) {
    sub = strtok_r(act, delim, &ptr);
    if (sub == NULL) break;
  }
  return sub;
}

Arturo.


_alioth_

Testing the DME:


Very happy with the results.

Arturo.

Like the Website ?
Support Cockpitbuilders.com and Click Below to Donate