Optokobler 6N137 DIP8 – 1 Kanal

kr.4.00 inkl. moms

Optokobler 6N137 DIP8 – 1 Kanal.

På lager

Varenummer (SKU): 7129 Kategori: Tags: , , , ,

Optokobler 6N137 DIP8 – 1 Kanal kan bruges til mange forskellige formål. En af dem kunne være at opsamle DCC signalet fra skinnerne i et togskinne system.

En optokobler er en elektronisk komponent eller 2 delkredsløb, som ved hjælp af optiske signaler (lysimpulser) tillader overførsel (envejskobling) af (fortrinsvis digitale) elektriske signaler mellem to kredsløb, der er elektrisk isoleret fra hinanden.

Tekniske detaljer:

Operating Temperature Max: 85°C
Operating Temperature Min: -40°C
Input Type: DC
Power: 7V (Max)
Voltage Operating: 1.38V (Husk modstand)
Current – Output / Channel: 50mA

Installere Arduino IDE Software

Før du kan starte din programmering skal Arduino’s IDE software hentes. Dette program bruges til at programmere chippen.
Download fra dette link: Downlaod

Installere NmraDcc-master Library

  • Download library (Download)
  • Udpak filer
  • Flyt/kopir mappen “NmraDcc-master” til  “libraries” som findes i “Arduino IDE” mappen (C:Program Files (x86)Arduinolibraries)
  • Åben Arduino IDE software og klik på “Sketch/Include library”
  • Klik nu på “Add Zip. library” og find Zip filen du lige har downloaded.
  • Åben “Sketch/Include library/Manage Librarys” for at opdatere library.
  • Luk, og åben Arduino IDE programmet. (Genstart programmet)
  • Nu er “NmraDcc-master” installeret

Programmering

Inden programmeringen kan udfæres skal den rigtige “COM” port findes. Klik “Værktøj/Port” – og vælg COM port.

Eksempel:

Her vises et eksempel på hvordan du læser DCC signalet (togskinner) og sender det til en arduino.

Du skal bruge:

Kode: (Addresse Sniffer)

Brug denne sniffer kode til at se hvilken adresser som køre på systemet. dataerne vil blive vist i “Serial monitor” i arduino IDE (Værktøjer/Serial monitor). Vælg baud 38400. i serial monitoren. Tryk efter uploading på et skiftespor.

byte refreshTime = 3; // Time between DCC packets buffer refreshes in s
byte packetBufferSize = 16; // DCC packets buffer size

#define TIMER_PRESCALER 64
#define DccBitTimerCount (F_CPU * 80L / TIMER_PRESCALER / 1000000L)
// 16000000 * 80 / 64 / 1000000 = 20; 20 x 4usecs = 80us

boolean packetEnd;
boolean preambleFound;

const byte bitBufSize = 50; // number of slots for bits
volatile byte bitBuffer[bitBufSize];
volatile byte bitBuffHead = 1;
volatile byte bitBuffTail = 0;

byte pktByteCount=0;
byte packetBytesCount;
byte preambleOneCount;
byte dccPacket[6]; // buffer to hold a packet
byte instrByte1;
byte decoderType; //0=Loc, 1=Acc
byte bufferCounter=0;
byte isDifferentPacket=0;
byte showLoc=1;
byte showAcc=1;

unsigned int decoderAddress;
unsigned int packetBuffer[64];
unsigned int packetNew=0;

unsigned long timeToRefresh = millis() + refreshTime*1000;

//========================

void getPacket() {
preambleFound = false;
packetEnd = false;
packetBytesCount = 0;
preambleOneCount = 0;
while (! packetEnd) {
if (preambleFound) getNextByte();
else checkForPreamble();
}
}

//========================

void checkForPreamble() {
byte nextBit = getBit();
if (nextBit == 1) preambleOneCount++;
if (preambleOneCount < 10 && nextBit == 0) preambleOneCount = 0;
if (preambleOneCount >= 10 && nextBit == 0) preambleFound = true;
}

//========================

void getNextByte() {
byte newByte = 0;
for (byte n = 0; n < 8; n++) newByte = (newByte << 1) + getBit();
packetBytesCount ++;
dccPacket[packetBytesCount] = newByte;
dccPacket[0] = packetBytesCount;
if (getBit() == 1) packetEnd = true;
}

//========================

byte getBit() {
// gets the next bit from the bitBuffer
// if the buffer is empty it will wait indefinitely for bits to arrive
byte nbs = bitBuffHead;
while (nbs == bitBuffHead) byte nbs = nextBitSlot(bitBuffTail); //Buffer empty
bitBuffTail = nbs;
return (bitBuffer[bitBuffTail]);
}

