difference in objIds
« on: February 11, 2018, 10:23:15 pm »
Hi,

I am using a rpi3 to communicate with the CC3D FC, when i request an objectID from the controller, i seem to recieve a different id back, not matching the id i sent. I originally thought this may have been the controller using an old version of the firmware, however i have updated my controller to next and my object ids being generated via the arduino headers in the project on the next branch.

Any suggestion to why this may have happened?

i did notice when i tried to update the firmware on the board it said i had to manually do it as it wasn't responding, i tried again and it did the same but when i plug it in, it says the most up to date bootloader 4 and 16.09 firmware.

below is my code for the request and receive of the objects,

Code: [Select]
void request(unsigned long objId) {
        wiringSetup();
_pBuf[0] = 0x3c; //sync
  _pBuf[1] = 0x21; //msgtype (0x21 = request)
  _pBuf[2] = 0x0a; //len
  _pBuf[3] = 0x00; //len
  _pBuf[4] = (objId >> (8*0)) & 0xff;
  _pBuf[5] = (objId >> (8*1)) & 0xff;
  _pBuf[6] = (objId >> (8*2)) & 0xff;
  _pBuf[7] = (objId >> (8*3)) & 0xff;
  _pBuf[8] = 0x00; //iid
  _pBuf[9] = 0x00; //iid
  _pBuf[10] = _crc(10); //crc
  printf("i am about to send the data \n");
  serialPuts (fd, reinterpret_cast<const char*>(_pBuf));
}

And the code for receiving the message

Code: [Select]
bool receive(){
        wiringSetup();
       
        byte objId = FLIGHTSTATUS_OBJID;
        byte *ret = FlightStatusDataUnion.arr;
        bool loop = 1;
        unsigned long time = millis();
 
  while(loop) {
    if (serialDataAvail(fd)) {
               
        unsigned int timeout=2000;
        loop = millis() <= time + timeout;  //loop as long as start + timeout lower than current time
   
      _pBuf[0] = serialGetchar(fd);;
      if (_pBuf[0] == 0){
        //NOOP
      } else if(_pBuf[0] != 0x3c) {
        //Serial.print(sync, HEX);
        //printf(" Bad Byte ");
      } else {
        printf(" in the main loop \n");       
        _pBuf[1] = serialGetchar(fd); //msgtype
        printf("sync value = %X \n",_pBuf[0]);
        _pBuf[2] = serialGetchar(fd);
                 printf("msg type = %X \n",_pBuf[1]);
                  printf("length = %X",_pBuf[2]);
        _pBuf[3] = serialGetchar(fd);
         printf("%X \n",_pBuf[3]);
        unsigned int len = (unsigned int) _pBuf[2] | (unsigned int) _pBuf[3] << 8;
       
        if(len < 10 || len > 265) {
         
        } else {
            printf("\n");
            unsigned long oid0 = serialGetchar(fd);
            _pBuf[4] = oid0;
            printf("%X \n",_pBuf[4]);
            unsigned long oid1 = serialGetchar(fd);
            _pBuf[5] = oid1;
            printf("%X \n",_pBuf[5]);
            unsigned long oid2 = serialGetchar(fd);
            _pBuf[6] = oid2;
            printf("%X \n",_pBuf[6]);
            unsigned long oid3 = serialGetchar(fd);
            _pBuf[7] = oid3;
            printf("%X \n",_pBuf[7]);
            unsigned long oid_n = oid0 + oid1 + oid2 + oid3;
            unsigned long oid = oid0 + oid1 * 256 + oid2 * 65536 + oid3 * 16777216;
                    printf("\n\n");
                    printf("%lu", oid);
                    printf("\n");
                    printf("%lu", oid_n);
                    printf("\n just before objID");
          if(oid != objId) {
                          printf("values aint equal");
          } else {
            loop = 0;
               
            int iid0 = serialGetchar(fd);
            _pBuf[8] = iid0;
            int iid1 = serialGetchar(fd);
            _pBuf[9] = iid1;
                       
   
            unsigned int iid = iid0 + iid1 * 256;             
   
            int datalen = len - 10;;
 
             int j;         
             for (j = 10; j < len; j++) {
               _pBuf[j] = serialGetchar(fd);
               ret[j-10] = _pBuf[j];
                          // printf("putting values in the union struct");
             }
   
                        for(int i=0;i<sizeof(ret);i++){
                        printf("%X",ret[i]);
                        }
       
            byte crc = serialGetchar(fd);

            byte ccrc = _crc(len);
                         
            return crc == ccrc;   
          }       
        }   
      }   
    } else {
      loop = 0;
    }
  }
  return false;
}

I've basically copied the same thing the guy on Extend Arduino did. Any suggestion as to why my objIds may be different? Or am i missing something?

Any help much appreciated!

Jonny
« Last Edit: February 11, 2018, 10:37:17 pm by jmyth742 »

Re: difference in objIds
« Reply #1 on: February 11, 2018, 10:39:39 pm »
The first thing that comes to mind is that after changing an XML file (UAVO) at all you must recompile everything and that includes FC firmware, GCS, and your separate programs including those language specific programs that create the header files...

