-
Notifications
You must be signed in to change notification settings - Fork 423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sx126x txpower #57
Sx126x txpower #57
Conversation
Hi, thanks for the contribution. Unfortunately, I can't merge this before it's properly tested, and I too lack the hardware. If anyone knows of a simple way to meaure output power from these radio modules, that would be very much appreciated. |
After some more investigation I think it might be some other issue my side that results in the near constant power output above 17 dBm. It looks like I'm running into a ceiling of some sort. I'll continue to investigate why my modules aren't responding properly to power requests above 17 (either on the trunk or this branch) then retest the code when I figure it out. Gory details of testing follow... Here's what I did: I made a small arduino sketch that loops the power from 22 to -9. At each power, it calls lora.transmitDirect(0) and delays for a few seconds. I also have an RTL-SDR. I use GnuRadio Companion to view the received spectrum (it's a sharp spike since the unit is only transmitting on the carrier frequency). From this I can read off the peak emission spectral density. Figuring that the only part of the system that changes is the software controlled power output, comparing the relative spectral density should give an the relative power output of the SX1262. The table below shows what I found (With the pull request).
|
Was I supposed to close that? Sorry I'm new to this whole git thing. |
Thanks for the thorough investigation - this is actually a pretty simple way to check how the ouput power changes, even though it doesn't give the actual power output. What are using to power the radio? If you take a look at SX1262 datasheet, pages 29 - 30, you'll see curves that have similar shape to yours - perhaps your power source can't supply enough current? Also, what was the current limit set to? I think we should keep this PR open. |
Thanks for this - when I was writing the SX126x driver, there was no section 15 in the datasheet - might be worth it to go over the datasheet again, see if it's as bad as it was back then :D
Yes, the changes you make in the branch you want to pull from are reflected in the PR. Could you please take a look at SX1268 datasheet, if the same fixes should be applied there as well? I won't be able to merge this for some time anyway (since it looks like the latest update to ESP8266 Arduino core broke something in SoftwareSerial handling, which is why all Travis build fail now ... ). |
It looks like there's similar work to be done on SX1268. Also in #61 I hadn't looked much into the SX1268, but now that I look through its datasheet it looks identical to the SX1262 except for frequency range. It seems the code supports this idea. What's your approach to code duplication in a situation like this? Frequency stuff looks the same in 1261 / 1262 and different in 1268, but power is the same in 1262 / 1268 and different in 1261. Write the stuff common to the majority of the classes in the base (SX126x) then override in the derived classes, or duplicate it in the derived classes? |
Code duplicity should be kept at minimum, so anything that is common to all the modules should be in the base class. The code in the derived classes (SX1262, SX1268 etc.) deals with things like parameter ranges etc. If there's something in common to just a few modules. it can be implemeted in the derived class, then other derived classes can inherit from that one - see SX127x/SX1278/SX1276, for example. |
Ensured OCP is always restored when changing power. Slight refactor to avoid duplicated SX1262 / SX1268 code.
Alright, that one has the optimal high power PA code moved to SX126x so it can also be used by SX1268. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I left a few comments. If those could be addressed, I think we can merge this.
Fixed power adjustment for SX1261
Requested changes are implemented. One minor functional change: When adding the comment about power scaling in SX1261.cpp I noticed I had not read the datasheet closely enough and was scaling by 4dB instead of the advised 3dB. |
Thanks, I really appreciate this! Merging now, next release will be probably later this week. |
@BarryPSmith could you please share the exact setup you used when testing this? It would help me a lot, thank you very much. |
The arduino code is messy. I just took one of the radiolib examples (hard to tell which) and hacked at it until it did what I wanted. Then I hacked at it a bunch more while I was trying to figure out why I was seeing those weird steps (eventually realised it was the This looks like the code I was using. It probably wasn't exactly the same, and it'll need to be modified to work with the newer version of radiolib (or probably rewritten with good style, unless you want to spend ages staring at the computer figuring out why a small change broke it). /*
RadioLib SX126x Transmit Example
This example transmits packets using SX1262 LoRa radio module.
Each packet contains up to 256 bytes of data, in the form of:
- Arduino String
- null-terminated char array (C-string)
- arbitrary binary data (byte array)
Other modules from SX126x family can also be used.
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
#define BUSY 4
// SX1262 has the following connections:
// NSS pin: 10
// DIO1 pin: 2
// DIO2 pin: None
// BUSY pin: 4
SX1262 lora = new Module(9, 2, -1, BUSY);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 lora = RadioShield.ModuleA;
void Dio1Action();
void CheckDio1();
void setup() {
Serial.begin(9600);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
// carrier frequency: 434.0 MHz
// bandwidth: 125.0 kHz
// spreading factor: 9
// coding rate: 7
// sync word: 0x1424 (private network)
// output power: 14 dBm
// current limit: 60 mA
// preamble length: 8 symbols
// CRC: enabled
//while(1) Serial.println(digitalRead(BUSY));
int state = lora.begin();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
state = lora.standby();
if (state)
{
Serial.print(F("standby failed, code "));
Serial.println(state);
while (true);
}
// NOTE: Some SX126x modules use TCXO
// (Temprature-Compensated Crystal Oscillator).
// To be able to use these modules, TCXO
// control must be enabled by calling
// setTCXO() and specifying the reference
// voltage.
/*
Serial.print(F("[SX1262] Setting TCXO reference ... "));
// enable TCXO
// reference voltage: 1.6 V
// timeout: 5000 us
state = lora.setTCXO(1.6);
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
*/
// our unit doesn't work at 434 for some reason.
// (We're using a licensed 425 frequency. In North America, it's in the UHF ham band for "Experimental". This seems like an experiment to me.
Serial.println("== Setting Frequency ==");
auto resF = lora.setFrequency(425);
if (resF) {
Serial.print("Error setting frequency: ");
Serial.println(resF);
}
lora.setSpreadingFactor(5);
lora.setCodingRate(5);
lora.setBandwidth(10.4);
lora.setDio2AsRfSwitch();
lora.setCurrentLimit(140);
for (int i = 22; i >= -17; i--)
{
Serial.print("Testing at...");
Serial.println(i);
Serial.println("== Setting power ==");
auto resP = lora.setOutputPower(i);
if (resP) {
Serial.print("Error setting output power: ");
Serial.println(resP);
}
// enable this block to test using a long packet
#if 0
Serial.println("== Transmitting Packet ==");
char message[] = "<Callsign> Testing ###\t#.###############################################################################################################################################";
message[15] = i < 0 ? '-' : '+';
message[16] = '0' + abs(i) / 10;
message[17] = '0' + abs(i) % 10;
Serial.println(message);
auto resT = lora.transmit(message);
CheckDio1();
if (resT) {
Serial.print("Error transmitting packet: ");
Serial.println(resT);
}
delay(1000);
#endif
//enable this block to test using a sine wave
#if 1
Serial.println("== Transmit Direct ==");
auto resD = lora.transmitDirect(0);
if (resD) {
Serial.print("Error in transmit direct: ");
Serial.println(resD);
}
delay(5000);
auto resStd = lora.standby();
if (resStd)
{
Serial.print("Error entering standby: ");
Serial.println(resStd);
}
// enable this to stop it from automatically stepping through power levels.
#if 0
//Clear the serial buffer:
while (Serial.read() >= 0);
Serial.println("Send anything to continue");
//Wait for a response:
while (!Serial.available());
#endif
#endif
} //i (power)
}
void loop() {
} |
Here's the gnu radio companion setup I was using. This was my first time using GRC, so I was just figuring it out as I went along. When I opened this project to check it before replying to this message, I had deleted the file sink for some reason (maybe some other testing I was doing?), so it might not be configured perfectly right now. The system does:
|
Sorry, I'm not a particularly organised person. Given that the things are unlikely to just work out of the box, if you care to share your intended use of this stuff I might be able to clean it up for that. |
Oh, I had to hack together a script to convert the binary data into something I could plot. I have an aversion to matlab, so I used C# -> text file -> excel. This likely doesn't need to be shared, but for completeness I figure I'd paste it here. Saves having to look up the GRC binary format (It's just an array of 32 bit floating points.) This just takes the input binary and writes a number on each line. From the shape of the data, you can see where the steps happen. using System;
using System.IO;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
var ifn = @"C:\Users\Barry_Main\Documents\425Mhz Power";
var ofn = Path.ChangeExtension(ifn, "csv");
using (var ifs = new FileStream(ifn, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var writer = new StreamWriter(ofn))
using (var br = new BinaryReader(ifs))
{
while (br.BaseStream.Position < br.BaseStream.Length - sizeof(float))
{
writer.WriteLine(br.ReadSingle());
Console.WriteLine(br.ReadSingle());
}
}
}
}
} |
Thank you, I wasn't expecting as much detail in the response :D Could you please get in touch with me on [email protected]? I don't want to clog up issues and PRs with off-topic stuff and I don't want to expose your email publicly - mine is already in the library properties file. |
Maybe it's a hardware issue with my devices? My (unnamed from banggood) SX1262 modules don't transmit when told to use the SX1261 PA (the logic did this for power less than or equal 14 dBm).
I also found that if I request less than -9 dBm output power, the module doesn't properly process the request and instead transmits at its maximum power.
To avoid breaking it for anyone using SX1261: Added (untested) SX1261 class to have different logic in the setOutputPower function.
Sadly when testing this I see imperfect behaviour when requested power is greater than 14 dBm:
I'm lacking the proper skills and hardware to take this further right now.