PDA

View Full Version : QT segmentation falut when communicating with a bluetooth function..



medampudi
13th September 2010, 14:26
Hi every one,

I am trying to integrate the the bluetooth functionality with the QT applciation. I was just wondering what would be the problem with the sprintf statement(tested out both) but does not work...

the function is called from the main function which specifies the struct and initialises its comPort ... Then the data are passed to the connectRobot function and hence this error...

A error of segmentation is shown up if i debug the program at line 9.... crashing the whole program when I run it...

any suggestions on the mistake i would have made...


Thanking you...

Rajesh Medampudi



int connectRobot(struct robot *rbt, int comPort)
{



char portname[20];
sprintf(portname,"COM%d",comPort);
//sprintf(portname,"\\\\.\\COM%d",comPort);
hSerialPort[rbt->serialConnection] = CreateFileA(portname,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hSerialPort[rbt->serialConnection] == INVALID_HANDLE_VALUE) return -1;



dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerialPort[rbt->serialConnection], &dcbSerialParams)) return -2;

dcbSerialParams.BaudRate = 115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;

comt.ReadIntervalTimeout = 500;
SetCommTimeouts( hSerialPort[rbt->serialConnection], &comt);
if (!SetCommState(hSerialPort[rbt->serialConnection], &dcbSerialParams)) return -3;

rbt->port=comPort;
rbt->connected=1;



return 0;
}

wysota
13th September 2010, 14:47
Where do you initialize hSerialPort and how do you call connectRobot()?

medampudi
13th September 2010, 14:54
I just initialized them right before in the same file at the start....


struct robot robots[7];


HANDLE hSerialPort[7]; //up to 7 connection
DCB dcbSerialParams={0};
COMMTIMEOUTS comt;

// fine



//stat
clock_t startTime;
clock_t endTime;

int dtime;


and connect robot is called something like this....



connectRobot(&robots[1], 1036);

wysota
13th September 2010, 15:12
And what does the constructor for struct robot look like? Is the serialConnection field initialized properly?

medampudi
13th September 2010, 15:26
anything else that i need for this....




struct robot
{
int connected;
int serialConnection; //refers to HANDLE vector hSerialPort
int port;

//Sensors
int IR[8]; //infrared sensors 'N'
int LI[8]; //light sensors 'O'
int FL[3]; //floor sensors 'M'
int AC[3]; //acceleration s. 'A'
int MC[3]; //microphone 'U'
int MR[6]; //microretina //cam is dived in 6 sector an then for each sector the number of pixel of a target color is computed
char videoBuffer[1600]; //img 'I'
int imageRGB[1600]; //rgb image built upon videobuffer
char sensorsBuffer[60];
int camW; //cam width 'X cam_mode,cam_widht, cam_heigth,cam_zoom :expressed in byte
int camH; //cam height
int camZ; //cam zoom
//used by Joachim
int old_floor_input[2]; //floor input from previous timestep
int floor_mean[3]; //mean floor value from previous timesteps
int target_prototype[3];//prototypes of floorsensor values for [0]=no target(white), [1]=target1(grey), [2]=target2(black)
int epuck_angle_old; //angle of other epuck at previous timestep
float old_input[3]; //camera input from previous timestep


};

wysota
13th September 2010, 15:31
But do you initialize the object in any way? If not, then rbt->serialConnection will return a random value and you will dereference the hSerialPort array in a wrong way causing a crash of your program.

medampudi
13th September 2010, 15:35
Is this what was on your mind....




int initRobots()
{
int id;
for(id=0;id<7;id++)
{
robots[id].serialConnection=id;
robots[id].port=-1;
robots[id].connected=0;
}
return 0;
}

wysota
13th September 2010, 15:40
Where do you call it? By the way, I suggest you make your code less C-ish and more C++-ish, it will get much more cleaner and more readable.

medampudi
13th September 2010, 16:53
Thank you for the suggestion and i have tried to change a lot of things in my code. i would also be adding the codes and the errors...

the cpp file...


#include "epucksercomm.h"


