Reading serial port when data available, not getting data

Is there something conceptually wrong with this piece of code. I seem to be able to parse the start character and the sensor ID but I get no data bytes. x is all zeroes.

Thanks
Chris

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int Biscuit::biscStreamRead() {
unsigned char Sensor_byte_count = 0;
unsigned char Sensor_Data_Byte = 0;
unsigned char Sensor_ID = 0;
unsigned char Sensor_Num_Bytes = 0;
unsigned char Sensor_Checksum = 0;

if (select(deviceDescriptor + 1, &read_fds, &write_fds, &except_fds, &timeout) == 1) {
                unsigned char start_character;
                biscReceiveByte(start_character);
                if (start_character == 19) { //Sensor_byte_count++;
                   biscReceiveByte(Sensor_Num_Bytes);
                   biscReceiveByte(Sensor_ID);
                   biscReceiveByte(Sensor_Data_Byte);
                   biscReceiveByte(Sensor_Checksum);
                   std::cout << "Got start byte " << std::endl;
                }       
                unsigned char bumpbyte=Sensor_Data_Byte;
                
                if (Sensor_ID == 9) {
                      std::cout << "Cliff Stream Data received" << std::endl;
                      if (isNthBitSet(bumpbyte, 0))
                          std::cout << "BUMP STREAM" << std::endl;  
                                       
                }            
                std::bitset<8> x(Sensor_Data_Byte);
                std::cout << "Data " << x << endl;
                return BISC_SUCCESS;
                
} else {
                usleep(1);
        //cout << "Timeout error" << endl;
       return BISC_ERR;
  }
}


