Voltage from emontxv3 continuous sampling?

I have 2 emontx3s with RFM12B from Aug 2014. I’m using a continuous sampling sketch on them, but I don’t get voltage sent across. Is there any way to get it please? Thanks.

Which sketch are you using? emonLibCM makes the voltage available - see the documentation that came with your download.

Moments ago, I looked at the “latest” sketch on Github and it is sending this:
MSG, Vrms, P1, P2, P3, P4, E1, E2, E3, E4, T1, T2, T3, pulse
which is a serial number of the message, the voltage (in hundredths), 4 power values (W), 4 energies (Wh), three temperatures and a pulse count.

You can use that, but to cater for your RFM12B, you’ll need to use the rfmTxLib.zip (61.3 KB) library instead of the file EmonTxV3CM_rfm.ino and there will be a some small changes to the radio’s function calls which should be fairly straightforward - but shout out if they’re not.

If your emonTx V3 is a V3.2, you’ll need other changes, but emonlibCM and rfmTxLib both work with the V3.2

I’ve attached the sketch I’m using. I did look at emonLibCM a few months ago, but got stuck as it didn’t seem compatible with the RFM12B.

I’ll do some more reading around, but I think I’d need a bit more help to work out what sketch I need. Are there any other threads to read?

emonTxV3_continuous-id5-Main.ino (29.4 KB)

Robin only uses the voltage for the power calculation and to determine the zero crossing point, he does not report it. It would be possible to extract the voltage, but it’s probably easier to use emonLibCM and rfmTxLib - these are proven so there is likely to be less debugging required.

I think your starting point will be the example sketches that come with emonLibCM - particularly the one with the radio: EmonTxV34CM_min_RFM69.ino – but this is RFM69CW only, so you need to remove the rfm.ino file and use rfmTxLib instead. You will need to make some minor changes as a result.

[Note, the “max” sketch is only there to illustrate every setting for emonLibCM - but it changes nothing because those settings above and beyond the “min” sketch only set the default values again anyway.

Thank you. I’ve modified the EmonTxV34CM_min_RFM69.ino sketch, but have an error somewhere around rfsend or the bool definition. If I comment out the bool line, then it compiles.

Arduino: 1.8.19 (Windows 10), Board: "Arduino Uno"





















C:\Users\Al\Documents\Arduino\EmonTxV34CM_min_RFM69_rf12b\EmonTxV34CM_min_RFM69_rf12b.ino: In function 'void loop()':

EmonTxV34CM_min_RFM69_rf12b:88:67: error: call of overloaded 'rfm_send(byte*, unsigned int, const int&, const int&)' is ambiguous

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

                                                                   ^

In file included from C:\Users\Al\Documents\Arduino\libraries\rfmTxLib/rfmTxLib.h:77:0,

                 from C:\Users\Al\Documents\Arduino\EmonTxV34CM_min_RFM69_rf12b\EmonTxV34CM_min_RFM69_rf12b.ino:25:

C:\Users\Al\Documents\Arduino\libraries\rfmTxLib/rfmTxLib.cpp:272:6: note: candidate: bool rfm_send(const byte*, byte, byte, byte, uint8_t, byte, int, byte)

 bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const uint8_t rf_freq, const byte rf_power, const int threshold, const byte timeout)

      ^~~~~~~~

C:\Users\Al\Documents\Arduino\EmonTxV34CM_min_RFM69_rf12b\EmonTxV34CM_min_RFM69_rf12b.ino:30:6: note: candidate: bool rfm_send(const byte*, byte, byte, byte)

 bool rfm_send(const byte *data, const byte size, const byte group, const byte node);

      ^~~~~~~~

exit status 1

call of overloaded 'rfm_send(byte*, unsigned int, const int&, const int&)' is ambiguous



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Here’s the sketch.



