Author Topic: 2 RFM69 & Moteino  (Read 3496 times)

farades

  • NewMember
  • *
  • Posts: 3
2 RFM69 & Moteino
« on: September 16, 2014, 03:07:03 PM »
Good day everybody!
I don't know where i can write this topic, then i'm writing here. I want to made a board with two RFM69 on board, but with only one Atmega328.
Accordingly we have one SPI. Atmega328 - master, 2xRFM69 - slaves.
The first RFM69 i connect ordinary - from 10 till 13 pin. SS of the second RFM69 i connected to A3, DI0 to D3.
Further we have:
1) A homemade board with Atmega328, 2xRFM69 and others..
2) Moteino.

Then i try to start the RFM69 separate to each other.
Everything is working.

When i try to work with two RFM69 in the same time, doesn't work neither.

The sketch Moteino
Code: [Select]
#include <RFM69.h>
#include <SPI.h>

#define NODEID             3 
#define NETWORKID       100
#define GATEWAYID_1    1
#define GATEWAYID_2    2
#define ACK_TIME          30
#define LED                   9
#define FREQUENCY       RF69_433MHZ
#define ENCRYPTKEY     "sampleEncryptKey"
#define IS_RFM69HW   
#define SERIAL_BAUD   115200

int TRANSMITPERIOD = 1000;
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
byte sendSize=29;
boolean requestACK = false;
RFM69 radio;

void setup() {
    Serial.begin(SERIAL_BAUD);
    radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
    radio.setHighPower();
#endif
    radio.encrypt(ENCRYPTKEY);
    Serial.println("Transmitting at 433 Mhz...");
}

long lastPeriod = -1;
void loop() {
    if (Serial.available() > 0)
    {
        char input = Serial.read();
        if (input == 49)
        {
            Serial.print("Sending to NodeID:");Serial.print(GATEWAYID_1);Serial.print(" ...");
            if (radio.sendWithRetry(GATEWAYID_1, payload, sendSize))
                Serial.println(" ok!");
            Blink(LED,3);
        }
        if (input == 50)
        {
            Serial.print("Sending to NodeID:");Serial.print(GATEWAYID_2);Serial.print(" ...");
            if (radio.sendWithRetry(GATEWAYID_2, payload, sendSize))
                Serial.println(" ok!");
            Blink(LED,3);
        }
    }

    if (radio.receiveDone())
    {
        Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
        for (byte i = 0; i < radio.DATALEN; i++)
            Serial.print((char)radio.DATA[i]);
            Serial.print("   [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]");
        if (radio.ACKRequested())
        {
            radio.sendACK();
            Serial.print(" - ACK sent");
        }
        Blink(LED,5);
        Serial.println();
    }
}

void Blink(byte PIN, int DELAY_MS) {
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
}

The sketch of homemade board
Code: [Select]
#include <RFM69.h>
#include <SPI.h>

#define NODEID_1      1
#define NODEID_2      2
#define NETWORKID     100 
#define FREQUENCY     RF69_433MHZ
#define ENCRYPTKEY    "sampleEncryptKey"
#define ACK_TIME      30
#define SERIAL_BAUD   115200

RFM69 radio1(10, 2, false, 0);
RFM69 radio2(A3, 3, false, 1);
bool promiscuousMode = false;

void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
        Serial.println("First RFM69 initialize.");
    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
        Serial.println("Second RFM69 initialize.");
    radio1.encrypt(ENCRYPTKEY);
    radio2.encrypt(ENCRYPTKEY);
    radio1.promiscuous(promiscuousMode);
    radio2.promiscuous(promiscuousMode);
}

byte ackCount=0;

void loop() {
    if (radio1.receiveDone())
    {
        Serial.print('[');Serial.print(radio1.SENDERID, DEC);Serial.print("] ");
        if (promiscuousMode)
        {
            Serial.print("to [");Serial.print(radio1.TARGETID, DEC);Serial.print("] ");
        }
        for (byte i = 0; i < radio1.DATALEN; i++)
            Serial.print((char)radio1.DATA[i]);
        Serial.print("   [RX_RSSI:");Serial.print(radio1.RSSI);Serial.print("]");
   
        if (radio1.ACKRequested())
        {
            byte theNodeID = radio1.SENDERID;
            radio1.sendACK();
            Serial.print(" - ACK sent.");
            if (ackCount++%3==0)
            {
                Serial.print(" Pinging node ");
                Serial.print(theNodeID);
                Serial.print(" - ACK...");
                delay(3);
                if (radio1.sendWithRetry(theNodeID, "ACK TEST", 8, 0))  // 0 = only 1 attempt, no retries
                    Serial.print("ok!");
                else Serial.print("nothing");
            }
        }
        Serial.println();
        Blink(9,3);
    }

    if (radio2.receiveDone())
    {
        Serial.print('[');Serial.print(radio2.SENDERID, DEC);Serial.print("] ");
        if (promiscuousMode)
        {
            Serial.print("to [");Serial.print(radio2.TARGETID, DEC);Serial.print("] ");
        }
        for (byte i = 0; i < radio2.DATALEN; i++)
        Serial.print((char)radio2.DATA[i]);
        Serial.print("   [RX_RSSI:");Serial.print(radio2.RSSI);Serial.print("]");

        if (radio2.ACKRequested())
        {
            byte theNodeID = radio2.SENDERID;
            radio2.sendACK();
            Serial.print(" - ACK sent.");
            if (ackCount++%3==0)
            {
                Serial.print(" Pinging node ");
                Serial.print(theNodeID);
                Serial.print(" - ACK...");
                delay(3);
                if (radio2.sendWithRetry(theNodeID, "ACK TEST", 8, 0)) 
                    Serial.print("ok!");
                else Serial.print("nothing");
            }
        }
        Serial.println();
        Blink(A1,3);
    }
}

