MIC mismatch on SparkFun SAMD21 Pro RF

Hello all,
I’m trying to get my lorawan packets working with a SparkFun SAMD21 Pro RF device.

I keep getting the MIC Mismatch error and can’t seem to get past that.

I’m using an TTN Indoor gateway using the US 915 frequency band.

I was following Sparkfun’s hookup guide here (admittedly it’s pretty outdated)
https://learn.sparkfun.com/tutorials/sparkfun-samd21-pro-rf-hookup-guide/all#hardware-overview

I started with the lmic library that was mentioned there and got this error.

If I try to use the ttn-otaa example, (keeping in mind the endianness of the keys, and lifting the keys from the gui while the correct toggle is set msb/lsb), I get MIC mismatch.

I’ve also tried to make the code change which does something with the timing to get it working, and it hasn’t worked for me.

The gateway is receiving the packet and is ‘trying to’ forward it to my app, but it seems to fail the test of the mic checksum so I’m not able to receive the message in my app and decode it and do something useful with it.

I’m able to get this working (i.e. messages getting received by the app without the mic mismatch) if I use the other example ttn-abp and supply all the keys. But it quickly stops working if the device has to be restarted and the frame counters go out of sync between the server and the device (which starts at zero after the reboot)

I know I’m not running out of memory on my samd21 processor because when I compile my sketch on the Arduino IDE, my sketches memory footprint never goes beyond 15-18%, in general.

I’ve since tried other lorawan libraries and have had no luck. I’ve tried MCCI_LoRaWAN_LMIC_library, and also Beelan_LoRaWAN library, installed directly from the IDE.

I’m also keeping the version of LoRaWAN at 1.0.3 when I setup my end device.

The message coming through the gateway looks like this:

{
  "name": "gs.up.receive",
  "time": "2023-09-02T17:54:20.223951078Z",
  "identifiers": [
    {
      "gateway_ids": {
        "gateway_id": "eui-58a0cbfffe803eed",
        "eui": "58A0CBFFFE803EED"
      }
    }
  ],
  "data": {
    "@type": "type.googleapis.com/ttn.lorawan.v3.GatewayUplinkMessage",
    "message": {
      "raw_payload": "AAAAAAAAAAAA6wkG0H7Vs3AIe2tU05g=",
      "payload": {
        "m_hdr": {},
        "mic": "a1TTmA==",
        "join_request_payload": {
          "join_eui": "0000000000000000",
          "dev_eui": "70B3D57ED00609EB",
          "dev_nonce": "7B08"
        }
      },
      "settings": {
        "data_rate": {
          "lora": {
            "bandwidth": 125000,
            "spreading_factor": 9,
            "coding_rate": "4/5"
          }
        },
        "frequency": "903900000",
        "timestamp": 3210588796,
        "time": "2023-09-02T17:54:20.159689903Z"
      },
      "rx_metadata": [
        {
          "gateway_ids": {
            "gateway_id": "eui-58a0cbfffe803eed",
            "eui": "58A0CBFFFE803EED"
          },
          "time": "2023-09-02T17:54:20.159689903Z",
          "timestamp": 3210588796,
          "rssi": -85,
          "channel_rssi": -85,
          "snr": 13,
          "uplink_token": "CiIKIAoUZXVpLTU4YTBjYmZmZmU4MDNlZWQSCFigy//+gD7tEPzk9voLGgsIzO3NpwYQsbXUaiDg6ISwuLMO",
          "received_at": "2023-09-02T17:54:20.049262536Z"
        }
      ],
      "received_at": "2023-09-02T17:54:20.223681201Z",
      "correlation_ids": [
        "gs:conn:01H99M32GWBM7RA6B8QY1YGVQS",
        "gs:uplink:01H9BGG3DZSGT5Q249Z1H1GNCN"
      ]
    },
    "band_id": "US_902_928"
  },
  "correlation_ids": [
    "gs:conn:01H99M32GWBM7RA6B8QY1YGVQS",
    "gs:uplink:01H9BGG3DZSGT5Q249Z1H1GNCN"
  ],
  "origin": "ip-10-101-5-145.us-west-1.compute.internal",
  "context": {
    "tenant-id": "CgN0dG4="
  },
  "visibility": {
    "rights": [
      "RIGHT_GATEWAY_TRAFFIC_READ"
    ]
  },
  "unique_id": "01H9BGG3DZGK09GWNSA72XFHCV"
}