/*

"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(); } 

#define RFM12B 
#include <rfmTxLib.h>

void rfm_init(void);
//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);
//bool rfm_send(const byte *data, const byte size, const byte group, const byte node[, const uint8_t RF_freq[, const byte rf_power[, const int threshold[, const byte timeout] ] ] ] );
bool rfm_send(const byte *data, const byte size, const byte group, const byte node);



                                                           
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);
    } 
  }
}

It’s lying. rfm_send( ) isn’t overloaded. Have you deleted the file rfm.ino from the sketch directory - because rfmTxLib replaces that file?

Yes, only EmonTxV34CM_min_RFM69_rf12b.ino is in the sketch folder.

I added rfmTxLib as a zip to the Arduino Libraries.

You’ve declared rfm_send( ) in line 28 of your sketch. It’s already declared in the library header file - you don’t need it twice. That’s where your error is, comment line 28.

Ah ok thank you. I’ll give it a try on the emontx during the week.

The RFM12 is on 868MHz, so I’ve added a 2 onto the rfm_send line. Is that correct?

rfm_send((byte *)&emontx, sizeof(emontx), networkGroup, nodeID, 2);

Cheers.

That will work, but as RFM_868MHZ is defined for you in the header file, I’d say using that is clearer.
rfm_send((byte *)&emontx, sizeof(emontx), networkGroup, nodeID, RFM_868MHZ);
Generally, using mystical numbers like that is frowned up - will you remember what it means in another 8 years time?

1 Like

I can barely remember what I did yesterday, so I’ve changed to use RFM_868MHZ :slight_smile:

Guess why I knew what would happen. rotfl

1 Like

Not yet uploaded to my emontx, but just thinking about the next update. What do I have to change to get the incrementing Wh that you describe in your 1st reply? I guess that it is preferable to have the emontx calculate and send the Wh, rather than emoncms calculate it from the instantaneous power?
Cheers.

If I understand correctly what you want, you must pick up the values emonLibCM provides and use them in your sketch, that is, add them to the “payload” to the RF Module in exactly the same way as all the other variables. Look at the present ‘latest’ sketch if you’re unsure.

I suggest you keep to one of our standard formats - e.g. the one in post no.2, if only to avoid confusion later on.

The theory was, if the emonTx always accumulates the energy total, and remembers it across a restart, it should never be far wrong and never start again from zero when you have a power cut, and it keep going even when the data fails to reach emonCMS.

where are you looking for the latest sketch?
I can’t see any mention of Wh here.

from EmonTxV3CM/src/EmonTxV3CM.ino

You can also try reading the documentation that comes with emonLibCM.

I’ve tried the sketch. It hangs on the rfm_send line. If I comment that out, then I get all the values appearing in the serial monitor every 5 seconds. Wonder if you could take a peek at it please?

Here is the sketch
EmonTxV34CM_min_RFM69_rf12b.ino (3.7 KB)

Here is the rfmTxLib.h

#ifndef rfmTxLib_h
#define rfmTxLib_h

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif


#include <SPI.h>								                 // SPI bus for the RFM module
#include <util/crc16.h>                          // Checksum for JeeLib compatibility

enum rfband {RFM_433MHZ = 1, RFM_868MHZ, RFM_915MHZ }; // frequency band.

/*
 * "Public" functions for general use
 */
 
void rfm_init(void);

bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const uint8_t rf_freq = RFM_433MHZ, const byte rf_power = 25, const int threshold = -97, const byte timeout = 15);

/* rf_power: 69CW range is min = 0 to max = 31. 12B range is 8 - 25 
   threshold: 69CW range is 0 = 0 dBm to -127 dBm   12B range is -73 dBm to -103 dBm
   timeout: the maximum hold-off time in ms. Special value: timeout = 0 means there is NO check for band occupancy
*/

#ifndef RFMSELPIN
 #define RFMSELPIN 10   // RFM select pin
#endif
#ifndef RFMIRQPIN
 #define RFMIRQPIN 2    // RFM interrupt pin
#endif

/*
 * Private functions
 */
 

#ifdef RFM69CW
void writeReg(uint8_t addr, uint8_t value);
uint8_t readReg(uint8_t addr);
void select();
void unselect();
void rfm_sleep(void);

#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
#endif

#ifdef RFM12B
word rfm_write(word cmd);
#ifndef SDOPIN
  #define SDOPIN 12  // SDO pin
#endif
#define REG_RSSI          0x0080
#endif

#include <rfmTxLib.cpp>

#endif

And the CPP