void Blink(byte PIN, int DELAY_MS) {
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
}

Please, tell me where do seek the problems? I think the hardware haven't any problems. Likely the problems are in the software.
I hope for your help. Thank you.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6867
  • Country: us
    • LowPowerLab
Re: 2 RFM69 & Moteino
« Reply #1 on: September 16, 2014, 06:46:56 PM »
Just glancing over your code it looks ok to me. Not sure what to suggest... other than ... maybe time to pull the logic analyzer to see if the initializing works properly.
You have to look at the SPI communication and the IRQ pins to see how they are asserted in relation to one another. Also assuming everything else hardware-wise is done properly, like 3.3V and not 5V etc.

kiwisincebirth

  • Jr. Member
  • **
  • Posts: 69
Re: 2 RFM69 & Moteino
« Reply #2 on: September 16, 2014, 11:18:00 PM »
Hi There, I am guessing (not sure) that this RFM69 class doesn't support multiple instances, as per your example. Looking at the code RFM69.h many of the variables declared are 'static', for things I would expect should not be shared across multiple instances.

Code: [Select]
class RFM69 {
  public:
    static volatile byte DATA[RF69_MAX_DATA_LEN];
    .....

I would try removing the 'static' declarations and test. The only possible issue may be in the interrupt handling i.e. in the line of code.

attachInterrupt(_interruptNum, RFM69::isr0, RISING);

 I dont know enough about interrupts but the documentation for the above method states "Typically global variables are used to pass data between an ISR and the main program", this may be the reason why variables are defined as static.

Not sure if this can be overcome.

farades

  • NewMember
  • *
  • Posts: 3
Re: 2 RFM69 & Moteino
« Reply #3 on: September 17, 2014, 03:17:56 AM »
Use the code
Code: [Select]
#include <RFM69.h>
#include <SPI.h>

#define NODEID_1          1
#define NODEID_2          2
#define NETWORKID     100
#define FREQUENCY     RF69_433MHZ
#define ENCRYPTKEY    "sampleEncryptKey"
#define ACK_TIME           30
#define SERIAL_BAUD   115200

RFM69 radio1(10, 2, false, 0);
RFM69 radio2(A3, 3, false, 1);
bool promiscuousMode = false;
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
byte sendSize=5;

void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
        Serial.println("First RFM69 OK");
    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
        Serial.println("Second RFM69 OK");
    radio1.encrypt(ENCRYPTKEY);
    radio2.encrypt(ENCRYPTKEY);
    radio1.promiscuous(promiscuousMode);
    radio2.promiscuous(promiscuousMode);
}

byte ackCount=0;

void loop() {
    if (Serial.available() > 0)
    {
        char input = Serial.read();
        if (input == 'r') //read register
        {
            Serial.println("Radio 1:");
            radio1.readAllRegs();
            Serial.println("Radio 2:");
            radio2.readAllRegs();
        } 
        if (input == 49)
        {
            Serial.print("Send From 1 RFM... ");
            if (radio1.sendWithRetry(25, payload, sendSize))
                Serial.println(" ok!");
        }
        if (input == 50)
        {
            Serial.print("Send From 2 RFM... ");
            if (radio2.sendWithRetry(25, payload, sendSize))
                Serial.println(" ok!");
        }
    }
}

void Blink(byte PIN, int DELAY_MS)
{
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
}

Result

Initialize:

Yellow - First RFM69 SS. Blue - Second RFM69 SS.

Read register's:

Yellow - First RFM69 SS. Blue - Second RFM69 SS.


Sending from 1st RFM69:

Yellow - First RFM69 SS. Blue - Second RFM69 SS.

Sending from 2nd RFM69:

