Inverterare med open collector

Elektronikrelaterade (på komponentnivå) frågor och funderingar.
Användarvisningsbild
matsadona
Inlägg: 759
Blev medlem: 28 februari 2010, 23:05:17

Inverterare med open collector

Inlägg av matsadona »

Nu har jag återigen hamnat i en situation då mina begränsade kunskaper sätter stopp och ber därmed om en knuff i rätt riktning.
Problemet består i att jag har ett några digitala utgångar i en Arduino tillämpning som behöver inverteras. Det är en bugg i koden (library) och den kommer tyvärr inte att uppdateras i närtid, så därför behöver jag lösa detta hårdvarumässigt tillsvidare.

Så jag tog första bästa inverterare, dvs 74(LS)05 som matas med en utgång från Arduinon. Utgången är kopplad till en ULN2803 för att driva en lampa (i nuläget har jag bara en lysdiod för test).
Naturligtvis var det inte så här enkelt och jag misstänker att det har att göra med att just 05:an är av så kallad open collector.
Som jag tolkar det så behöver jag någon form a pull-up motstånd, eller? Eller fungerar det rakt av med en 7404?
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
H.O
Inlägg: 5950
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: Inverterare med open collector

Inlägg av H.O »

Du har identifierat problemet korrekt.
Pull-up funkar, byte till 7404 likaså.
Användarvisningsbild
matsadona
Inlägg: 759
Blev medlem: 28 februari 2010, 23:05:17

Re: Inverterare med open collector

Inlägg av matsadona »

Tack. Svebry hade inga 7404 kvar på lager, så det ficka jag beställa på nätet.
Jag har försökt läsa på om pull-up och pull-down, och tror jag har kläm på det när det gäller ingångar. Är lite för trött för att tycka det är glasklart, men men...
Så om jag gör så här så borde det fungera? Vad är lämpligt värde på motståndet? Har sett olika exempel men 1k eller 10k verkar vara ganska vanligt. Jag förstår att det måste vara lägra än den interna resistansen/impedansen, och att det bör vara ett lägre värde vid högre frekvenser.
Kollade i databladet men osäker på vilka värden där som hjälper mig att beräkna detta.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 47223
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Inverterare med open collector

Inlägg av TomasL »

Du får titta i din ULN hur mycket ström den behöver, och vilken spänning den vill ha, det bestämmer ditt pull-up värde.
sc3
Inlägg: 179
Blev medlem: 10 januari 2011, 11:05:40
Ort: Umeå

Re: Inverterare med open collector

Inlägg av sc3 »

Vad är det för bibliotek som är felaktigt? Låter som enklast att ändra där, för jag gissar att du har tillgång till källkoden? Eller situationen är kanske inte så enkel?
Användarvisningsbild
matsadona
Inlägg: 759
Blev medlem: 28 februari 2010, 23:05:17

Re: Inverterare med open collector

Inlägg av matsadona »

