OnTheMove not working on Tracker V2 due wrong Pin mapping in Sodaq Arduino Core

Hi guys,

According One V2 schematic here accelerometer LIS3DE interrupts line are connected as follow to SAMD21:

ACCEL_INT1 => PA21
ACCEL_INT2 => PA20

And default Arduino Zero pin mapping is

PA21 => Digital Pin 7
PA20 => Digital Pin 6

So in variant.h of SODAQ SAMD Boards V1.6.14 (latest today) ACCEL pin definition are wrong

static const uint8_t ACCEL_INT1    = (4u);
static const uint8_t ACCEL_INT2    = (5u);

I spend the whole afternoon trying to understand why on the move didn’t fire interrupt on board movement until I replaced with the correct pin values as follow

static const uint8_t ACCEL_INT1    = (7u);
static const uint8_t ACCEL_INT2    = (6u);

For core team, just opened issue on github

Hi,

The board files are correct.

We made the tracker software for the Sodaq One.
If you want to use the Tracker V2 software, use a Sodaq One V2.
And select as board “Sodaq One” and NOT the Arduino Zero.

It’s opensource software if you want to use it on an other board you need to adjust the software yourself.

For more information about the Sodaq One:
http://support.sodaq.com/sodaq-one/sodaq-one/

Here you can buy a Sodaq One

Regards,
Jan

Jah
Of course I’m using sodaq one V2.
The pin definition I talked about is the sodaq one board definition (latest one)
I’m not at the office now I’ll double check later and post my investigation

Have a look at variant.cpp in the SodaqOne variant folder.

You will find that entries 4 and 5 are tied to PA21 and PA20 respectively.

@Jan,
I’m sorry, but I’m thing my assomption are correct, may be I missed something, in this case , just tell me.
I’m using in Aduino IDE 1.8.4 with SODAQ SAMD board definition 1.6.14 from
http://downloads.sodaq.net/package_sodaq_samd_index.json
this file contains

{
name":"SODAQ SAMD Boards",
                    "architecture":"samd",
                    "version":"1.6.14",
                    "category":"Contributed",
                    "url":"http://downloads.sodaq.net/sodaqsamdboards-1.6.14.tar.bz2"
}

When compiling in IDE with Board SODAQ One, compilers use the file contained in the archive downloads.sodaq.net/sodaqsamdboards-1.6.14.tar.bz2
this file : SodaqCore-samd-1.6.14\variants\sodaq_one\pins_arduino.h
and this file has the following definition

static const uint8_t ACCEL_INT1    = (4u);
static const uint8_t ACCEL_INT2    = (5u);

Until there, SAMD21 (in arduino IDE sense) pin D4 is PAO8 and pin D5 is PA15 and LIS3DE is connected to PA20/PA21 that are pin (in arduino IDE sense) D6 and D7

Anyway I changed as follow in SodaqCore-samd-1.6.14\variants\sodaq_one\pins_arduino.h

static const uint8_t ACCEL_INT1    = (7u);
static const uint8_t ACCEL_INT2    = (6u);

And now my accel is working fine and get interrupt fired. But once again I may misunderstood something so any explanation is welcome.

Anyone would put this sketch in IDE and set board to Sodaq One V2 and display Serial Result to check ?

void setup()
{
    SerialUSB.begin(115200);
    while (!SerialUSB);
}

void loop()
{
    SerialUSB.print("ACCEL_INT1=");
    SerialUSB.println(ACCEL_INT1);
    SerialUSB.print("ACCEL_INT2=");
    SerialUSB.println(ACCEL_INT2);
    delay(5000);
}

with modified files SodaqCore-samd-1.6.14\variants\sodaq_one\pins_arduino.h here is the output and with this setting accel is working on SodaqOne

ACCEL_INT1=7
ACCEL_INT2=6

