I really need your support.
I have to Atmega328p devices, each is assembled with a RFM69HW. Both running the same code.
One Atmega is @16Mhz and the other @8Mhz.
I can transmit data from the 16Mhz device to the 8Mhz device. But in the other direction from 8Mhz to 16Mhz it does not work.
Therefore 16Mhz TX definitely works and @8Mhz RX works... :(
Can anybody give me a hint what the problem could be?
I am desperate...
SPI clock gets divided by 4 in my library. On the 8mhz one it might be too slow even though I would be surprised. But that's where I would look first.
I also thought about that...
I changed it to the following in the select() function
SPI.setClockDivider(SPI_CLOCK_DIV2);
But it still does not work in the direction of 8MHz -> 16MHz atmega...
I also built up a second hardware....the same issue.....
(By the way, I am using your Node and Gateway Sketch)
please help!
Do you have a schematic of your 8mhz device?
Other than that ... im out of ideas, I know almost nothing about what you're doing and how you're doing it.
Although it sometimes works, fortunately electronics is not a game of dice or guessing. Time to get the logic analyzer and do some analyzing.
Enclosed the schematic.
The Quarz and the Capacitors 22pF are not connected.
Thanks for your support!
The strange thing is that it works just fine in receiving messages. It just does not work for transmitting messages.... :(
Quote from: ulli on January 04, 2015, 03:18:24 PM
I really need your support.
I have to Atmega328p devices, each is assembled with a RFM69HW. Both running the same code.
One Atmega is @16Mhz and the other @8Mhz.
I can transmit data from the 16Mhz device to the 8Mhz device. But in the other direction from 8Mhz to 16Mhz it does not work.
Therefore 16Mhz TX definitely works and @8Mhz RX works... :(
Can anybody give me a hint what the problem could be?
I am desperate...
What are your fuses set to? I am running just fine with RFM69HW & internal 8MHz clock. So it's not the frequency that's the issue.
Here is my avrdude command to set the fuses:
avrdude -b 19200 -c usbtiny -p atmega328p -u -v -U lfuse:w:0xE2:m -U hfuse:w:0xDA:m -U efuse:w:0x07:mCheck what the CPU THINKS the frequency is with:
Serial.println(F_CPU);Tom
Hello Tom and Felix,
I spend some more hours on my issue and found the real issue.
Tom you are right, it is not an issue of frequency.
The strange thing is, I have a very low output power on the 8MHz device. (Distance between two devices is about 2 meters)
I configured the RFM69 on the 8MHz device to HighPower mode. This let the 16MHz device receive the messages..... :-[
Do you know what can effect the output power in that way?
In the following my RFM69 configuration....Did I do something wrong?
const byte RFM69_CONFIG_MyProtocol[][2] =
{
//* 0x00 */ Fifo
/* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY }, //Sequencer on | Standby Mode
/* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, //no shaping
/* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_17240}, //LaCrosse 17.24 kbps
/* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_17240},
/* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_90000}, //default:5khz, (FDEV + BitRate/2 <= 500Khz) /FDEV = frequency deviation
/* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_90000}, // rfm12 90kHz Deviation -> (90kHz + 17,24kbps/2) <= 500kHz i.O.
/* 0x07 */ { REG_FRFMSB, 0xD9 }, //FRF_MSB }, //868,3 MHz
/* 0x08 */ { REG_FRFMID, 0x13 }, //FRF_MID },
/* 0x09 */ { REG_FRFLSB, 0x33 }, //FRF_LSB },
//* 0x0A */ calibration of the RC oscillator, trigger and read
/* 0x0B */ { REG_AFCCTRL, RF_AFCCTL_LOWBETA_OFF }, // Improved AFC // needed when index<2 modulation index 0.5 <= beta = 2*Fdev/BitRate <=10 -> Standard AFC routine
//* 0x0C */ unused
//* 0x0D */ { REG_LISTEN1, RF_LISTEN1_CRITERIA_RSSI }, // match >minRSSI & AddressSync
//* 0x0D - 0x10 */ RegListen deaktivated
/* Transmitter Registers */
/* 0x11 */
/* 0x13 */
/* 0x12 */
/* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, //over current protection (default is 95mA)
/* Receiver Registers */
//* 0x14 - 0x17 */ unused
/* 0x18 */ { REG_LNA, RF_LNA_ZIN_50 | RF_LNA_GAINSELECT_AUTO }, // 200Ohm default / rfm12 MAX-LNA Gain setting
/* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_1 }, //(BitRate < 2 * RxBw) -> (17,24kbs < 2* rfm12 166,7 kHz
//* 0x1A */ RegAfcBw
//* 0x1B */ OOK Data Mode
//* 0x1C */ OOK Data Mode
//* 0x1D */ OOK Data Mode
/* 0x1E */ { REG_AFCFEI, RF_AFCFEI_AFCAUTO_ON | RF_AFCFEI_AFC_CLEAR | RF_AFCFEI_AFCAUTOCLEAR_ON | RF_AFCFEI_FEI_START },
//* 0x1E - 0x22 */ Afc Setting
//* 0x23 0x24 */ RSSI
/* IRQ and Pin Mapping */
/* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, //DIO0 is the only IRQ we're using
//* 0x26 */ ClockOut
//* 0x27 */ RegIrqFlags1 read only
/* 0x28 */ { REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN }, // Writing to this bit ensures the FIFO & status flags are reset
/* 0x29 */ { REG_RSSITHRESH, 0xE4 /*MAX*/ }, //(97*2) rfm -91dBm //must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm
//* 0x2A-0x2B */ Timeout after switching to Rx mode if Rssi interrupt doesn't occur
/* Packet Engine Registers */
/* 0x2C */ { REG_PREAMBLEMSB, RF_PREAMBLESIZE_MSB_VALUE },
/* 0x2D */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE }, // default 3 preamble bytes 0xAAAAAA
/* 0x2E */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 },
/* 0x2F */ { REG_SYNCVALUE1, 0x2D }, //attempt to make this compatible with sync1 byte of RFM12B lib
/* 0x30 */ { REG_SYNCVALUE2, 0xe4 }, //NETWORK ID LaCrosse 0xD4
//* 0x31 - 0x36 */ possible SyncValues
/* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF |
RF_PACKET1_CRC_OFF | RF_PACKET1_CRCAUTOCLEAR_OFF |
RF_PACKET1_ADRSFILTERING_NODEBROADCAST },
/* 0x38 */ { REG_PAYLOADLENGTH, RFM69_PROTOCOL_MYPROTOCOL_PAYLOADLENGTH }, //max0x40 in variable length mode: the max frame size, not used in TX
/* 0x39 */ { REG_NODEADRS, DEVICE_ID }, //using address filtering
/* 0x3A */ { REG_BROADCASTADRS, DEVICE_ID_BROADCAST }, //0 is the broadcast address
//* 0x3B */ { REG_AUTOMODES, 0 }, // Automatic Modes, currently not needed
/* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, //TX on FIFO not empty
/* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
//* 0x3E - 0x4D */ AesKey
/* Temperature Sensor Registers */
/* 0x4E - 0x4F */
/* Test Registers */
/* 0x58 - 0x71 */
/* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0
{255, 0}
};
ulli,
I can't take the time look at the configuration table you've included (for several reasons), but I will say that I do not believe that you need to change these at all. IMO, the RFM69 method interface is the correct way to configure the radio to meet your needs. Playing with the raw configuration values is too fragile and can easily break your device (not physically, but it won't work the way you expect).
If you have an RFM69HW you MUST use the high power settings (via radio.setHighPower(true)) otherwise the HW power amplifiers are turned off and you will not get any signal generated. Once you have setHighPower(true) then setPowerLevel(0) to consume the least amount of power on the RFM69HW. You should have enough RF power to communicate within one or two rooms in your house with this setting.
Tom
Hi Tom,
sounds like a noob failure :/
I did
setHighPower(true);
setPowerLevel(0);
and it works! Thanks a lot!
Still the wired thing is that one device worked without setHighPower and the other not....
Quote from: ulli on January 08, 2015, 10:25:24 AM
<...snip>
Still the wired thing is that one device worked without setHighPower and the other not....
EXACTLY the same SW loaded on both???
If so, I can't explain. If not, use diff...
Tom
I have a question regarding the power options in the RFM69 library. I currently do not understand how to use the available PowerLevel functions right.
I understood I always have to execute setHighPower.
In the case I have a RFM69HW the _powerLevel will not be set up by the function "setHighPower" because the variable will only be considered for RFM69W.
Shouldn`t it be "writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON | _powerLevel);"?
void RFM69::setHighPower(bool onOff) {
_isRFM69HW = onOff;
writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON);
if (_isRFM69HW) // turning ON
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages
else
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); // enable P0 only
}
Can the power be adjusted for the RFM69HW and RFM69W with the following function?
// set output power: 0=min, 31=max
// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver
void RFM69::setPowerLevel(byte powerLevel)
{
_powerLevel = powerLevel;
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | (_powerLevel > 31 ? 31 : _powerLevel));
}
Is the setHighPowerRegs function just for the library internal use or is it public and have to be used for output power adjustments?
void RFM69::setHighPowerRegs(bool onOff) {
writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55);
writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70);
}
I already tried fot the initialization the following for the RFM69HW
setHighPower(true);
setPowerLevel(0);
But when I adjust the "setPowerLevel" from 0-31 I do not see any changes in the RSSI value of the receiver....
Thanks a lot!
Quote from: ulli on January 09, 2015, 03:14:18 AM
I have a question regarding the power options in the RFM69 library. I currently do not understand how to use the available PowerLevel functions right.
I understood I always have to execute setHighPower.
In the case I have a RFM69HW the _powerLevel will not be set up by the function "setHighPower" because the variable will only be considered for RFM69W.
Shouldn`t it be "writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON | _powerLevel);"?
void RFM69::setHighPower(bool onOff) {
_isRFM69HW = onOff;
writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON);
if (_isRFM69HW) // turning ON
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages
else
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); // enable P0 only
}
This function needs to be called first for two reasons. First, it does enable PA1 & PA2, but secondly, it sets the _isRFM69HW which is used elsewhere in the library.
Quote from: ulli on January 09, 2015, 03:14:18 AM
Can the power be adjusted for the RFM69HW and RFM69W with the following function?
// set output power: 0=min, 31=max
// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver
void RFM69::setPowerLevel(byte powerLevel)
{
_powerLevel = powerLevel;
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | (_powerLevel > 31 ? 31 : _powerLevel));
}
Yes, the
(readReg(REG_PALEVEL) & 0xE0) section masks everything but the PA control bits so they can be combined with the powerlevel value.
Quote from: ulli on January 09, 2015, 03:14:18 AM
Is the setHighPowerRegs function just for the library internal use or is it public and have to be used for output power adjustments?
void RFM69::setHighPowerRegs(bool onOff) {
writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55);
writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70);
}
This function is used internally as the radio switches between TX & RX since the high power regs can not be left on while in RX mode.
Quote from: ulli on January 09, 2015, 03:14:18 AM
I already tried fot the initialization the following for the RFM69HW
setHighPower(true);
setPowerLevel(0);
But when I adjust the "setPowerLevel" from 0-31 I do not see any changes in the RSSI value of the receiver....
Thanks a lot!
How close are your radios (ie, what is the RSSI value you're getting from the radio you're trying to control)? Also, the receiver has its own AGC control that you'll need to disable if you want an accurate measure of the setPowerLevel effect.
You could add this method to the RFM69 code to control the AGC (read the datasheet for the various values):
byte RFM69::setLNA(byte newReg) { // TWS: New method used to disable LNA AGC for testing purposes
byte oldReg;
oldReg = readReg(REG_LNA);
writeReg(REG_LNA, ((newReg & 7) | (oldReg & ~7))); // just control the LNA Gain bits for now
return oldReg; // return the original value in case we need to restore it later
}
Note that the AGC will need to be disabled in the RECEIVING radio, not the device under test.
Tom
Thanks for your great support.
All right, for the RFM69HW:
I understood "setHighPower" configures the max output power at the beginning.
But the output power can be still changed with "setPowerLevel".
Due to the active AFC the sensitivity will be changed by the receiver therefore I can not just compare the RSSI values after a "setPowerLevel" change at the transmitter, right?
I configured the LNA and ADC like
/* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, //over current protection (default is 95mA)
/* 0x0B */ { REG_AFCCTRL, RF_AFCCTL_LOWBETA_OFF },
/* 0x18 */ { REG_LNA, RF_LNA_ZIN_50 | RF_LNA_GAINSELECT_AUTO },
/* 0x1E */ { REG_AFCFEI, RF_AFCFEI_AFCAUTO_ON | RF_AFCFEI_AFC_CLEAR | RF_AFCFEI_AFCAUTOCLEAR_ON | RF_AFCFEI_FEI_START },
Currently I try to reduce the power consumption as much as possible...
I also found a source code from you Tom and I am thinking to include your function which is the following to reduce the power consumption more..
// set output power: 0=min, 31=max (for RFM69W or RFM69CW), 0-31 or 32->51 for RFM69HW (see below)
// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver
void RFM69::setPowerLevel(byte powerLevel)
{
// TWS Update: allow power level selections above 31. Select appropriate PA based on the value
_transmitLevel = powerLevel; // save this for later in case we do auto power control.
_powerBoost = (powerLevel >= 50);
if (!_isRFM69HW || powerLevel < 32) { // use original code without change
_powerLevel = powerLevel;
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | (_powerLevel > 31 ? 31 : _powerLevel));
} else {
// the allowable range of power level value, if >31 is: 32 -> 51, where...
// 32->47 use PA2 only and sets powerLevel register 0-15,
// 48->49 uses both PAs, and sets powerLevel register 14-15,
// 50->51 uses both PAs, sets powerBoost, and sets powerLevel register 14-15.
if (powerLevel < 48) {
_powerLevel = powerLevel & 0x0f; // just use 4 lower bits when in high power mode
_PA_Reg = 0x20;
} else {
_PA_Reg = 0x60;
if (powerLevel < 50) {
_powerLevel = powerLevel - 34; // leaves 14-15
} else {
if (powerLevel > 51)
powerLevel = 51; // saturate
_powerLevel = powerLevel - 36; // leaves 14-15
}
}
writeReg(REG_OCP, (_PA_Reg==0x60) ? RF_OCP_OFF : RF_OCP_ON);
writeReg(REG_PALEVEL, _powerLevel | _PA_Reg);
}
}
void RFM69::setHighPower(bool onOff, byte PA_ctl) {
_isRFM69HW = onOff;
writeReg(REG_OCP, (_isRFM69HW && PA_ctl==0x60) ? RF_OCP_OFF : RF_OCP_ON);
if (_isRFM69HW) { //turning ON based on module type
_powerLevel = readReg(REG_PALEVEL) & 0x1F; // make sure internal value matches reg
_powerBoost = (PA_ctl == 0x60);
_PA_Reg = PA_ctl;
writeReg(REG_PALEVEL, _powerLevel | PA_ctl ); //TWS: enable selected P1 & P2 amplifier stages
}
else {
_PA_Reg = RF_PALEVEL_PA0_ON; // TWS: save to reflect register value
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); //enable P0 only
}
}
Is my understanding and assumption right?
Thanks a lot!
Ulli,
as I said before, changing the initialization table is not the right way to configure your radios. The RFM69 library has a rich set of functions for configuring the radio. Use those and you will get support from this forum, use the tables and no one will know what's been changed.
Also, disabling the AGC should only be used as a TEMPORARY means to test your devices. Your radios will not perform well if you permanently disable AGC.
Regarding the function to set power, that function was part of a complete library with several changes. I can't comment on how well it will work if you simply copy one function.
Tom
Of course your functions will not work alone....I included the needed code lines in my code to use the setPowerLevel properly....looks good.
I also checked the additional settings I have in the initialization table and made it aligned with moteinos...I could not discover any signal TX or RX issues. Therefore I use the moteinos...
I just have one remark regarding the AFC. Looks like your AFC is turned off. Because your initialization table does not set the REG_AFCFEI.
Per default the Bit AfcAutoOn is set to 0. Therefore the AFC just running when you manually set the AfcStart flag....
I have after the initialization a Calibration function which looks like that
void myRFM69::rcCalibration()
{
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
writeReg(REG_AFCFEI, RF_AFCFEI_AFC_CLEAR | RF_AFCFEI_AFC_START | RF_AFCFEI_AFCAUTO_OFF | RF_AFCFEI_AFCAUTOCLEAR_OFF /*default*/);
while ((readReg(REG_AFCFEI) & RF_AFCFEI_AFC_DONE) == 0x00);
//RF_AFCFEI_AFCAUTO_ON -> 1 → AFC is performed each time Rx mode is entered
writeReg(REG_AFCFEI, RF_AFCFEI_AFCAUTO_ON | RF_AFCFEI_AFCAUTOCLEAR_OFF /*default*/);
}
What do you think?
Quote from: ulli on January 10, 2015, 06:24:57 AM
Of course your functions will not work alone....I included the needed code lines in my code to use the setPowerLevel properly....looks good.
I also checked the additional settings I have in the initialization table and made it aligned with moteinos...I could not discover any signal TX or RX issues. Therefore I use the moteinos...
Good, I'm glad its working for you. You might consider the auto-transmit level feature as well - this works very well for me, automatically dialing back the transmit power to achieve a usable, but not over (or wasted) powered signal. Admittedly, the code in that library is a bit messy and it has not been aligned with the recent deadlock changes in the distribution library. I'll have a cleaned up branch at some point and let you know.
Quote from: ulli on January 10, 2015, 06:24:57 AM
I just have one remark regarding the AFC. Looks like your AFC is turned off. Because your initialization table does not set the REG_AFCFEI.
Per default the Bit AfcAutoOn is set to 0. Therefore the AFC just running when you manually set the AfcStart flag....
I have after the initialization a Calibration function which looks like that
void myRFM69::rcCalibration()
{
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
writeReg(REG_AFCFEI, RF_AFCFEI_AFC_CLEAR | RF_AFCFEI_AFC_START | RF_AFCFEI_AFCAUTO_OFF | RF_AFCFEI_AFCAUTOCLEAR_OFF /*default*/);
while ((readReg(REG_AFCFEI) & RF_AFCFEI_AFC_DONE) == 0x00);
//RF_AFCFEI_AFCAUTO_ON -> 1 → AFC is performed each time Rx mode is entered
writeReg(REG_AFCFEI, RF_AFCFEI_AFCAUTO_ON | RF_AFCFEI_AFCAUTOCLEAR_OFF /*default*/);
}
What do you think?
I haven't looked at the AFC side of things but I do know that Felix made a change within the last few months related to fixing how Frequency is set, but I don't if this is related. I'll have to have Felix answer about both of these.
Tom
Felix what would you say to my Calibration function?
Tim, I also thought about your auto-transmit level feature but I think that will not work for me. Because I have more than two devices communicating to each other and also other protocols (ETH200, HX2262, FS20, LaCrosse, Moteino)
If the moteino would adjust the output power just on one device it could happen that an other device will not longer be received....because the distance for example is bigger...
As you can read in the DS on p84 (http://www.semtech.com/images/datasheet/sx1231.pdf), calibration is done automatically on v2 die versions of the chip.
Also see this post for an interactive frequency drift calibration in relation to temperature: https://lowpowerlab.com/forum/index.php/topic,357.0.html
All right, I skipped the rcCalibration.
But what about the frequency drift calibration...I read the posts...does it mean that I have to start an FEI all ~1hour? Is that enough?
Well not really, it depends. The DS says the rc cal is done when the chip is powered up or after reset. If your node experiences very wide temperature drifts the frequency might drift because of the crystal. As John noted in his thread, the crystals seem to be very good quality. I have had nodes out in the hot summer and cold winter (although with restarts/recharges in between) and have not seen issues to to drift, so I don't like to spend time fixing problems that don't exist.