Whinis' Webpage
About Me
Hobbies
Projects
Random Pictures

Star Trek Communicators Post


Created :04-23-2021
Last Updated:04-24-2021 08:39
When using libraries goes wrong

Created :04-16-2021
Last Updated:04-16-2021 20:26
Specs of the Communicator

Created :04-16-2021
Last Updated:04-16-2021 19:40
How I found this project and how its went all wrong.

Fixing Silly Code and Library Issues

Fixing Booting without Debugger

So this is the main thing I left off on in this post. I believe it has something todo with the crystal being slightly off and the debugger allows the device to continue through other means, not entirely sure. The crystal is not entirely required as there is an 8mhz and 32khz internal that can be used with less accuracy. So I decided to use those and set the define on the arduino stack to CRYSTALLLESS and it boots without issues

Switching to a new Bootloader

So, the bootloader showed no issue, however I added in the standard UF2 bootloader than all feather m0's use. I modified it so that it worked with the board and processor I chose since I am using a cheaper samd21g17a instead of the samd21g18a that is in most of the arduino products. In the future I may downgrade further for cost savings as the sketch doesn't take that much space. I will likely make this a pull requests to the UF2 bootloader github. I have already made a pull requests to allow the lower voltage that I run at on this board.

Issues with Accelerometer

So, this was an issue I didn't see coming and I am unsure if I had older code that already had this fix I lost or if the library updated. The problem was the interrupt line stayed high forever regardless of if a tap is detected or not. I double checked the original hackaday code without seeing any difference. So I replaced the accelerometer on the board thinking maybe I overheated it when building the board but the new one showed the same symptoms. Also I noticed that if I read constantly it would fluctuate between high and low. I remove the accelerometer and determine the micro had no issues driving it high or low without the accelerometer but once initialized the accelerometer drove the line high and nothing could bring it down. So I started looking into code.

I am using the LIS3DH library from adafruit, it consist of a few calls. First and foremost a initialization

if (! lis.begin(0x19)) {
    Serial.println("Couldnt start LIS3DH");
    //while (1); //we just hope it is still there... seems like i2c port is slow ro boot up some times
}

lis.begin takes the address of the LIS3DH which since I am pulling all unneeded lines to ground is 0x19. It also changes if using SPI.

lis.begin does a few things internally. First it checks if you told it to use SPI or I2c and saves that internally. Next it checks if the device is present

  Adafruit_BusIO_Register _chip_id = Adafruit_BusIO_Register(
  i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS3DH_REG_WHOAMI, 1);

  /* Check connection */
  if (getDeviceID() != _wai) {
        /* No LIS3DH detected ... return false */
        // Serial.println(deviceid, HEX);
        return false;
  }

This calls the device for register 0x0f which should always return 0x33 If it doesn't respond then we know there is something wrong with the accelerometer. Next we setup a few control registers

  Adafruit_BusIO_Register _ctrl1 = Adafruit_BusIO_Register(
  i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS3DH_REG_CTRL1, 1);
  _ctrl1.write(0x07); // enable all axes, normal mode

This sends 0x07 to control one which looking at the datasheet reads

datasheet 1

As the comment suggest enabling X,Y,Z axis and power mode to normal

  // 400Hz rate
  setDataRate(LIS3DH_DATARATE_400_HZ);

So this claims it sets the data rate, looking at the function itself

  Adafruit_BusIO_Register _ctrl1 = Adafruit_BusIO_Register(
  i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS3DH_REG_CTRL1, 1);
  Adafruit_BusIO_RegisterBits data_rate_bits =
  Adafruit_BusIO_RegisterBits(&_ctrl1, 4, 4);

  data_rate_bits.write(dataRate);

So, this is setting the 4th-7th bit of ctrl 1 to whatever data rate is. Well if we look above bits 4-7 of ctrl is the Output Data Rate or ODR so that matches up. Next we do some stuff to ctrl4

  Adafruit_BusIO_Register _ctrl4 = Adafruit_BusIO_Register(
  i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS3DH_REG_CTRL4, 1);
  _ctrl4.write(0x88); // High res & BDU enabled

So this code sets ctrl4 to 0x88 or 10001000. So what is that in the data sheet?

datasheet2

Seems to match up, BDU rather than continuous mode is set and high resolution mode is enabled. The next call is interesting however

  enableDRDY(true, 1);

Enable Data ready? what is data ready, well lets look at the function

/**
* @brief Enable or disable the Data Ready interupt
*
* @param enable_drdy true to enable the given Data Ready         interrupt on INT1,
* false to disable it
* @param int_pin which DRDY interrupt to enable; 1 for DRDY1, 2 for DRDY2
* @return true: success false: failure
*/
bool Adafruit_LIS3DH::enableDRDY(bool enable_drdy, uint8_t int_pin) {
    Adafruit_BusIO_Register _ctrl3 = Adafruit_BusIO_Register(
  i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS3DH_REG_CTRL3, 1);
    Adafruit_BusIO_RegisterBits _drdy1_int_enable =
  Adafruit_BusIO_RegisterBits(&_ctrl3, 1, 4);
    Adafruit_BusIO_RegisterBits _drdy2_int_enable =
  Adafruit_BusIO_RegisterBits(&_ctrl3, 1, 3);

    if (int_pin == 1) {
        return _drdy1_int_enable.write(enable_drdy);
    } else if (int_pin == 2) {
        return _drdy2_int_enable.write(enable_drdy);
    } else {
        return false;
    }
}

So it claims from the description it sets DRDY1 or DRDY2 depending on pin to true or false depending on whats passed. It says this is bits 4 and 3 in ctrl3. So what is in ctrl3?

datasheet3

Sadly its not super well documented, however I see no data ready and bits 3 and 4 correspond to i1_321DA and i1_ZYXDA respectively. Both of these appear to be interrupt 1 which is what I am using and not int1 and 2 and the function description claims. The intitialization function doesn't call with pin=2 and as far as I can tell is never used, that being said the i1_321da bit has essentially no documentation. The only reference to is in the datasheet is this one register, if you google it you get a forum asking what 321da is at particle.io and a reference to an app note with a different status register and some reference to the ADCs on the LIS3DH. The suggesting is it causes a high on the interrupt line whenever the ADCs have new data. ZYXDA however has better, but not great, documentation in the status register where it states its an interrupt whenever new data is available or Z,Y, or X buffers.

So how does this affect me? Being that its setting it in BDU mode that means its constantly (400 times per second) reading data and setting the interrupt pin to high to signal new data is available. This mask the tap interrupt that I enable later in my own code. It gives the appearnce that the device is broken as as soon as the interrupt it cleared it signaled again.

A call to lis.enableDRDY(false, 1); fixed the issue and now the communicators can detect taps again

Next issue to tackle

Sadly this was all the time I had to work on it at this time. However with the above fix I got my pair of communicators connecting to each other however the transmitter freezes nearly instantly at trying to read from the I2S microphone. Hopefully this is an easy fix.