pozyxLabs/Pozyx-Arduino-library

api documentation/bugs/stuck

ivannunyadambiz opened this issue · 9 comments

hi there!

although i have the arduino library and the comments in the source code, there's much amiss.

This, for example doesn't work. I guess I should see a list of devices visible? However with the documentation I have, I really cannot find out why.

#include <Pozyx.h>
#include <Pozyx_definitions.h>
#include <Wire.h>

uint8_t num_anchors = 4;                                    // the number of anchors
uint16_t anchors[4] = {0x6018, 0x601f, 0x6048, 0x603e};     // the network id of the anchors: change these to the network ids of your anchors.
int32_t heights[4];// = {2500, 2120, 1260, 1760};              // anchor z-coordinates in mm

void setup()
{
  int status;
  uint8_t listsize;

  Serial.begin(115200);

  if(Pozyx.begin(true) == POZYX_FAILURE)
  {
    Serial.println(F("ERROR: Unable to connect to POZYX shield"));
    Serial.println(F("Reset required"));
    delay(100);
    abort();
  }

  Serial.println(F("\n----------POZYX DIAGNOSTICS----------"));

  Pozyx.clearDevices();

  /*status = Pozyx.doAnchorCalibration(POZYX_2_5D, 10, num_anchors, anchors, heights);
  if(status != POZYX_SUCCESS)
  {
    //Serial.println(status);
    Serial.println(F("ERROR: doAnchorCalibration"));
    Serial.println(Pozyx.getSystemError());
    delay(100);
    abort();
  }
  else
  {
    Serial.println(F("DONE: doAnchorCalibration"));
  }
*/
  status = Pozyx.doDiscovery(POZYX_DISCOVERY_ALL_DEVICES, 5, 10);
  if(status != POZYX_SUCCESS)
  {
    Serial.println(status);
    Serial.println(F("ERROR: doDiscovery"));
    Serial.println(Pozyx.getSystemError());
    delay(100);
    abort();
  }
  else
  {
    Serial.println(F("DONE: doDiscovery"));
  }

  status = Pozyx.getDeviceListSize(&listsize);
  if(status != POZYX_SUCCESS)
  {
    Serial.println(F("ERROR: getDeviceListSize"));
    Serial.println(Pozyx.getSystemError());
    delay(100);
    abort();
  }
  else
  {
    Serial.println(F("DONE: getDeviceListSize"));

    Serial.print("listsize: ");
    Serial.println(listsize);
  }

  // none of these three actually work
  //status = Pozyx.getTagIds(anchors);
  //status = Pozyx.getAnchorIds(anchors);
  status = Pozyx.getDeviceIds(anchors);
  if(status != POZYX_SUCCESS)
  {
    Serial.println(F("ERROR: getDeviceIds"));
    Serial.println(Pozyx.getSystemError());
    delay(100);
    abort();
  }
  else
  {
    Serial.println(F("DONE: getDeviceIds"));

    for(int i = 0; i < listsize; i++)
    {
      Serial.println(anchors[i], HEX);
    }
  }
}

void loop()
{

}

All I get is:

Pozyx Shield

WhoAmI: 0x43
SW ver.: 1
HW ver.: 35
selftest: 0b111111

----------POZYX DIAGNOSTICS----------
DONE: doDiscovery
DONE: getDeviceListSize
listsize: 5
ERROR: getDeviceIds

Sometimes it's even only:

Pozyx Shield

WhoAmI: 0x43
SW ver.: 1
HW ver.: 35
selftest: 0b111111

----------POZYX DIAGNOSTICS----------
8
ERROR: doDiscovery

static int getDeviceIds(uint16_t devices[], int size = MAX_ANCHORS_IN_LIST, uint16_t remote_id = NULL);
the problem lies here:
if int size > 15, getDeviceIds fails hard.

this doesn't resolve the doDiscovery error, though, so I'll leave this opened.

Hello,
I am not sure if this issue is solved as a result of solving the other issues you posted.
Concerning the failing if size > 15; this is probably due to the Arduino model, where the I2C buffer is limited to 32bytes for the Arduino Uno. 15 device ids is already 30 bytes plus the overhead bytes are probably causing this error. I will verify later if this issue remains when using the Arduino Mega which has a larger buffer.

I might add that I use pozyx only on an arduino mega 2560

On the Arduino Uno, I can confirm that the problem is related due to the I2C buffer size which is too small. Enlarging the buffer size on the Arduino fixes the problem.

To remedy this, the easiest (and perhaps only?) way is to change the Arduino library:

  1. In wire.h change BUFFER_LENGTH to a larger value
  2. In twi.h change TWI_BUFFER_LENGTH to a larger value
    These files are located under (../Arduino/hardware/arduino/avr/libraries/Wire/)

On the Arduino Mega, you can verify if the buffer is too small by printing out the value of BUFFER_LENGTH as follows:
Serial.println(BUFFER_LENGTH);

On a side-note: changing the libraries of the Arduino is not something I would recommend as good practice. However, currently, it's the only way. But, if you are 'tweaking' the I2C library of the Arduino anyways, you may immediately increase the i2c speed. I have verified with the logic analyzer that changing
#define TWI_FREQ 200000L
to
#define TWI_FREQ 800000L
increases the speed x3: from 2bytes/100µs to 6bytes/100µs

Seems like you're right with the buffer size. I get 32 for the Mega.

but fixing it by editing the arduino lib is not a real fix. this should be handled by the pozyx lib, essentially if needed splitting it into two or more chunks.

Hi,
I completely agree with you, however, fixing this without changing the library is not possible.
The Arduino library only offers a few functions for the i2c communication. The actual i2c communication is implemented in twi.h and twi.c using interrupts (wire.c/.h is a bit the wrapper for this). However, there is no function to simply read from the i2c. The only functions available are:

  void twi_init(void);
  void twi_setAddress(uint8_t);
  uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
  uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
  uint8_t twi_transmit(const uint8_t*, uint8_t);
  void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
  void twi_attachSlaveTxEvent( void (*)(void) );
  void twi_reply(uint8_t);
  void twi_stop(void);
  void twi_releaseBus(void);

The only Arduino function available for reading bytes as a i2c Master is twi_readFrom, which also sends address information and start/nack signals. Because of this, splitting the communication with this function will not work: sending a new address and start signal will disrupt reading the bytes in one go.
In other words, we must either fix the Arduino library, or write a new independent i2c library.

good point...
however, as an intermediate fix try this:
assert(((BUFFER_LENGTH > 32) && (size <= 20)) || (size <= 15));
duckandrun

Thanks, I have included your fix.
Notice, btw that regRead() and regWrite() already handles this i2c buffer issue as it splits up the read/write in several smaller calls. For these functions this is possible because data registers can be accessed separately.