Skip to content

Commit

Permalink
version V2.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
glynhudson committed Aug 2, 2020
1 parent 8d0539c commit 9b7d534
Show file tree
Hide file tree
Showing 9 changed files with 577 additions and 211 deletions.
7 changes: 5 additions & 2 deletions Examples/EmonTxV34CM_max/EmonTxV34CM_max.ino
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Application Interface section of the User Documentation gives full details.
*/

#include <Arduino.h>
#include "emonLibCM.h"
#include "emonLibCMx.h"

#define RF69_COMPAT 1 // Set to 1 if using RFM69CW, or 0 if using RFM12B
#define RF69_COMPAT 0 // Set to 1 if using RFM69CW, or 0 if using RFM12B
#include <JeeLib.h> // https://github.com/jcw/jeelib - Tested with JeeLib 10 April 2017
// ISR(WDT_vect) { Sleepy::watchdogEvent(); }

Expand Down Expand Up @@ -170,4 +170,7 @@ void loop()
}
}
}
else
rf12_recvDone();

}
4 changes: 3 additions & 1 deletion Examples/EmonTxV34CM_min/EmonTxV34CM_min.ino
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ void loop()

delay(10);


}
else
rf12_recvDone();

}
100 changes: 100 additions & 0 deletions Examples/EmonTxV34CM_min_RFM69/EmonTxV34CM_min_RFM69.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
"Minimal" sketch to demonstrate emonLibCM - not using JeeLib
ONLY the Hope RFM69CW radio is suitable for use with this sketch.
This sketch assumes that the default values for the emonTx V3.4 are
applicable, that no input calibration is required, mains frequency
is 50 Hz and data logging period interval is 10 s, pulse counting
and temperature monitoring are not required, and that 4 'standard'
100 A CTs and the UK a.c. adapter from the OEM Shop are being used.
*/
#include <Arduino.h>
#include "emonLibCM.h"
#include <SPI.h>
#include <util/crc16.h>


// ISR(WDT_vect) { Sleepy::watchdogEvent(); }


enum rfband {RF12_433MHZ = 1, RF12_868MHZ, RF12_915MHZ}; // frequency bands.
void rfm_init(byte RF_freq = RF12_433MHZ);
bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const byte rf_power = 0x99, const int threshold = -97, const byte timeout = 15);

#define RFMSELPIN 10 // RFM pins
#define RFMIRQPIN 2 // RFM pins

const int nodeID = 10; // node ID for this emonTx. This sketch does NOT interrogate the DIP switch.

const int networkGroup = 210; // wireless network group - OEM standard is 210

/*
emonhub.conf nodeid is 10 - switch is ignored)
See: https://github.com/openenergymonitor/emonhub/blob/emon-pi/configuration.md
[[10]]
nodename = emontx1
[[[rx]]]
names = power1, power2, power3, power4, vrms, temp1, temp2, temp3, temp4, temp5, temp6, pulse
datacode = h
scales = 1,1,1,1,0.01,0.1,0.1,0.1,0.1,0.1,0.1,1
units =W,W,W,W,V,C,C,C,C,C,C,p
*/

struct {int power1, power2, power3, power4, Vrms, T1, T2, T3, T4, T5, T6; unsigned long pulseCount; } emontx; // package the data for RF comms


void setup()
{

Serial.begin(9600);
Serial.println("Set baud=115200");
Serial.end();
Serial.begin(115200);

Serial.println("\nEmonTx v3.4 EmonLibCM Continuous Monitoring Minimal Demo - not using JeeLib");

rfm_init(); // initialize radio module - Default = 433 MHz. You must use the frequency matching the module you have.

EmonLibCM_Init(); // Start continuous monitoring.

}