@GabrielNotman
Yeah, I saw that’s why I’m lost ;-(

Anyway without the changes I made in SodaqCore-samd-1.6.14\variants\sodaq_one\pins_arduino.h the ACCEL interrupt was never fired, strange not ?

The pins_arduino.h is the old AVR way of defining the board. For the SAMD boards that file just links to variant.h.

You should ignore the Arduino Zero pin mapping. The Sodaq boards use their own custom mappings which are defined in the associated variant.cpp.

The numbers in variant.h are the indices for that main array in variant.cpp.

It is possible the labeling might be swapped (i.e. ACCEL_INT1->INT2 and ACCEL_INT2->INT1).

@GabrielNotman
Thanks for this explanation, I see much better now :wink:

Anyway I revert back files to original one, here is my on the move init code I added 4 interrupts,
The defined for Sodaq One (4 and 5) firing up accelerometerInt1Handler
and (6 and 7) firing up accelerometerInt2Handler

void initOnTheMove()
{
    pinMode(ACCEL_INT1, INPUT);
    attachInterrupt(ACCEL_INT1, accelerometerInt1Handler, CHANGE);
    pinMode(ACCEL_INT2, INPUT);
    attachInterrupt(ACCEL_INT2, accelerometerInt1Handler, CHANGE);

    pinMode(6, INPUT);
    attachInterrupt(6, accelerometerInt2Handler, CHANGE);
    pinMode(7, INPUT);
    attachInterrupt(7, accelerometerInt2Handler, CHANGE);


    // Configure EIC to use GCLK1 which uses XOSC32K, XOSC32K is already running in standby
    // This has to be done after the first call to attachInterrupt()
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_EIC) |
        GCLK_CLKCTRL_GEN_GCLK1 |
        GCLK_CLKCTRL_CLKEN;

    accelerometer.enable(true, 
        Sodaq_LIS3DE::NormalLowPower10Hz, 
        Sodaq_LIS3DE::XYZ, 
        Sodaq_LIS3DE::Scale8g, 
        true);
    sodaq_wdt_safe_delay(100);

    accelerometer.enableInterrupt1(
        Sodaq_LIS3DE::XHigh | Sodaq_LIS3DE::XLow | Sodaq_LIS3DE::YHigh | Sodaq_LIS3DE::YLow | Sodaq_LIS3DE::ZHigh | Sodaq_LIS3DE::ZLow,
        params.getAccelerationPercentage() * 8.0 / 100.0,
        params.getAccelerationDuration(),
        Sodaq_LIS3DE::MovementRecognition);

    debugPrint("On The Move setup done! INT1=");
    debugPrint(ACCEL_INT1);
    debugPrint("  INT2=");
    debugPrintln(ACCEL_INT2);
}

void accelerometerInt1Handler()
{
    debugPrintln("On-the-move INT1 is triggered");
}

void accelerometerInt2Handler()
{
    debugPrintln("On-the-move INT2 is triggered");
}