//========================

void beginBitDetection() {
TCCR0A &= B11111100;
attachInterrupt(0, startTimer, RISING);
}

//========================

void startTimer() {
OCR0B = TCNT0 + DccBitTimerCount;
TIMSK0 |= B00000100;
TIFR0 |= B00000100;
}

//========================

ISR(TIMER0_COMPB_vect) {
byte bitFound = ! ((PIND & B00000100) >> 2);
TIMSK0 &= B11111011;
byte nbs = nextBitSlot(bitBuffHead);
if (nbs == bitBuffTail) return;
else {
bitBuffHead = nbs;
bitBuffer[bitBuffHead] = bitFound;
}
}

//========================

byte nextBitSlot(byte slot) {
slot ++;
if (slot >= bitBufSize) slot = 0;
return(slot);
}

//========================

void printPacket() {
Serial.print(" ");
for (byte n=1; n<pktByteCount; n++) {
Serial.print(" ");
Serial.print(dccPacket[n],BIN);
}
Serial.println(" ");
}

//========================

void refreshBuffer() {
timeToRefresh = millis() + refreshTime*1000;
for (byte n=0; n<packetBufferSize; n++) packetBuffer[n]=0;
bufferCounter=0;
Serial.println("-");
/*
Serial.print("Loc ");
Serial.print(showLoc);
Serial.print(" / Acc ");
Serial.print(showAcc);
Serial.print(" / Time ");
Serial.print(refreshTime);
Serial.print(" / Buff ");
Serial.println(packetBufferSize);
Serial.println(" ");
*/

}

//========================