epuckSercomm::epuckSercomm()
{

}
int epuckSercomm::initRobots(struct robot *rbt)
{
int id;
for(id=0;id<7;id++)
{
rbt[id].serialConnection=id;
rbt[id].port=-1;
rbt[id].connected=0;
}
return 0;
}
int epuckSercomm::connectRobot(struct robot *rbt, int comPort)
{



char portname[20];
//sprintf(portname,"COM%d",comPort);
sprintf(portname,"\\\\.\\COM%d",comPort);
hSerialPort[rbt->serialConnection] = CreateFileA(portname,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hSerialPort[rbt->serialConnection] == INVALID_HANDLE_VALUE) return -1;



dcbSerialParams.dcb.DCBlength=sizeof(dcbSerialPara ms);
if (!GetCommState(hSerialPort[rbt->serialConnection], &dcbSerialParams.dcb)) return -2;

dcbSerialParams.dcb.BaudRate = 115200;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;

comt.ReadIntervalTimeout = 500;
SetCommTimeouts( hSerialPort[rbt->serialConnection], &comt);
if (!SetCommState(hSerialPort[rbt->serialConnection], &dcbSerialParams.dcb)) return -3;

rbt->port=comPort;
rbt->connected=1;



return 0;
}


int epuckSercomm::setRobotSpeed(struct robot *rbt, int speedL, int speedR)
{



DWORD dwBytesReadWrite = 0;
char command[5];

command[0]='D';
command[1]=speedL & 0xff;
command[2]=speedL >> 8;
command[3]=speedR & 0xff;
command[4]=speedR >>8;

if (!WriteFile(hSerialPort[rbt->serialConnection],command,5,&dwBytesReadWrite,NULL)) return -1;



return 0;


}
int epuckSercomm::disconnectRobot(struct robot *rbt)
{

CloseHandle(hSerialPort[rbt->serialConnection]);
rbt->connected=0;


return 0;
}
int epuckSercomm::printRobotSensors(struct robot *rbt)
{
printf("Robot no:%d\r\n",rbt->serialConnection);

printf("IR: %d %d %d %d %d %d %d %d\r\n",
rbt->IR[0],rbt->IR[1],rbt->IR[2],rbt->IR[3],
rbt->IR[4],rbt->IR[5],rbt->IR[6],rbt->IR[7]);

printf("LI: %d %d %d %d %d %d %d %d\r\n",
rbt->LI[0],rbt->LI[1],rbt->LI[2],rbt->LI[3],
rbt->LI[4],rbt->LI[5],rbt->LI[6],rbt->LI[7]);

printf("FL: %d %d %d\r\n",
rbt->FL[0],rbt->FL[1],rbt->FL[2]);

printf("MC: %d %d %d\r\n",
rbt->MC[0],rbt->MC[1],rbt->MC[2]);

return 0;

}
int epuckSercomm::setRobotLed(struct robot *rbt,int noLed, int value)
{


DWORD dwBytesReadWrite = 0;
char command[3];
if (value<0)value=0; //on
if (value>1)value=1; //off

command[0]='L';
command[1]= noLed; //number of led to switch
command[2]= value; //0: off, 1: on

if (!WriteFile(hSerialPort[rbt->serialConnection],command,3,&dwBytesReadWrite,NULL))
return -1;


return 0;


}





.h FILE


#ifndef EPUCKSERCOMM_H
#define EPUCKSERCOMM_H

#include <QObject>
#include <stdio.h>
#include "mode.h"
#include "windows.h"
#include "time.h"
#include "defs.h"

class epuckSercomm : public QObject
{
public:
epuckSercomm();
int setRobotLed(struct robot *rbt,int noLed, int value);
int printRobotSensors(struct robot *rbt);
int disconnectRobot(struct robot *rbt);
int setRobotSpeed(struct robot *rbt, int speedL, int speedR);
int connectRobot(struct robot *rbt, int comPort);
int initRobots(struct robot *rbt);

//struct robot robots[7];
HANDLE hSerialPort[7]; //up to 7 connection
COMMCONFIG dcbSerialParams;
COMMTIMEOUTS comt;
// fine
//stat
clock_t startTime;
clock_t endTime;

int dtime;
};


#endif // EPUCKSERCOMM_H



and the initialization...

in the main UI program is




epuckSercomm *epuck = new epuckSercomm();
epuck->initRobots(&robots[0]);
epuck->connectRobot(&robots[1], 1036);
epuck->setRobotLed(&robots[1],7,1);
epuck->setRobotLed(&robots[1],7,0);





i am getting the following as my output error...i think it is something really that i am missing out... could you please point it out...
5183

