Skip to content

Commit

Permalink
PERL EmonBase example
Browse files Browse the repository at this point in the history
  • Loading branch information
mharizanov committed Aug 29, 2012
1 parent a18174c commit ac2ba83
Show file tree
Hide file tree
Showing 4 changed files with 307 additions and 11 deletions.
4 changes: 4 additions & 0 deletions TinySensor_Current_monitor/TinySensor_Current_monitor.ino
Expand Up @@ -95,6 +95,10 @@ void setup() {

void loop() {

#define BODS 7 //BOD Sleep bit in MCUCR
#define BODSE 2 //BOD Sleep enable bit in MCUCR
MCUCR |= _BV(BODS) | _BV(BODSE); //turn off the brown-out detector

setPrescaler(3); // div 8, i.e. 1 MHz
bitClear(PRR, PRADC); // power up the ADC
ADCSRA |= bit(ADEN); // enable the ADC
Expand Down
Expand Up @@ -4,17 +4,23 @@
// GNU GPL V3
//--------------------------------------------------------------------------------------

#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU 1000000 // 1 MHz

#include <JeeLib.h> // https://github.com/jcw/jeelib
#include "pins_arduino.h"

ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving

#define myNodeID 17 // RF12 node ID in the range 1-30
#define myNodeID 18 // RF12 node ID in the range 1-30
#define network 210 // RF12 Network group
#define freq RF12_868MHZ // Frequency of RFM12B module

#define LEDpin PB0

#define TEMPERATURE_ADJUSTMENT 2
#define TEMPERATURE_ADJUSTMENT 26-43
#define EXTREMES_RATIO 5
#define MAXINT 32767
#define MININT -32767
Expand All @@ -32,47 +38,73 @@ int pos=0;
typedef struct {
int temp; // Temperature reading
int supplyV; // Supply voltage
int temp2; // Temperature reading
} Payload;

Payload temptx;

static void setPrescaler (uint8_t mode) {
cli();
CLKPR = bit(CLKPCE);
CLKPR = mode;
sei();
}

void setup() {

setPrescaler(1); // div 1, i.e. 4 MHz
pinMode(LEDpin,OUTPUT);
digitalWrite(LEDpin,LOW);
delay(1000);
digitalWrite(LEDpin,HIGH);

rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above
// Adjust low battery voltage to 2.2V UNTESTED!!!!!!!!!!!!!!!!!!!!!
rf12_control(0xC040);
rf12_sleep(0); // Put the RFM12 to sleep
Serial.begin(9600);
// Serial.begin(9600);
PRR = bit(PRTIM1); // only keep timer 0 going
}

void loop() {
pinMode(LEDpin,OUTPUT);
digitalWrite(LEDpin,LOW);
setPrescaler(3); // div 8, i.e. 1 MHz
bitClear(PRR, PRADC); // power up the ADC
ADCSRA |= bit(ADEN); // enable the ADC
Sleepy::loseSomeTime(16); // Allow 10ms for the sensor to be ready

int_sensor_init();
sprint();
// sprint();
temptx.temp = in_c() * 100; // Convert temperature to an integer, reversed at receiving end
temptx.temp2 = 1 * 100; // Convert temperature to an integer, reversed at receiving end

temptx.supplyV = readVcc(); // Get supply voltage

ADCSRA &= ~ bit(ADEN); // disable the ADC
bitSet(PRR, PRADC); // power down the ADC

digitalWrite(LEDpin,HIGH);

rfwrite(); // Send data via RF

for(int j = 0; j < 1; j++) { // Sleep for 5 minutes
Sleepy::loseSomeTime(1000); //JeeLabs power save function: enter low power mode for 60 seconds (valid range 16-65000 ms)
Sleepy::loseSomeTime(60000); //JeeLabs power save function: enter low power mode for 60 seconds (valid range 16-65000 ms)
}
}

//--------------------------------------------------------------------------------------------------
// Send payload data via RF
//--------------------------------------------------------------------------------------------------
static void rfwrite(){
static void rfwrite(){
setPrescaler(1); // div 1, i.e. 4 MHz
bitClear(PRR, PRUSI); // enable USI h/w
rf12_sleep(-1); //wake up RF module
while (!rf12_canSend())
rf12_recvDone();
rf12_recvDone();
rf12_sendStart(0, &temptx, sizeof temptx);
rf12_sendWait(2); //wait for RF to finish sending while in standby mode
rf12_sleep(0); //put RF module to sleep
bitSet(PRR, PRUSI); // disable USI h/w
setPrescaler(4); // div 4, i.e. 1 MHz
}

//--------------------------------------------------------------------------------------------------
// Read current supply voltage
//--------------------------------------------------------------------------------------------------
Expand Down
140 changes: 140 additions & 0 deletions TinySensor_PinChangeInterrupt/TinySensor_PinChangeInterrupt.ino
@@ -0,0 +1,140 @@
//--------------------------------------------------------------------------------------
// Internal temperature measurement of Attiny84 based TinySensor
// harizanov.com
// GNU GPL V3
//--------------------------------------------------------------------------------------

#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU 1000000 // 1 MHz

#include <avr/sleep.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#include <JeeLib.h> // https://github.com/jcw/jeelib
#include "pins_arduino.h"

ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving

#define myNodeID 8 // RF12 node ID in the range 1-30
#define network 210 // RF12 Network group
#define freq RF12_868MHZ // Frequency of RFM12B module

#define LEDpin PB0


//########################################################################################################################
//Data Structure to be sent
//########################################################################################################################

typedef struct {
int state; // State
int supplyV; // Supply voltage
} Payload;

static Payload temptx;

static void setPrescaler (uint8_t mode) {
cli();
CLKPR = bit(CLKPCE);
CLKPR = mode;
sei();
}

ISR(PCINT0_vect) {
temptx.state=bitRead(PINA,1);
}

void setup() {

setPrescaler(1); // div 1, i.e. 4 MHz
pinMode(LEDpin,OUTPUT);
digitalWrite(LEDpin,LOW);
delay(1000);
digitalWrite(LEDpin,HIGH);


pinMode(1,INPUT);
sbi(GIMSK,PCIE0); // Turn on Pin Change interrupt
sbi(PCMSK0,PCINT1); // Which pins are affected by the interrupt

rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above
// Adjust low battery voltage to 2.2V
rf12_control(0xC040);
rf12_sleep(0); // Put the RFM12 to sleep
// Serial.begin(9600);
PRR = bit(PRTIM1); // only keep timer 0 going
}

void loop() {
pinMode(LEDpin,OUTPUT);
digitalWrite(LEDpin,LOW);
setPrescaler(3); // div 8, i.e. 1 MHz
bitClear(PRR, PRADC); // power up the ADC
ADCSRA |= bit(ADEN); // enable the ADC
Sleepy::loseSomeTime(16); // Allow 10ms for the sensor to be ready

// temptx.state=1;
temptx.supplyV = readVcc(); // Get supply voltage

ADCSRA &= ~ bit(ADEN); // disable the ADC
bitSet(PRR, PRADC); // power down the ADC

digitalWrite(LEDpin,HIGH);

rfwrite(); // Send data via RF

/*
for(int j = 0; j < 1; j++) { // Sleep for 5 minutes
Sleepy::loseSomeTime(60000); //JeeLabs power save function: enter low power mode for 60 seconds (valid range 16-65000 ms)
}
*/


set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
sleep_mode(); // System sleeps here

}

//--------------------------------------------------------------------------------------------------
// Send payload data via RF
//--------------------------------------------------------------------------------------------------
static void rfwrite(){
setPrescaler(1); // div 1, i.e. 4 MHz
bitClear(PRR, PRUSI); // enable USI h/w
rf12_sleep(-1); //wake up RF module
while (!rf12_canSend())
rf12_recvDone();
rf12_sendStart(0, &temptx, sizeof temptx);
rf12_sendWait(2); //wait for RF to finish sending while in standby mode
rf12_sleep(0); //put RF module to sleep
bitSet(PRR, PRUSI); // disable USI h/w
setPrescaler(4); // div 4, i.e. 1 MHz
}
//--------------------------------------------------------------------------------------------------
// Read current supply voltage
//--------------------------------------------------------------------------------------------------

long readVcc() {
long result;
// Read 1.1V reference against Vcc
ADMUX = _BV(MUX5) | _BV(MUX0);
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
return result;
}




120 changes: 120 additions & 0 deletions perl_gateway/serial.pl
@@ -0,0 +1,120 @@
#!/usr/bin/perl -w
# Reads data from serial port and posts to emoncms


# Run apt-get install libdevice-serialport-perl
# if you ger "Can't locate device/SerialPort.pm in @INC (@INC includes ..."


# use lib '/usr/lib/perl5/Device'
# sudo apt-get install libwww-mechanize-perl

# Martin Harizanov
# http://harizanov.com


# Declare the subroutines
sub trim($);


BEGIN {
push @INC,"/usr/lib/perl5/";
}

use strict;
use Device::SerialPort qw( :PARAM :STAT 0.07 );
use WWW::Mechanize;
use Time::localtime;
use Scalar::Util 'looks_like_number';

print "Serial to EmonCMS gateway for RaspberryPi with TinySensor\r\n";

my $PORT = "/dev/ttyAMA0";

my $ob = Device::SerialPort->new($PORT);
$ob->baudrate(9600);
$ob->parity("none");
$ob->databits(8);
$ob->stopbits(1);
$ob->handshake("xoff");
$ob->write_settings;

$ob->lookclear;

$ob->write("\r\n");
$ob->write("22i"); #Node ID=22
sleep 2;
$ob->write("8b"); #868Mhz
sleep 2;
$ob->write("210g"); #Group=210
sleep 2;
$ob->lookclear;

open(SERIAL, "+>$PORT");

while (my $line = trim(<SERIAL>)) {
print $line; print "\r\n";
my @values = split(' ', $line);
my $bindata;
if(looks_like_number($values[0]) && $values[0] >=1 && $values[0]<=26) {

$bindata="";
for(my $j=1; $j<@values; $j++) {
$bindata.=sprintf ("%.2x",$values[$j]);
}
#print $bindata . "\r\n";
$bindata=pack("H*",$bindata);

#Example of decoding packet content for nodes 17 and 18
if($values[0]==18 || $values[0]==17) {

my($temperature, $battery) = unpack("ss",$bindata);
$temperature /=100;
print "Temperature $temperature\n";
print "Battery $battery\n";

}

my $msubs ="";
for(my $i=1; $i<@values; $i+=2){
$msubs .= $values[$i] + $values[$i+1]*256;
if($i) {$msubs .= ","};
}
post2emoncms($values[0],$msubs);

my $hour=localtime->hour();
my $min=localtime->min();
$ob->write("$hour,00,$min,00,s\r\n");
}
}

sub post2emoncms {

my $ua = WWW::Mechanize->new();
my $url = "http://127.0.0.1/emoncms3/api/post?apikey=23338d373027ce83b1f81b9e9563b629&node=" . $_[0] ."&csv=" . $_[1];
#print $url; print "\r\n";
my $response = $ua->get($url);
if ($response->is_success)
{
#print "Success!\n";
#my $c = $ua->content;
#print ("$c");
}
else
{
#print "Failed to update emoncms!";
#die $response->status_line;
}

}


# Perl trim function to remove whitespace from the start and end of the string
sub trim($)
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}
#

0 comments on commit ac2ba83

Please sign in to comment.