I'm writing two programs on Qt 5. The first ("Debug") program sends requests to the second ("Simulator") through a PCI-E device. The "Simulator" must respond as fast as possible. This is a separate issue, but now I want to ask about another strange effect. The "Debug" program writes 10 bytes from QLineEdit to a PCI-E device and then waits for an answer from the "Simulator". When the answer came fast enough, I see the right data bytes in the "Debug" program window, otherwise a PCI-E device returns a copy of a sended data and I see it too. The issue is that data can be sended by two ways: by clicking the Send button on the form and by clicking the Return button on a keyboard. In both cases the data is sent from the following slot:
void MyWin::on_pushButton_Send_clicked()
{
if(data_matched)
{
QString exp = ui.lineEdit_Data->text();
QStringList list = exp.split(QRegExp("\\s"),
QString::SkipEmptyParts);
for(int i=0; i<list.size(); i++)
{
quint8 a = list[i].toUInt(0, 16);
data[i] = a;
}
write_insys(bHandle, data, DataSize);
ui.textEdit->append( /* show sended bytes */ );
read_insys(bHandle, data, DataSize);
ui.textEdit->append( /* show received bytes */ );
}
}
But in the second case (on Return key press) the only difference is that the above slot is invoked inside the following:
void MyWin::on_lineEdit_Data_returnPressed()
{
on_pushButton_Send_clicked();
}
But the results:
1st case: 90% wrong answers
2st case: 90% right answers
The code of write_insys and read_insys is absolutely trivial, simply call the library functions:
bool write_insys(BRD_Handle handle, void* data, int size)
{
S32 res = BRD_putMsg(handle, NODE0, data, (U32*)&size, BRDtim_FOREVER);
return (res >= 0);
}
bool read_insys(BRD_Handle handle, void* data, int size)
{
S32 res = BRD_getMsg(handle, NODE0, data, (U32*)&size, BRDtim_FOREVER);
return (res >= 0);
}
Does anyone know why this might happen?
Windows 7, Qt 5.4.2, Msvc 2010.
edit: Most likely it is a Qt bug...
Related
I am trying to build a simple FLASH memory programmer (for 39SF020A) using my arduino mega. I wrote the C code and Python script to send the data over (And it all works as expected).
I need to transfer about 32k of hexadecimal data, but with my settings only 10k of data took about 4 minutes (115200 BAUD), which i found unnecessary long. Currently, i am sending over serial (from Python) my value with a terminator (i chose '$'), so for exmple '3F$'. adresses are calulated on the arduino, so no need to send them.
In my arduino code, i have
String received_string = Serial.readStringUntil('$');
and after programming every byte to teh FLASH using arduino, it sends back a '\n' to let the Python know, that it is ready to receive next byte (the python is waiting for receiving a 'line' and then continues). I am not really sure if this is a way to do it, if sending only one byte at the time is good idea and if not, how many and how do i parse them on the arduino? Is the feedback loop useful?
Thanks.
Python Code:
('file' contains all data)
for item in file[1:]:
ser.write((item + "$").encode("ascii"))
line = ser.readline()
i += 1
if i >= top:
break
elif (i % 100) == 0:
print(i)
Arduino code (just part of it)
if (Serial.available() > 0){
String received_string = Serial.readStringUntil('$');
programData(received_string.toInt(),program_adress);
program_adress++;
}
void programData(char data_in, unsigned long adress)
{
digitalWrite(OE,HIGH);
digitalWrite(CE,LOW);
writeByte(0xAA, 0x5555);
writeByte(0x55, 0x2AAA);
writeByte(0xA0, 0x5555);
writeByte(data_in, adress);
Serial.print("\n"); // Feedback for Python
delayMicroseconds(30); // Just to be on the safe side
}
void writeByte(char data_in, unsigned long adress)
{
setDataAs(OUTPUT);
digitalWrite(OE,HIGH);
digitalWrite(WE,HIGH);
setAdress(adress);
setData(data_in);
digitalWrite(WE,LOW);
delayMicroseconds(1);
digitalWrite(WE,HIGH);
}
// Sets data BUS to input or output
void setDataAs(char dir){
for (unsigned int i = 0; i < data_size ;i++) pinMode(data[i],dir);
}
// Sets data to specific values
void setData(char data_i){
setDataAs(OUTPUT);
for (int i = 0; i < data_size;i++) { digitalWrite(data[i],bitRead(data_i,i)); }
}
void setAdress(long adr){
// Set all adresses
for (int i = 0; i < adresses_size;i++)
digitalWrite(adresses[i],bitRead(adr,i));
}
I want to read a String in Arduino from the keyboard outside of the loop() method.
I have the following method:
void readFromKeyboard(byte arrayAddress[])
{
int count = 0, i = 0;
while ((count = Serial.available()) == 0);
while (i<count)
{
arrayAddress[i++] = Serial.read();
}
}
In the loop() method I am calling it like:
readFromKeyboard(userInput);
where userInput is a byte[];
The problem is that when I input more than one characters it read the 1st character initially and it call the readFromKeyboard again an then reads the rest.
Example; if I input "asdf":
--the 1st time it will do ==> userInput = "a"
--the 2nd time it will do ==> userInput = "sdf"
I have tryed many things but the same happens again and again...
Any suggestions??
So that's what worked:
In the loop():
while(Serial.available() == 0);
delay(100);
readInputFlag = readFromKeyboard(userInput);`
And in the readFromKeyboard method:
void readFromKeyboard(byte arrayAddress[])
{
int i = 0;
while (Serial.available() > 0)
{
arrayAddress[i++] = Serial.read();
}
}
This delay, in the loop method, somehow makes the Serial get the whole string instead of just the first letter.
I know you got it working, but I wanted to show you something that I use to deal with this issue. This is a two-tiered delay system for catching bytes that come in a bit late for whatever reason. It's designed to minimize the delay needed to accomplish that task.
int received_length = 0;
byte serial_incoming_buffer[200];
while(Serial.available()) {
serial_incoming_buffer[received_length++] = Serial.read();
if(!Serial.available()) {
delay(3);
if(!Serial.available()) {
delay(20);
}
}
}
Sometimes the Arduino falls behind in picking up serial from the sender and sometimes it grabs serial too fast. Sometimes the sender lags a little bit. This code will wait 3 ms for more bytes, and if they come in it goes back to receiving as many as are available having only had that very brief delay. This repeats as necessary, then when 3 ms goes by without anything being available, it waits a bit longer (20 ms here) for more bytes. If nothing comes in after the long delay, then the transmission is most likely done and you can safely move on.
I recommend tweaking the delays based on your baud rate.
I am having problems communicating FROM the arduino to my Qt application through QSerialPort. I have a listening signal that tells me when there is data ready to be read from the arduino. I expect a value for the number of steps that a stepper motor has undertaken before hitting a limit switch, so only a simple int such as "2005". When the data is available for reading, sometimes I get two separate reads with "200" and "5". Obviously this messes things up when I am parsing the data because it records it as two numbers, both much smaller than the intended number.
How can I fix this without me putting in a Sleep or QTimer to allow for a bit more time for the data to come in from the arduino? Note: my program is not multithreaded.
Example Qt code:
//Get the data from serial, and let MainWindow know it's ready to be collected.
QByteArray direct = arduino->readAll();
data = QString(direct);
emit dataReady();
return 0;
Arduino:
int count = 2005;
Serial.print(count);
You can add line break to synchronize.
Example Qt code:
//Get the data from serial, and let MainWindow know it's ready to be collected.
QByteArray direct = arduino->readLine();
data = QString(direct);
emit dataReady();
return 0;
Arduino:
int count = 2005;
Serial.print(count);
Serial.println();
If you are going to use QSerialPort::readyRead signal, you need to also use the QSerialPort::canReadLine function, see this.
Thank you for your help Arpegius. The println() function was definitely a good choice to use for the newline delimiter. And following that link, I was able to get a listening function that got everything the arduino sent as seperate strings. The extra if statements in the loop handle any cases where the incoming string does not contain the newline character (I am paranoid :D)
My code for anyone that has the same problem in the future.
int control::read()
{
QString characters;
//Get the data from serial, and let MainWindow know it's ready to be collected.
while(arduino->canReadLine())
{
//String for data to go.
bool parsedCorrectly = 0;
//characters = "";
//Loop until we find the newline delimiter.
do
{
//Get the line.
QByteArray direct = arduino->readLine();//Line();
//If we have found a new line character in any line, complete the parse.
if(QString(direct).contains('\n'))
{
if(QString(direct) != "\n")
{
characters += QString(direct);
characters.remove(QRegExp("[\\n\\t\\r]"));
parsedCorrectly = 1;
}
}
//If we don't find the newline straight away, add the string we got to the characters QString and keep going.
else
characters += QString(direct);
}while(!parsedCorrectly);
//Save characters to data and emit signal to collect it.
data = characters;
emit dataReady();
//Reset characters!
characters = "";
}
return 0;
}
I have just downloaded the latest Arduino Library code from Github, and it's broken my MQTT client program. I'm using PubSubClient 1.91 on Arduino, and Mosquitto 1.1.2 (Build 2013-03-07) on Mac OSX. (I also tested against Mosquitto on Windows 7, same problem.)
The supplied Mosquitto clients work fine, (Mac over to Windows, Windows over to Mac) so it's some problem with what's coming from the Arduino end. A wireshark trace shows the Arduino client sending the following data packet:
10:15:ff:ff:4d:51:49:73:64:70:03:02:00:0f:00:07:41:72:64:75:69:6e:6f
And the Mosquitto broker shows:
New connection from 10.0.0.115
Socket read error on client (null), disconnecting.
Before I start to crawl through the MQTT spec, can anyone see anything wrong with the data packet being sent? It's got to be something to do with new Arduino library code...
* Update
Upon further investigation, it appears to be a code generation problem with avr-g++, although life experience tells me it will turn out not to be so. Here is a snippet of code from PubSubClient.cpp
boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, uint8_t willQos, uint8_t willRetain, char* willMessage) {
if (!connected()) {
int result = 0;
if (domain != NULL) {
result = _client->connect(this->domain, this->port);
} else {
result = _client->connect(this->ip, this->port);
}
if (result) {
nextMsgId = 1;
uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};
// d[0] = 0;
// d[1] = 6;
Serial.print("d[0]="); Serial.println(d[0],HEX);
Now, the result of the Serial.print just above turns out to be 0xFF !!! So, the uint8_t array is not being initialised correctly. #knoleary Your pointer to the bad FF bytes lead me to this.
If I now uncomment the two lines above, and manually initialise the first 2 bytes to 0 and 6, all works fine, and my program communicates happily with Mosquitto.
I've looked at the generated code, but I'm not an Atmel expert.
Does anyone have any clue why this might be?
I'm compiling using the AVR-G++ toolset from Arduino 1.05, in Eclipse.
I'm going for a beer!
OK, I found it. It's a relatively subtle bug. Essentially, when the following line of source code is compiled;
uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};
the 9 bytes get stored as a constant in the data section of the image. At runtime, a small loop copies the 9 bytes into the array (d[]) By looking at a combined Assembler / source listing, I could see where in the data section the 9 bytes were stored, and then print them out at regular intervals, until I found what was over-writing them. (A bit primitive, I know!)
It turns out the there's a bug in WiFi.cpp , the Arduino WiFi code. Here's the code:
uint8_t WiFiClient::connected() {
if (_sock == 255) {
return 0;
} else {
uint8_t s = status();
return !(s == LISTEN || s == CLOSED || s == FIN_WAIT_1 ||
s == FIN_WAIT_2 || s == TIME_WAIT ||
s == SYN_SENT || s== SYN_RCVD ||
(s == CLOSE_WAIT));
}
}
It turns out the the _sock variable is actually initialised like this:
WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
}
and MAX_SOCK_NUM is 4, not 255. So, WiFiClient::status returned true, instead of false for an unused Socket.
This method was called by the MQTT Client like this:
boolean PubSubClient::connected() {
boolean rc;
if (_client == NULL ) {
rc = false;
} else {
rc = (int)_client->connected();
if (!rc) _client->stop();
}
return rc;
}
And, since the _client->connected() method erroneously returned true, the _client_stop() method was called. This resulted in a write to a non-existent socket array element, and so overwrote my string data.
#knolleary, I was wondering, is there any specific reason that your PubSubClient::connected() method does a disconnect? I use the ::connected method in a loop, to check that I'm still connected, and, of course it results in my getting a disconnect / reconnect each time round the loop. Any chance we could just make connected return true / false , and handle the disconnect in PuBSubClient::connect?
Nearly one and a half year later I ran into the same problem. Removing the
boolean PubSubClient::connected() {
int rc = (int)_client->connected();
if (!rc) _client->stop();
return rc;
}
the _client->stop() from the connected method of PubSubClient forehand fixed this problem for me. However, I'm not sure whether this is actually a solution or just a very dirty quick hack to localize the problem.
What have you done to fix this problem - your explanation of the problem above is fine however, I was not able to extract the solution easily ;-)
I am currently in the process of making a Client and Server in the Unix/Windows environment but right now I am just working on the Unix side of it. One of the function we have to create for the program is similar to the list function in Unix which shows all files within a dir but we also have to show more information about the file such as its owner and creation date. Right now I am able to get all this information and print it to the client however we have to also add that once the program has printing 40 lines it waits for the client to push any key before it continues to print.
I have gotta the program to sort of do this but it will cause my client and server to become out of sync or at least the std out to become out of sync. This means that if i enter the command 'asdad' it should print invalid command but it won't print that message until i enter another command. I have added my list functions code below. I am open to suggestions how how to complete this requirement as the method I have chosen does not seem to be working out.
Thank-you in advance.
Server - Fork Function: This is called when the list command is enter. eg
fork_request(newsockfd, "list", buf);
int fork_request(int fd, char req[], char buf[])
{
#ifndef WIN
int pid = fork();
if (pid ==-1)
{
printf("Failed To Fork...\n");
return-1;
}
if (pid !=0)
{
wait(NULL);
return 10;
}
dup2(fd,1); //redirect standard output to the clients std output.
close(fd); //close the socket
execl(req, req, buf, NULL); //run the program
exit(1);
#else
#endif
}
Here is the function used to get all the info about a file in a dir
void longOutput(char str[])
{
char cwd[1024];
DIR *dip;
struct dirent *dit;
int total;
char temp[100];
struct stat FileAttrib;
struct tm *pTm;
int fileSize;
int lineTotal;
if(strcmp(str, "") == 0)
{
getcwd(cwd, sizeof(cwd));
}
else
{
strcpy (cwd, str);
}
if (cwd != NULL)
{
printf("\n Using Dir: %s\n", cwd);
dip = opendir(cwd);
if(dip != NULL)
{
while ((dit = readdir(dip)) != NULL)
{
printf("\n%s",dit->d_name);
stat(dit->d_name, &FileAttrib);
pTm = gmtime(&FileAttrib.st_ctime);
fileSize = FileAttrib.st_size;
printf("\nFile Size: %d Bytes", fileSize);
printf("\nFile created on: %.2i/%.2i/%.2i at %.2i:%.2i:%.2i GMT \n", (pTm->tm_mon + 1), pTm->tm_mday,(pTm->tm_year % 100),pTm->tm_hour,pTm->tm_min, pTm->tm_sec);;
lineTotal = lineTotal + 4;
if(lineTotal == 40)
{
printf("40 Lines: Waiting For Input!");
fflush(stdout);
gets(&temp);
}
}
printf("\n %d \n", lineTotal);
}
else
{
perror ("");
}
}
}
At here is the section of the client where i check that a ! was not found in the returned message. If there is it means that there were more lines to print.
if(strchr(command,'!') != NULL)
{
char temp[1000];
gets(&temp);
}
Sorry for the long post but if you need anything please just ask.
Although, I didn't see any TCP/IP code, I once had a similar problem when I wrote a server-client chat program in C++. In my case, the problem was that I didn't clearly define how messages were structured in my application. Once, I defined how my protocol was suppose to work--it was a lot easier to debug communication problems.
Maybe you should check how your program determines if a message is complete. In TCP, packets are guaranteed to arrive in order with no data loss, etc. Much like a conversation over a telephone. The only thing you have to be careful of is that it's possible to receive a message partially when you read the buffer for the socket. The only way you know to stop reading is when you determine a message is complete. This could be as simple as two '\n' characters or "\n\r".
If you are using UDP, then that is a completely different beast all together (i.e. messages can arrive out of order and can be lost in transit, et cetera).
Also, it looks like you are sending across strings and no binary data. If this is the case, then you don't have to worry about endianess.