Det hela handlar om DCS (Digital Combat Simulator) som är en flygsimulator.
Tack vare några kreativa människor som har utvecklat DCS-BIOS (https://github.com/dcs-bios) är det möjligt att importera och exportera signaler mellan verklig hårdvara och simulatorn via en Arduino. Dvs allt från knappar och reglage till servo (instrument osv) och lysdioder.
Det sker genom att relevant data exporteras via lua-script och sedan via en seriell kommunikation med Arduinon.

I just detta fallet handlar det om en specifik funktion för indikatorerna för landningsstället på MIG-21. Dessa indikeras av tre gröna (när landningsstället är nedfällt och låst) eller tre röda (när landningsstället är uppfällt) lampor.
Det är någon bugg i exporten som gör att de röda lamporna (också) lyser när landningsstället är ute. Det är förövrigt rapporterat, men ingen av utvecklar verkar ha haft tid att kolla på detta (https://github.com/dcs-bios/dcs-bios/issues/59).

Så det är dessa tre röda lampor jag vill invertera tills vidare (med förhoppningen om att det kommer att fixas). Det är långt över min kompetens att felsöka källkoden respektive den data som exporteras från simulatorn.



Exempel på kod för export, import och export:

DcsBios::LED gearLeftDown(0x225c, 0x0800, PIN);

DcsBios::LED gearLeftUp(0x225c, 0x0400, PIN);

DcsBios::Switch2Pos gearLock("GEAR_LOCK", PIN);

DcsBios::Potentiometer coneAdj("CONE_ADJ", PIN);

DcsBios::ServoOutput coneNd(0x22bc, PIN, 544, 2400);

DcsBios::RotaryEncoder clkLeftLvrRot("CLK_LEFT_LVR_ROT", "-3200", "+3200", PIN_A, PIN_B);

const byte wpnSelPins[11] = {PIN_0, PIN_1, PIN_2, PIN_3, PIN_4, PIN_5, PIN_6, PIN_7, PIN_8, PIN_9, PIN_10};
DcsBios::SwitchMultiPos wpnSel("WPN_SEL", wpnSelPins, 11);
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
H.O
Inlägg: 5950
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: Inverterare med open collector

Inlägg av H.O »

Som TomasL skriver. Värdet på pull-up-motståndet bestämms av den ström som ingången "suger i sig" och vilken spänning ingången behöver för korrekt nivå.
En ULN2803A från Texas Instruments (datablad) har en specificerad ingångsström på 1.35mA max och kräver 3V* (minst) på ingången för att det ska vara en gilltig "etta".

Med 5V på ovansidan av din pull-up har du alltså råd att tappa 2V över resistorn när det går 1.35mA genom den. Ohms lag säger då 2/0.00135 = 1481ohm, i alla fall inte mer än det om du vill vara på den säkra sidan. 1k hade jag valt.

* Lite beroende på belastningström.
Användarvisningsbild
matsadona
Inlägg: 759
Blev medlem: 28 februari 2010, 23:05:17

Re: Inverterare med open collector

Inlägg av matsadona »

Tack, då börjar bitarna falla på plats.
sc3
Inlägg: 179
Blev medlem: 10 januari 2011, 11:05:40
Ort: Umeå

Re: Inverterare med open collector

Inlägg av sc3 »

Ok, spännande!

Jag kikade lite i koden för projektet, kanske lite för länge :)
Har du möjlighet att posta din arduino-sketch? Jag tror att man enkelt skulle kunna lägga till kod i

Kod: Markera allt

void onDcsBiosWrite(unsigned int address, unsigned int value) { 
}
som hanterar dina lampor istället för t.ex.:

Kod: Markera allt

DcsBios::LED gearLeftDown(0x225c, 0x0800, PIN);
Men du kanske är klar med inverteraren?
Användarvisningsbild
prototypen
Inlägg: 11107
Blev medlem: 6 augusti 2006, 13:25:04
Ort: umeå

Re: Inverterare med open collector

Inlägg av prototypen »

Hoppas verkligen att du inte letar efter 7404 eller någon LS variant, sedan 25 år tillbaka används mest HC kretsar och du kan leta efter 74HC04 eller 74HC14. Alternativt 74HCTxx

Protte
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Inverterare med open collector

Inlägg av lillahuset »

Men lämna aldrig CMOS-ingångar flytande.
Användarvisningsbild
matsadona
Inlägg: 759
Blev medlem: 28 februari 2010, 23:05:17

Re: Inverterare med open collector

Inlägg av matsadona »

sc3 skrev:Ok, spännande!

Jag kikade lite i koden för projektet, kanske lite för länge :)
Har du möjlighet att posta din arduino-sketch? Jag tror att man enkelt skulle kunna lägga till kod i

Kod: Markera allt

void onDcsBiosWrite(unsigned int address, unsigned int value) { 
}
som hanterar dina lampor istället för t.ex.:

Kod: Markera allt

DcsBios::LED gearLeftDown(0x225c, 0x0800, PIN);
Men du kanske är klar med inverteraren?

Här är den sketch jag kör med. Det är alltså endast de tre Gear up som har problemet, i övrigt fungerar allt klockrent.

Kod: Markera allt

#include <DcsBios.h>
#include <Servo.h>

/* Instantiate a ProtocolParser object to parse the DCS-BIOS export stream */

