Arduino RS232 Serial Communication to Laser Control Board

Hello everyone!

I am a mechanical engineering student currently making my master thesis and I do not have much programming experience. Hopefully someone can help me here.

I am making the control of an Additive Manufacturing machine, that directly melts powder metal through a laser.

I have feedback control, with a pyrometer (temperature sensor), and a 200W Fiber laser to melt the metal. The PID controller is ready to be calibrated, my only issue is the communication to the laser control board.

The laser uses a RS-232 interface. I leave below the user's manual Rs232 Laser Interface description.

########################## RS 232 INTERFACE DESCRIPTION ####################
"A three wire (RxD, TxD, GND) interface is used. Most computers are DTE (Data Terminal Equipment) devices. The laser is also a DTE device and therefore you must use a DTE-to-DTE interface cable. These cables are also called null-modem, modem-eliminator, or crossover cables. In addition, the interface cable must have the proper connector on each end. Cables typically have 9 pins (DB-9) or 25 pins (DB-25) with ‘male’ pins or ‘female’ receptacles inside the connector shell. For RS-232 connections on the rear panel of the Laser Driver please refer to the interface connector pin out. The other end of this cable needs to match the computers interface connector. Remember that this cable must be wired in a null-modem or crossover configuration.

The RS-232 interface has been set to the following parameters:
Baud Rate: 57600
Data Bits: 8 Bits
Stop Bits: 1 Bit
Parity: None
Flow Control: None

Note: After power on the laser sends some service bytes to RS-232 interface. These bytes should be ignored.

All commands and responses will consist of printable ASCII characters. Commands are typically a 3 or 4 letter mnemonic followed by a parameter, if required.

All commands and responses will be terminated with a ‘carriage return’ (CR, 0x0D, \r) character. If a CR terminated string is received, but no valid command is found, a response of “BCMD” will be sent.

The commands are shown here as all uppercase for clarity; the actual commands are not case sensitive.

A space character is also shown between the command and parameter for clarity.

Every command will generate a response. The responses generally consist of the command echoed back.

If there is a returned value, it will be separated from the echoed command by a ‘:’ character." "

###############################################################

