Photon via RS232 sending bytes

Hello together!

I am facing a problem and after trying forever I see no other way than to ask for help.

I want to send a command bytestring to a machine.
via Realterm and PC works great via serial to USB.

Now I would like to send the same command from my Photon using the same USB to serial cable.

Do you have any idea how I could do this correctly?
I am grateful for any help.

I want to send this–>0x36 0x30 0x30 0x32 0x39 0x36 0x30 0x34 0x46 0x30 0x03


USB auf RS-232 Adapter (35 cm) - UC232A, ATEN USB-Konverter | ATEN Belgium - Deutsch

The USB-Serial port on the Photon is not a host port but a client. When your other device also is a client there is no-one to take the lead in the conversation.
A PC is a USB host, that’s why it works with that.

However, your Photon has RX and TX lines (tied to Serial1) which would talk the same language as your target device, but you need a level shifter 3.3V <-> 12V between the two devices.

3 Likes

Thank you for your competent and quick reply.
what do you think of this level shifter?

Level shifter and buffer 12V (ezsbc.com)

Would the code itself be correct to send the command to the machine after installing the level shifter?

Perhaps something like the MAX232

https://www.ti.com/product/MAX232

1 Like

@Muskie

thank you! I will try it with this.

Do you think the code itself would be correct?

I wouldn’t use a 10 second delay in loop() since that is going to block the underlying OS. Even if you enable system threading, I would still use the millis() paradigm to look for a 10 second difference in millis and then send at that time. Keep the loop executing as fast as possible without delays.

3 Likes

Hello again!
I now have the level shifter I need:
RS232-Shifter

After endless attempts to send the command I have to come back to you.
I assume that the error now lies exclusively in the code.
Perhaps the Photon converts the desired command into a wrong form?

I want to send this via serial1–> 0x36 0x30 0x30 0x32 0x39 0x36 0x30 0x34 0x46 0x30 0x03



Do you have any idea where the error could be?
I am grateful for any help.

Your hardware photo isn't very clear, but to me it looks as you may have connected RX and TX the wrong way round. The RX pin on your controller needs to connect to TX on the level shifter and vice versa.
It even looks as if you had TX on the controller (black wire) plugged into GND on the level shifter and TX on the level shifter (purple wire) into the GND rail on the breadboard.
This looks like a rats nest that needs tidying up urgently IMHO :wink:

You also state

but I don't see what your exact problem is.
Does the other side receive the wrong thing or nothing at all?

BTW, a simpler way to encode your data stream would be like this

char arr1[] = "60029604F0\x03";
// with
  Serial1.print(arr1);

alternative

  Serial1.printf("%010X\x03", 0x60029604F0);

The somewhat convoluted German description above seems to miss the point that this "encoding" is nothing but the ASCII representation of a string that represents a hexadecimal number.
And they misappropriate EOT (End Of Transmission) as 0x03. 0x03 would be ETX (End of TeXt). EOT would actually be 0x04.
If this should in fact be EOT this could explain why your transmission doesn't render the expected result.

I'd also suggest you change your arrX[] variables for a two-dimensional array arr[][MAX_LEN_COMMAND].

Also it would be preferable if you posted your code as text and not as a screenshot.
With text, it's much easier to copy and try your code. I'd not be willing to type-off your code from a screenshot to check and possibly improve it :wink:

3 Likes

Once your hardware setup is correct you can try this code

Stream& out = Serial1;  
SerialLogHandler logger(LOG_LEVEL_ERROR, {{ "app", LOG_LEVEL_INFO }});

const int MAX_COMMAND_LEN = 8;

enum CD160_CMD 
{ CARD_LOAD_FRONT = 0
, CARD_EJECT_FRONT
, CARD_EJECT_BACK
, CARD_STACK_READ
, CARD_DISPENSE
, INFO_VERSION
, CARD_READ_POS1
, CARD_READ_POS2
, CARD_SWAP_POS
, INFO_STATE
, INFO_TEST
, CTRL_RESET
, CTRL_SHUTTER
, INFO_POS
, BARCODE_INIT
, BARCODE_READ
, DATA_PASSTHROUGH
, DATA_RAW
};

