-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8d0539c
commit 9b7d534
Showing
9 changed files
with
577 additions
and
211 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,8 @@ void loop() | |
|
||
delay(10); | ||
|
||
|
||
} | ||
else | ||
rf12_recvDone(); | ||
|
||
} |
100 changes: 100 additions & 0 deletions
100
Examples/EmonTxV34CM_min_RFM69/EmonTxV34CM_min_RFM69.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
Oops, something went wrong.