PDA

View Full Version : Moving stage using udp command in qt gui



ankit.1g@gmail.com
28th January 2016, 18:09
Hi all,

I am new to qt, I am trying to make a gui to control my stage(based on stepper motor). it uses udp protocol to send commands. command structure is as:
header =07 ( 2 bytes)
command to move = FL10000 ( to move 1 cm)
termination <CR> = 13

I made a push button and created slot for the same shown below:


void MainWindow::on_move_1cm_clicked()
{
QByteArray datagram;
datagram[0] = 0;
datagram[1] = 7;
datagram[2] = 70;
datagram[3] = 76;
datagram[4] = 45;
datagram[5] = 49;
datagram[6] = 48;
datagram[7] = 48;
datagram[8] = 48;
datagram[9] = 48;
datagram[10] = 13;

QUdpSocket udpSocket;
udpSocket.writeDatagram(datagram, QHostAddress("10.10.10.10"),7775);

The problem I am facing is on clicking the button at the first time the stage move, but doesnot when I click it again.
to make this code work again i have to power off my motor.
can anyone tell me what can be wrong.
I am planning on having 3-4 push buttons for different length of move.

Please help me out.

thanks.

ChrisW67
28th January 2016, 20:15
Given that "FL10000" is a string of ASCII characters, and you say the header is two bytes, then I would expect those two bytes to be two ASCII characters also. Try this:

QByteArray datagram("07FL10000\r"); That is, the first two bytes have value 48 and 55 decimal.

ankit.1g@gmail.com
28th January 2016, 20:26
Given that "FL10000" is a string of ASCII characters, and you say the header is two bytes, then I would expect those two bytes to be two ASCII characters also. Try this:

QByteArray datagram("07FL10000\r"); That is, the first two bytes have value 48 and 55 decimal.


this didnt work,

my code works[with first 2 bytes as 0 and 7] but only once..I have to restart the system and compile the program again or i have to disable the connection and re-enable it everytime. do I have to use socket close or something? what will be syntax for that.

d_stranz
29th January 2016, 17:00
i have to disable the connection and re-enable it everytime

Did you read the documentation (and example) for using QUdpSocket? You are creating a new UDP socket on the stack every time you execute the button click slot. The firswt time around, this works, but maybe the second time around the old socket is still connected (even though UDP is supposed to be connectionless). Try creating a single QUdpSocket instance as a member of your MainWindow class instead.

ChrisW67
29th January 2016, 20:31
It moved != it is working correctly... Even the first time

If the two bytes 0x00, 0x07 represent the length of the following command string then:

Should the length include or exclude the trailing CR? Currently it would exclude the CR, which might leave the controller with a spurious byte in a buffer when it receives the next command datagram.
Should the length value include the two bytes of the length indicator itself? Different spurious bytes in the buffer.
Is the byte order correct? 0x00, 0x07 could mean 7 or 1792 decimal. Might still be waiting for more bytes to arrive.

ankit.1g@gmail.com
1st February 2016, 14:39
It moved != it is working correctly... Even the first time

If the two bytes 0x00, 0x07 represent the length of the following command string then:

Should the length include or exclude the trailing CR? Currently it would exclude the CR, which might leave the controller with a spurious byte in a buffer when it receives the next command datagram.
Should the length value include the two bytes of the length indicator itself? Different spurious bytes in the buffer.
Is the byte order correct? 0x00, 0x07 could mean 7 or 1792 decimal. Might still be waiting for more bytes to arrive.


the command is as:
Header = 07 (two bytes)
FL1000
<cr> (ASCII carriage return) = 13.

They only have C# example in the manual which forms the send bytes as:

sendBytes[0] = 0;
sendBytes[1] = 7;
Byte[] SCLstring = Encoding.ASCII.GetBytes(“RV”); // for sendin RV command///
// copy string to the byte array
System.Array.Copy(SCLstring, 0, sendBytes, 2, SCLstring.Length);
// insert terminator
sendBytes[sendBytes.Length - 1] = 13; // CR
// send it to the drive
udpClient.Send(sendBytes, sendBytes.Length);



should i create array of specific length then?


Did you read the documentation (and example) for using QUdpSocket? You are creating a new UDP socket on the stack every time you execute the button click slot. The firswt time around, this works, but maybe the second time around the old socket is still connected (even though UDP is supposed to be connectionless). Try creating a single QUdpSocket instance as a member of your MainWindow class instead.

How can I do that...? creating in main window? can you please give me an example.
thank you

ChrisW67
1st February 2016, 21:00
the command is as:
Header = 07 (two bytes)
FL1000
<cr> (ASCII carriage return) = 13.

This is different to your first post. Fewer zeroes.


They only have C# example in the manual which forms the send bytes as:

sendBytes[0] = 0;
sendBytes[1] = 7;
Byte[] SCLstring = Encoding.ASCII.GetBytes(“RV”); // for sendin RV command///
// copy string to the byte array
System.Array.Copy(SCLstring, 0, sendBytes, 2, SCLstring.Length);
// insert terminator
sendBytes[sendBytes.Length - 1] = 13; // CR
// send it to the drive
udpClient.Send(sendBytes, sendBytes.Length);

I am no C# guru, but this looks like it overwrites the 'V' with the <CR> Unless the array is a fixed length prefilled with spaces or GetBytes() returns a trailing terminator byte and that is counted in the length. Have you tried mimicking this command?


should i create array of specific length then?

No, you should create a QByteArray of the correct length for a correct command. We have no way to know whether what you are sending is correct. That will be somewhere in the documentation for the device. I have given you a list of generic ways it may be wrong.


How can I do that...? creating in main window? can you please give me an example.
thank you
You create a QUdpSocket member variable in the main window class, exactly as d_stranz wrote. Then you use that member variable instead of creating a new local object everytime you need one. No magic involved, just C++ 101.


class MainWindow: public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *p = 0);
private:
QUdpSocket *m_socket;
}



MainWindow::MainWindow(QWidget *p = 0):
QMainWindow(p)
{
...
m_socket = new QUdpSocket(this);
}

// elsewhere
m_socket->writeDatagram(datagram, ...);

ankit.1g@gmail.com
1st February 2016, 21:31
This is different to your first post. Fewer zeroes.

I am no C# guru, but this looks like it overwrites the 'V' with the <CR> Unless the array is a fixed length prefilled with spaces or GetBytes() returns a trailing terminator byte and that is counted in the length. Have you tried mimicking this command?

No, you should create a QByteArray of the correct length for a correct command. We have no way to know whether what you are sending is correct. That will be somewhere in the documentation for the device. I have given you a list of generic ways it may be wrong.

You create a QUdpSocket member variable in the main window class, exactly as d_stranz wrote. Then you use that member variable instead of creating a new local object everytime you need one. No magic involved, just C++ 101.


class MainWindow: public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *p = 0);
private:
QUdpSocket *m_socket;
}



MainWindow::MainWindow(QWidget *p = 0):
QMainWindow(p)
{
...
m_socket = new QUdpSocket(this);
}

// elsewhere
m_socket->writeDatagram(datagram, ...);



Thanks a lot...!!! It turns out that binding to any one port solved my problem.
but having qbytes with correct length and making socket once is very nice suggestion thanks a lot for the example.