void loop()
{

if (EmonLibCM_Ready())
{

Serial.println(EmonLibCM_acPresent()?"AC present ":"AC missing ");
delay(5);

emontx.power1 = EmonLibCM_getRealPower(0); // Copy the desired variables ready for transmission
emontx.power2 = EmonLibCM_getRealPower(1);
emontx.power3 = EmonLibCM_getRealPower(2);
emontx.power4 = EmonLibCM_getRealPower(3);
emontx.Vrms = EmonLibCM_getVrms() * 100;

rfm_send((byte *)&emontx, sizeof(emontx), networkGroup, nodeID); //send data: Defaults: power = 0x99, threshold = -97 dB, timeout = 15 ms
delay(50);

Serial.print(" V=");Serial.println(EmonLibCM_getVrms());

for (byte ch=0; ch<4; ch++)
{
Serial.print("Ch ");Serial.print(ch+1);
Serial.print(" I=");Serial.print(EmonLibCM_getIrms(ch),3);
Serial.print(" W=");Serial.print(EmonLibCM_getRealPower(ch));
Serial.print(" VA=");Serial.print(EmonLibCM_getApparentPower(ch));
Serial.print(" Wh=");Serial.print(EmonLibCM_getWattHour(ch));
Serial.print(" pf=");Serial.print(EmonLibCM_getPF(ch),4);
Serial.println();
delay(10);
}
}
}
229 changes: 229 additions & 0 deletions Examples/EmonTxV34CM_min_RFM69/rfm.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
Interface for the RFM69CW Radio Module
Routines for Transmit-only, with Channel Busy detection.
========================================================
Required definitions in main sketch:
#define RFMSELPIN 10 // RFM pins
#define RFMIRQPIN 2 // RFM pins
// RFM Power setting - see below for more information
#include <SPI.h>
#include <util/crc16.h>
enum rfband {RF12_433MHZ = 1, RF12_868MHZ, RF12_915MHZ }; // frequency band.
Functions:
void rfm_init(byte RF_freq);
Initialises the radio module to JeeLib protocol standards
RF_freq - must be either 1 (=433 MHz), 2 (=868 MHz) or 3 (=915 MHz)
bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const byte rf_power, const int threshold, const byte timeout)
Transmits the data
data - byte stream to be transmitted
size - length of the data
group - transmission group: 210 for OEM
node - the unique ID of this node (1 - 30)
rf_power - Min value is 0x80 (-18 dBm), max is 0x9F (+13 dBm) -- RFM12B equivalent: 0x99
threshold - the RSSI level below which the radio channel is considered clear (suggested value: -97)
timeout - the maximum time in milliseconds that the function will wait for the channel to become clear,
after which it transmits regardless. Suggested value: 10
returns: true if no timeout occurred, otherwise false.
*/


#include <avr/sleep.h>
#define REG_FIFO 0x00
#define REG_OPMODE 0x01
#define MODE_SLEEP 0x00
#define MODE_TRANSMITTER 0x0C
#define MODE_RECEIVER 0x10
#define REG_DIOMAPPING1 0x25
#define REG_IRQFLAGS1 0x27
#define MODE_READY 0x80
#define REG_IRQFLAGS2 0x28
#define IRQ2_FIFOFULL 0x80
#define IRQ2_FIFONOTEMPTY 0x40
#define IRQ2_PACKETSENT 0x08
#define IRQ2_FIFOOVERRUN 0x10
#define REG_PACKET_CONFIG2 0x3D
#define RESTART_RX 0x04
#define REG_RSSI_CONFIG 0x23
#define RSSI_START 0x01
#define RSSI_DONE 0x02
#define REG_RSSI_VALUE 0x24


void rfm_init(byte RF_freq)
{
// Set up to drive the Radio Module
digitalWrite(RFMSELPIN, HIGH);
pinMode(RFMSELPIN, OUTPUT);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(0);
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present

// Initialise RFM69CW
do
writeReg(0x2F, 0xAA); // RegSyncValue1
while (readReg(0x2F) != 0xAA) ;
do
writeReg(0x2F, 0x55);
while (readReg(0x2F) != 0x55);

writeReg(0x01, 0x04); // RegOpMode: RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY
writeReg(0x02, 0x00); // RegDataModul: RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 = no shaping
writeReg(0x03, 0x02); // RegBitrateMsb ~49.23k BPS
writeReg(0x04, 0x8A); // RegBitrateLsb
writeReg(0x05, 0x05); // RegFdevMsb: ~90 kHz
writeReg(0x06, 0xC3); // RegFdevLsb
if (RF_freq == RF12_868MHZ)
{
writeReg(0x07, 0xD9); // RegFrfMsb: Frf = Rf Freq / 61.03515625 Hz = 0xD90000 = 868.00 MHz as used JeeLib
writeReg(0x08, 0x00); // RegFrfMid
writeReg(0x09, 0x00); // RegFrfLsb
}
else if (RF_freq == RF12_915MHZ) // JeeLib uses 912.00 MHz
{
writeReg(0x07, 0xE4); // RegFrfMsb: Frf = Rf Freq / 61.03515625 Hz = 0xE40000 = 912.00 MHz as used JeeLib
writeReg(0x08, 0x00); // RegFrfMid
writeReg(0x09, 0x00); // RegFrfLsb
}
else // default to 433 MHz band
{
writeReg(0x07, 0x6C); // RegFrfMsb: Frf = Rf Freq / 61.03515625 Hz = 0x6C8000 = 434.00 MHz as used JeeLib
writeReg(0x08, 0x80); // RegFrfMid
writeReg(0x09, 0x00); // RegFrfLsb
}
// writeReg(0x0B, 0x20); // RegAfcCtrl:
// writeReg(0x11, 0x99); // Transmit Power - set at transmit time
writeReg(0x1E, 0x2C); //
writeReg(0x25, 0x80); // RegDioMapping1: DIO0 is used as IRQ
writeReg(0x26, 0x03); // RegDioMapping2: ClkOut off
writeReg(0x28, 0x00); // RegIrqFlags2: FifoOverrun

// RegPreamble (0x2c, 0x2d): default 0x0003
writeReg(0x2E, 0x88); // RegSyncConfig: SyncOn | FifoFillCondition | SyncSize = 2 bytes | SyncTol = 0
writeReg(0x2F, 0x2D); // RegSyncValue1: Same as JeeLib
writeReg(0x37, 0x00); // RegPacketConfig1: PacketFormat=fixed | !DcFree | !CrcOn | !CrcAutoClearOff | !AddressFiltering >> 0x00
}


