Page 1 of 1

How to send a signal through 2 wires using rmt.h ?

Posted: Thu Dec 12, 2019 2:20 pm
by GeorgeFlorian1
Board: ESP32-EVB
OS: Linux Mint

Hello !

For the past week, I have been trying to send this binary number: 01100000101111001011111000 through two wires, emulating the Wiegand Protocol, to a Card Reader.

Wiegand Protocol starts with both pins HIGH. When I send a 0, W0 pin is pulled LOW for usually 20-100us and W1 stays HIGH. When a 1 is being sent W1 is pulled LOW for usually 20-100us and W0 stays HIGH.

I have been able to send that number by doing this:

Code: Select all

void setup() {
  Serial.begin(115200);

  pinMode(W0, OUTPUT);
  pinMode(W1, OUTPUT);
  digitalWrite(W0, HIGH);
  digitalWrite(W1, HIGH);
  // ...
}
  
void loop() {
  delay(100);
  if(change) {
    Serial.println("Sending ID...");
    pulse = pulseWidth.toInt();
    portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
    portENTER_CRITICAL(&mux);
    for(int i = 0; i<26; i++) {
      if(wiegandArray[i] == 0) {
        digitalWrite(W0, LOW);
        delayMicroseconds(pulse);
        digitalWrite(W0, HIGH);
      } else {
        digitalWrite(W1, LOW);
        delayMicroseconds(pulse);
        digitalWrite(W1, HIGH);
      }
      delayMicroseconds(pulse);
    }
    portEXIT_CRITICAL(&mux);
  }

  if(change) {
    change = false;
    for(int i = 0; i<26; i++) {
      Serial.print(wiegandArray[i]);
    }
    Serial.println();
  }
}
The problem with this is that it isn't reliable. It won't work all the time.

I've then tried implementing it in a task:

Code: Select all

void taskOne(void * parameter ) {
  for( ; ; ) {
    if(change) {
      int pulse = pulseWidth.toInt();
      vTaskSuspendAll();
      for(int i = 0; i<26; i++) {
        if(wiegandArray[i] == 0) {
          digitalWrite(W0, LOW);
          delayMicroseconds(pulse);
          digitalWrite(W0, HIGH);
        } else {
          digitalWrite(W1, LOW);
          delayMicroseconds(pulse);
          digitalWrite(W1, HIGH);
        }
        delayMicroseconds(pulse);
      }
      xTaskResumeAll();
      if(change) {
        change = false;
        for(int i = 0; i<26; i++) {
          Serial.print(wiegandArray[i]);
        }
        Serial.println();
      }
      uxTaskGetStackHighWaterMark(NULL);
    } // if(change)
  } // for( ; ; )
}

void setup() {
  xTaskCreate(
              taskOne,          /* Task function. */
              "TaskOne",        /* String with name of task. */
              10000,            /* Stack size in bytes. */
              NULL,             /* Parameter passed as input of the task */
              1,                /* Priority of the task. */
              NULL);            /* Task handle. */
}

void loop() {
delay(100);
}
But this doesn't do anything.

Now, I am being told to try the RMT driver, that can only send one signal through one pin at a time, but I need one signal through two pins, which can apparently be done by doing this:
If you need to split the signal on the output you can do that via NPN/PNP transistors to create an inverse signal or direct the output to two outputs based on the high/low state of the single output.
But, I have no idea how to use transistors. Will I have to split the signal by 0 and 1 in code or from hardware ? How is the split happening ?

I want to send 01100000101111001011111000. Do I send it all at once with a little pause between each one of the bits and the transistor will split the signal and send the zeros (0) to a pin, the ones (1) to the other pin and hope that they will be synchronized ? Because I can't have 0 and 1 sent at the same time.

Can I get some help in understanding how this works and how can I implement it ?
Thank you.

Re: How to send a signal through 2 wires using rmt.h ?

Posted: Thu Dec 12, 2019 8:09 pm
by tommeyers
Take a look here: https://www.arduinolibraries.info/libra ... nd-library

In the in file there is a readme that describes the protocol.

Maybe the code could be adapted to your project.

Tom Meyers

Re: How to send a signal through 2 wires using rmt.h ?

Posted: Fri Dec 13, 2019 8:56 am
by GeorgeFlorian1
tommeyers wrote:
Thu Dec 12, 2019 8:09 pm
Take a look here: https://www.arduinolibraries.info/libra ... nd-library

In the in file there is a readme that describes the protocol.

Maybe the code could be adapted to your project.

Tom Meyers
This is at the beginning of the readme:
# Yet Another Arduino Wiegand Library

A library to received data from Wiegand RFID Card readers.
All of the examples I could find are similar to this one. They are all Wiegand Readers/Receiver and I want a Wiegand Writer/Transmitter/Sender.

Re: How to send a signal through 2 wires using rmt.h ?

Posted: Fri Dec 13, 2019 2:04 pm
by tommeyers
Goerge,

Oops, I read through that too quickly.

Here is another try an transmitting: https://www.codeproject.com/Articles/12 ... th-Arduino

I thought it would be necessary to invert the second line from the first. This shows how to wiggle each line in code.

Tom Meyers

Re: How to send a signal through 2 wires using rmt.h ?

Posted: Tue Dec 17, 2019 9:22 am
by GeorgeFlorian1
tommeyers wrote:
Fri Dec 13, 2019 2:04 pm
Goerge,

Oops, I read through that too quickly.

Here is another try an transmitting: https://www.codeproject.com/Articles/12 ... th-Arduino

I thought it would be necessary to invert the second line from the first. This shows how to wiggle each line in code.

Tom Meyers
I have already achieved the same results in my project:

Code: Select all

for(int i = 0; i<26; i++) {
      if(wiegandArray[i] == 0) {
        digitalWrite(W0, LOW);
        delayMicroseconds(pulse);
        digitalWrite(W0, HIGH);
      } else {
        digitalWrite(W1, LOW);
        delayMicroseconds(pulse);
        digitalWrite(W1, HIGH);
      }
      delayMicroseconds(pulse);
    }
The problem with this is that it won't work 100% of the time, because of the FreeRTOS scheduler that will interfere and can screw up the signal.

Re: How to send a signal through 2 wires using rmt.h ?

Posted: Tue Dec 17, 2019 9:08 pm
by tommeyers
George i don't see the similarities with this code:
void outwiegbit(unsigned int b)
{
int sel = b == 0 ? W_D0 : W_D1;
digitalWrite(sel, 0);
delayMicroseconds(80);
digitalWrite(sel, 1);
delayMicroseconds(240);
}
You wiggle one or the other. This wiggles both at the same time. See what think.
Tom