Redboard Artemis ATP

Hello Everyone,

I’ve recently purchased the Sparkfun Artemis ATP (DEV-15442) along with the LIDAR Lite v3HP (SEN-14599).

Upon compiling, I get the following error log:

C:\Users\Me\Documents\Arduino\libraries\LIDARLite_Arduino_Library\src\LIDARLite_v4LED.cpp: In member function 'void LIDARLite_v4LED::read(uint8_t, uint8_t*, uint8_t, uint8_t)':
C:\Users\Me\Documents\Arduino\libraries\LIDARLite_Arduino_Library\src\LIDARLite_v4LED.cpp:374:5: error: no matching function for call to 'TwoWire::requestFrom(uint8_t&, uint8_t&, uint8_t&, int, bool)'
     );
     ^
In file included from C:\Users\Me\Documents\Arduino\libraries\LIDARLite_Arduino_Library\src\LIDARLite_v4LED.cpp:27:
C:\Users\Me\AppData\Local\Arduino15\packages\SparkFun\hardware\apollo3\1.2.1\libraries\Wire\src/Wire.h:51:11: note: candidate: 'uint8_t TwoWire::requestFrom(uint8_t, size_t, bool)'
   uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit = true);
           ^~~~~~~~~~~
C:\Users\Me\AppData\Local\Arduino15\packages\SparkFun\hardware\apollo3\1.2.1\libraries\Wire\src/Wire.h:51:11: note:   candidate expects 3 arguments, 5 provided
C:\Users\Me\Documents\Arduino\libraries\LIDARLite_Arduino_Library\src\LIDARLite_v3HP.cpp: In member function 'void LIDARLite_v3HP::read(uint8_t, uint8_t*, uint8_t, uint8_t)':
C:\Users\Me\Documents\Arduino\libraries\LIDARLite_Arduino_Library\src\LIDARLite_v3HP.cpp:400:5: error: no matching function for call to 'TwoWire::requestFrom(uint8_t&, uint8_t&, uint8_t&, int, bool)'
     );
     ^
In file included from C:\Users\Me\Documents\Arduino\libraries\LIDARLite_Arduino_Library\src\LIDARLite_v3HP.cpp:27:
C:\Users\Me\AppData\Local\Arduino15\packages\SparkFun\hardware\apollo3\1.2.1\libraries\Wire\src/Wire.h:51:11: note: candidate: 'uint8_t TwoWire::requestFrom(uint8_t, size_t, bool)'
   uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit = true);
           ^~~~~~~~~~~
C:\Users\Me\AppData\Local\Arduino15\packages\SparkFun\hardware\apollo3\1.2.1\libraries\Wire\src/Wire.h:51:11: note:   candidate expects 3 arguments, 5 provided
exit status 1
Error compiling for board SparkFun RedBoard Artemis ATP.

Which boils down to the fact that the Sparkfun Artemis Wire library does not implement an overload function of requestFrom that accepts these inputs:

Excerpt from Arduino Wire.cpp

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
{
  if (isize > 0) {
  // send internal address; this mode allows sending a repeated start to access
  // some devices' internal registers. This function is executed by the hardware
  // TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers)

  beginTransmission(address);

  // the maximum size of internal address is 3 bytes
  if (isize > 3){
    isize = 3;
  }

  // write internal register address - most significant byte first
  while (isize-- > 0)
    write((uint8_t)(iaddress >> (isize*8)));
  endTransmission(false);
  }

  // clamp to buffer length
  if(quantity > BUFFER_LENGTH){
    quantity = BUFFER_LENGTH;
  }
  // perform blocking read into buffer
  uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
  // set rx buffer iterator vars
  rxBufferIndex = 0;
  rxBufferLength = read;

  return read;
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
	return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)sendStop);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}

uint8_t TwoWire::requestFrom(int address, int quantity)
{
  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}

uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
{
  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
}

Excerpt from Artemis Wire.cpp library:

uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
{
	if (quantity == 0)
	{
		return 0;
	}
	size_t byteRead = 0;
	_rxBuffer.clear();

	am_hal_iom_transfer_t iomTransfer = {0};
	iomTransfer.uPeerInfo.ui32I2CDevAddr = address;
	iomTransfer.ui32InstrLen = 0;		 // 8-bit transfers
	iomTransfer.ui32Instr = 0;			 // Offset;
	iomTransfer.ui32NumBytes = quantity; // How many bytes to receive
	iomTransfer.eDirection = AM_HAL_IOM_RX;
	iomTransfer.pui32TxBuffer = NULL;
	iomTransfer.pui32RxBuffer = (uint32_t *)_linearBugger; // Link in the RX buffer
	iomTransfer.bContinue = stopBit ? false : true;
	iomTransfer.ui8RepeatCount = 0;		// ?
	iomTransfer.ui8Priority = 1;		// ?
	iomTransfer.ui32PauseCondition = 0; // ?
	iomTransfer.ui32StatusSetClr = 0;   // ?

	uint32_t retVal32 = am_hal_iom_blocking_transfer(_handle, &iomTransfer);
	if (retVal32 != 0)
	{
		// Serial.println("got an error on requestFrom");
		return retVal32;
	}

	// Copy the bytes into the rx buffer
	for (byteRead = 0; byteRead < quantity; byteRead++)
	{
		_rxBuffer.store_char(_linearBugger[byteRead]); // Read data and send the ACK
	}

	return byteRead;
}

