0

I have a payment terminal which uses UART (or simply speaking Rx, Tx, Gnd pins) and I have an Android tablet app which is connected to the terminal using USB to DB9 adapter based on PL2303 chip. The Android app works well and it uses https://github.com/felHR85/UsbSerial to support serial communication. The protocol is very simple, basically Android sends strings like "REQINFO,4", "L2,xxx,xxx,*" etc. and recieves back a string statuses.

I'm trying to replace Android app with Arduino UNO, for which I naively assumed would be enough just to connect Tx,Rx of the terminal with Rx,Tx pins of the Arduino and also to connect Gnd pins. But I can't get it working. The only thing I noticed is when I connect Arduino Rx to terminal Tx, the terminal's screens briefly shows "Connecting..." but that's probably because it detects some incoming voltage. When it comes to reading Serial (or also I tried SoftwareSerial) nothing is ever returned.

String data = "";

void setup() {
  Serial.begin(9600);
  while (!Serial);
  delay(1000);
  Serial.println("REQINFO,4");
  delay(1000);
}

void loop() {
  if (Serial.available())  {
    char c = Serial.read(); // also I tried readString() and readStringUntil()
    if (c == '\n' || c == '\r') {
      Serial.println(data); // jsut to see it in the montor
    } else {
      data += c;
    }
  }
}

So do I miss anyting in order to have a proper communication? Thanks.

  • It seems this package supports various methods of flow control (for example rts/dts and others) these are used by the two devices to coordinate communications. If your terminal is setup to use flow control, then you will have to add more to your arduino code to support it depending upon the nature of the flow control. You should also consider the message format (parity, start/stop bits and baud rate). github.com/felHR85/UsbSerial/wiki/4.-Asynchronous-api – GMc Oct 7 at 22:22
  • @GMc In the Android code flow control set to NONE, so I presume I can ignore that. Also, just for test I disconnected DB9 from the terminal COM port and connected just Rx,Tx pins and everything continued to function. – Ivan Oct 8 at 7:07
0

Check (e.g. with a multimeter) the DB9 voltages! Mostly RS-232 is used on those kind of connectors with voltages +-12Volts (there are other variants as well, up to 15V), but your Arduino's UART uses TTL levels (0V as logic low or 5V as high on a 5V Arduino). You'll need to convert these, possibly with a chip like MAX232 or similar.

Also, for reverse engineering this I recommend using an Arduino with multiple serial ports (e.g. Mega), or at least multiple software serials (with proper level shifting of course). You connect your Android tablet to your reader through your Arduino, and when you receive a byte from one device, send it to the other one, and also send it to your PC along with the information about direction. This way you can understand all the used commands if you sniff long enough. You could also use an SD card on SPI if you need your sniffer system to be mobile (walking in a warehouse scanning items).

If you have access to a logic analyzer, it can also be used as a sniffer. This has an additional advantage, you can change BAUD rates later if your guess was wrong.

(started as a comment but ran out of characters, so I thought I'll explain it a bit more)

https://www.db9-pinout.com/db9-pinout/db9-pinout.gifpinout

If it's a standard cable for RS-232, this diagram shows which pin is which. DCE-DCE and DCE-DTE cables were different back then (one connects a PC to a modem, the other 2 PCs), so you should check both voltages from 5 (GND) to either 2 or 3. An empty line has logic high, which is 5V in case it uses TTL, and -5 or lower (like -12 or -15) for RS-232.

Test different BAUD rates as well!

  • I'm pretty sure that whole system functioning using 5V but indeed it's a good idea to doublecheck that. Regarding sniffing, I actually tried something similar by connecting my Arduino to the tablet and staring into monitor window. For some reason that didn't show me any info either. – Ivan Oct 8 at 7:15
  • So, are you suggesting to try a TTL adapter like this -m.ebay.co.uk/itm/… ? – Ivan Oct 8 at 7:17
  • That hardware would do it, yes. You might need 2 of them, one to the tablet, and one for the reader. But first, check the voltages! – Nyos Oct 8 at 12:17
  • today I tried your suggestion with TTL converter and indeed it works well. Now I can sniff data coming from tablet to Arduino. I used Arduino Mega so I hooked terminal to Rx2,Tx2. But for some reason attaching another TTL on between these pins and the terminal didn't bring any value. I wonder do I need it at all, as without TTL for terminal I can at leat recieve some gibberish -- ⸮⸮i⸮v맧⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮u[[⸮⸮_gu}Yu⸮Yucw⸮}⸮gaqmc⸮[uya[w⸮⸮ possible there's a way to adjust something (baud rate?) to see real content. Anyway thanks, you helped me a lot! – Ivan Oct 11 at 2:05
  • If you have access to - even a cheap ($8) - logic analyzer, you can determine the speed. Or you can test common baud values. You can also send to your PC hex values, the data might be binary, and it'll stay gibberish, even when the settings are right. – Nyos Oct 12 at 15:36
1

There is already an answer and comment about possible hardware / flow control issues, so this answer is only dealing with your Arduino sketch. Iv’e added a couple of print statements and the FreeMemory library to test your sketch.

#include <MemoryFree.h>
String data = "";

void setup() {
  Serial.begin(9600);
  while (!Serial);
  delay(1000);
  Serial.println("REQINFO,4");
  delay(1000);
}

void loop() {
  if (Serial.available())  {
    char c = Serial.read(); // also I tried readString() and readStringUntil()
    if (c == '\n' || c == '\r') {
      Serial.println(data); // jsut to see it in the montor
      Serial.print("freeMemory()=");
      Serial.println(freeMemory());
    } else {
      data += c;
    }
  }
}

When I repeatedly enter the following text in the serial monitor "1234567890", here is the results of the print statements:

REQINFO,4
1234567890
freeMemory()=1770
1234567890
freeMemory()=1770
12345678901234567890
freeMemory()=1760
12345678901234567890
freeMemory()=1760
123456789012345678901234567890
freeMemory()=1750
123456789012345678901234567890
freeMemory()=1750
1234567890123456789012345678901234567890
freeMemory()=1740
1234567890123456789012345678901234567890
freeMemory()=1740
12345678901234567890123456789012345678901234567890

Every time you receive new data, it is appended to the data string, causing the string to grow and available memory to disappear. Using the String object should be avoided.

Here is a simple sketch that uses a char array as a buffer for the incoming data:

// Set the buffer size to accomodate the largest
// "chunk" of data you will be receiving.
const byte bufferSize = 64;
char inputBuffer[bufferSize + 1];

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

void loop(){
  if(Serial.available() > 0){
    Serial.readBytesUntil('\n', inputBuffer, bufferSize);
    Serial.print("inputBuffer=");
    Serial.println(inputBuffer);
    memset(inputBuffer, 0, sizeof(inputBuffer));
  }
}
  • Ah, yeah that sketch is just to test the communication is possible in general. But nonetheless, appreciate your input. – Ivan Oct 8 at 7:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.