Current projectThe Household PowerMeter is a simple circuit with an AVR and a photodetector that detects flashes from the household wattmeter. The AVR software utilizes the on-chip UART serial port and sends arbitrary data to notify a host about the flashes. With this simple circuit and software one can log and analyze the total household power usage. A perl-script for logging the data into a mySQL database and a PHP page to display the data is also made.Picture of the circuit with labelsPHP based web-interface displaying statistics
Pål Driveklepp
<source lang=c> /*
Source for software for atmega16 running at 8MHz sensing optical flashes and notifying host via USART
unsigned char pulsecounter = 0;
unsigned int uptime = 0;
unsigned int downtime = 0;
unsigned char sufficientdowntime = 0;
unsigned char sendpointer = 0;
void flash(unsigned char pattern);
void notify(void);
int foo = 0;
void delay(unsigned int delayet){
for (unsigned int i = 0; i < delayet; i++){
foo++;
}
}
/* AD-converter conversion complete interrupt routine */
ISR(ADC_vect){
int sample = (ADCW>>2);
if ((sample>32)&&(sufficientdowntime)){
uptime++;
downtime = 0;
}
else {
if (uptime){
if((uptime>5)&&(uptime<60)){ //led flash duration was measured to 16 samples
notify();
pulsecounter++;
PORTC = pulsecounter&0x01;
}
}
uptime = 0;
downtime++;
if(downtime>60){
sufficientdowntime = 1;
}
else{
sufficientdowntime = 0;
}
}
delay(2500);
ADCSRA |= (1<<ADSC); //AD start conversion
}
int main(void){
//LEDS
DDRC = 0xFF;
//ADC
DDRA = 0x00;
//serialport
DDRD = 0xFF;
//ADC READS ADC0 (pin1 on PortA)
ADMUX = (1<<REFS0)|(1<<REFS1);
//adc prefrences
ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS0);
//setup USART
UCSRB = (1<<TXEN);
//8 databits see page 163 for writing to this register
UCSRC = (1<<URSEL)|(3<<UCSZ0);//(1<<UCSZ1)|
//baud-rate = 9600 (when mcu=8MHz)
UBRRL = 51;
flash(0x00);
for (int i = 0; i < 256; i++){
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = i;
}
//ENABLES GLOBAL INTERRUPTS
sei();
while(1){
}
}
/* flash arbitrary signal */
void flash(unsigned char pattern){
for (int i = 0; i < 10; i++){
PORTC = pattern;
delay(60000);
PORTC = 0xFF;
delay(60000);
}
}
/* send signal to host */
void notify(void){
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = 0x41 + sendpointer;
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* send end of text */
UDR = 0x0A;
if(sendpointer<25){
sendpointer++;
}
else{
sendpointer = 0;
}
} </source>
<source lang=perl>
use Device::SerialPort 0.12;
$PORT = "/dev/ttyS0"; # port to watch
$ob = Device::SerialPort->new ($PORT) || die "Can't Open $PORT: $!";
$ob->baudrate(9600) || die "failed setting baudrate";
$ob->parity("none") || die "failed setting parity";
$ob->databits(8) || die "failed setting databits";
$ob->handshake("none") || die "failed setting handshake";
$ob->write_settings || die "no settings";
$pass=$ob->write("AT");
sleep 1;
open(DEV, "<$PORT")
|| die "Cannot open $PORT: $_";
use DBI;
$username = '*****';$password = '******';$database =
'******';$hostname = 'localhost';
$dbh = DBI->connect("dbi:mysql:database=$database;" .
"host=$hostname;port=3306", $username, $password);
$watted = 0;
$SQL= "INSERT INTO ticktable VALUES ( , NOW( ) , '26')";
while($_ = <DEV>){ # print input device to file
if (($_ eq "X\n") || ($_ eq "Y\n") || ($_ eq "Z\n")){
$watted = 1;
print "reached end!";
}
else {
if($watted>0){
$dbh = DBI->connect("dbi:mysql:database=$database;" .
"host=$hostname;port=3306", $username, $password);
$InsertRecord = $dbh->do($SQL);
if ($InsertRecord){
print "SQL success!";
}
else{
print "SQL failed!: $DBI::errstr";
}
$watted = 0;
}
}
print $_;
}
undef $ob;
</source>