LowPowerLab Forum

Hardware support => RF - Range - Antennas - RFM69 library => Topic started by: blebson on March 12, 2017, 12:28:41 AM

Title: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 12, 2017, 12:28:41 AM
I recently started a project to create Moteino powered automated blinds. I have been able to figure out everything so far other than how to set up my ESP8266 gateway to allow me to send values to the different Moteinos. I have a feeling it's something fairly simple that needs to be corrected in on the software side. I would share some code but I literally have nothing at this point past trying to get the Gateway example to work.

I am currently using the following WeMos D1 Mini Shield: https://github.com/hallard/WeMos-RFM69

I mistakenly assumed that using a published circuit board would reduce my software workload however lack of foresight and general software inexperience are getting the best of me. Is there anyone who can point me in the right direction in order to get this RFM69 shield working with my multiple Moteinos?
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: WhiteHare on March 12, 2017, 06:03:41 AM
https://lowpowerlab.com/forum/projects/(update)-rfm69-library-for-esp8266-moteino-compatible!/
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: Felix on March 12, 2017, 04:45:18 PM
For the blinds part check out this project too (http://snorp.net/2016/05/20/blinds-controller.html)!
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 12, 2017, 05:08:50 PM
That is the project that got me interested in using the Moteino. I have designed a moteino shield which will allow me to control the blinds using a servo. I'm also integrating solar lipo charging as well in order to ensure I always have enough battery life. That side of it is all working, my issue is now actually sending commands to the blinds using HTTP GET commands. Ultimately I'm working to integrate this into my SmartThings Home Automation system. All of my experience is with hardware (I have a Mech/EE background) so I'm a bit over my head with the software side.

I was hoping to use your Arduino library with the ESP8266 so that I can keep everything on the same platform. Unfortunately it looks like the above linked RFM69 ESP library is no longer arduino based which moved me further outside of my comfort zone. Is there any way to define the custom pinout using the LowPowerLab RFM69 library? Or any other way of making my current board work with the Arduino IDE?
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: WhiteHare on March 12, 2017, 06:03:04 PM
ESP8266 has been working from the Arduino IDE for well over a year now.
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 12, 2017, 06:13:26 PM
The issue isn't programming the ESP, it's getting the ESP to talk with the RFM69 module using an Arduino library. I can flash the ESP with the gateway example after removing the flash references but nothing comes through.
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 13, 2017, 02:07:22 PM
I suppose the real question is; Is there any way to reassign what pins the RFM69W is connected to on the D1 Mini (or arduino) in regards to the RFM69 Library?
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: WhiteHare on March 13, 2017, 02:36:04 PM
I don't understand your question, but there does exist a very simple adapter board that will make the correct wiring connections for you between a D1 Mini and an RFM69HW:  https://www.openhardware.io/view/277/ESP8266-RFM69HW-gateway-with-dipole-antenna

If you want just a monopole antenna, rather than a dipole antenna, you can leave off the GND antenna leg.

If you go looking, there are a lot of other similar boards out there also.  I think the one linked to above, though, may be the simplest.

Alternatively, just use a Moteino and connect that to a D1 Mini.  If you opt to go that route instead, here's a different simple adapter board that will do that:  https://www.openhardware.io/view/273/ESP-LINK-ESP8266-WeMos-D1-Mini-Adapter-Board


Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 13, 2017, 03:52:22 PM
I have a board already created as linked in the OP. I'm just trying to get it to work with the RFM69 library within Arduino. (https://github.com/hallard/WeMos-RFM69)

I'm trying to see if it is possible to get that board to work or if I will have to start over and get one of the other RFM69 adapters.
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: WhiteHare on March 13, 2017, 05:17:28 PM
Hallard tends to pile a lot onto his boards.  That's can be great when it all works, but harder to debug when it doesn't.  Not really a criticism.  Just an observation about more complex systems generally.
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 13, 2017, 05:22:47 PM
I can determine which pins are connected between the RFM and the ESP, I just need some way to use that info to get the RFM library to work. Is that even possible?
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: WhiteHare on March 13, 2017, 05:30:52 PM
It boils down to this:
1.  Is the RFM69 getting adequate power at the right voltage?  You can check that with a multimeter and/or an o-scope.
2.  Is the SPI communication working between the RFM69 and the ESP8266.  You can check that with a logic probe.

The RFM69 library uses the generic arduino SPI communication library. 

Are you sure you followed all the directions in the original thread, including adding the ESP8266 pin definitions to the RFM69 library?
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 13, 2017, 05:41:38 PM
I will have to go back and confirm. It is likely that I didn't add the definitions properly or something. I'll give it a try after work and let you know. I'll also check the power to the RFM69 and the SPI communication. Thanks for the suggestions.
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 13, 2017, 11:58:59 PM
So I confirmed that my RFM69.h and RFM69.cpp were properly modified. The one thing I've noticed about the board I'm using is that it has a different pin-out than the ones posted about in the ESP thread. Mine uses the following:

Node  ESP            RFM69W
D8     GPIO15     DIO0 (interrupt)
D5     GPIO14     SCK (spi clock)
D6     GPIO12     MISO (spi miso)
D7     GPIO13     MOSI (spi mosi)
D0     GPIO16     NSS (spi ss)
+3V                    3.3V
G                        GND

compared to:

Node  ESP            RFM69HW
D2     GPIO04     DIO0 (interrupt)
D5     GPIO14     SCK (spi clock)
D6     GPIO12     MISO (spi miso)
D7     GPIO13     MOSI (spi mosi)
D8     GPIO15     NSS (spi ss)
+3V                    3.3V
G                        GND

Also, I confirmed that the RFM69 chip is getting 3.3v (3.28v) and that the DIO0 pin is getting a signal from the ESP when it tries to transmit.

Below is the code I'm currently trying to use to test:

Code: [Select]
// Sample RFM69 sender/node sketch, with ACK and optional encryption, and Automatic Transmission Control
// Sends periodic messages of increasing length to gateway (id=1)
// It also looks for an onboard FLASH chip, if present
// RFM69 library and sample code by Felix Rusu - http://LowPowerLab.com/contact
// Copyright Felix Rusu (2015)

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h>//get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
//#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash

//*********************************************************************************************
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NODEID        2    //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
#define NETWORKID     100  //the same on all nodes that talk to each other (range up to 255)
#define GATEWAYID     1
//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 ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ESP8266
//*********************************************************************************************

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#define SERIAL_BAUD   115200

int TRANSMITPERIOD = 150; //transmit a packet to gateway so often (in ms)
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buff[20];
byte sendSize=0;
boolean requestACK = false;
//SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)

#ifdef ENABLE_ATC
  RFM69_ATC radio;
#else
  RFM69 radio;
#endif

void setup() {
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  //radio.setFrequency(919000000); //set frequency to some custom frequency

//Auto Transmission Control - dials down transmit power to save battery (-100 is the noise floor, -90 is still pretty good)
//For indoor nodes that are pretty static and at pretty stable temperatures (like a MotionMote) -90dBm is quite safe
//For more variable nodes that can expect to move or experience larger temp drifts a lower margin like -70 to -80 would probably be better
//Always test your ATC mote in the edge cases in your own environment to ensure ATC will perform as you expect
#ifdef ENABLE_ATC
  radio.enableAutoPower(-70);
#endif

  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);

//  if (flash.initialize())
//  {
//    Serial.print("SPI Flash Init OK ... UniqueID (MAC): ");
//    flash.readUniqueId();
//    for (byte i=0;i<8;i++)
//    {
//      Serial.print(flash.UNIQUEID[i], HEX);
//      Serial.print(' ');
//    }
//    Serial.println();
//  }
//  else
//    Serial.println("SPI Flash MEM not found (is chip soldered?)...");

#ifdef ENABLE_ATC
  Serial.println("RFM69_ATC Enabled (Auto Transmission Control)\n");
#endif
}

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

long lastPeriod = 0;
void loop() {
  //process any serial input
  if (Serial.available() > 0)
  {
    char input = Serial.read();
    if (input >= 48 && input <= 57) //[0,9]
    {
      TRANSMITPERIOD = 100 * (input-48);
      if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000;
      Serial.print("\nChanging delay to ");
      Serial.print(TRANSMITPERIOD);
      Serial.println("ms\n");
    }

    if (input == 'r') //d=dump register values
      radio.readAllRegs();
    //if (input == 'E') //E=enable encryption
    //  radio.encrypt(KEY);
    //if (input == 'e') //e=disable encryption
    //  radio.encrypt(null);

//    if (input == 'd') //d=dump flash area
//    {
//      Serial.println("Flash content:");
//      uint16_t counter = 0;
//
//      Serial.print("0-256: ");
//      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);
//    }
  }

  //check for any received packets
  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,3);
    Serial.println();
  }

  int currPeriod = millis()/TRANSMITPERIOD;
  if (currPeriod != lastPeriod)
  {
    lastPeriod=currPeriod;

    //send FLASH id
//    if(sendSize==0)
//    {
//      sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId());
//      byte buffLen=strlen(buff);
//      if (radio.sendWithRetry(GATEWAYID, buff, buffLen))
//        Serial.print(" ok!");
//      else Serial.print(" nothing...");
//      //sendSize = (sendSize + 1) % 31;
//    }
//    else
//    {
      Serial.print("Sending[");
      Serial.print(sendSize);
      Serial.print("]: ");
      for(byte i = 0; i < sendSize; i++)
        Serial.print((char)payload[i]);

      if (radio.sendWithRetry(GATEWAYID, payload, sendSize))
       Serial.print(" ok!");
      else Serial.print(" nothing...");
//    }
    sendSize = (sendSize + 1) % 31;
    Serial.println();
    Blink(LED,3);
  }
}

Any suggestions of what to try next are greatly appreciated.
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 14, 2017, 01:08:03 AM
I finally got it working! I had to modify RFM69.h to read the following;

Code: [Select]
#elif defined(ESP8266)
  #define RF69_IRQ_PIN          D8  // needed for esp8266
  #define RF69_IRQ_NUM          D8  // needed for esp8266
  #define RF69_SPI_CS D0  // needed for esp8266
  #define LED 2   // LED on ESP12F is on GPIO2

The NSS pin was on D0 instead of D8 which was causing my issues. It now works perfectly with the following code:

Code: [Select]
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <SPI.h>
#include <RFM69.h>

const char* ssid = "SSID";
const char* password = "PASSWORD";
char reqBuffer[100];
MDNSResponder mdns;


//RADIO SETTINGS
#define FREQUENCY     RF69_915MHZ
#define ENCRYPT_KEY "sampleEncryptKey"
#define ADDRESS 1
#define NETWORK_ID 1
#define REMOTE_ADDRESS 2
#define BURST_REPLY_TIMEOUT_MS 250

RFM69 radio;

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);


void setup() {
  Serial.begin(115200);
  delay(10);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected");

  // Start the server
  server.begin();
  Serial.println("HTTP Server Started");

  // Print the IP address
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  Serial.println();
  Serial.println();

  radio.initialize(FREQUENCY, ADDRESS, NETWORK_ID);
  radio.encrypt(ENCRYPT_KEY);

}

char payload[5];

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while (!client.available()) {
    delay(1);
  }

  // Read the first line of the request
  String req = client.readStringUntil('\r');
  req.toCharArray(reqBuffer, 100);
  Serial.println(req);
  client.flush();

  // Match the request
  String level;
  String blindID;
  int levelInt;

  char *get = strtok(reqBuffer, " ");
  char *request = strtok(NULL, " ");
  char *rtype = strtok(NULL, " ");

  if (request != NULL) {
    char *part = strtok(request, "/");
    String request = String(part);
    Serial.println(request);
    bool seenBlind = false;
    while (part) { // While there is a section to process...

      if (seenBlind) {
        if (!strncmp(part, "level=", 6)) { // We have the ID
          level = String(part + 6);
          Serial.print("Level: ");
          Serial.println(level);
          levelInt = level.toInt();
        }
        else if (!strncmp(part, "ID=", 3)) { // We have the ID
          blindID = String(part + 3);
          Serial.print("Blind ID: ");
          Serial.println(blindID);
        }

      } else if (!strcmp(part, "Blind")) {
        seenBlind = true;
      }

      part = strtok(NULL, "/");
    }

    if ((level != null) && (blindID != null)) {

      sprintf(payload, "%d", levelInt);
      Serial.print("Sending command to Blind ");
      Serial.print(blindID);
      Serial.print(". Set to angle: ");
      Serial.print(payload);
      Serial.print("...");


      bool replied = false;
      int i = 0;
      while (!replied && i < 3) {
        radio.listenModeSendBurst(blindID.toInt(), payload, sizeof(payload));

        long start = millis();
        while (millis() - start < BURST_REPLY_TIMEOUT_MS) {
          if (radio.receiveDone()) {
            Serial.println("Success");
            replied = true;
            Blink(D3, 3);
            break;
          }
        }

        if (!replied) {
          Serial.println("Failed");
          Blink(D3, 3);
          i++;
        }
      }
    }
  }
  else {
    Serial.println("Invalid request.");
    client.stop();
    return;
  }

  client.flush();

  // Send the response to the client
  //client.print(s);
  client.print("HTTP/1.1 200 OK\r\n");
  delay(1);
  Serial.println("Client Disconnected");
  Serial.println();
  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN, HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN, LOW);
}
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: WhiteHare on March 14, 2017, 06:58:22 AM
Great!  I really do hope you continue to post, as it sounds like a cool project.   8)
Title: Re: Struggling with the basics - WeMos D1 Mini (ESP8266) - RFM69 Gateway
Post by: blebson on March 14, 2017, 11:38:28 AM
I'll be sure to put a post together once I have it all set up and working. I'm currently waiting on some circuit boards to be fabricated and then I have to create the interface program for my smart home (but that's the easy part :))