RS232 to TTL serial

Hi all!

I am trying to control via serial communication from my Arduino an Itech power supply. First I tried to do the same with pyserial in my pc. It worked after defining the device as:

SERIAL_PORT = 'COM3'  
ser = serial.Serial(
    port=SERIAL_PORT,
    baudrate=9600,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    timeout=1 
)

Some of the commands I tried successfully are:

def mesure_voltage(ser):
    ser.write("MEAS:VOLT?\n".encode())
    response = ser.readline().decode().strip()
    print("Voltage (V):", response)
    time.sleep(.2)


def mesure_current(ser):
    ser.write("MEAS:CURR?\n".encode())
    response = ser.readline().decode().strip()
    print("Current (A):", response)
    time.sleep(.2)

In my arduino, I defined a simple code to see if I could communicate to the device via the max3232 adapter:

#include <SoftwareSerial.h>
SoftwareSerial rs232(8, 9); // RX, TX

void setup() {
  Serial.begin(9600);       
  rs232.begin(9600);        
  Serial.println("Ready.");
}

void loop() {
  // From PC to device
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    rs232.print(cmd);    
    rs232.print('\n');  
    Serial.println("> Sent: " + cmd);
  }

  // From device to PC
  if (rs232.available()) {
    String response = rs232.readStringUntil('\n');
    Serial.println("< Received: " + response);
  }
}

No response from the device. I tested the adapter with a jumper between rx and tx pins and they work.

Any idea on how to make more tests?

What is the voltage between your device's data out pin and the ground pin?

1 Like

Does your device rely on seeing DTR or RTS from the PC to communicate?

1 Like

Welcome!
Post an annotated schematic showing exactly how you have wired it, be sure to show all power, ground connections and power source(s). Also post a link to your Itech power supply technical specifications.

I've successfully tested your code.

I changed the pins used by software serial to match my setup.
I commented out the line:

rs232.print('\n');  

as I knew my power supply doesn't want a '\n' character.

Here are the results when I:

  • Sent *IDN?
  • Received the power supply's model and firmware version.
  • Set the output voltage to 5V.
  • Turned the output on.
  • Measured the current into a 100Ω resistor - 48mA.

A very common mistake with RS232 is to get the Rx and Tx lines reversed. You may need to swap pins 2 and 3 between the RS232 adapter and the RS232 cable to the Itech power supply.

Are you using a null modem cable (crossover)?

i don't think so. Maybe this helps:

Does this mean that the DB9 cable may not swap the pins between input and output?

null modem

Depends on the cable, some swap the Rx and Tx pins, some are wired straight through.
For equipment designed to be connected to a PC, the only thing you can reasonably assume is that the cable is wired to work with the standard serial port of a PC. The RS232 adapter for the Arduino may not have the same pinout for Rx and Tx as a PC port, depends on the adapter you have.

2 Likes

I built one. There is a handshake protocol which i assume the device does not need if I use baud9600 8N1.
No response.

what would the problem be if that was the case?

I have no idea if that is true or not.
Post the users manual for your device.

What problem would you see? The exact problem you are seeing.

Hi @all:
I built the rts-cts protocol and created what I thought was a correct code. Every time I plugged in the channel assigned to cts, the handshake protocol worked wrongly and all signals were not as accurate as without that pin plugged. I swapped pins in the Arduino card and in the adapter (Artekit AK-3232 and AK-3232L | Artekit Labs Tutorials). The problem only depends on the pin associated to the cts channel. The code is this:

#include <SoftwareSerial.h>

// SoftwareSerial on pins 10 (RX), 11 (TX)
#define RS232_RX 10
#define RS232_TX 11
// RTS/CTS pins
#define RTS_PIN 5  // Arduino says it is ready to send
#define CTS_PIN 6  // Arduino checks if it is allowed to send

SoftwareSerial rs232Serial(RS232_RX, RS232_TX);

String inputCommand = "";

void setup() {
  // Set up serial interfaces
  Serial.begin(9600);        // Serial Monitor
  rs232Serial.begin(9600);   // RS232 communication

  // Set pin modes
  pinMode(RTS_PIN, OUTPUT);
  pinMode(CTS_PIN, INPUT);

  // Initially not ready to send
  digitalWrite(RTS_PIN, LOW);

  Serial.println("Type a command and press Enter. Response will be shown if received.");
}

void loop() {
  // ===== Read from Serial Monitor and send to RS-232 =====
  if (Serial.available()) {
    char c = Serial.read();

    // Collect characters into a command
    if (c == '\n' || c == '\r') {
      if (inputCommand.length() > 0) {
        // Signal we want to send
        digitalWrite(RTS_PIN, HIGH);
        delayMicroseconds(100);  // Give time for CTS to respond

        // Wait for CTS HIGH with timeout
        unsigned long timeout = millis() + 1000;  // 1 second
        while (digitalRead(CTS_PIN) != HIGH && millis() < timeout)
          ;

        if (digitalRead(CTS_PIN) == HIGH) {
          rs232Serial.println(inputCommand);  // Send the command
          rs232Serial.flush();                // Wait for transmit to complete
          Serial.print(">> Sent: ");
          Serial.println(inputCommand);
        } else {
          Serial.println("CTS timeout - RS232 device not ready.");
        }

        digitalWrite(RTS_PIN, LOW);  // Done sending
        inputCommand = "";           // Clear input
      }
    } else {
      inputCommand += c;  // Append character
    }
  }

  // ===== Read from RS-232 and show on Serial Monitor =====
  if (rs232Serial.available()) {
    String response = rs232Serial.readStringUntil('\n');
    Serial.print("<< Received: ");
    Serial.println(response);
  }
}

Trying to find a solution, I did the following code, which keeps the rts channel on for a while in case one wants to read from the device:


#include <SoftwareSerial.h>

// SoftwareSerial pins
#define RS232_RX 10
#define RS232_TX 11

// RTS pin
#define RTS_PIN 2

SoftwareSerial rs232Serial(RS232_RX, RS232_TX);

String inputCommand = "";

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

  pinMode(RTS_PIN, OUTPUT);
  digitalWrite(RTS_PIN, LOW);  

  Serial.println("Type any command and press Enter. Waiting for response...");
}

void loop() {
  // === Collect input from Serial Monitor ===
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '\n' || c == '\r') {
      if (inputCommand.length() > 0) {
        digitalWrite(RTS_PIN, HIGH);
        delayMicroseconds(1000); 
        rs232Serial.println(inputCommand);
        Serial.print(">> Sent: ");
        Serial.println(inputCommand);

        unsigned long startTime = millis();
        while (millis() - startTime < 2000) {
          if (rs232Serial.available()) {
            String response = rs232Serial.readStringUntil('\n');
            Serial.print("<< Received: ");
            Serial.println(response);
            break; 
          }
        }

        digitalWrite(RTS_PIN, LOW);  
        inputCommand = ""; 
      }
    } else {
      inputCommand += c;
    }
  }
}

I can now type for example *IDN?, but no other command to for example swap the channel value or see the channel value. Also i do not get a response after typing *IDN?.

I will keep trying from time to time. Thx for your support!!

Somehow, if I connect the device to python, disconnect it and then connect it to arduino, commands work! Now I am missing the messages generated by the device to get them in my serial terminal. If I manage, I will post it for other people.

You seem to not know that ALL the pins require RS-232 protocol, including the RTS/CTS connections. Are you using a separate adapter for the RTS/CTS connections?

I solved it. The last step was to use a digital pin without PWM (~).