How can I edit the library/code to accommodate this incompatibility?

Thanks

Moath

The Artemis/Apollo3 core files install directory on Windows is C:\Users\YourUserName\AppData\Local\Arduino15\packages\SparkFun\hardware\apollo3

There’s a path to the library install in one your error messages.

You could also try rolling back to core v1.2.0 before getting too carried away.

Hello @stephenf,

I am not sure if I understood your reply, but I am actually looking for help on updating the code to suite the function call.

Regards,

Moath

This is an extended TwoWire call that actually that handles BOTH selecting the slave and register + read from the slave. Some platforms have this, some others do not.

Fastest way around is to change the read call to perform these functions separate yourself in LIDARLite_Arduino_Library the file LIDARLite_v3HP.cpp around line 384

void LIDARLite_v3HP::read(uint8_t regAddr,  uint8_t * dataBytes,
                          uint8_t numBytes, uint8_t lidarliteAddress)
{
    // This single function performs the following actions -
    //     1) I2C START
    //     2) I2C write to set the address
    //     3) I2C REPEATED START
    //     4) I2C read to fetch the required data
    //     5) I2C STOP
    
    Wire.beginTransmission(lidarliteAddress);

    // write internal register address - most significant byte first
    Wire.write(regAddr);
    Wire.endTransmission(false);

    Wire.requestFrom
    (
        lidarliteAddress, // Slave address
        numBytes,         // number of consecutive bytes to read
        true              // true = set STOP condition following I2C read
    );

    uint8_t  numHere = Wire.available();
    uint8_t  i       = 0;

    while (i < numHere)
    {
        dataBytes[i] = Wire.read();
        i++;
    }

    delayMicroseconds(100); // 100 us delay for robustness with successive reads and writes
} /* LIDARLite_v3HP::read */

I have not been able to test changed version however… but expect it to work…

I can see that you have just remove the extra register selector, I have actually already tested with:

void LIDARLite_v3HP::read(uint8_t regAddr,  uint8_t * dataBytes,
                          uint8_t numBytes, uint8_t lidarliteAddress)
{
    // This single function performs the following actions -
    //     1) I2C START
    //     2) I2C write to set the address
    //     3) I2C REPEATED START
    //     4) I2C read to fetch the required data
    //     5) I2C STOP
    Wire.requestFrom
    (
        lidarliteAddress, // Slave address
        39,//numBytes,         // number of consecutive bytes to read
       // regAddr,          // address of first register to read
       // 1,                // number of bytes in regAddr
        true              // true = set STOP condition following I2C read
    );

    uint8_t  numHere = Wire.available();
    uint8_t  i       = 0;
	
	uint8_t * dataBytes_tmp;
	
    while (i < numHere)
    {
        dataBytes_tmp[i] = Wire.read();
        i++;
    }
	
	uint8_t k=0;
	for (uint8_t j = regAddr; j< (regAddr+numBytes); j++) {
		dataBytes[k] = dataBytes_tmp[j];
		k++;
	}

    delayMicroseconds(100); // 100 us delay for robustness with successive reads and writes
} /* LIDARLite_v3HP::read */

You can see I am reading 39 bytes, because I’ve checked in the code and seen that the maximum read address is with the call:

read(0x26, dataBytes, 2, lidarliteAddress);

and then, I will only return the bytes that were requested.

The code compiled just fine, downloaded to the redboard, but then for some reason, the code just hangs while printing a debug message:

Serial Output:

08:31:06.251 -> =====================================
08:31:06.251 -> == Type a single character command ==
08:31:06.251 -> =====================================
08:31:06.251 ->  S - Single Measurement
08:31:06.251 ->  C - Continuous Measurement
08:31:06.251 ->  T - Timed Measurement
08:31:06.251 ->  . - Stop Measurement
08:31:06.251 ->  D - Dump Correlation Record
08:31:06.251 ->  P - Peak Stack Example
08:31:11.624 -> RANGE_SINGLE
08:31:11.624 -> dist

Code:

....
            case RANGE_SINGLE:
                Serial.println("RANGE_SINGLE");
                newDistance = distanceSingle(&distance);


....
....

