Have set up the following:
Sensor/Transmitter:
LDR detecting blinking LED (domestic elec. meter) => triggers Arduino Nano interrupt ISR (pin 2) => blink counter incremented, milliseconds since last blink recorded => sent in payload struct via 433Mhz Transmitter (cheap type XD-FST).
Receiver/Storage:
Arduino Uno with 433Mhz Receiver (cheap type XY-MK-5V - data pin connected to Arduino D4 pin) receives message payload sent from XD-FST => sends data to webservice using HTTP POST via ENC28J60 => webservice stores info in db ready for online display etc.
I've fixed a 173mm wire antenna to both Tx and Rx modules. I'm getting a great range from ground floor to second floor of house.
I'm using the VirtualWire library for the 433Mhz comms, and the EtherCard library for the ENC28J60
All the above appears to work perfectly, and yet after some short while (a few minutes) the payload seen at the receiver seems to get corrupted....not complete garbage but just the same values repeated despite new messages continuing to be received.
Pressing RESET on Arduino Uno fixes the corruption, only for it to happen again after a similar length of time.
I'm trying to convince myself that this is something to do with the Arduino running out of memory....but I don't know enough about the idiosyncrasies of the cheap Tx/Rx modules to be sure if I'm not encountering some other common problem.
The behaviour does suggest a problem at the Rx end, since resetting the Arduino here sees 'normal' messages arriving again albeit for a short while.
I'd be very grateful for any thoughts on where I might be going wrong.
Happy to supply any further info you may need.
Here's my code - n.b. some portions commented out intentionally...just used for testing :
Transmitter:
#include <VirtualWire.h>
int last_blink_count_sent = 0;
struct payloadData
{
int TX_ID;
unsigned long blink_ms;
int blinkCount;
float inst_power;
float kwh_consumed;
float cost_consumed;
};
payloadData payload;
const float METER_BLINKS_PER_KWH = 800.0;
const float KWH_PER_METER_BLINK = 1/METER_BLINKS_PER_KWH;
const float MILLIS_PER_HOUR = 3600000.0;
const float COST_PER_BILL_UNIT = 12.23;
const long BOUNCE_WINDOW_MS=450;
unsigned long prev_interrupt_ms = 0;
unsigned long interrupt_ms = 0;
unsigned long millis_since_last_blink = 0;
volatile unsigned long last_blink_ms = 0;
volatile int blinks = 0;
int interruptPinLDR = 2;
void onBlink()
{
interrupt_ms = millis();
millis_since_last_blink = (unsigned long)(interrupt_ms - prev_interrupt_ms);
if(millis_since_last_blink >= BOUNCE_WINDOW_MS)
{
last_blink_ms = millis_since_last_blink;
blinks++;
prev_interrupt_ms = interrupt_ms;
}
}
void createPayload()
{
payload.TX_ID = 99;
payload.blink_ms = last_blink_ms;
payload.blinkCount = blinks;
payload.inst_power = MILLIS_PER_HOUR / ((float)last_blink_ms * METER_BLINKS_PER_KWH); // 3600000 / [X * 800]
payload.kwh_consumed = blinks * KWH_PER_METER_BLINK;
payload.cost_consumed = payload.kwh_consumed * COST_PER_BILL_UNIT / 100;
}
void transmitPayload()
{
digitalWrite(13,HIGH);
vw_send((uint8_t *)&payload, sizeof(payload));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,LOW);
free(&payload);
}
void setup()
{
pinMode(13,OUTPUT);
pinMode(interruptPinLDR,INPUT);
attachInterrupt(0, onBlink, FALLING);
vw_set_ptt_inverted(true); //
vw_set_tx_pin(12);
vw_setup(4000);// speed of data transfer Kbps
}
void loop()
{
if(blinks > last_blink_count_sent)
{
last_blink_count_sent = blinks;
createPayload();
transmitPayload();
delay(200);
}
}
Receiver:
#include <EtherCard.h>
#include <VirtualWire.h>
struct payloadData
{
int TX_ID;
unsigned long blink_ms;
int blinkCount;
float inst_power;
float kwh_consumed;
float cost_consumed;
};
payloadData payload;
uint8_t pyldSize = 0;
char postData[50];
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
byte Ethernet::buffer[700];
char dataReceiveHost[] PROGMEM = "192.168.2.9";
uint8_t dataReceiveHostIP[4] = {192, 168, 2, 9};
int plen = 0;
uint16_t dat_p;
static void dataReceiveRequest_callback (byte status, word off, word len)
{
//Serial.println(F("Callback"));
//Ethernet::buffer[off+300] = 0;
//Serial.print((const char*) Ethernet::buffer + off);
// Serial.println(F("..."));
}
void setup()
{
Serial.begin(9600);
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println( "Failed to access Ethernet controller");
if (!ether.dhcpSetup())
Serial.println("DHCP failed");
ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);
ether.copyIp(ether.hisip, dataReceiveHostIP);
ether.printIp("SRV: ", ether.hisip);
pyldSize = (uint8_t)sizeof(payload);
vw_set_ptt_inverted(true); // Required for DR3100
vw_set_rx_pin(4);////////////////////////////////////////////////change from 12
vw_setup(4000); // Bits per sec
vw_rx_start();
}
void loop()
{
plen = ether.packetReceive();
dat_p=ether.packetLoop(plen);
if(vw_get_message((uint8_t *)&payload, &pyldSize))// Non-blocking
{
if(payload.TX_ID == 99)
{
sprintf(postData, "data=%u:%lu", payload.blinkCount, payload.blink_ms);
ether.httpPost(PSTR("/ArduinoWebServices/Service1.asmx/AcceptData"),dataReceiveHost,NULL,postData,dataReceiveRequest_callback);
}
}
free(&payload);
}