/*
================================================================================================================

  Routines for Transmit-only, using the "Classic" JeeLib packet format.
  (To use the "Native" Hope RFM69 format, use rfm69nTxLib

  Derived from JeeLib and work by Martin Roberts by Robert Wall
  
  -----------------------------------------
  Part of the openenergymonitor.org project
  Licence: GNU GPL V3
  -----------------------------------------

  
  Change Log:
  Version 1.0  27/6/2020 First release
  Version 2.0  10/3/2021 Frequency setting moved into transmit function, ability to ignore 'busy channel detection' (timeout = 0) added.


================================================================================================================
These definitions are required in the main sketch if different:

#define RFMSELPIN 10   // RFM select pin
#define RFMIRQPIN 2    // RFM interrupt pin

================================================================================================================


Functions:

void rfm_init(void);   
    Initialises the radio module to JeeLib protocol standards
                       
bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const uint8_t rf_freq, 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 - 630)
        rf_freq   - must be either 1 (=433 MHz), 2 (=868 MHz) or 3 (=915 MHz)
        rf_power  - 0 - 31 = -18 dBm (min value) - +13 dBm (max value). RFM12B equivalent: 25 (+7 dBm)
        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 <rfmTxLib.h>


/*
Interface for the RFM69CW Radio Module in "RFM69 Classic" mode, with Channel Busy detection.
*/

#ifdef RFM69CW


void rfm_init(void)
{	
	// 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
//	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 uint8_t rf_freq, const byte rf_power, const int threshold, const byte timeout) 
{
  // rf_power:  0 - 31 = -18 dBm (min value) - +13 dBm (max value). RFM12B equivalent: 25 (+7 dBm)  
  // timeout:  set to zero to inhibit channel occupancy check.
  
	if (rf_freq == RFM_868MHZ)
  {
		writeReg(0x07, 0xD9); // RegFrfMsb: Frf = Rf Freq / 61.03515625 Hz = 0xD90000 = 868.00 MHz as used by JeeLib  
		writeReg(0x08, 0x00); // RegFrfMid
		writeReg(0x09, 0x00); // RegFrfLsb
	}
  else if (rf_freq == RFM_915MHZ) // JeeLib uses 912.00 MHz
  {	
		writeReg(0x07, 0xE4); // RegFrfMsb: Frf = Rf Freq / 61.03515625 Hz = 0xE40000 = 912.00 MHz as used by 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 by JeeLib 
		writeReg(0x08, 0x80); // RegFrfMid
		writeReg(0x09, 0x00); // RegFrfLsb
	}


  unsigned long t_start = millis();
  bool success = true;                                     // return false if timed out, else true

  if (timeout)
  {
    success = false;
    writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | MODE_RECEIVER);		// Receive mode - listen 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
    }
    // 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 < 5)
	{
		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;
			}
			if(txstate<4) crc = _crc16_update(crc, next);
			writeReg(REG_FIFO, next);								              // RegFifo(next);
		}
	}
  while (txstate++ < 17) 
    writeReg(REG_FIFO, 0xAA);                               // Dummy bytes - if total FIFO < 12 bytes, locks up                   
    
    // Transmit buffer is now filled, transmit it
    // rf_power: RegPaLevel = 0x9F = PA0 on, +13 dBm (max value) Min value is 0x80 (-18 dBm), RFM12B equivalent: +7 dBm = 0x99  

	writeReg(0x11, (rf_power & 0x1F)|0x80); 
	writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | MODE_TRANSMITTER);		// Transmit mode - 60 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();
}
#endif


/*********************************************************************************
Interface for the RFM12B Radio Module
*********************************************************************************/

#ifdef RFM12B