Inside my app, the mic mismatch says this:

{
  "name": "ns.up.join.cluster.fail",
  "time": "2023-09-03T17:32:57.410469072Z",
  "identifiers": [
    {
      "device_ids": {
        "device_id": "eui-70b3d57ed00609eb",
        "application_ids": {
          "application_id": "my-new-sparkfun-application"
        },
        "dev_eui": "70B3D57ED00609EB",
        "join_eui": "0000000000000000"
      }
    }
  ],
  "data": {
    "@type": "type.googleapis.com/ttn.lorawan.v3.ErrorDetails",
    "namespace": "pkg/joinserver",
    "name": "mic_mismatch",
    "message_format": "MIC mismatch",
    "correlation_id": "f2a82591ce5c4fecad4e02f4d1fb5330",
    "code": 3
  },
  "correlation_ids": [
    "gs:conn:01H9C6FW7G67AN3JTZ3Z4WWC6G",
    "gs:up:host:01H9C6FWBTWZ8CNXQDXW6WV56K",
    "gs:uplink:01H9E1NNNQ672SJD4KB8930W3C",
    "ns:uplink:01H9E1NNNR2XATSAK6KMH906ZS",
    "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01H9E1NNNRRSVP8VYPRZ32TM3B"
  ],
  "origin": "ip-10-101-15-68.us-west-1.compute.internal",
  "context": {
    "tenant-id": "CgN0dG4="
  },
  "visibility": {
    "rights": [
      "RIGHT_APPLICATION_TRAFFIC_READ"
    ]
  },
  "unique_id": "01H9E1NNP22WQ0DBVQ11FYARQA"
}

Sorry for unloading a ton of information about all the stuff I’ve already tried.

I’m a lorawan noob and have tried to comb through all of the previous threads to see if I can find something that’s applicable, and nothing has worked.

Any help you can provide will be much appreciated.

The EUIs have endianness. The keys are a 16 byte hex string and should be used as initially displayed.

Btw. Next time, please use the formatting tools at the top of the input dialog to format code/json for readability.

Have you searched the forum for “MIC mismatch”? It typically means you’ve not got the key in the code matching the one on the console.

As for the EUI’s, for LMIC, as you mention, you need to get them set to LSB.

The LMIC linked to in the SparkFun guide is deprecated, use GitHub - mcci-catena/arduino-lmic: LoraWAN-MAC-in-C library, adapted to run under the Arduino environment - you can load it via the Arduino library manager - search for LMIC and check it’s from MCCI.

I use SAMD21 + RFM95W with MCCI LMIC - it just works, once you’ve got over the learning hump.

As for frame counters, read the Learn section (link at the top of the page) for more info.

I’ve done a search like you suggested and looked through various threads but nothing was helpful. Trust me, I don’t usually create new posts unless I can find the answer myself.

Is there anywhere I can find debug information about where the mismatch is occurring (ie. what is it expecting versus what’s coming in). I tried to enable debug info to serial console within the lmic library’s config.h but it only spit out info like what frequency its sending at, and receiving at. Nothing about low level packet info.

I feel it’s a bit of a closed system where I can’t see what’s going on behind the scenes.

I looked at the live data screen on nam1 and toggled on the debug info but it didn’t yield anything I could use in the way of diagnose and fix.

Thanks again for any help.

The gateway console at TTN shows the raw packet. Use an online decoder to check what it reports. Reverse the skey to check if it makes a difference.

Or take an offline packet decoder (Google should find you some) to analyse the raw data.

Thanks for the link to the decoder. I’m going to try that out to decipher what’s coming in.

Hello All,
Thanks for your help, the online decoder was very helpful in decoding the raw data and seeing the MIC checksum and comparing it with what’s expected given my NwkSKey and AppSKey.

Unfortunately I wasn’t able to get to the bottom of why my MIC was getting mismatch.