DcsBios::ProtocolParser parser;
DcsBios::LED chkGearLight(0x22a0, 0x2000, 18);
DcsBios::LED gearLeftDown(0x225c, 0x0800, 17);
DcsBios::LED gearNoseDown(0x225c, 0x0200, 15);
DcsBios::LED gearRightDown(0x225c, 0x2000, 19);
DcsBios::LED gearLeftUp(0x225c, 0x0400, 16);
DcsBios::LED gearNoseUp(0x225c, 0x0100, 14);
DcsBios::LED gearRightDown(0x225c, 0x2000, 20);
DcsBios::LED flapsLight(0x22a0, 0x4000, 2);
DcsBios::LED airbrkLight(0x22a0, 0x8000, 3);
DcsBios::LED forsaz1(0x22a0, 0x0002, 4);
DcsBios::LED nozzleLight(0x22a0, 0x0008, 5);
DcsBios::Switch3Pos gearLvr("GEAR_LVR", 6, 7);
DcsBios::Switch2Pos flapsNeut("FLAPS_NEUT", 8);
DcsBios::Switch2Pos flapsTo("FLAPS_TO", 9);
DcsBios::Switch2Pos flapsLdg("FLAPS_LDG", 10);
DcsBios::LED engStartLight(0x22a0, 0x0001, 52);
DcsBios::LED lowAltLight(0x227a, 0x0010, 53);
DcsBios::LED masterCaution(0x22a0, 0x0400, 51);
DcsBios::LED sodAns(0x22be, 0x0010, 50);


void setup() {
  Serial.begin(500000);
}

/*
Your main loop needs to pass data from the DCS-BIOS export
stream to the parser object you instantiated above.
It also needs to call DcsBios::PollingInput::pollInputs()
to detect changes in the state of connected controls and
pass them on to DCS.
*/

void loop() {
  // feed incoming data to the parser
  while (Serial.available()) {
      parser.processChar(Serial.read());
  }
  
  // poll inputs
  DcsBios::PollingInput::pollInputs();
}

/*
You need to define
void sendDcsBiosMessage(const char* msg, const char* arg)
so that the string msg, followed by a space, the string arg
and a newline gets sent to the DCS-BIOS import stream.
In this example we send it to the serial port, so you need to
run socat to read the data from the serial port and send it
over UDP to DCS-BIOS.
If you are using an Ethernet Shield, you would probably want
to send a UDP packet from this subroutine.
*/

void sendDcsBiosMessage(const char* msg, const char* arg) {
  Serial.write(msg);
  Serial.write(' ');
  Serial.write(arg);
  Serial.write('\n');
}

/*
This subroutine gets called every time a write access is received
from the export stream (you need to define it even if it
does nothing).
Use this to handle outputs which are not covered by the
DcsBios Arduino library (e.g. displays).
*/