And this is how I connect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int Biscuit::biscConnect(char const *device) {
    if(device == NULL) return BISC_ERR;

    struct termios tty;

    // Try to open the device
    if((deviceDescriptor = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1) {
        return BISC_ERR;
    }

    tcgetattr(deviceDescriptor, &tty);
    tty.c_iflag     = IGNBRK | IGNPAR;
    tty.c_lflag     = 0;
    tty.c_oflag     = 0;
    tty.c_cflag     = CREAD | CS8 | CLOCAL;
    cfsetispeed(&tty, BISC_BAUD_RATE);
    cfsetospeed(&tty, BISC_BAUD_RATE);
    tcsetattr(deviceDescriptor, TCSANOW, &tty);
    
    // Initialize file descriptor sets
    
    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    FD_ZERO(&except_fds);
    FD_SET(deviceDescriptor, &read_fds);
    
    
    
    // Set timeout to 20 microseconds for serialport stream reading
    timeout.tv_sec = 0;
    timeout.tv_usec = 20;
    
    return deviceDescriptor;
}
Last edited on
Is it Arduino Programming?
You may want to ask this question in Arduino forum. This forum is for general C++ problems only.
Last edited on
First, are you absolutely sure that your payload signal isn't constantly low?
What are the contents of biscRecieveByte?
Here is the additional code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int Biscuit::biscReceiveByte(unsigned char  &byte) {
    std::lock_guard<std::recursive_mutex> lock(s_mutex);
    usleep(10000);
    return (read(deviceDescriptor, &byte, 1) == 1 ? BISC_SUCCESS : BISC_ERR);
}

int Biscuit::biscReceiveByte(signed char  &byte) {
    std::lock_guard<std::recursive_mutex> lock(s_mutex);
    usleep(10000);
    return (read(deviceDescriptor, &byte, 1) == 1 ? BISC_SUCCESS : BISC_ERR);
}

  int isNthBitSet (unsigned char c, int n) {
    static unsigned char mask[] = {1, 2, 4, 8, 16, 32, 64, 128};
    // c =  00000010 n= 1 ( rightmost bit is n=0, leftmost is n=7), result is 1
    return ((c & mask[n]) != 0);
}


Here is the link to the Irobot Create's Open Interface serial protocol.

http://www.irobot.com/filelibrary/create/Create%20Open%20Interface_v2.pdf

On Page 14:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
14
iRobot Create Open Inter face (OI) Specification
Stream 
Opcode: 148  
Data Bytes: N + 1,
where N is the number 
of packets requested.
This command starts a continuous stream of data packets.  
The list of packets requested is sent ever y 15 ms, which is 
the rate iRobot Create uses to update data.
This  is  the  best  method  of  requesting  sensor  data  if  you 
are controlling Create over a wireless network (which has 
poor  real-time  characteristics)  with  software  running  on  a 
desktop computer. 
•   Serial sequence:  [148] [Number of packets] 
[Packet ID 1] [Packet ID 2] [Packet ID 3] etc.
• Available in modes: Passive, Safe, or Full
• Changes mode to: No Change
•   Stream data byte 1: Number of packets requested 
(0 - 43)
•   Stream data bytes 2 - N: IDs of packets requested 
(0 - 42)
The format of the data returned is:
[19][N-bytes][Packet ID 1][Packet 1 data...]
[Packet ID 2][Packet 2 data...][Checksum]
N-bytes is the number of bytes between the n-bytes byte and 
the checksum.
The checksum is a 1-byte value. It is the 8-bit complement 
of all of the bytes between the header and the checksum.  
That is, if you add all of the bytes after the checksum, and 
the checksum, the low byte of the result will be 0.

Example:
To  get  data  from  Create’s  left  cliff  signal  (packet  29) 
and  Virtual  Wall  detector  (packet  13),  send  the  following 
command string to Create:
[148] [2] [29] [13]
NOTE: The left cliff signal is a 2-byte packet and the IR 
Sensor is a 1-byte packet.
Create starts streaming data that looks like this:

header  -> n-bytes -> packet ID 1 -> Packet data 1 -> packet id 2 -> Packet data 2 -> checksum
   19     ->    5        -> 29              -> 2 (bytes) 25  -> 13              -> 0                   -> 182

Checksum computation:
(5 + 29 +2 + 25 +13 + 0 + 182) = 182 and (256 & 0xFF) =0



I have not worked out the checksum computation yet. I am still a bit confused about that. In my particular code example, I am only streaming one packet which returns one byte in order to simplify things. I am sending BISC_SENSOR_CLIFF_LEFT (packet ID 9).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define BISC_SENSOR                           142
#define BISC_SENSOR_STREAM                    148 
#define BISC_SENSOR_STREAM_TOGGLE             150
#define BISC_SENSOR_STREAM_STOP               1
#define BISC_SENSOR_STREAM_START              0 

#define BISC_SENSOR_CLIFF_LEFT                9

int Biscuit::biscStreamStart(){
    std::lock_guard<std::recursive_mutex> lock(s_mutex);
    
    if(!biscSendByte(BISC_SENSOR_STREAM)) return BISC_ERR;
    unsigned char num_packets=1;
    if(!biscSendByte(num_packets)) return BISC_ERR;
    if(!biscSendByte(BISC_SENSOR_CLIFF_LEFT)) return BISC_ERR;
    return BISC_SUCCESS;

}


Requesting a single packet works with :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int Biscuit::biscCliff(int cliff) {
    std::lock_guard<std::recursive_mutex> lock(s_mutex);
    
    unsigned char cliffbyte;
    if(!biscSendByte(BISC_SENSOR)) return BISC_ERR;
    switch (cliff) {
        case 1 :
            if(!biscSendByte(BISC_SENSOR_CLIFF_LEFT)) return BISC_ERR;
            if(!biscReceiveByte(cliffbyte)) return BISC_ERR;
            if (isNthBitSet(cliffbyte, 0))
                return 1;
        case 2: 
            if(!biscSendByte(BISC_SENSOR_CLIFF_FRONT_LEFT)) return BISC_ERR;
            if(!biscReceiveByte(cliffbyte)) return BISC_ERR;
            if (isNthBitSet(cliffbyte, 0))
                return 2;
        case 3:
            if(!biscSendByte(BISC_SENSOR_CLIFF_RIGHT)) return BISC_ERR;
            if(!biscReceiveByte(cliffbyte)) return BISC_ERR;
            if (isNthBitSet(cliffbyte, 0))
                return 3;
        case 4:
            if(!biscSendByte(BISC_SENSOR_CLIFF_FRONT_RIGHT)) return BISC_ERR;
            if(!biscReceiveByte(cliffbyte)) return BISC_ERR;
            if (isNthBitSet(cliffbyte, 0))
                return 4;
        
    }
    
    return BISC_ERR;
}


So I am trying to get the streaming sensor way working. I tried the bump sensor first then switched to the cliff sensor as it was easier to pick up the robot than to kick the bumper repeatedly.

As a side effect to the start of the streaming process, single packet requests of sensor data returns corrupted values. I have to restart the program and the irobot create in order to restore the integrity of the serial read.

This is my output :

1
2
3
4
5
6
7
8
9
10
11
Cliff Stream Data received
Data 00000000
Got start byte 
Cliff Stream Data received
Data 00000000
Got start byte 
Cliff Stream Data received
Data 00000000
Got start byte 
Cliff Stream Data received



This is the code that starts, reads, and pauses the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (tokens[0] == "cstream") {
                std::cout << "Received command : Create Sensor Stream "  <<  std::endl;
                cout << "Press q to quit " << endl;
                if (!robot.biscStreamStart())
                  std::cout << "failed to stream " << std::endl;
                
                for (;;) {
                    if (waitKey(1) == 'q')
                        break;
                    usleep(1000000);
                    robot.biscStreamRead();
                }
                robot.biscStreamPause();
              }


Thanks

Chris
Can you let us know the real robot you are making? Show us a picture.

Here are the images:

https://postimg.org/image/7j9f25as1/

https://postimg.org/image/vyhn379ox/

I'm still looking around for a case that is cylindrical and smaller than the size of the base.

Chris
Topic archived. No new replies allowed.