uint8_t distanceSingle(uint16_t * distance)
{
    // 1. Wait for busyFlag to indicate device is idle. This must be
    //    done before triggering a range measurement.
    Serial.println("distanceSingle: waitForBusy");


    Serial.println("distanceSingle: waitForBusy");
    // 3. Wait for busyFlag to indicate device is idle. This should be
    //    done before reading the distance data that was triggered above.
    myLidarLite.waitForBusy();

    Serial.println("distanceSingle: readDistance");
    // 4. Read new distance data from device registers
    *distance = myLidarLite.readDistance();

    Serial.println("distanceSingle: ");
    return 1;
}

I am using the example code provided with the library, I have only added the debugging Serial.prints

https://github.com/garmin/LIDARLite_Ard … HP_I2C.ino

Hi,

please look again at my code, I have added selecting the slave and register BEFORE the changed requestFrom() call. Looks to me you have only changed requestFrom(). in that case you miss steps:

// 1) I2C START

// 2) I2C write to set the address + register

// 3) I2C REPEATED START

paulvha:
Hi,

please look again at my code, I had added also selecting the slave and register BEFORE the changed requestFrom() call. Looks to me you have only changed requestFrom(). in that case you miss steps:

// 1) I2C START

// 2) I2C write to set the address + register

// 3) I2C REPEATED START

DrNeo:
I can see that you have just remove the extra register selector, I have actually already tested with:

void LIDARLite_v3HP::read(uint8_t regAddr,  uint8_t * dataBytes,
                      uint8_t numBytes, uint8_t lidarliteAddress)

{
// This single function performs the following actions -
// 1) I2C START
// 2) I2C write to set the address
// 3) I2C REPEATED START
// 4) I2C read to fetch the required data
// 5) I2C STOP
Wire.requestFrom
(
lidarliteAddress, // Slave address
39,//numBytes, // number of consecutive bytes to read
// regAddr, // address of first register to read
// 1, // number of bytes in regAddr
true // true = set STOP condition following I2C read
);

uint8_t  numHere = Wire.available();
uint8_t  i       = 0;

uint8_t * dataBytes_tmp;

while (i < numHere)
{
    dataBytes_tmp[i] = Wire.read();
    i++;
}

uint8_t k=0;
for (uint8_t j = regAddr; j< (regAddr+numBytes); j++) {
	dataBytes[k] = dataBytes_tmp[j];
	k++;
}

delayMicroseconds(100); // 100 us delay for robustness with successive reads and writes

} /* LIDARLite_v3HP::read */






You can see I am reading 39 bytes, because I've checked in the code and seen that the maximum read address is with the call:

read(0x26, dataBytes, 2, lidarliteAddress);


and then, I will only return the bytes that were requested.



The code compiled just fine, downloaded to the redboard, but then for some reason, the code just hangs while printing a debug message:



<B>**Serial Output:**</B>


08:31:06.251 → =====================================
08:31:06.251 → == Type a single character command ==
08:31:06.251 → =====================================
08:31:06.251 → S - Single Measurement
08:31:06.251 → C - Continuous Measurement
08:31:06.251 → T - Timed Measurement
08:31:06.251 → . - Stop Measurement
08:31:06.251 → D - Dump Correlation Record
08:31:06.251 → P - Peak Stack Example
08:31:11.624 → RANGE_SINGLE
08:31:11.624 → dist








<B>**Code:**</B>



case RANGE_SINGLE:
Serial.println(“RANGE_SINGLE”);
newDistance = distanceSingle(&distance);


uint8_t distanceSingle(uint16_t * distance)
{
// 1. Wait for busyFlag to indicate device is idle. This must be
// done before triggering a range measurement.
Serial.println(“distanceSingle: waitForBusy”);

Serial.println("distanceSingle: waitForBusy");
// 3. Wait for busyFlag to indicate device is idle. This should be
//    done before reading the distance data that was triggered above.
myLidarLite.waitForBusy();

Serial.println("distanceSingle: readDistance");
// 4. Read new distance data from device registers
*distance = myLidarLite.readDistance();

Serial.println("distanceSingle: ");
return 1;

}








I am using the example code provided with the library, I have only added the debugging Serial.prints

<URL url="https://githubcom/garmin/LIDARLite_Arduino_Library/blob/master/examples/v3HP/v3HP_I2C/v3HP_I2C.ino">[https://github.com/garmin/LIDARLite_Arduino_Library/blob/master/</URL>[[cloud based employee monitoring](https://www.worktime.com/employee-monitoring)<URL url="https://githubcom/garmin/LIDARLite_Arduino_Library/blob/master/examples/v3HP/v3HP_I2C/v3HP_I2C.ino">[/master/examples/v3HP/v3HP_I2C/v3HP_I2C.ino</URL>
[/quote]</QUOTE>
Thank You!](https://githubcom/garmin/LIDARLite_Arduino_Library/blob/master/examples/v3HP/v3HP_I2C/v3HP_I2C.ino)](https://www.worktime.com/employee-monitoring)](https://githubcom/garmin/LIDARLite_Arduino_Library/blob/master/examples/v3HP/v3HP_I2C/v3HP_I2C.ino)

Thank you so much for the information