Yellow - First RFM69 SS. Blue - Second RFM69 SS.

After sending from second RFM69 Atmega328 froze  :)
Change function setup:
Code: [Select]
void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
        Serial.println("First RFM69 OK");
//    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
//        Serial.println("Second RFM69 OK");
    radio1.encrypt(ENCRYPTKEY);
//    radio2.encrypt(ENCRYPTKEY);
    radio1.promiscuous(promiscuousMode);
//    radio2.promiscuous(promiscuousMode);
}

Sending from 1st RFM69:

Yellow - First RFM69 SS. Blue - First RFM69 Interrupt.

Change function setup:
Code: [Select]
void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
//    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
//        Serial.println("First RFM69 OK");
    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
        Serial.println("Second RFM69 OK");
//    radio1.encrypt(ENCRYPTKEY);
    radio2.encrypt(ENCRYPTKEY);
//    radio1.promiscuous(promiscuousMode);
    radio2.promiscuous(promiscuousMode);
}

Sending from 2nd RFM69:

Yellow - Second RFM69 SS. Blue - Second RFM69 Interrupt.

After sending from second RFM69 also Atmega328 froze  :)

I do not know what to do next :( Help please

farades

  • NewMember
  • *
  • Posts: 3
Re: 2 RFM69 & Moteino
« Reply #4 on: September 17, 2014, 04:25:36 AM »
Noticed this feature.
Poor working module, which is initialized to the first.

Code: [Select]
void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
        Serial.println("Second RFM69 OK");
    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
        Serial.println("First RFM69 OK");   
    radio1.encrypt(ENCRYPTKEY);
    radio2.encrypt(ENCRYPTKEY);
    radio1.promiscuous(promiscuousMode);
    radio2.promiscuous(promiscuousMode);
}

Result:
Code: [Select]
Second RFM69 OK
First RFM69 OK
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 2 RFM... Fail
Send From 2 RFM... Fail
Send From 2 RFM... Fail
Send From 2 RFM... Fail
Send From 2 RFM... Fail
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!
Send From 2 RFM... Fail
Send From 1 RFM...  ok!
Send From 1 RFM...  ok!

Code: [Select]
void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
        Serial.println("First RFM69 OK");
    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
        Serial.println("Second RFM69 OK");   
    radio1.encrypt(ENCRYPTKEY);
    radio2.encrypt(ENCRYPTKEY);
    radio1.promiscuous(promiscuousMode);
    radio2.promiscuous(promiscuousMode);
}

Result:
Code: [Select]
First RFM69 OK
Second RFM69 OK
Send From 1 RFM... Fail
Send From 1 RFM... Fail
Send From 1 RFM... Fail
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 1 RFM... Fail
Send From 2 RFM...  ok!
Send From 2 RFM...  ok!
Send From 1 RFM... Fail

Also, if you first sending with a "bad" (for the current firmware) RFM69 and then sending with a "good" (for the current firmware) RFM69 will be a delay.
Then, at a constant parcels with good RFM69 no delay.
For example:
Code: [Select]
First RFM69 OK
Second RFM69 OK
Send From 1 RFM...  !!!no delay!!! Fail
Send From 2 RFM...  !!!delay!!!    ok!
Send From 2 RFM...  !!!no delay!!! ok!
Send From 2 RFM...  !!!no delay!!! ok!
Send From 1 RFM...  !!!no delay!!! Fail
Send From 2 RFM...  !!!delay!!!    ok!

UPDATE:
New result:
If you send a "good" RFM69. That comes ACK.
If bad, then there is no ACK.

Sender result:
Code: [Select]
Second RFM69 OK
First RFM69 OK
Send From 1 RFM...  ok!
Send From 2 RFM... Fail

Receiver result:
Code: [Select]
[1] 123 A   [RX_RSSI:-34] - ACK sent
[2] 123 A   [RX_RSSI:-39] - ACK sent
[2] 123 A   [RX_RSSI:-40] - ACK sent
[2] 123 A   [RX_RSSI:-40] - ACK sent

Conclusions:
Homemade board -> Moteino:
With the RFM69 initialized last all is well.
With the first RFM69 initialized no ACK.
Moteino->Homemade board:
With the RFM69 initialized last, sending only occurs the first time. In this Atmega does not froze.
With the first RFM69 initialized not take anything.

UPDATE 2:
The problem is interrupted.
I corrected the library:
Code: [Select]
bool RFM69::initialize(byte freqBand, byte nodeID, byte networkID)
{
...
  if (_slaveSelectPin == 10)
    Serial.print("[1]: ");
  else if (_slaveSelectPin == 17)
    Serial.print("[2]: ");
  return true;
...
}