wysota
13th September 2010, 18:16
Ouch... first of all please preview your posts before you send them. Second of all don't inline large amount of code directly in your posts. Use attachments instead.

Your error is probably caused by the same file being referenced twice in the project file (or wrong files being there in the first place).

And really... your code is hardly readable because of all those pointers and dereferencing, why don't you clean it up a bit?


class RobotController {
public:
RobotController(int rbtCnt = 7) {
for(int i=0; i<rbtCnt; i++) {
robot r;
r.serialConnection = i;
r.port = -1;
r.connected = false;
m_robots.append(r);
}
}

bool connectRobot(int index, int port) {
if(index<0 || index>=m_robots.count()) return;
QString portName = QString("//./COM%1").arg(port);
// seems that you can use QFile and QFileSystemWatcher or QSocketNotifier here but ok...
m_handles[index] = CreateFileA(portName.toAscii().constData(), ...);
if(!m_handles[index]) {
m_handles.remove(index);
return false;
}
//...
m_robots[index].port = port;
m_robots[index].connected = true; // this is not needed, robot is connected if there is a handle for it or port != -1
return true;
}

void disconnectRobot(int index) {
if(!m_robots.contains(index)) return; // not connected
CloseFile(m_handles.value(index));
m_handles.remove(index);
m_robots[index].port = -1;
m_robots[index].connected = false; // again, not needed
}
private:
QList<robot> m_robots; // clean up "robot" class too
QMap<int, HANDLE> m_handles;
};

and so on...

medampudi
14th September 2010, 18:04
IT is true that many of the Classes in the robots and the other things needs cleaning up but they are the ones needed in my project for robot control... any how... the point is even after making all the changes you have suggested i am still getting the same error at the line 17 of the code shown above.. the HANDLE gives out a error always and leads to improper shutting down of the whole program.. While debugging it I have come across that the HANDLE returns a INVALID_HANDLE_VALUE always leading the program to shutdown improperly... is there any way i could use something for the CreateFileA instead and get the HANDLE working....

Rajesh...

wysota
14th September 2010, 18:32
The handle is not the problem. The problem is you are indexing the array improperly. Please provide a backtrace/callstack after the crash and we'll see what is going on.

medampudi
14th September 2010, 19:52
I am really thankful to you MR Wysota... I think both our codes work.. it was just a problem of referencing of my bluetooth port number... the number 1036 i gave a couple of posts ago was the pass code kind of number for the robot which i was passing in vain ..... I am really sorry about this grave but silly blunder... It was actually connected to COM5 so i changed the number to 5 and it works perfectly...

thank you for bearing up with me..

I am really sorry once again...

Rajesh Medampudi.......

wysota
14th September 2010, 19:54
No problem. Just please make your code less C-ish and more object oriented ;)

medampudi
14th September 2010, 21:14
I thought the post 9 had more c++ in it than the previous post :cool:... dont you think it is good... I definitely agree that my code base was just c- ish and changes need to be made to a complete c++ kind .... i will transition my code to c++ from now on... i really like it... And my platform base would be QT for it...

thank you once again...

wysota
14th September 2010, 21:28
I thought the post 9 had more c++ in it than the previous post :cool:
Not at all. Wrapping a set of C functions into a class doesn't make the code object oriented.


... dont you think it is good...
Not really. First of all you are exposing pointers to the outside world which is not necessary. Moreover you are also receiving pointers into your own code and operating on them - instead of using external structs you should make those structures proper classes and move all those methods to the class itself.

For example:


class Robot {
public:
Robot() { /* initialization Code goes here */ }
bool connect(int port) { /* epuckSercomm::connectRobot() functionality goes here */ }
bool disconnect() { /* epuckSercomm::disconnectRobot() functionality goes here */ }
void printSensors() { ... }
void setSpeed(int left, int right) { ... }
private:
// ... member variables related to the robot go here
};
and so on. Then each robot operates on itself:

Robot robot(...);
robot.connect(5);
If you want to manage all robots from a single place then write a RobotManager class (similar to what I wrote a few posts ago). If you have to use pointers for the Robot (which makes some sense here as robots are individuals) then go ahead:

Robot *robot = new Robot(...);
robot->connect(5);

Finally, don't expose your internal variables to the outside world. If you need to access them, add proper methods for your class to get and set their values. There you can sanitize the values passed so that you are sure nothing will break your object too easily (i.e. you could verify that 'port' value passed to Robot::connect() is not negative).