Nemeus NIS-UL – Ultrasonic sensor

Jut to be sure: in LoRaWAN 1.0.x, that should only be set every 64 packets (and only if no downlink was received in the meantime). But for each uplink, the ADR bit should be set as well, so TTN knows it needs to keep track of the link quality.

So: is the ADR bit indeed set for every uplink?

Using an online LoRaWAN decoder you can easily check:

  • if ADR is set for every uplink (like if it has FCtrl = 0x80 = 0b10000000, hence has bit 7 for ADR set)
  • and if ADRACKReq is set for every 64th uplink (like if it has FCtrl = 0xC0 = 0b11000000, hence has bit 6 for ADRACKReq set)
  • and if any downlink is an ADR response (like for me, after an ADRACKReq uplink, TTN would generate a downlink right away, but and ADR downlink could also be postponed for another 32 uplinks if TTN feels like that).

If the uplinks look fine: any chance the uplinks are received by multiple gateways, and TTN tells another gateway to send the ADR downlink, which is then somehow lost?

Note that at some point TTN will give up to not waste more downlinks; such is then shown as “too many failed ADR requests” in the “trace” part of an expanded downlink in the gateway’s Traffic page in TTN Console:

:warning: Well, actually the above screenshot still resulted in a downlink, which I linked to in the 3rd bullet above… I did not investigate; see Error: too many failed ADR requests.

Maybe it even gives up if it has tried to send ADR commands before your node even has set ADRACKReq, which I think can happen when the node is using SF12 despite a good link quality?

Hello there,

I am unable to get the sensor to register to the TTN application, although i can see the frames in the gateway traffic, it was working fine, but it stopped suddenly, i tried deleting the app and creating it again with no luck, any advice ?

Thanks

are you using new TTN generated keys , a new application (with a different name) ? or re using the same keys as before …

I am using a new application with a different name but i am using a specific DEV EUI, APP EUI and a APP KEY provided by Nemeus.

if you scroll back a bit I read it’s not the first time you encounter this.
how did you solve it a few months back ?

A DevAddr as assigned by TTN will always start with 0x26 or 0x27 , and for TTN the next bytes indicate other details such as the region; see https://www.thethingsnetwork.org/docs/lorawan/address-space.html , a manufacturer cannot assign those addresses.

You would have to make sure the AppEUI and AppKey are exactly as they were before since there’s no way to change them on the device. I expect the AppKey will be different each time it’s generated, but there seems to be an option to override it and paste in the old AppKey for that device.

Also make sure the sensor is properly reset to trigger a join. Setting the device to standby mode and back doesn’t trigger a join if it thinks it’s already joined. Using the magnet for 20 seconds will hardware reset it, triggering a join.

tnx… I don’t own a device like that but I’ve read that you allready advised him about this in the past.

Thanks sir, I have thought about resetting it by holding the magnet for 20 sec, but won’t this reset the configuration also?, and unfortunately, these sensors were shipped configured and i don’t think we know how to reconfigure them again.

At that time, i think it was by re creating the app. but i am not sure

1 Like

Hi @habibraed ,

Using hardware reset doesn’t clear the configuration of the device, but does reset the session keys. No other options cause a Join message to be sent, so this is the only choice except maybe leaving the battery out, but flash storage would survive this and supercapacitors can complicate the process.

You must make sure you get your keys correct in the application, but for a quick check you can see the join attempt in the gateway traffic console.

Ben

Hi Ben, thanks so much for your help. It finally worked…
What i did is i let the newly created app generate the Dev EUI, at that moment i could see the join attempt in he gateway traffic and i could see that it has failed, then i manually modified the Dev EUI back to the sensors specific, the join was successful and the app worked.

I just have a quick question regarding the coverage, it seems that the sensor only work when it is extremly close to the gateway, i have tested the battery level and it looks fine.
I have contacted nemeus regarding this, and they send us a few models for an external antenna, but their seems no where to connect a SMA connecter on the PCB once i opened the sensor, is their some sort of modification needs to be done ?

Thanks

@habibraed great news that you are back online!

We have had no range problems with the NIS-UL like that you describe. The external antenna model is currently being tested by a client and comes with a bulkhead SMA connector. The other versions I assume have a PCB or ceramic antenna but have achieved several km range without problems. Perhaps you have a faulty device? Is it an 868MHz model? Also be sure your gateway is multi-channel or you’ll be missing many messages.

Hi Ben,
Thanks again, We have a multitech outdoor unit, and i think all chanels are enabled, or atleast when i ran the ttn packet forwarder script i think it showed that.

and yes we have the 868MHz model

(Traducteur)

Hello,
I am a novice, I own the NIS-UL - ultrasonic sensor - Nemeus and I want a script following a routing.
Can you help me thanks.
Serge

Hi Serge, the script @arjanvanb wrote works if you put it into the decoder in your application.

The rest of the setup is documented here https://docs.google.com/document/d/1NTxXAZfil4A_-HATGzWrAGN91Xp9zjthKxkNbL8ZY-4

If you need help on where to apply the decoder code then let me know.