```

And with no surprise, when I move board, logs shows INT2 is fired so pin (6,7) not 4 or 5 
Amazing not ?
```
On The Move setup done! ACCEL_INT1=4  ACCEL_INT2=5
** Boot-up completed successfully!
Starting getGpsFixAndTransmit()...
Setting RTC from 946684807 to 1505223504
Timestamp, BatteryVoltage, BoardTemperature, Lat, Long, Altitude, Speed, Course, SatelliteCount, TimeToFix
1505223504, 128, 23, 466573811, 3650997, 107, 1, 46, 4, 0
Data transmitted successfully.
On-the-move INT2 is triggered
On-the-move INT2 is triggered
On-the-move INT2 is triggered
On-the-move INT2 is triggered
```

Do you have the correct target board selected?

Of course, if not, it won’t use pins 6 and 7 when I modify the variants\sodaq_one\pins_arduino.h file :wink:

Well, if you have selected the Zero as the target, it would also work.

I totally agree, this is what I expected to :wink:
Anyway works with pin changes, think mystery will stay until got time to find it :wink:

I believe you are pickup up level changes due to those pins floating.

Have you set your accelerometer parameters in the startup menu?

    Sodaq_LIS3DE::XHigh | Sodaq_LIS3DE::XLow | Sodaq_LIS3DE::YHigh | Sodaq_LIS3DE::YLow  | Sodaq_LIS3DE::ZHigh | Sodaq_LIS3DE::ZLow, 
        params.getAccelerationPercentage() * 8.0 / 100.0, params.getAccelerationDuration(), Sodaq_LIS3DE::MovementRecognition);

Specifically the AccelerationPercentage must not be 0. The default value (see Config.cpp) is set to 0 in ConfigParams::reset().

Yes it is set up like that

On-the-move Functionality 
  Acceleration% (100% = 8g)  (acc=): 20
  Acceleration Duration      (acd=): 100
  Fix Interval (min)         (acf=): 1
  Timeout (min)              (act=): 10

hummm, pin floating, good catch, could be that. Would you mind tell me what are your settings for on the move so I’d to be able to catch INT when I move the board in my hand so I can try ?

thanks

I would recommend using an acceleration duration of 1 (or even 0 will work).

Here is the code I tested with:

#include "Sodaq_LIS3DE.h"
#include "Sodaq_wdt.h"
#include <Wire.h>

Sodaq_LIS3DE accelerometer;

#define debugPrint(X) SerialUSB.print(X)
#define debugPrintln(X) SerialUSB.println(X)

void setup() {
  delay(5000);
  SerialUSB.println("Startup");
  Wire.begin();
  initOnTheMove();
}

void loop() {
  // put your main code here, to run repeatedly:
  debugPrintln("X reading: " + String(accelerometer.getX()));
  debugPrintln("Y reading: " + String(accelerometer.getY()));
  debugPrintln("Z reading: " + String(accelerometer.getZ()));
  debugPrintln();
  delay(1000);
}

void initOnTheMove()
{
    pinMode(ACCEL_INT1, INPUT);
    attachInterrupt(ACCEL_INT1, accelerometerInt1Handler, CHANGE);
    pinMode(ACCEL_INT2, INPUT);
    attachInterrupt(ACCEL_INT2, accelerometerInt2Handler, CHANGE);

  // Configure EIC to use GCLK1 which uses XOSC32K, XOSC32K is already running in standby
  // This has to be done after the first call to attachInterrupt()
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_EIC) |
    GCLK_CLKCTRL_GEN_GCLK1 |
    GCLK_CLKCTRL_CLKEN;

  accelerometer.enable(true, 
    Sodaq_LIS3DE::NormalLowPower10Hz, 
    Sodaq_LIS3DE::XYZ, 
    Sodaq_LIS3DE::Scale8g, 
    true);
  sodaq_wdt_safe_delay(100);

  accelerometer.enableInterrupt2(
    Sodaq_LIS3DE::XHigh | Sodaq_LIS3DE::XLow | Sodaq_LIS3DE::YHigh | Sodaq_LIS3DE::YLow | Sodaq_LIS3DE::ZHigh | Sodaq_LIS3DE::ZLow,
    5.0 * 8.0 / 100.0, //params.getAccelerationPercentage() * 8.0 / 100.0,
    0, //params.getAccelerationDuration(),
    Sodaq_LIS3DE::MovementRecognition);

  debugPrint("On The Move setup done! INT1=");
  debugPrint(ACCEL_INT1);
  debugPrint("  INT2=");
  debugPrintln(ACCEL_INT2);
}

void accelerometerInt1Handler()
{
  debugPrintln("On-the-move INT1 is triggered");
}

void accelerometerInt2Handler()
{
  debugPrintln("On-the-move INT2 is triggered");
}

This one rocks !!! thanks, you were right, leaving pin floating triggered when tapping on board.
and my settings wasn’t able to trigger interrupt.

So in your example, I tried to change accelerometer.enableInterrupt2 to accelerometer.enableInterrupt1 to see, and after upload, I noticed both IRQ were triggered.
After unplug / replug power, only IRQ1 was triggered, so I think uploading to Sodaq does not reset LIS3DE ?
Can you confirm that accelerometer.reboot() on setup would be better ?

Anyway, thank for your help

There is a function in the library (reboot())to reboot the accelerometer.
If you add this to your code, you will ensure that it is reset every time.
A power on reset should also reset it.

Yes, correct, tested, works (need to be done after wire.begin())
Thanks,

Notice that upload does not reset LIS3DE, good to know when your playing with LIS3DE parameters and uploading sketch, at startup parameters could be not the reset default values except if you call reboot() :wink:

Just closed github issue.

According to the datasheet, the interrupt duration registers (IG1_DURATION, IG2_DURATION)_

… set the minimum duration of the interrupt 1 event to be recognized. Duration steps and maximum values depend on the ODR chosen.

From this it seems that the interrupt signal is continued for N multiples of the Output Data Rate (ODR). The configuration above was using a 10Hz ODR, with a duration of 100. This would keep the interrupt signal active for 10 seconds, and possibly immediately re-trigger if there was movement detected during those 10 seconds. This is likely the reason why you were having difficulty detecting the interrupt.

The menu parameter does not specify the activity duration but the interrupt duration.