Hallo,
ich habe schon einige TinyTX Platinen mit diversen Sensoren (Temp/Humi/Reed) am laufen.
Nun möchte ich den Stromverbrauch am Zählerrad mittels diesem PhotoSensor (EE-SY310) abgreifen.
Das klappt wunderbar, der Puls wird erkannt.
Die Umrechnung des Verbrauchs 75U = 1kWh möchte ich nun direkt im dem Sketch machen und dann nur den Verbrauch in Wh und die Batteriespannung übertragen.
Leider hat sich im Sketch wohl ein Fehler eingeschlichen und ich finde ihn nicht.
Ab einem unbestimmten Intervall (meist nach mehrerern Stunden) schwanken die Werte plötzlich sehr stark zw. 15000Wh und 0, vorher sind sie plausibel (zw. 4000 mit Herd und 300 im "Ruhezustand" mit Kühlschrank an und diversen Standby-Geräten).
Das Auslesen mache ich per Python:
elif node_id == 6:
print ("******** node power: ", node_id)
a = int(data[1])
b = int(data[2])
c = int(data[3])
d = int(data[4])
powerusage = float(a+b*256)
voltage = float(c+d*256)
print ("powerusage: ", powerusage, "Wh")
print ("voltage: ", voltage, "mV")
Alles anzeigen
Wo ist der Fehler im Sketch?
//----------------------------------------------------------------------------------------------------------------------
// TinyTX_EE_SYS_POWER - An ATtiny84 Power Usage Monitoring Node
// By Nathan Chantrell. For hardware design see http://nathan.chantrell.net/tinytx
//
// Simplified version, sends whenever there is a new pulse.
//
// Using an EE_SYS Sensor
//
// Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence:
// http://creativecommons.org/licenses/by-sa/3.0/
//
// Requires Arduino IDE with arduino-tiny core: http://code.google.com/p/arduino-tiny/
//----------------------------------------------------------------------------------------------------------------------
#include <JeeLib.h> // https://github.com/jcw/jeelib
#define myNodeID 6 // RF12 node ID in the range 1-30
#define network 210 // RF12 Network group
#define freq RF12_433MHZ // Frequency of RFM12B module
#define USE_ACK // Enable ACKs, comment out to disable
#define RETRY_PERIOD 5 // How soon to retry (in seconds) if ACK didn't come in
#define RETRY_LIMIT 5 // Maximum number of times to retry
#define ACK_TIME 10 // Number of milliseconds to wait for an ack
#define P_UNUSED 2 // Configure unsused pins as pull-up to save power
#define sensorPin 10 // Sensors data pin is on D10 (ATtiny pin 13)
byte lastPulse = 0; // Last reading from sensor
static long last;
static int watts; // 75 pulses/kWh = 1/75 or 1/75*1000 pulse per Wh - Number of pulses per wh - found or set on the meter.
//--------------------------------------------------------------------------------------------------
//Data Structure to be sent
//--------------------------------------------------------------------------------------------------
typedef struct {
int power; // Wh since last TX
int supplyV; // Supply voltage
} Payload;
Payload tinytx;
//--------------------------------------------------------------------------------------------------
// Wait for an ACK
//--------------------------------------------------------------------------------------------------
#ifdef USE_ACK
static byte waitForAck() {
MilliTimer ackTimer;
while (!ackTimer.poll(ACK_TIME)) {
if (rf12_recvDone() && rf12_crc == 0 &&
rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID))
return 1;
}
return 0;
}
#endif
//########################################################################################################################
void setup() {
ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above
rf12_sleep(0); // Put the RFM12 to sleep
pinMode(sensorPin, INPUT); // set sensor pin as input
pinMode(P_UNUSED, INPUT_PULLUP); // Configure unsused pins as pull-up to save power
digitalWrite(sensorPin, HIGH); // and turn on pullup
last = millis();
}
void loop() {
byte newPulse = digitalRead(sensorPin); // Read sensor pin
// New pulse detected
if (newPulse == 0 && lastPulse == 1)
{
static int nBlinks = 0;
unsigned long time = millis();
unsigned long interval = time - last;
nBlinks++;
if (interval < 0) { // millis() overflow
last = time;
nBlinks = 0;
} else {
// Blinks are 75 per kWh, or 1/75 kWh equal 1/75*1000 Wh each
// One hour has 3.6M milliseconds
//watts = int(nBlinks * ppwh * 3.6E6 / interval ));
watts = long( nBlinks * 4.8E7 / interval );
last = time;
nBlinks = 0;
tinytx.power = int(watts); // Get realtime power Wh
tinytx.supplyV = readVcc(); // Get supply voltage
rfwrite(); // Send data via RF
}
}
lastPulse = newPulse;
}
//--------------------------------------------------------------------------------------------------
// Send payload data via RF
//-------------------------------------------------------------------------------------------------
static void rfwrite(){
#ifdef USE_ACK
for (byte i = 0; i <= RETRY_LIMIT; ++i) { // tx and wait for ack up to RETRY_LIMIT times
rf12_sleep(-1); // Wake up RF module
while (!rf12_canSend())
rf12_recvDone();
rf12_sendStart(RF12_HDR_ACK, &tinytx, sizeof tinytx);
rf12_sendWait(2); // Wait for RF to finish sending while in standby mode
byte acked = waitForAck(); // Wait for ACK
rf12_sleep(0); // Put RF module to sleep
if (acked) { return; } // Return if ACK received
Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again
}
#else
rf12_sleep(-1); // Wake up RF module
while (!rf12_canSend())
rf12_recvDone();
rf12_sendStart(0, &tinytx, sizeof tinytx);
rf12_sendWait(2); // Wait for RF to finish sending while in standby mode
rf12_sleep(0); // Put RF module to sleep
return;
#endif
}
//--------------------------------------------------------------------------------------------------
// Read current supply voltage
//--------------------------------------------------------------------------------------------------
long readVcc() {
bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC
long result;
// Read 1.1V reference against Vcc
#if defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate Vcc in mV
ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
return result;
}
Alles anzeigen