void onDcsBiosWrite(unsigned int address, unsigned int value) {
  
}
I referens manualen så finns det två alternativ - det förenklade (som jag använder mig av ovan, eller ett mer avancerat:

Nose Gear Up Light
Output Type: integer Address: 0x225c Mask: 0x0100 Shift By: 8 Max. Value: 1 Description: 0 if light is off, 1 if light is on

Förenklat

Kod: Markera allt

DcsBios::LED gearNoseUp(0x225c, 0x0100, PIN);
Avancerat

Kod: Markera allt

if (address == 0x225c) {
    unsigned int gearNoseUpValue = (value & 0x0100) >> 8;
    /* your code here */
}
Förövrigt är det nog så att det är i exporten från simulatorn felet ligger, inte i arduino libraryt eller sketchen. Det jag baserar detta på är att det finns andra programvaror som visar samma data grafiskt (dvs du kan få upp instrument osv på en separat skärm) - och även där indikeras landingställets position felaktigt. Se bild.

Och nej, jag har inte hunnit göra något praktiskt med detta ännu.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
sc3
Inlägg: 179
Blev medlem: 10 januari 2011, 11:05:40
Ort: Umeå

Re: Inverterare med open collector

Inlägg av sc3 »

Jag tror också att felet ligger i exporten från simulatorn, efter att ha funderat lite och kollat i koden.

Det verkar som att du initierat 'DcsBios::LED gearRightDown(0x225c, 0x2000, 20);' 2gånger, se nedan, men det är ju inte det aktuella felet.

Kod: Markera allt

DcsBios::ProtocolParser parser;
DcsBios::LED chkGearLight(0x22a0, 0x2000, 18);
DcsBios::LED gearLeftDown(0x225c, 0x0800, 17);
DcsBios::LED gearNoseDown(0x225c, 0x0200, 15);
DcsBios::LED gearRightDown(0x225c, 0x2000, 19);
DcsBios::LED gearLeftUp(0x225c, 0x0400, 16);
DcsBios::LED gearNoseUp(0x225c, 0x0100, 14);
DcsBios::LED gearRightDown(0x225c, 0x2000, 20);
DcsBios::LED flapsLight(0x22a0, 0x4000, 2);
DcsBios::LED airbrkLight(0x22a0, 0x8000, 3);
DcsBios::LED forsaz1(0x22a0, 0x0002, 4);
DcsBios::LED nozzleLight(0x22a0, 0x0008, 5);
DcsBios::Switch3Pos gearLvr("GEAR_LVR", 6, 7);
DcsBios::Switch2Pos flapsNeut("FLAPS_NEUT", 8);
DcsBios::Switch2Pos flapsTo("FLAPS_TO", 9);
DcsBios::Switch2Pos flapsLdg("FLAPS_LDG", 10);
DcsBios::LED engStartLight(0x22a0, 0x0001, 52);
DcsBios::LED lowAltLight(0x227a, 0x0010, 53);
DcsBios::LED masterCaution(0x22a0, 0x0400, 51);
DcsBios::LED sodAns(0x22be, 0x0010, 50);
Om du vill kan jag nog skriva ihop några rader kod senare (om ingen annan hinner före) som enbart använder sig av gearDown och "inverterar" gearUP lamporna. (precis som du vill med hårdvaran)
sc3
Inlägg: 179
Blev medlem: 10 januari 2011, 11:05:40
Ort: Umeå

Re: Inverterare med open collector

Inlägg av sc3 »

Du kan testa och se om denna kod funkar, det är lite skrivet i blindo (och förhoppningsvis läsbart) med hjälp av den befintliga koden. Den kompilerar under Arduino IDE 1.6.7, dock med varningar men det härrör från DCS-BIOS biblioteket.

Nu lyssnar den på alla gearDown och ställer gearUp lampor till motsatt/inverterat gearDown.

Kod: Markera allt

#include <DcsBios.h>
#include <Servo.h>

/* Instantiate a ProtocolParser object to parse the DCS-BIOS export stream */

DcsBios::ProtocolParser parser;
DcsBios::LED chkGearLight(0x22a0, 0x2000, 18);
//DcsBios::LED gearLeftDown(0x225c, 0x0800, 17);
//DcsBios::LED gearNoseDown(0x225c, 0x0200, 15);
//DcsBios::LED gearRightDown(0x225c, 0x2000, 19);
//DcsBios::LED gearLeftUp(0x225c, 0x0400, 16);
//DcsBios::LED gearNoseUp(0x225c, 0x0100, 14);
//DcsBios::LED gearRightUp(0x225c, 0x2000, 20);
DcsBios::LED flapsLight(0x22a0, 0x4000, 2);
DcsBios::LED airbrkLight(0x22a0, 0x8000, 3);
DcsBios::LED forsaz1(0x22a0, 0x0002, 4);
DcsBios::LED nozzleLight(0x22a0, 0x0008, 5);
DcsBios::Switch3Pos gearLvr("GEAR_LVR", 6, 7);
DcsBios::Switch2Pos flapsNeut("FLAPS_NEUT", 8);
DcsBios::Switch2Pos flapsTo("FLAPS_TO", 9);
DcsBios::Switch2Pos flapsLdg("FLAPS_LDG", 10);
DcsBios::LED engStartLight(0x22a0, 0x0001, 52);
DcsBios::LED lowAltLight(0x227a, 0x0010, 53);
DcsBios::LED masterCaution(0x22a0, 0x0400, 51);
DcsBios::LED sodAns(0x22be, 0x0010, 50);

#define LEDRIGHTDOWN 19
#define LEDLEFTDOWN 17
#define LEDNOSEDOWN 15
#define LEDRIGHTUP 20	
#define LEDLEFTUP 16
#define LEDNOSEUP 14

void ledSetup(int pin){
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

void setup() {

  ledSetup(LEDRIGHTDOWN);
  ledSetup(LEDLEFTDOWN);
  ledSetup(LEDNOSEDOWN);
  ledSetup(LEDRIGHTUP);
  ledSetup(LEDLEFTUP);
  ledSetup(LEDNOSEUP);

  Serial.begin(500000);
}

/*
Your main loop needs to pass data from the DCS-BIOS export
stream to the parser object you instantiated above.
It also needs to call DcsBios::PollingInput::pollInputs()
to detect changes in the state of connected controls and
pass them on to DCS.
*/

void loop() {
  // feed incoming data to the parser
  while (Serial.available()) {
      parser.processChar(Serial.read());
  }
  
  // poll inputs
  DcsBios::PollingInput::pollInputs();
}

/*
You need to define
void sendDcsBiosMessage(const char* msg, const char* arg)
so that the string msg, followed by a space, the string arg
and a newline gets sent to the DCS-BIOS import stream.
In this example we send it to the serial port, so you need to
run socat to read the data from the serial port and send it
over UDP to DCS-BIOS.
If you are using an Ethernet Shield, you would probably want
to send a UDP packet from this subroutine.
*/

void sendDcsBiosMessage(const char* msg, const char* arg) {
  Serial.write(msg);
  Serial.write(' ');
  Serial.write(arg);
  Serial.write('\n');
}

/*
This subroutine gets called every time a write access is received
from the export stream (you need to define it even if it
does nothing).
Use this to handle outputs which are not covered by the
DcsBios Arduino library (e.g. displays).
*/

void onDcsBiosWrite(unsigned int address, unsigned int value) {
  
if (address == 0x225c) {
    unsigned int gearNoseDownValue = (value & 0x0200) >> 9;
    unsigned int gearLeftDownValue = (value & 0x0800) >> 11;
    unsigned int gearRightDownValue = (value & 0x2000) >> 13;
   
   if(gearNoseDownValue == 1){
       digitalWrite(LEDNOSEDOWN,HIGH);
       digitalWrite(LEDNOSEUP,LOW);
   }else{
       digitalWrite(LEDNOSEDOWN,LOW);
       digitalWrite(LEDNOSEUP, HIGH);
   }

   if(gearLeftDownValue == 1){
       digitalWrite(LEDLEFTDOWN, HIGH);
       digitalWrite(LEDLEFTUP, LOW);
   }else{
        digitalWrite(LEDLEFTDOWN, LOW);
        digitalWrite(LEDLEFTUP, HIGH);
   }	   

   if(gearRightDownValue == 1){
        digitalWrite(LEDRIGHTDOWN, HIGH);
        digitalWrite(LEDRIGHTUP, LOW);
   }else{
        digitalWrite(LEDRIGHTDOWN, LOW);
        digitalWrite(LEDRIGHTUP, HIGH);
   }
}	  
}
Användarvisningsbild
matsadona
Inlägg: 759
Blev medlem: 28 februari 2010, 23:05:17

Re: Inverterare med open collector

Inlägg av matsadona »

sc3 skrev: Det verkar som att du initierat 'DcsBios::LED gearRightDown(0x225c, 0x2000, 20);' 2gånger, se nedan, men det är ju inte det aktuella felet.
Ja, det där var ett klipp och klistra fel, vilket inte motsvarar den aktuella koden jag har i Arduinon.
Den senaste versionen jag hade sparad hade jag kommenterat bort alla tre "gear up" och använt till andra indikatorer, och nu för att visa exempel så klippte jag tillbaka.

Skall testa ditt exempel senare. Tack för hjälpen.
Skriv svar