const uint8_t cmd[][MAX_COMMAND_LEN] =
//  len  prefix cmd         checksum (precalculated but not used)
{ { 0x02, 0x96, 0x01,       0xf5 } 
, { 0x03, 0x96, 0x02, 0x01, 0xf6 }
, { 0x03, 0x96, 0x02, 0x02, 0xf5 }
, { 0x02, 0x96, 0x03,       0xf7 }
, { 0x02, 0x96, 0x04,       0xf0 }
, { 0x02, 0x96, 0x06,       0xf2 }
, { 0x03, 0x96, 0x07, 0x01, 0xf3 }
, { 0x03, 0x96, 0x07, 0x02, 0xf0 }
, { 0x02, 0x96, 0x08,       0xfc }
, { 0x02, 0x96, 0x09,       0xfd }
, { 0x02, 0x96, 0x0A,       0xfe }
, { 0x02, 0x96, 0x0B,       0xff }
, { 0x02, 0x96, 0x0C,       0xf8 }
, { 0x02, 0x96, 0x0D,       0xf9 }
, { 0x02, 0x96, 0x10,       0xe4 }
, { 0x02, 0x96, 0x11,       0xe5 }
, { 0x02, 0x96, 0x20             } // checksum cannot be precalculated w/o additional data
, { 0x00                         } // checksum cannot be precalculated w/o additional data
};

uint8_t sendTLP224(const uint8_t* data, size_t len = 0);
uint8_t sendTLP224(CD160_CMD idxCommand, const uint8_t* data = NULL, size_t len = 0);

void setup() {
  System.on(button_click, btnHandler);
  Serial1.blockOnOverrun(false);
  Serial1.begin(9600);

  Log.info("Command list");
  for (int i=0; i < DATA_PASSTHROUGH; i++)
    Log.info("checksum for %2d: 0x%02X", i, sendTLP224((CD160_CMD)i));
}

void loop() {
}

void btnHandler(system_event_t event, int param) {
  Serial.printlnf("INFO_STATE request sent (checkSum: %02x)", sendTLP224(INFO_STATE));
}

void serialEvent1() {
  return;
  char c;
  while(Serial1.available()) {
    c = Serial1.read();
    Serial.printf("%c (0x%02X)%s", c, c, (c == '\x03' ? "\r\n" : " ") );
  }
}

uint8_t sendTLP224(CD160_CMD idxCommand, const uint8_t* data, size_t len) {
  uint8_t lenRaw = cmd[idxCommand][0] + 1;          // first byte of cmd indicates command length (w/o length byte itself)
  uint8_t command[lenRaw + len];                    // reserve data for combination of command and additional data
  memcpy(command, cmd[idxCommand], lenRaw);         // copy over the raw command
  memcpy(command+lenRaw, data, len);                // copy additional data
  command[0] = sizeof(command) - 1;                 // new/combined length (length byte doesn't count itself, hence -1)
  return sendTLP224(command, sizeof(command));      // call actual protocol algo
}

uint8_t sendTLP224(const uint8_t* data, size_t len) {
  uint8_t checkSum = 0x60;                          // ACK byte per protocol definition
  char    tx[4];
  if (!data) return 0xFF;                           // when no data is provided, nothing to do
  if (!len) len = data[0] + 1;                      // when no length is provided, the first byte of the provided data must be the length indicator
  
  out.print("60");                                  // always acknowledge, even an initial transmission
  for (int i = 0; i < len; i++) {
    checkSum ^= data[i];                            // XOR checkSum with current byte
    snprintf(tx, sizeof(tx), "%02X", data[i]);      // translate binary byte to ASCII string representation 
    out.print(tx);                                  // emit packet
  }
  snprintf(tx, sizeof(tx), "%02X\x03", checkSum);   // emit checksum and ETX as per protocol definition
  out.print(tx);                                    //
  
  return checkSum;
}

(press the SETUP/MODE button to emit a state request and check the response via particle serial monitor --follow)

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.