void rfm_init(void)
{	
	// Set up to drive the Radio Module
	pinMode (RFMSELPIN, OUTPUT);
	digitalWrite(RFMSELPIN,HIGH);
	// start the SPI library:
	SPI.begin();
	SPI.setBitOrder(MSBFIRST);
	SPI.setDataMode(0);
	SPI.setClockDivider(SPI_CLOCK_DIV8);
	// initialise RFM12
	delay(200); // wait for RFM12 POR
	rfm_write(0x0000); // clear SPI
	rfm_write(0x8208); // Turn on crystal,!PA
	rfm_write(0xC606); // approx 49.2 Kbps, as used by emonTx
	//rfm_write(0xC657); // approx 3.918 Kbps, better for long range
	rfm_write(0xCC77); // PLL 
	rfm_write(0xC2AC); // AL,!ml,DIG,DQD4 
	rfm_write(0xCA83); // FIFO8,2-SYNC,!ff,DR 
	rfm_write(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN 
	rfm_write(0xE000); // wake up timer - not used 
	rfm_write(0xC800); // low duty cycle - not used 
	rfm_write(0xC000); // 1.0MHz,2.2V 
}


// transmit data via the RFM12
bool rfm_send(const byte *data, const byte size, const byte group, const byte node, const uint8_t rf_freq, const byte rf_power, const int threshold, const byte timeout)
{
	byte i=0,next,txstate=0;
	word crc=~0;
  byte pwr = rf_power & 0x1F;
  byte rssi = -threshold;
  
  unsigned long t_start = millis();
  bool success = true;                                     // return false if timed out, else true

  if (rssi < 73)
    rssi = 73;
  if (rssi > 103)
    rssi = 103;
  rssi = (103 - rssi) / 6.0; // scale as per RFM69

  if (pwr > 25)
    pwr = 25;
  if (pwr < 8)
    pwr = 8;
  pwr = (25 - pwr) / 2.4; // scale as per RFM69
  
  if (rf_freq == RFM_868MHZ)
  {	  
    rfm_write(0x80E7); // EL (ena dreg), EF (ena RX FIFO), 868 MHz, 12.0pF 
	  rfm_write(0xA640); // 868.00 MHz as used JeeLib 
	}
  else if (rf_freq == RFM_915MHZ) // JeeLib uses 912.00 MHz
  {	
	  rfm_write(0x80F7); // EL (ena dreg), EF (ena RX FIFO), 915 MHz, 12.0pF 
	  rfm_write(0xA640); // 912.00 MHz as used JeeLib 	
  }
	else // default to 433 MHz band @ 434 MHz
	{
	  rfm_write(0x80D7); // EL (ena dreg), EF (ena RX FIFO), 433 MHz, 12.0pF 
	  rfm_write(0xA640); // 434.00 MHz as used JeeLib 
	}  
	rfm_write(0x94A0 | rssi); // VDI,FAST,134kHz,0dBm,threshold -103dBm+rssi
	rfm_write(0xCE00 | group); // SYNC=2DD2 => group 210
	rfm_write(0x9850 | pwr); // !mp,90kHz,MAX OUT - 0x9850 = 0dB, 0x9857 = -17.5 dB in steps of 2.5 dB
  
  if (timeout)
  {
    success = false;
    rfm_write(0x8298); // er,es,ex - Receive mode - sniff for channel is busy
    while ((millis()-t_start)<(unsigned long)timeout)
    {
      if ((rfm_write(0x00) & REG_RSSI) == 0)                  // REG_RSSI_VALUE < threshold
      {
        success = true;
        break;                                                // Nothing heard - go ahead and transmit
      }
    }                                                         // We have waited long enough - go ahead and transmit anyway
  }
  
	rfm_write(0x8228); // OPEN PA
	rfm_write(0x8238);

	digitalWrite(RFMSELPIN,LOW);
	SPI.transfer(0xb8); // tx register write command
  
	while(txstate<13)
	{
		while(digitalRead(SDOPIN)==0); // wait for SDO to go high
		switch(txstate)
		{
			case 0:
			case 1:
			case 2: next=0xaa; txstate++; break;
			case 3: next=0x2d; txstate++; break;
			case 4: next=group; txstate++; break;
			case 5: next=node; txstate++; break; // node ID
			case 6: next=size; txstate++; break; // length
			case 7: next=data[i++]; if(i==size) txstate++; break;
			case 8: next=(byte)crc; txstate++; break;
			case 9: next=(byte)(crc>>8); txstate++; break;
			case 10:
			case 11:
			case 12: next=0xaa; txstate++; break; // dummy bytes (if <3 CRC gets corrupted sometimes)
		}
		if((txstate>4)&&(txstate<9)) crc = _crc16_update(crc, next);
		SPI.transfer(next);
	}
	digitalWrite(RFMSELPIN,HIGH);
	rfm_write( 0x8208 ); // CLOSE PA
	rfm_write( 0x8200 ); // enter sleep
  return success;
}


// Write a command to or read from the RFM12
word rfm_write(word cmd)
{
	word result;
  
	digitalWrite(RFMSELPIN,LOW);
	result=(SPI.transfer(cmd>>8)<<8) | SPI.transfer(cmd & 0xff);
	digitalWrite(RFMSELPIN,HIGH);
	return result;
}

#endif

You’d forgotten to define the correct pins on your emonTx V3.2 for how the RFM module is connected. RFMSELPIN to be precise. See the RFMTxLib documentation for what you need.

Thank you, it now works, and I’ve added the energy counters to the TX. I don’t use the temps or the pulse count, and there will always be AC present otherwise the emontx would not be powered.

Here’s my sketch. Is there any error checking I should be doing - there is a lot more in the main sketch you linked to.

One problem I used to have was after a power cut or brownout, most times the emontxes (I have 2) would not start up cleanly, and would not transmit. I had to unplug and replug the DC socket. Is that a known issue?



/*

"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(); } 

#define RFM12B 
#define RFMSELPIN 4   // RFM select pin
#define RFMIRQPIN 3    // RFM interrupt pin
#include <rfmTxLib.h>

void rfm_init(void);
//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);
//bool rfm_send(const byte *data, const byte size, const byte group, const byte node[, const uint8_t RF_freq[, const byte rf_power[, const int threshold[, const byte timeout] ] ] ] );
//bool rfm_send(const byte *data, const byte size, const byte group, const byte node);



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

const int networkGroup = 210;                              //  wireless network group - OEM standard is 210
int allTemps[3];
/*  

emonhub.conf nodeid is 10 - switch is ignored)
See: https://github.com/openenergymonitor/emonhub/blob/emon-pi/configuration.md

[[15]]
  nodename = emontx1
  [[[rx]]]
    names = MSG, Vrms, P1, P2, P3, P4, E1, E2, E3, E4, T1, T2, T3, pulse
    datacodes = L,h,h,h,h,h,l,l,l,l,h,h,h,L
    scales = 1,0.01,1,1,1,1,1,1,1,1,0.01,0.01,0.01,1
    units = n,V,W,W,W,W,Wh,Wh,Wh,Wh,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

typedef struct {
    unsigned long Msg;
    int Vrms,P1,P2,P3,P4; 
    long E1,E2,E3,E4; 
    int T1,T2,T3;
    unsigned long pulse;
} PayloadTX;
PayloadTX emontx;   
 
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()             
{
 static double E1 = 0.0, E2 = 0.0, E3 = 0.0, E4 = 0.0;    // Sketch's own value to use when a.c. fails.
  if (EmonLibCM_Ready())   
  {
    #ifdef DEBUG
    if (emontx.Msg==0) {
      Serial.println(EmonLibCM_acPresent()?F("AC present "):F("AC missing "));
      delay(5);
    }
    #endif

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


    if (EmonLibCM_acPresent())
    {
      emontx.P1 = EmonLibCM_getRealPower(0); 
      emontx.E1 = EmonLibCM_getWattHour(0); 
      E1        = EmonLibCM_getWattHour(0);

      emontx.P2 = EmonLibCM_getRealPower(1); 
      emontx.E2 = EmonLibCM_getWattHour(1); 
      E2        = EmonLibCM_getWattHour(1);
      
      emontx.P3 = EmonLibCM_getRealPower(2); 
      emontx.E3 = EmonLibCM_getWattHour(2); 
      E3        = EmonLibCM_getWattHour(2);
    
      emontx.P4 = EmonLibCM_getRealPower(3); 
      emontx.E4 = EmonLibCM_getWattHour(3); 
      E4        = EmonLibCM_getWattHour(3);
    }
    emontx.Vrms = EmonLibCM_getVrms() * 100;
    
    emontx.T1 = allTemps[0];
    emontx.T2 = allTemps[1];
    emontx.T3 = allTemps[2];

    emontx.pulse = EmonLibCM_getPulseCount();

/*
    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, RFM_868MHZ); //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);
    } 
  }
}

It’s up to you what your sketch does, or doesn’t do, to take advantage of the data provided by the library. The “standard” sketch only sends a small selection of what is available.

You could for example remove the temperature and pulse parts of your sketch, and in setting up emonLibCM (or in the EEPROM settings), disable both. If you take the values out of the data you’re sending, you’ll need to change emonHub accordingly.

Not starting up is not a complaint I can recall hearing, if it continues with the software you are now running, then it’s something that could be looked at.