Power Levels ... again

Started by Robert, February 05, 2022, 05:55:30 AM

Robert

      Felix,

      In my journey to review the RFM69 library I see a problem with the setPowerDBm function.
      If the function setPowerlLevel is now greatly improved
         0-15  ie [-2 to 13dBm]
         16-19  ie [12 to 15dBm]
         20-23  ie [17 to 20dBm]

      It is also a good idea of introducing the setPowerDBm one which is more clear while setting the transceiver transmit power, however I see two issues with the current library implementation.

int8_t RFM69::setPowerDBm(int8_t dBm) {
  if (_isRFM69HW) {
    //fix any out of bounds
    if (dBm<-2) dBm=-2;
    else if (dBm>20) dBm=20;

    //map dBm to _powerLevel according to implementation in setPowerLevel()
    if (dBm<17) setPowerLevel(2+dBm);
    //else if (dBm<16) setPowerLevel(4+dBm);
    else setPowerLevel(3+dBm);
  } else { //W/CW
    if (dBm<-18) dBm=-18;
    else if (dBm>13) dBm=13;
  }
  return dBm;
}


1. The discontinued power setting for level from 14 to 16 in high power mode don't fit with the power level scheme

Value Corr Level  dBm
-2   +2   0   -2
-1   +2   1   -1
0   +2   2   0
1   +2   3   1
2   +2   4   2
3   +2   5   3
4   +2   6   4
5   +2   7   5
6   +2   8   6
7   +2   9   7
8   +2   10   8
9   +2   11   9
10   +2   12   10
11   +2   13   11
12   +2   14   12
13   +2   15   13
14   +2   16   12
15   +2   17   13
16   +2   18   14

17   +4   20   17
18   +4   21   18
19   +4   22   19
20   +4   23   20

2. The lack of level setting for low power mode

So I propose the following:

int8_t RFM69::setPowerDBm(int8_t dBm) {
  if (_isRFM69HW) {
    //fix any out of bounds
    if (dBm<-2) dBm=-2;
    else if (dBm>20) dBm=20;

    //map dBm to _powerLevel according to implementation in setPowerLevel()
    if (dBm<12) setPowerLevel(2+dBm);
    else if (dBm<16) setPowerLevel(4+dBm);
    else setPowerLevel(3+dBm);
  } else { //W/CW
    if (dBm<-18) dBm=-18;
    else if (dBm>13) dBm=13;
    setPowerLevel(18+dBm);
  }


Allowing update of a Low power transceiver
and a better power distribution though the new level scheme as follow:
NB: 16dBm is not actually possible
Value Corr Level dBm
-2   +2   0   -2
-1   +2   1   -1
0   +2   2   0
1   +2   3   1
2   +2   4   2
3   +2   5   3
4   +2   6   4
5   +2   7   5
6   +2   8   6
7   +2   9   7
8   +2   10   8
9   +2   11   9
10   +2   12   10
11   +2   13   11
12   +4   16   12
13   +4   17   13
14   +4   18   14
15   +4   19   15
16   +3   19   15

17   +3   20   17
18   +3   21   18
19   +3   22   19
20   +3   23   20

Regards
Robert

Felix

Robert, thanks for the proposal.
Have you done any output power testing with the proposed change or is this from a theoretical POV?
I assume from your post that you have already read my in detail blog about the power level fix/change.

Robert

Felix,
Yes I did verify your blog about the power level management, and its OK for me, I mean the way the setPowerLevel is now implemented
I had also long time ago done some measurements in order to rationalize my RFM transceivers to only High power ones, but with the possibility to set the PA registers to fake as much as possible RFM69W ones for battery usage.
So your new implementation is good especially when using the dBm values instead of the levels

It's only by looking at the way the setPowerDBm is  implemented that I see incoherence with the way the setPowerLevel is now done, so if I am not wrong the proposal above should correct it.

To test it I did use the TxPowerTest_Transmitter example with IS_RFM69HW_HCW  true and false and without ATC, with the expected results
Robert



Felix

If I understand it correctly, the region you mention is an overlap region between the different PA domains. That is where you will find nonlinearities. The theory does not match the output. Hence I had to come up with a way to smooth out the transitions because otherwise you will get power output stepping in the wrong direction when you just increase power levels.

The setPowerDBm() was added because someone requested it, although IMO it has little practical value, ATC does not think in dBm levels, it just asks for less/more power, if it is available.

The setPowerLevel() and setPowerDBm() have to be in sync. If one is changed, the other has to change as well, and testing has to be done to ensure they output the exact same thing. I did this exercise extensively when I implemented this change, to ensure we get a smooth power output curve.

Robert

I am not sure we are on the same line.
For instance a power in dbm of 14 gives in your function setpowerdbm a value of 14 +2  i.e. a level of 16 and mapping 16 as power level gives a dbm value of 12  (16 -19 is equivalent to  12 to15 dbm) instead of the expected value of 14 dbm which should correspond to level of 18 in the mapping slice. So the proposed correction

Also the setpowerdbm doesn

Felix

Ok I made the change you suggested. I see about the same nonlinearity in the PA domain transitions, and it does address the issue you noticed about the lower power radios.
Please get latest directly from Github or see this commit. I will make an official release 1.5.1 if you approve ;)

Robert


Felix