I eventually just created a new end device and generated a fresh set of keys off of that and used those in my Arduino sketch.

This time it worked pretty good. I’m still a bit unsure if it will work every time, but for now I think I’m all set.

Thanks all for your help. This topic can be marked as closed and resolved.

As above, MIC mismatch is normally the AppKey being different - you can create a new one on the console and have it copied to the clipboard for easy pasting in to the code.

This isn’t a help desk, it’s a community forum of volunteers. If there is a post that led you to a solution, you can mark it as such.

@pepsiplease69 great topic, I’ve been trying to get SAMD21 to work and have not been successful, would you post your sketch (or IM it to me) so I can just upload it and see what happens on my end? Thank you

Hi,
Here’s the code I used. It’s basically the example sketch. I didn’t make any changes to it.
You will have to supply your own keys.

/**
 *  Test in all frequencies of US_915 band
 *      Using SUB BAND 1 [ 903.9 - 905.3 Mhz] see config.h
 *      channel [0 - 7]
 *      data rate [0 - 3]
 *  Class A and C devices with OTAA activation
 *      
 *  Gateway:    Sentrius RG101
 * 
 * Using CATWAN USB STICK hardware
 * 
 * Author: Ivan Moreno
 *  June 2019
 */

#include <lorawan.h>
#define Serial SerialUSB
// OTAA credentials
const char *devEui = "";
const char *appEui = "0000000000000000";
const char *appKey = "";
const char *nwkKey = "";


const unsigned long interval = 30000;   // 15 s interval to send message
unsigned long previousMillis = 0; // will store last time message sent
unsigned long currentMillis;

union _cntCI {
  unsigned char _cb[2];
  unsigned int val;
} counter;

char payload[10];
char outStr[100];
byte recvStatus = 0;

byte _dataRate;
byte _channel;
byte _times;

const sRFM_pins RFM_pins = {
  .CS = 12,
  .RST = 7,
  .DIO0 = 6,
  .DIO1 = 10,
  .DIO2 = 11,
  .DIO5 = 15,
};


void setup() {
  Serial.begin(115200);
  delay(5000);

  if (!lora.init()){
    Serial.println("RFM no init");
    delay(5000);
    return;
  }
  lora.setDeviceClass(CLASS_A);
  lora.setTxPower(15,PA_BOOST_PIN);
  lora.setChannel(CH0);
  lora.setDataRate(SF9BW125);

  counter.val = 0;
  _channel = 0; // 0 - 7
  _dataRate = 0; // 0 - 3 
  _times = 0;

  lora.setDevEUI(devEui);
  lora.setAppEUI(appEui);
  lora.setAppKey(appKey);
  lora.setNwkSKey(nwkKey);

  bool isJoined;
  do {
    Serial.println("Joining...");
    isJoined = lora.join();
    delay(10000);
  }while(!isJoined);
  Serial.println("Joined to network");
}

void loop() {
  currentMillis = millis();
  // Check interval overflow
  if(currentMillis - previousMillis > interval) {
    if(_times > 0){
        _times = 0;
        _dataRate++;
        if (_dataRate > 3){
            _dataRate = 0;
            _channel++;
            if (_channel > 7) {
                _channel = 0;
            } 
        }
    }
    // Set Channel
    lora.setChannel(_channel);

    // Set Data Rate
    lora.setDataRate(_dataRate);
    
    Serial.print("SND[");
    Serial.print(counter.val);
    Serial.print("], CH: ");
    Serial.print(_channel);    
    Serial.print(", DR: ");
    Serial.println(_dataRate);

    previousMillis = currentMillis; 

    payload[0] = _channel;
    payload[1] = _dataRate;
    payload[2] = 15;
    payload[3] = _times + 1;
    payload[4] = counter._cb[1];
    payload[5] = counter._cb[0];

    lora.sendUplink(payload, 6, 0, 1);
    counter.val++;
    _times++;
  }

  // Check Lora RX
  lora.update();

  recvStatus = lora.readData(outStr);
  if(recvStatus) {
    Serial.print("Rcv: ");
    Serial.println(outStr);
  }
}