// transmit data via the RFM69CW
bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const byte rf_power, const int threshold, const byte timeout) // *SEND RF DATA
{
// rf_power: RegPaLevel = 0x9F = PA0 on, +13 dBm -- RFM12B equivalent: 0x99 | 0x88 (-10dBm) appears to be the max before the AC power supply fails @ 230 V mains. Min value is 0x80 (-18 dBm)
unsigned long t_start = millis();
bool success = false; // return false if timed out, else true

writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | MODE_RECEIVER); // Receive mode - sniff for channel is busy
while ((millis()-t_start)<(unsigned long)timeout)
{
while((readReg(REG_IRQFLAGS1) & MODE_READY) == 0)
;
writeReg(REG_RSSI_CONFIG, RSSI_START);
while((readReg(REG_RSSI_CONFIG) & RSSI_DONE) == 0x00)
;

if (readReg(REG_RSSI_VALUE) > (threshold * -2)) // because REG_RSSI_VALUE is upside down!
{
success = true;
break; // Nothing heard - go ahead and transmit
}
writeReg(REG_PACKET_CONFIG2, (readReg(REG_PACKET_CONFIG2) & 0xFB) | RESTART_RX); // Restart the receiver
}

// Either we can transmit now, or we have waited long enough - go ahead and transmit anyway

writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | MODE_SLEEP); // Sleep

while (readReg(REG_IRQFLAGS2) & (IRQ2_FIFONOTEMPTY | IRQ2_FIFOOVERRUN)) // Flush FIFO
readReg(REG_FIFO);
writeReg(0x30, group); // RegSyncValue2

writeReg(REG_DIOMAPPING1, 0x00); // PacketSent

volatile uint8_t txstate = 0;
byte i = 0;
uint16_t crc = _crc16_update(~0, group);

while(txstate < 7)
{
if ((readReg(REG_IRQFLAGS2) & IRQ2_FIFOFULL) == 0) // FIFO !full
{
uint8_t next;
switch(txstate)
{
case 0: next=node & 0x1F; txstate++; break; // Bits: CTL, DST, ACK, Node ID(5)
case 1: next=size; txstate++; break; // No. of payload bytes
case 2: next=data[i++]; if(i==size) txstate++; break;
case 3: next=(byte)crc; txstate++; break;
case 4: next=(byte)(crc>>8); txstate++; break;
case 5:
case 6: next=0xAA; txstate++; break; // dummy bytes (if < 2, locks up)
}
if(txstate<4) crc = _crc16_update(crc, next);
writeReg(REG_FIFO, next); // RegFifo(next);
}
}
//transmit buffer is now filled, transmit it
writeReg(0x11, rf_power);
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | MODE_TRANSMITTER); // Transmit mode - 56 Bytes max payload

rfm_sleep();
return success;

}

void rfm_sleep(void)
{
// Put into sleep mode when buffer is empty
while (!(readReg(REG_IRQFLAGS2) & IRQ2_PACKETSENT)) // wait for transmission to complete (not present in JeeLib)
delay(1); //

writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | 0x01); // Standby Mode
}



void writeReg(uint8_t addr, uint8_t value)
{
select();
SPI.transfer(addr | 0x80);
SPI.transfer(value);
unselect();
}

uint8_t readReg(uint8_t addr)
{
select();
SPI.transfer(addr & 0x7F);
uint8_t regval = SPI.transfer(0);
unselect();
return regval;
}

// select the transceiver
void select()
{
noInterrupts();
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
digitalWrite(RFMSELPIN, LOW);
}

// UNselect the transceiver chip
void unselect()
{
digitalWrite(RFMSELPIN, HIGH);
interrupts();
}

Binary file modified emonLibCM User Doc.pdf
Binary file not shown.
Loading

0 comments on commit 9b7d534

Please sign in to comment.