LowPowerLab Forum

Hardware support => Moteino => Topic started by: A on December 10, 2013, 02:01:51 AM

Title: Moteino Two Way Tester Sketch (Work in progress)
Post by: A on December 10, 2013, 02:01:51 AM
As the result of this thread. (http://lowpowerlab.com/forum/index.php/topic,227.0.html)

Here is a sketch that combines the functions of the Node and Gateway demo sketches. It currently transmits out the test string to nodes 1 through 7, and replies back with which nodes ACK'd. Currently each node must have a NODEID manually set, I'd like to either set this randomly or by first listening for other nodes currently broadcasting and then incrementally setting them (1, then 2, then 3).

There is a chance to end up with two nodes that are integer multiples of each other (e.g. 2 & 4) in sync and transmitting on top of each other, however this isn't super likely given how quickly these guys get on an off the air. Another option would be to only use primes for NODEIDs so that they don't ever properly lock-step.

Still some commented out (incomplete) nested loops that might turn into keeping the radio in TX mode and doing multiple transmissions of the string in the 1 second period that the node is TX mode (would get 3x transmissions with TRANSMITPERIOD set to 300).

This was kind of a one-off programming exercise for me tonight. I might come back to it or I might not. If anyone makes any future improvements, please reply to this thread with what you've done with it.

Enjoy!

// Sample RFM69 Two way tester sketch, with /*ACK and*/ optional encryption
// On a 1 to 7 second interval (determined by NODEID), transmits
// For other time slices passes through any wireless received messages to the serial port
// Responds to ACKs when not transmiting
// It also looks for an onboard FLASH chip, if present
// Based Very heavily on the Gateway & Node example sketches by Felix Rusu
// Modified by A - My changes are released into the public domain
// Library and code by Felix Rusu - [email protected]
// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/

#include <RFM69.h>
#include <SPI.h>
#include <SPIFlash.h>

#define NODEID        1    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ACK_TIME      30 // max # of ms to wait for an ack
#define LED           9  // Moteinos have LEDs on D9
#define SERIAL_BAUD   115200

int TRANSMITPERIOD = 300; //transmit a packet to gateway so often (in ms)
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buff[20];
byte sendSize=0;
boolean requestACK = false;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nOperating at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  if (flash.initialize())
    Serial.println("SPI Flash Init OK!");
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

byte ackCount=0;
long lastPeriod = -1;
long lastIdentityPeriod = -1;
int IdentityPeriod = NODEID * 1000; // In seconds //Needs to be changed to be random from list of primes

void loop() {
  //process any serial input
  if (Serial.available() > 0)
  {
    char input = Serial.read();
    if (input == 'r') //d=dump all register values
      radio.readAllRegs();
    if (input == 'E') //E=enable encryption
      radio.encrypt(ENCRYPTKEY);
    if (input == 'e') //e=disable encryption
      radio.encrypt(null);
    if (input == 'p')
    {
      promiscuousMode = !promiscuousMode;
      radio.promiscuous(promiscuousMode);
      Serial.print("Promiscuous mode ");Serial.println(promiscuousMode ? "on" : "off");
    }
   
    if (input == 'd') //d=dump flash area
    {
      Serial.println("Flash content:");
      int counter = 0;

      while(counter<=256){
        Serial.print(flash.readByte(counter++), HEX);
        Serial.print('.');
      }
      while(flash.busy());
      Serial.println();
    }
    if (input == 'e')
    {
      Serial.print("Erasing Flash chip ... ");
      flash.chipErase();
      while(flash.busy());
      Serial.println("DONE");
    }
    if (input == 'i')
    {
      Serial.print("DeviceID: ");
      word jedecid = flash.readDeviceId();
      Serial.println(jedecid, HEX);
    }
    if (input == 't')
    {
      byte temperature =  radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient
      byte fTemp = 1.8 * temperature + 32; // 9/5=1.8
      Serial.print( "Radio Temp is ");
      Serial.print(temperature);
      Serial.print("C, ");
      Serial.print(fTemp); //converting to F loses some resolution, obvious when C is on edge between 2 values (ie 26C=78F, 27C=80F)
      Serial.println('F');
    }
  }

  //check for any received packets
  if (radio.receiveDone())
  {
    Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
    if (promiscuousMode)
    {
      Serial.print("to [");Serial.print(radio.TARGETID, 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.ACK_REQUESTED)
    {
      byte theNodeID = radio.SENDERID;
      radio.sendACK();
      Serial.print(" - ACK sent.");

      // When a node requests an ACK, respond to the ACK
      // and also send a packet requesting an ACK (every 3rd one only)
      // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY
      if (ackCount++%3==0)
      {
        Serial.print(" Pinging node ");
        Serial.print(theNodeID);
        Serial.print(" - ACK...");
        delay(3); //need this when sending right after reception .. ?
        if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0))  // 0 = only 1 attempt, no retries
          Serial.print("ok!");
        else Serial.print("nothing");
      }
     
    }
    Serial.println();
    Blink(LED,3);
  }
 
  int currIdentityPeriod = millis()/IdentityPeriod;
  if (currIdentityPeriod != lastIdentityPeriod)
  {
  lastIdentityPeriod=currIdentityPeriod;

//  int currPeriod = millis()/TRANSMITPERIOD;
//  if (currPeriod != lastPeriod)
//  {
//  lastPeriod=currPeriod;
          for(byte target = 1; target < 8; target++)
          {
  Serial.print("Sending[");
  Serial.print(sendSize);
  Serial.print("] to node ");
                Serial.print(target);
                Serial.print(": ");
                  for(byte i = 0; i < sendSize; i++)
                    Serial.print((char)payload[i]);

                    if (radio.sendWithRetry(target, payload, sendSize))
  Serial.println(" ok!");
                    else Serial.println(" nothing...");
                 
                }

    sendSize = (sendSize + 1) % 31;
    Serial.println();
Blink(LED,3);
// }
  }
}

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