void setup() {
Serial.begin(38400); // 38400 when on DCC, 9600 when testing on 123Circuits !!!!!!!!!!!!!!!!!!!!!!!
Serial.println("---");
Serial.println("DCC Packet Analyze started");
Serial.print("Updates every ");
Serial.print(refreshTime);
Serial.println(" seconds");
Serial.println("---");
beginBitDetection(); //Uncomment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}

//====================

void loop() {
getPacket(); //Uncomment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
byte speed;
byte checksum = 0;

if (millis() > timeToRefresh) refreshBuffer();

/* Dummy packet for test purposes. Comment when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Loc 1782 CV Write 3 128
dccPacket[0]=6;
dccPacket[1]=B11000111;
dccPacket[2]=B01101110;
dccPacket[3]=B11101100;
dccPacket[4]=B00000011;
dccPacket[5]=B10000000;
dccPacket[6]=B11111111;
*/
pktByteCount = dccPacket[0];
if (!pktByteCount) return; // No new packet available

for (byte n = 1; n <= pktByteCount; n++) checksum ^= dccPacket[n];
//checksum=0; //Comment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (checksum) return; // Invalid Checksum

else { // There is a new packet with a correct checksum
isDifferentPacket=1;
for (byte n=0; n<packetBufferSize ; n++) {// Check if packet is not already in the buffer.
// The checksum byte is used for the test, not ideal, some new packets may not show (only 256 different checksums)
if (dccPacket[pktByteCount]==packetBuffer[n]) isDifferentPacket=0;
}

if (isDifferentPacket) { // packet does not yet exist in the packet buffer
packetBuffer[bufferCounter] = dccPacket[pktByteCount]; // add new packet to the buffer
bufferCounter = (++bufferCounter)&(packetBufferSize-1);

if (dccPacket[1]==B11111111) { //Idle packet
Serial.println("Idle ");
return;
}

if (!bitRead(dccPacket[1],7)) { //bit7=0 -> Loc Decoder Short Address
decoderAddress = dccPacket[1];
instrByte1 = dccPacket[2];
decoderType = 0;
}
else {
if (bitRead(dccPacket[1],6)) { //bit7=1 AND bit6=1 -> Loc Decoder Long Address
decoderAddress = 256 * (dccPacket[1] & B00000111) + dccPacket[2];
instrByte1 = dccPacket[3];
decoderType = 0;
}
else { //bit7=1 AND bit6=0 -> Accessory Decoder
decoderAddress = dccPacket[1]&B00111111;
instrByte1 = dccPacket[2];
decoderType = 1;
}
}
if (decoderType) { // Accessory Basic
if (showAcc) {
if (instrByte1&B10000000) { // Basic Accessory
decoderAddress = (((~instrByte1)&B01110000)<<2) + decoderAddress;
byte port = (instrByte1&B00000110)>>1;
Serial.print("Acc ");
Serial.print((decoderAddress-1)*4 + port + 1);
Serial.print(" ");
Serial.print(decoderAddress);
Serial.print(":");
Serial.print(port);
Serial.print(" ");
Serial.print(bitRead(instrByte1,3));
if (bitRead(instrByte1,0)) Serial.print(" On");
else Serial.print(" Off");
}
else { // Accessory Extended NMRA spec is not clear about address and instruction format !!!
Serial.print("Acc Ext ");
decoderAddress = (decoderAddress<<5) + ((instrByte1&B01110000)>>2) + ((instrByte1&B00000110)>>1);
Serial.print(decoderAddress);
Serial.print(" Asp ");
Serial.print(dccPacket[3],BIN);
}
printPacket();
}
}
else { // Loc / Multi Function Decoder
if (showLoc) {
Serial.print("Loc ");
Serial.print(decoderAddress);
byte instructionType = instrByte1>>5;
switch (instructionType) {

case 0:
Serial.print(" Control ");
break;

case 1: // Advanced Operations
if (instrByte1==B00111111) { //128 speed steps
if (bitRead(dccPacket[pktByteCount-1],7)) Serial.print(" Forw128 ");
else Serial.print(" Rev128 ");
byte speed = dccPacket[pktByteCount-1]&B01111111;
if (!speed) Serial.print(" Stop ");
else if (speed==1) Serial.print(" E-stop ");
else Serial.print(speed-1);
}
else if (instrByte1==B00111110) { //Speed Restriction
if (bitRead(dccPacket[pktByteCount-1],7)) Serial.print(" On ");
else Serial.print(" Off ");
Serial.print(dccPacket[pktByteCount-1])&B01111111;
}
break;

case 2: // Reverse speed step
speed = ((instrByte1&B00001111)<<1) - 3 + bitRead(instrByte1,4);
if (speed==253 || speed==254) Serial.print(" Stop ");
else if (speed==255 || speed==0) Serial.print(" E-Stop ");
else {
Serial.print(" Rev ");
Serial.print(speed);
}
break;

case 3: // Forward speed step
speed = ((instrByte1&B00001111)<<1) - 3 + bitRead(instrByte1,4);
if (speed==253 || speed==254) Serial.print(" Stop ");
else if (speed==255 || speed==0) Serial.print(" E-Stop ");
else {
Serial.print(" Forw ");
Serial.print(speed);
}
break;

case 4: // Loc Function L-4-3-2-1
Serial.print(" L F4-F1 ");
Serial.print(instrByte1&B00011111,BIN);
break;

case 5: // Loc Function 8-7-6-5
if (bitRead(instrByte1,4)) {
Serial.print(" F8-F5 ");
Serial.print(instrByte1&B00001111,BIN);
}
else { // Loc Function 12-11-10-9
Serial.print(" F12-F9 ");
Serial.print(instrByte1&B00001111,BIN);
}
break;

case 6: // Future Expansions
switch (instrByte1&B00011111) {
case 0: // Binary State Control Instruction long form
Serial.print(" BinStateLong ");
Serial.print(256 * dccPacket[pktByteCount-1] + (dccPacket[pktByteCount-2]&B01111111));
if bitRead(dccPacket[pktByteCount-2],7) Serial.print(" On ");
else Serial.print(" Off ");
break;
case B00011101: // Binary State Control
Serial.print(" BinStateShort ");
Serial.print(dccPacket[pktByteCount-1]&B01111111);
if bitRead(dccPacket[pktByteCount-1],7) Serial.print(" On ");
else Serial.print(" Off ");
break;
case B00011110: // F13-F20 Function Control
Serial.print(" F20-F13 ");
Serial.print(dccPacket[pktByteCount-1],BIN);
break;
case B00011111: // F21-F28 Function Control
Serial.print(" F28-F21 ");
Serial.print(dccPacket[pktByteCount-1],BIN);
break;
}
break;

case 7:
Serial.print(" CV ");
if (instrByte1&B00010000) { // CV Short Form
byte cvType=instrByte1&B00001111;
switch (cvType) {
case B00000010:
Serial.print("23 ");
Serial.print(dccPacket[pktByteCount-1]);
break;
case B00000011:
Serial.print("24 ");
Serial.print(dccPacket[pktByteCount-1]);
break;
case B00001001:
Serial.print("Decoder Lock ");
Serial.print(dccPacket[pktByteCount-1]);
break;
}
}
else { // CV Long Form
int cvAddress = 256 * (instrByte1&B00000011) + dccPacket[pktByteCount-2] + 1;
Serial.print(cvAddress);
Serial.print(" ");
switch (instrByte1&B00001100) {
case B00000100: // Verify Byte
Serial.print("Verify ");
Serial.print(dccPacket[pktByteCount-1]);
break;
case B00001100: // Write Byte
Serial.print("Write ");
Serial.print(dccPacket[pktByteCount-1]);
break;
case B00001000: // Bit Write
Serial.print("Bit ");
if (dccPacket[pktByteCount-2]&B00010000) Serial.print("Verify ");
else Serial.print("Write ");
Serial.print(dccPacket[pktByteCount-1]&B00000111);
Serial.print(" ");
Serial.print((dccPacket[pktByteCount-1]&B00001000)>>3);
break;
}
}
break;
}
printPacket();
}
}
}
}
if (Serial.available()) {
Serial.println(" ");
switch (Serial.read()) {
case 49:
Serial.println("Refresh Time = 1s");
refreshTime=1;
break;
case 50:
Serial.println("Refresh Time = 2s");
refreshTime=2;
break;
case 51:
Serial.println("Refresh Time = 4s");
refreshTime=4;
break;
case 52:
Serial.println("Refresh Time = 8s");
refreshTime=8;
break;
case 53:
Serial.println("Refresh Time = 16s");
refreshTime=16;
break;
case 54:
Serial.println("Buffer Size = 4");
packetBufferSize=2;
break;
case 55:
Serial.println("Buffer Size = 8");
packetBufferSize=8;
break;
case 56:
Serial.println("Buffer Size = 16");
packetBufferSize=16;
break;
case 57:
Serial.println("Buffer Size = 32");
packetBufferSize=32;
break;
case 48:
Serial.println("Buffer Size = 64");
packetBufferSize=64;
break;
case 97:
if (showAcc) showAcc=0; else showAcc=1;
Serial.print("show loc packets = ");
Serial.println(showAcc);
break;
case 108:
if (showLoc) showLoc=0; else showLoc=1;
Serial.print("show loc packets = ");
Serial.println(showLoc);
break;
}
Serial.println(" ");
}
}

Kode (Styring)

Upload efter denne kode til skiftespor controllering.

  • #define DCC_PIN = Den pin på arduino som modtager DCC signalet (Pin 2)
  • #define BOARD_ADDRESS = Adressen på skiftestoret, IKKE tog addressen.
  • #define PAIR_ADDRESS = Under address, bruges til ON/OFF værdi.

I denne kode har jeg valg inde i min app, at sporskifte 1 har addressen 1. (BOARD_ADDRESS)

#include <NmraDcc.h>
NmraDcc Dcc;

// definitions
#define DCC_PIN 2
#define BOARD_ADDRESS 1
#define PAIR_ADDRESS 1
#define GREEN_LED_PIN 3
#define RED_LED_PIN 4


void notifyDccAccState(uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {

int pairAddress = (OutputAddr >> 1) + 1;
int outputInPair = OutputAddr & 0x01;

Serial.print("* new accessory decoder packet received (BoardAddr=");
Serial.print(BoardAddr, DEC);
Serial.print(", pairAddress=");
Serial.print(pairAddress, DEC);
Serial.print(", outputInPair=");
Serial.println(outputInPair, DEC);

// check if the command is for our address and output
if((BoardAddr == BOARD_ADDRESS) && (pairAddress == PAIR_ADDRESS)) {
if(outputInPair == 0) {
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(GREEN_LED_PIN, LOW);
Serial.println("! RED led activated");
} else {
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(GREEN_LED_PIN, HIGH);
Serial.println("! GREEN led activated"); 
}
}
}


void setup() {

// Serial output for debugging
Serial.begin(115200);
Serial.println("DCC Led Accessory Decoder");
Serial.println();

// init NmraDcc library (PIN, manufacturer, version...) 
Dcc.pin(digitalPinToInterrupt(DCC_PIN), DCC_PIN, 1);
Dcc.init(MAN_ID_DIY, 1, FLAGS_DCC_ACCESSORY_DECODER, 0);

// configure pins
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);

Serial.println("- decoder ready");
}


void loop() {

Dcc.process();
}

Download

Kontakt os

Du er altid velkommen til at kontakte os på info@ardustore.dk, eller sende os en besked via messenger (Klik her) og vi vil hjælpe dig.

Anmeldelser

Der er endnu ikke nogle anmeldelser.

Vær den første til at anmelde “Optokobler 6N137 DIP8 – 1 Kanal”

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *