Congrats on the new Moteino R4 (http://lowpowerlab.com/blog/2013/10/23/moteino-r4-is-here/) designs; looks good! The R4-USB looks similar in function to the JeeLink (http://jeelabs.com/products/jeelink) which is not entirely cheap at 32.5 Euro, or $36.50 from ModernDevice (http://moderndevice.com/product/jeelink-module-assembled/).
So feel free to price your R4-USB lower than that, if you can! :-)
Does having a single board to host either RFM12B or RFM69W/HW modules imply that we will eventually be able to inter-operate (eg. some code that can send packets from the 12B and receive them on the 69W, or the reverse?) Just this week I put in an order for several Moteino R3 modules since the RFM69 looks like the wave of the future, but I still have a number of JeeNodes and it would be nice to have them all talk to one host, if possible.
Thanks, I will try to price it lower :)
I really want to make the two libs talk to each other, however there are a few breaking decisions to make - like encryption. To mention just one - the 12B has no AES hardware encryption, which means I either figure out how to implement the exact same algorithm in firmware (which could prove difficult and increase the code significantly) or drop it on both ends (which I don't want since encryption is pretty vital) or maybe implement the simplistic encryption in the 12b lib on the RFM69 (which defeats the purpose of having the fast AES hardware encryption). Then there's the packet engine which is different, etc. I did try to make them talk early on with the most default settings but had no success. I probably did not match the settings exactly right and I don't have the expensive tools to analyze RF signals and such. Maybe the experts in the forum can devise a clever solution...
Perhaps a bridge between the two types of transceiver networks would be more within reach.
Do I see pads for a UF l coax connector?
I wanted to add that but didn't really find a good way to place it. On the other hand it could be soldered between the ANT and GND pads which are spaced just right to make that possible.
In fact both UF.l and SMA connectors can be soldered with a little care. I will take some photos of both of those and post them to the blog sometime...
Yes. I've been doing that. Was using SMA, now Uf.l. Glad the pads still accommodate Uf.l
Glad to see you're still innovating!
BTW did you just add a spell checker to the forum?
Thanks. No I didn't add a spell checker.
Just got some of the new R4 boards in (I'd ordered them as R3, before the announcement). Very happy to see them working nicely. It is really great to see the RSSI readout, as previously I've only used RFM12B units where you had to guess. You really get to see what matters and what doesn't as far as antennas, positions, & etc. It looks like (for the RFM69W unit) the difference between max and min Tx power settings
radio.setPowerLevel(0); // 0 = min power, 31 = max power
is consistently 35 dB in reported RSSI at the other end.
According to the data sheet the Tx power range is -18 to +13 dB, which is a range of 31 dB. I'm sending 3 packets at low power and 3 at high power, and the readings are pretty steady, within 2 units. I guess it's just that the RSSI units are not exactly calibrated at 1.0 dB per unit.
[99] [RX_RSSI:-87] 18 - ACK sent.Lo Pinging node 99 - ACK...ok! 999,957,1019,100
[99] [RX_RSSI:-86] 19 - ACK sent.Hi Pinging node 99 - ACK...ok! 1000,957,1019,101
[99] [RX_RSSI:-86] 20 - ACK sent.Lo Pinging node 99 - ACK...ok! 997,957,1019,102
[99] [RX_RSSI:-51] 21 - ACK sent.Hi Pinging node 99 - ACK...ok! 999,957,1019,103
[99] [RX_RSSI:-51] 22 - ACK sent.Lo Pinging node 99 - ACK...ok! 997,957,1019,104
[99] [RX_RSSI:-51] 23 - ACK sent.Hi Pinging node 99 - ACK...ok! 1000,957,1019,105
[99] [RX_RSSI:-86] 24 - ACK sent.Lo Pinging node 99 - ACK...ok! 997,957,1019,106
[99] [RX_RSSI:-87] 25 - ACK sent.Hi Pinging node 99 - ACK...ok! 1000,957,1019,107
[99] [RX_RSSI:-86] 26 - ACK sent.Lo Pinging node 99 - ACK...ok! 997,957,1019,108
[99] [RX_RSSI:-51] 27 - ACK sent.Hi Pinging node 99 - ACK...ok! 999,957,1019,109
[99] [RX_RSSI:-51] 28 - ACK sent.Lo Pinging node 99 - ACK...ok! 998,957,1019,110
[99] [RX_RSSI:-51] 29 - ACK sent.Hi Pinging node 99 - ACK...ok! 999,957,1019,111
[99] [RX_RSSI:-86] 30 - ACK sent.Lo Pinging node 99 - ACK...ok! 1001,957,1019,112
[99] [RX_RSSI:-86] 0 - ACK sent.Hi Pinging node 99 - ACK...ok! 993,957,1019,113
[99] [RX_RSSI:-86] 1 - ACK sent.Lo Pinging node 99 - ACK...ok! 998,957,1019,114
In case of interest- what generated output in previous post:
slightly modified node sketch
#include <RFM69.h>
#include <SPI.h>
#include <SPIFlash.h>
#define NODEID 99
#define NETWORKID 100
#define GATEWAYID 1
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define LED 9
#define SERIAL_BAUD 115200
#define ACK_TIME 30 // # of ms to wait for an ack
int TRANSMITPERIOD = 1000; //transmit a packet to gateway so often (in ms)
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
byte sendSize=0;
boolean requestACK = false;
bool hiPower = true; // set radio Tx to maximum power
long packetCount = 0;
SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip
RFM69 radio;
void setup() {
Serial.begin(SERIAL_BAUD);
radio.initialize(FREQUENCY,NODEID,NETWORKID);
//radio.setHighPower(); //must uncomment for RFM69HW!
radio.encrypt(KEY);
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.println("SPI Flash Init OK!");
else
Serial.println("SPI Flash Init FAIL! (is chip present?)");
}
long lastPeriod = -1;
void loop() {
//process any serial input
if (Serial.available() > 0)
{
char input = Serial.read();
if (input == 'r') //d=dump register values
radio.readAllRegs();
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);
}
}
//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.readRSSI());Serial.print("]");
if (radio.ACK_REQUESTED)
{
radio.sendACK();
Serial.print(" - ACK sent");
delay(10);
}
Blink(LED,5);
Serial.println();
}
int currPeriod = millis()/TRANSMITPERIOD;
if (currPeriod != lastPeriod)
{
lastPeriod=currPeriod;
Serial.print(packetCount);
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...");
if (hiPower) radio.setPowerLevel(31);
else radio.setPowerLevel(0); // 0 = min power, 31 = max power
if ((packetCount++)%3==0)
hiPower = !hiPower; // toggle signal strength
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);
}
slightly modified gateway sketch
#include <RFM69.h>
#include <SPI.h>
#include <SPIFlash.h>
#define NODEID 1
#define NETWORKID 100
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define LED 9
#define SERIAL_BAUD 115200
#define ACK_TIME 30 // # of ms to wait for an ack
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
bool showData = false; // should we print out the received packet?
bool firstPacket = true; // is this the first packet ever received?
bool hiPower = true; // set radio Tx to maximum power
long totalRec = 0; // total # packets received
long lastTime; // time of most recent reception
long maxTime = 0; // maximum time interval between packet reception
long minTime = 1000000; // minimum time interval between packets
void setup() {
Serial.begin(SERIAL_BAUD);
delay(10);
radio.initialize(FREQUENCY,NODEID,NETWORKID);
//radio.setHighPower(); //must uncomment for RFM69HW!
radio.encrypt(KEY);
radio.promiscuous(promiscuousMode);
char buff[50];
sprintf(buff, "\nListening 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;
void loop() {
long thisTime; // current time of packet reception
long dTime; // interval between current & previous packets
//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(KEY);
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');
}
}
if (radio.receiveDone())
{
totalRec += 1; // total number of packets received
if (firstPacket == true) {
lastTime = millis();
firstPacket = false;
} else {
thisTime = millis();
dTime = thisTime - lastTime;
lastTime = thisTime;
if (dTime > maxTime) maxTime = dTime;
if (dTime < minTime) minTime = dTime;
}
Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
if (promiscuousMode)
{
Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] ");
}
if (showData == true) {
for (byte i = 0; i < radio.DATALEN; i++)
Serial.print((char)radio.DATA[i]);
}
Serial.print(" [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("] ");
Serial.print(radio.DATALEN);
if (radio.ACK_REQUESTED)
{
byte theNodeID = radio.SENDERID;
radio.sendACK();
Serial.print(" - ACK sent.");
if (hiPower) Serial.print("Hi ");
else Serial.print("Lo ");
// 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)
if (true)
{
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");
}
if (hiPower) radio.setPowerLevel(31);
else radio.setPowerLevel(0); // 0 = min power, 31 = max power
hiPower = !hiPower; // toggle signal strength
}
if (firstPacket == false) {
Serial.print(" ");
Serial.print(dTime);
Serial.print(",");
Serial.print(minTime);
Serial.print(",");
Serial.print(maxTime);
Serial.print(",");
Serial.print(totalRec);
}
Serial.println();
Blink(LED,3);
}
}
void Blink(byte PIN, int DELAY_MS)
{
pinMode(PIN, OUTPUT);
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}
I've checked the RSSI here with a lab grade signal generator and found a one to one relationship of dbm output power and RSSI. I remember being extremely impressed.
jbeale, now you have me thinking.
I'll have to check to see how well the radio Tx output power follows the power settings.
Hi Felix,
As per the spell checker.
IE was my old browser and I just switched to Firefox. Looks like it adds the spell checking.
I'm feeling much smarter now, posting in half the time! :0
@John k2ox: Seems to me that the Tx power level has a step right in the middle at a setting of 15 to 16. See attached graph (with Tx/Rx at very short range, about 6 feet). Looks like a little compression at the top end also, not too surprisingly.
Hm, weird step, but at least the rest looks pretty consistent...
I took some more data, here are two different Tx Moteino v4 (RFM69W) at several different distances, showing the received RSSI (from a 3rd Moteino, with modified gateway sketch) versus applied power level setting at the Tx side. Note the vertical axis shows absolute value of RSSI, but all the values really should be negative.
The HopeRF RFM69W data sheet says "Programmable Pout: -18 to +13 dBm in 1dB steps". Now, when I was a kid, my dad would start his after-dinner story with "I will tell you a story that is part true and part not true..." and this data sheet is kind of like that. You get basically 1 dB steps except where you don't, particularly around step 15 to step 16, and the magnitude and sign of that discontinuity changes between specific units. Also, one of the two I tested starts out with < 0.5 dB steps near max power, but the other one was near 1 dB.
Probably few people care about this- most will just use the default max power setting. But it is good to know, if you were relying on the power setting to make some kind of measurement.
(https://lh5.googleusercontent.com/-9Y5GnafRGhM/UmrE4jT0YEI/AAAAAAAADLM/F0HY9yEJryE/s800/Kst%2520-%2520CDocuments%2520and%2520SettingsJohnMy%2520DocumentsRPiRFM69W-PowerSet2.kst%252010252013%2520122017%2520PM.jpg)
Also of possible interest: with the default bitrate, in my setup, at -100 dB RSSI you get only about 1% of the packets through. At -97 dB you get about half of them. At -90 you only miss a few percent. This is with a very short packet (1 byte payload). RSSI is fractional in the table below because I am averaging over RSSI of all received packets with a given Tx power setting.
PowerSetting,NumPackets,abs(RSSI)
0,0,
1,0,
2,0,
3,0,
4,0,
5,1,100.000
6,10,98.800
7,24,98.500
8,62,97.516
9,86,96.686
10,103,96.019
11,100,94.940
12,113,94.177
13,112,93.009
14,114,91.947
15,116,90.948
16,113,92.487
17,114,91.561
18,115,90.400
19,115,89.678
20,115,88.635
21,117,87.556
22,117,86.615
23,117,85.521
24,117,84.590
25,117,83.803