void RFM69::setMode(byte newMode)
{
  if (newMode == _mode) return; //TODO: can remove this?

  if (_slaveSelectPin == 10)
    Serial.print("[1]: ");
  else if (_slaveSelectPin == 17)
    Serial.print("[2]: ");
  switch (newMode) {
    case RF69_MODE_TX:
      writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER);
        if (_isRFM69HW) setHighPowerRegs(true);
          Serial.println("MODE_TX");
    break;
    case RF69_MODE_RX:
      writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);
      if (_isRFM69HW) setHighPowerRegs(false);
        Serial.println("MODE_RX");
    break;
    case RF69_MODE_SYNTH:
      writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER);
      Serial.println("MODE_SYNTH");
    break;
    case RF69_MODE_STANDBY:
      writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);
      Serial.println("MODE_STANDBY");
    break;
    case RF69_MODE_SLEEP:
      writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP);
      Serial.println("MODE_SLEEP");
    break;
    default: return;
}

void RFM69::interruptHandler() {
  if (_slaveSelectPin == 10)
    Serial.print("[1]: ");
  else if (_slaveSelectPin == 17)
    Serial.print("[2]: ");
  if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY))
  {
    ...
   Serial.println(" interrupt ok");
  }
  Serial.println("interrupt");
  RSSI = readRSSI();
}

Code: [Select]
void setup() {
    Serial.begin(SERIAL_BAUD);
    delay(10);
    if (radio1.initialize(FREQUENCY,NODEID_1,NETWORKID))
        Serial.println("First RFM69 OK");
    if (radio2.initialize(FREQUENCY,NODEID_2,NETWORKID))
        Serial.println("Second RFM69 OK");
    Serial.println();
    radio1.encrypt(ENCRYPTKEY);
    radio2.encrypt(ENCRYPTKEY);
    radio1.promiscuous(promiscuousMode);
    radio2.promiscuous(promiscuousMode);
}

Result
Code: [Select]
[1]: First RFM69 OK
[2]: Second RFM69 OK

Send From 1 RFM...
[1]: MODE_RX
[1]: MODE_STANDBY
[1]: MODE_TX
[2]: interrupt
[1]: MODE_STANDBY

Send From 1 RFM...
[1]: MODE_RX
[1]: MODE_STANDBY
[1]: MODE_TX
[2]: interrupt
[1]: MODE_STANDBY

Send From 2 RFM...
[2]: MODE_RX
[2]: MODE_STANDBY
[2]: MODE_TX
[2]: interrupt
[2]: MODE_STANDBY

Send From 2 RFM...
[2]: MODE_RX
[2]: MODE_STANDBY
[2]: MODE_TX
[2]: interrupt
[2]: MODE_STANDBY

Code: [Select]
[1] 123 A   [RX_RSSI:-29]
[1] 123 A   [RX_RSSI:-30]
[2] 123 A   [RX_RSSI:-35]
[2] 123 A   [RX_RSSI:-35]

Interrupt is triggered at the RFM69 which last initialized.
What to do?
« Last Edit: September 17, 2014, 07:24:11 AM by farades »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6867
  • Country: us
    • LowPowerLab
Re: 2 RFM69 & Moteino
« Reply #5 on: September 17, 2014, 09:07:00 AM »
One big tip: use a real logic analyzer, not a scope :)

kiwisincebirth

  • Jr. Member
  • **
  • Posts: 69
Re: 2 RFM69 & Moteino
« Reply #6 on: September 17, 2014, 10:23:19 PM »
Result
Code: [Select]
[1]: First RFM69 OK
[2]: Second RFM69 OK

Send From 1 RFM...
[1]: MODE_RX
[1]: MODE_STANDBY
[1]: MODE_TX
[2]: interrupt
[1]: MODE_STANDBY

Send From 1 RFM...
[1]: MODE_RX
[1]: MODE_STANDBY
[1]: MODE_TX
[2]: interrupt
[1]: MODE_STANDBY

Send From 2 RFM...
[2]: MODE_RX
[2]: MODE_STANDBY
[2]: MODE_TX
[2]: interrupt
[2]: MODE_STANDBY

Send From 2 RFM...
[2]: MODE_RX
[2]: MODE_STANDBY
[2]: MODE_TX
[2]: interrupt
[2]: MODE_STANDBY

Code: [Select]
[1] 123 A   [RX_RSSI:-29]
[1] 123 A   [RX_RSSI:-30]
[2] 123 A   [RX_RSSI:-35]
[2] 123 A   [RX_RSSI:-35]

Interrupt is triggered at the RFM69 which last initialized.
What to do?
This is what I would have expected to happen, based on how the code has been written. The problem (as stated above) is the 'static' declaration of variables. In this case the variable 'static RFM69* selfPointer;'. If you search the code for this variable you will see it is used as part of interrupt handling.