The next pages show the several instructions the laser understands and their description.
(users guide of a more recent fiber laser: http://www.uwlaser.com/uploadfiles/2020/04/20200423170358358.pdf )
On pages 78-forward you can see the type of instructions the laser control board understands (My laser is not as recent as this one, but the communication seems to be simmilar. They are the same manufacturer).

I know this is very dumb but previously I was hoping to code : "Serial.print(" "INSTRUCTION" "); and the laser would respond accordingly, but (probably obviously ahaha) this was not the case.

I have the baud rate set correctly (57600).

Previously I was able to successfully communicate with the laser control board using a common terminal emulation program for RS-232, just by typing the users manual instructions (such as, for example "ABN" or "ABF" which turn ON and OFF a laser guide).

To conclude, I am using an Arduino Uno, with a TTL to RS232 converter.

My main question is, (since I am not that good at programming), how should I write my code?
Is there a library that can help me?
How should I setup the "Serial." communication for the laser to understand me?

Thank you very much for your time.

EDIT:
You can see my code in the comments below :wink:

That's a good start :wink:
An Arduino Mega would make your life easier as it has multiple Hardware Serial ports, so you could have one for the laser and one for the Serial monitor to debug or give commands

You could use SoftwareSerial if there is very limited communication with your Laser as it will not be robust at 57600 bauds

I would suggest to study Serial Input Basics to handle this

1 Like

If you want to check the actual user manual:
https://ulisboa-my.sharepoint.com/:f:/g/personal/ist197195_tecnico_ulisboa_pt/ElyCnA8sz-JMmh5s1E9x-64Bbjlze47C6z5ecseavRRTPg?e=boDrmD

If you want to check my code:
https://ulisboa-my.sharepoint.com/:f:/g/personal/ist197195_tecnico_ulisboa_pt/EuKiwghPm7JOlIe_8DJGA8QBFnRonOa62j1ji3I41yfzoA?e=wjSnKY

If you do not want to open these files, I posted my code below.
There are 2 files:

  1. main.cpp
  2. system.cpp

Thank you very much! I will check that out

:wink:

Apparently, you can change the baud rate used to talk to the laser, so SoftwareSerial should be usable. Slow it down to 38400 and the Uno should be able to manage that. That you can do with your terminal program.

I'd start with a program that takes input from the serial monitor and sends it to the laser and echoes back what its response was.

1 Like

Post your code here
Few of us will click on links to random places

1 Like

main.cpp HERE:


 #include <Arduino.h>
 
 #include <PID_v1.h>
 
 #include "system.h"
 
 #define baudRate 57600
 
 System sys;
 
 //########################### myPID ###########################
 
 double Setpoint; //target value
 
 double Input;    //Temperature sensor (pyrometer)
 
 double Output;   //ouput value of the PID controller
 
 //PID parameters:
 
 double Kp = 0, Ki = 10, Kd = 0;
 
 //crate PID instance
 
 PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
 
 //#############################################################
 
 void setup()
 
 {
 
   Serial.begin(baudRate);
 
   //setup here
 
   sys.initPyrometer(); //initialize Pyrometer
 
   sys.initLaser();     //initialize Laser
 
   sys.laser_COM();     //laser setup communications
 
   //PID Setup
 
   Setpoint = 850;           //Target value (Temperature)
 
   myPID.SetMode(AUTOMATIC); //Turn PID ON
 
   myPID.SetTunings(Kp, Ki, Kd);
 
   myPID.SetSampleTime(10);        //Sample time = 10 [ms]
 
   myPID.SetOutputLimits(10, 100); //Output limits = Diode Current (10-100% of Max Laser Power)
 
 }
 
 void loop()
 
 {
 
   //main code, to run repeatedly
 
   sys.tempReading(); //temperature reading
 
   //PID Loop
 
   //Temperature Reading in [ÂșC]
 
   Input = sys.tempReading();
 
   //PID calculation
 
   myPID.Compute();
 
   sys.laser_output(Output); //laser output intructions (Serial communication, RS232)
 
   //sys.displayTemp(); //display temperature
 
}

System.cpp HERE:

#include "system.h"

//############################################## SETUP FUNCTIONS ##############################################

//############################################################################################################

void System::initLaser()

{

    pinMode(start_pin, INPUT); //Start laser pin (ON/OFF INPUT pin)

}

void System::laser_COM()

{

    //laser initial communications (to run once)

    //Check Laser YLR-200-AC User Manual for laser instructions descriprion

    Serial.println("DMOD"); // Disable Modulation

    Serial.println("DEC");  // Disable External Control

    Serial.println("ELE");  // Enable Hardware Emission Control

}

void System::initPyrometer()

{

    pinMode(pyrometer_in, INPUT); //pyrometer pin is INPUT

}

//############################################## LOOP FUNCTIONS ##############################################

//############################################################################################################

//###################################### TEMPERATURE READINGS FUNCTIONS ######################################

double System::tempReading()

{

    Temp_reading_V = analogRead(pyrometer_in);                  //Temperature read by pyrometer

    Temp_reading_C = map(Temp_reading_V, 205, 1023, 600, 2300); //Voltage to [ÂșC] conversion. Pyrometer Range = 600 to 2300 [ÂșC]

    return Temp_reading_C;

}

void System::displayTemp()

{

    //Temperature display (Time in [ms] / Temperature in [ÂșC])

    Serial.print(millis());

    Serial.print(" , ");

    Serial.println(Temp_reading_C);

}

//############################################# LASER  FUNCTIONS #############################################

void System::laser_output(float input)

{

    if (digitalRead(start_pin) == HIGH)

    {

        //sys.PID();

        //Check Laser YLR-200-AC User Manual for laser instructions descriprion

        Serial.println("EMON"); // Emission ON

        Serial.print("SDC ");   // Set Diode Current.

        Serial.println(input);  //PID_value = Diode Current (10-100% of Max Laser Power)

    }

    if (digitalRead(start_pin) == LOW)

    {

        //Check Laser YLR-200-AC User Manual for laser instructions descriprion

        Serial.println("EMOFF"); // Emission OFF

    }

}

Personally, I'd write a separate program just to prove to myself that I can control the laser over software serial. Once that's working you can take what you learned and transplant it into the main code.

1 Like

I will be doing that in the coming days, thanks!

I see you got the hang of code tags in reply #8 - you might want to go back and fix your earlier posts too.

actually, I think J-M-L did it for me :sweat_smile:
I tried to change it in #7 but couldn't do it

:edit: NVM I think I kind of got it, ahahah

As unnecessary as it might be, those introductory messages FROM the laser can help you confirm the comms is working.

A @wildbill suggested earlier, start with very simple code to echo between the laser and Serial Terminal.

Then you can confirm the startup messages are moving around properly.
Once that’s done, you can begin to play with sending and receiving messages.
I’d also suggest a MEGA, because software serial just adds another layer of unnecessary complexity and limitations that you don’t need.
(esp. with a 200W laser)

1 Like

I did :wink:

Any chance you can get a MEGA? Or an arduino with more than one hardware serial port ? This way you would not have to slow down the laser communication

Yes, I can get the Arduino Mega. I am now testing with SerialSoftware, following @wildbill and @lastchancename advice, I think I am getting a hang of things now, at least a little bit :sweat_smile:

You could also look at my Arduino Software Solutions which has a variety of alternative sketches for reading / parsing from Serial with the pros/cons of each.

1 Like

looks like the command language is pretty simple and straightforward, so should not be a massive issue to get or send commands as long as you Serial line is robust.

1 Like

When you get this working I would like to see video of it in action.

1 Like

just reading this again, the reason it was not working is that commands need to be be terminated by '\r' so

Serial.print("Command");
Serial.write('\r'); // end of command

is basically what it takes (if the laser is connected to the Serial port)

1 Like

I was just learning about that in Serial input basics (Serial Input Basics - updated - #3 by Robin2).
in the basics they use '\n' or '>' as end markers ('<' as a starter marker, or LF). I was reading through google and ASCII uses the number 13 as Carriage return.

with the terminal emulation software I was only able to send and read commands once I selected a check box with "+CR". I assume the terminal emulation program could now read and send the carriage return characters automaticaly, with me just needing to type "INSTRUCTION".

My question now is, what is the CR character I should use, are they all the same?
It will probably work if I just type 13 as the end marker character right? Since it is the ASCII value for carriage return.
Will '\n' or '\r' work the same?