To only use one channel, the following worked for me for ABP with the TTN libraries along with with RN2483 version 1.0.1 (Dec 15 2015 09:38:09), on EU868.
Of course, this is only for testing. To use, e.g., channel 5:
// Initialise ABP and set up the 8 standard channels:
ttn.personalize(devAddr, nwkSKey, appSKey);
// Disable 7 of the 8 default channels. This basically disables the
// mandatory LoRaWAN channel hopping, so FOR TESTING ONLY.
exec("mac set ch status 0 off");
exec("mac set ch status 1 off");
exec("mac set ch status 2 off");
exec("mac set ch status 3 off");
exec("mac set ch status 4 off");
// exec("mac set ch status 5 off");
exec("mac set ch status 6 off");
exec("mac set ch status 7 off");
Beware that when disabling channels, the resulting single-channel node will have a very low maximum duty cycle of only 0.125%. The wiki explains:
In the European band, a transmission on a channel within a frequency band, also influences the other frequencies in that band.
…and:
As a per-channel duty cycle limit is easier to implement, you can also divide the sub-band duty cycle over the number of channels in that sub-band. So for example, in a sub-band with 8 channels and a duty cycle of 1%, each channel has a duty cycle of 1/8% (that’s 0.125%).
This method is also implemented by the RN2483 module, and as a result, instead of seeing the no_free_ch
when you send too quickly after the first message you can send multiple messages before all 8 channels are “blocked” and the duty cycle is enforced.
One can validate that indeed the maximum duty cycle for, e.g., channel 5 is 0.125%:
// Print the default duty cycle: 799 means 100/(799+1) = 0.125%, which
// is 1% for the whole sub-band, divided over 8 channels; see explanation
// on https://www.thethingsnetwork.org/wiki/LoRaWAN/Duty-Cycle
exec("mac get ch dcycle 5");
Though the RN2483 allows one to set the maximum duty cycle for that one channel to be 1%, I think one should not do that. LoRaWAN mandates:
The end-device changes channel in a pseudo-random fashion for every transmission. The resulting frequency diversity makes the system more robust to interferences.
So, I’d say that disabling some default channels from a sub-band does not imply one can then (ab)use the full 1% for the one channel that is used. Instead, I feel that disabling default channels implies the node’s maximum duty cycle is decreased. (And it’s a maximum anyway; better stay below the maximum.)
The exec
function as used above needs to be defined like below.
/**
* Executes the given AT command and prints its result, if any.
* FOR TESTING ONLY; might cause a memory leak with String?
*/
String exec(const char* cmd) {
debugSerial.print(cmd);
debugSerial.print(F(": "));
loraSerial.println(cmd);
while(!loraSerial.available()) {
delay(50);
}
String s = "";
// This includes \r\n newline:
while(loraSerial.available()) {
s.concat((char)loraSerial.read());
}
debugSerial.write(s.c_str());
}