Ben

I am looking for a PHP script
Only, I do not know anything about PHP programming.
Thank you
Serge

I am sorry Serge, but this forum is not the right place to ask questions about PHP programming.

I think @BoRRoZ has a fair point. The end application is quite an important part of the process, but probably not for here. If you’re a novice then I’d recommend using the decoder to make the fields easier to work with. Arjan has done a great job in splitting them into human readable fields for posting, otherwise you’ll have the additional problem of learning bitwise operations in PHP.

1 Like

“Traducteur”
Ok about PHP.
I am proud to say that I could this question.

CLICK to see code

function Decoder(bytes, port) {
  
  // See http://wiki.nemeus.fr/index.php?title=NIS-UL_UltraSonic_Sensor#Nemeus_uplink_protocol
  // Test with:
  //   8B 02 0097 0098 1f 19: 151, 152cm; 31, 25°C
  //   8B 02 0097 0098 fe 03: 151, 152cm; -2, 3°C
  //   AF 03 0097 0098 0090 0fb9 0e91 0fff fe 03 00 0a: 151, 152, 144cm; 4025, 3729, 4095mV, -2, 3, 0°C
  //   82 00a0: 160cm
  //   88 1e: 30°C
  var usonic_dist = [], voltage = [], internal_temp = [];
  var i = 0, m = 0;

  var mask = bytes[i++];

  // If bit 0 set: 1 byte indicating the number of measurements, else 1
  var nb_meas = mask & 1<<0 ? bytes[i++] : 1;

  // If bit 1 set: distances in centimeters, each 2 bytes unsigned MSB, 1 to 300cm
  if (mask & 1<<1) {
    for (m = 0; m < nb_meas; m++) {
      usonic_dist.push(bytes[i++]<<8 | bytes[i++]);
    }
  }

  // If bit 2 set: voltages in millivolts, each 2 bytes unsigned MSB
  if (mask & 1<<2) {
    for (m = 0; m < nb_meas; m++) {
      voltage.push((bytes[i++]<<8 | bytes[i++]) / 1000);
    }
  }

  // If bit 3 set: internal temperatures, each 1 byte signed integer [-128..+127]
  if (mask & 1<<3) {
    for (m = 0; m < nb_meas; m++) {
      // Sign-extend to 32 bits to support negative values, by shifting 24 bits
      // (too far) to the left, followed by a sign-propagating right shift:
      internal_temp.push(bytes[i++]<<24>>24);
    }
  }

  // Bit 4: reserved

  // If bit 5 set: cause for the measurement, else "periodic measurement"
  var cause = mask & 1<<5 ? bytes[i++] : 1;

  // We should have consumed all bytes, if not then just return the payload as hex
  if (i !== bytes.length) {
    return {
      'error': 'failed to parse payload',
      'payload': bytes.map(function(b) {
         return ('0' + b.toString(16).toUpperCase()).substr(-2);
       }).join(' ')
    }
  }
  // Format the results
  var result = {};
  // Show all 8 bits, ensuring leading zeroes
  result.mask = '0b' + ('00000000' + mask.toString(2)).substr(-8);

  result.numberOfMeasurements = nb_meas;
  result.distances = usonic_dist;
  result.voltages = voltage;
  result.temperatures = internal_temp;

  // Same data, grouped by measurement
  result.measurements = [];
  for (m = 0; m < nb_meas; m++) {
    result.measurements.push({
      distance: usonic_dist[m],
      voltage: voltage[m],
      temperature: internal_temp[m]
    });
  }

  result.cause = cause;
  result.causeMask = '0b' + ('00000000' + cause.toString(2)).substr(-8);
  result.causes = [];
  if (cause & 1<<0) {
    result.causes.push('periodic');
  }
  if (cause & 1<<1) {
    result.causes.push('usonic_dist > high threshold');
  }
  if (cause & 1<<2) {
    result.causes.push('usonic_dist < high threshold - high hysteresis');
  }
  if (cause & 1<<3) {
    result.causes.push('usonic_dist < low threshold');
  }
  if (cause & 1<<4) {
    result.causes.push('usonic_dist > low threshold + low hysteresis');
  }
  if (cause & 1<<5) {
    result.causes.push('forced manually');
  }

  return result;
}
{
  "mask": "0b10101111",
  "numberOfMeasurements": 3,
  "distances": [
    151,
    152,
    144
  ],
  "voltages": [
    4.025,
    3.729,
    4.095
  ],
  "temperatures": [
    -2,
    3,
    0
  ],
  "measurements": [
    {
      "distance": 151,
      "voltage": 4.025,
      "temperature": -2
    },
    {
      "distance": 152,
      "voltage": 3.729,
      "temperature": 3
    },
    {
      "distance": 144,
      "voltage": 4.095,
      "temperature": 0
    }
  ],
  "cause": 10,
  "causeMask": "0b00001010",
  "causes": [
    "usonic_dist > high threshold",
    "usonic_dist < low threshold"
  ]
}

?>

Can I ask how to configure this script as it is on this forum?

Thank you
Serge