Re: difference in objIds
« Reply #2 on: February 11, 2018, 10:57:40 pm »
ok, so then how does me requesting telemetry data from the main port work?

I have tried to follow the code set up found at https://github.com/MarcProe/LibrePilot.arduino which they talk about in one of LibrePilot confluence pages!

f5soh

  • *****
  • 4572
    • LibrePilot
Re: difference in objIds
« Reply #3 on: February 11, 2018, 11:27:07 pm »
You may need to do at least, using the same GCS version used on board:
Code: [Select]
make all_clean
make uavobjects
New header files can be found in /build/uavobject-synthetics/arduino

Edit: You talk about a 16.09 version on board and arduino support was introduced later.
Latest next already compiled can be found here so you can flash the board from another computer.
Matching arduino header files are attached to post. (16.09+r589)
« Last Edit: February 11, 2018, 11:35:11 pm by f5soh »

Re: difference in objIds
« Reply #4 on: February 14, 2018, 08:59:32 pm »
Hi there,

so i have double checked the firmware build on the CC3D, which is at next, so is the corresponding header files i am using in my request. However, the objectIds are still different. Am i doing something silly here or? any other suggestions, greatly appreciated.

Re: difference in objIds
« Reply #5 on: February 14, 2018, 09:11:38 pm »
All files must be built from the ground up from the exact same xml files.  You can't even change comments or CR/LF line endings in an xml file.  The OBJID is the md5sum (or similar, I forget) of the xml file.

So the C language parser generates C language header files with something like a
#define XYZOBJID 0x12345678
where the 0x12345678 comes from the md5sum of the xml file.

First, make sure that all the XML files match if you build things in several different places.  Then rebuild all the individual language parsers, those are the programs that create the .h files for C, where the ObjIds are defined for instance.  Then rebuild all the programs and firmwares and flash the firmware.  That includes FC firmware, GCS, and your "other language" programs too.  And all libraries that depend on the headers.
« Last Edit: February 14, 2018, 09:17:27 pm by TheOtherCliff »

filnet

  • *****
  • 113
Re: difference in objIds
« Reply #6 on: February 15, 2018, 09:54:47 pm »
To complement Cliff's answer, here the code that produces the ID from the xml definition file.

Code: [Select]
void UAVObjectParser::calculateID(ObjectInfo *info)
{
    // Hash object name
    quint32 hash = updateHash(info->name, 0);

    // Hash object attributes
    hash = updateHash(info->isSettings, hash);
    hash = updateHash(info->isSingleInst, hash);
    // Hash field information
    for (int n = 0; n < info->fields.length(); ++n) {
        hash = updateHash(info->fields[n]->name, hash);
        hash = updateHash(info->fields[n]->numElements, hash);
        hash = updateHash(info->fields[n]->type, hash);
        if (info->fields[n]->type == FIELDTYPE_ENUM) {
            QStringList options = info->fields[n]->options;
            for (int m = 0; m < options.length(); m++) {
                hash = updateHash(options[m], hash);
            }
        }
    }
    // Done
    info->id = hash & 0xFFFFFFFE;
}

So it takes into account most if not all object attributes (name, etc...) and the ID should not be impacted by formatting and such things.

But Cliff is right that it is imperative to use the same versions and have matching IDs.

Re: difference in objIds
« Reply #7 on: February 20, 2018, 09:28:19 pm »
I tried the above and the wrong ids seem to be coming through, when i request the FLIGHTSTATUSID, for example, it never appears to be the same id which is returned twice. Maybe i have done some formatting wrong or i am handling some bytes wrong etc.

I will have to do more digging.

f5soh

  • *****
  • 4572
    • LibrePilot
Re: difference in objIds
« Reply #8 on: February 20, 2018, 09:36:36 pm »
Please post the Id error you have.

Re: difference in objIds
« Reply #9 on: February 21, 2018, 08:52:53 pm »
for instance,

i request FLIGHTSTATUSID, which equates to 2824D25E

then i receive 6737BB5A from the the byte steam. repeat the same test, and receive 5146807C, next C409985A

It just continues like that. Any ideas on what is going on?

f5soh

  • *****
  • 4572
    • LibrePilot
Re: difference in objIds
« Reply #10 on: February 21, 2018, 09:19:18 pm »
Quote
i request FLIGHTSTATUSID, which equates to 2824D25E
Should be 0x24D25E28 ?
#define FLIGHTSTATUS_OBJID 0x24D25E28
#define FLIGHTTELEMETRYSTATS_OBJID 0x6737BB5A
#define STABILIZATIONDESIRED_OBJID 0x5146807C
#define ACCESSORYDESIRED_OBJID 0xC409985A

Most "Data" UAVOs are send periodically so you will receive data, even if you request nothing.
"Settings" UAVOs need a request.

Re: difference in objIds
« Reply #11 on: March 11, 2018, 11:00:45 pm »
**SOLVED**

The problem was using the wiringPi library.

It wraps the c function 'write' into a putsChar function which uses strlen() to get the length of the data being sent.
This was causing any bytes which where 0x00 to be classified as end of string. Thus my objId wasn't fully being transmitted to the flight controller.

Cheers to everyone who has helped and commented. Muchly appreciated.