Some Sauce..

Hello world. Whilst I’m waiting for an image to download so I can fix a friends laptop I thought I’d do something useful for the world and post the source code (so far) from the energy meter I’m working on. The hardware is licensed under creative commons, so the same applies to the source code – see the blurb at the bottom.

The code here doesn’t actually do that much ‘of interest’ – just displays the values from a bunch of registers on a polling loop – and at the moment it only works via USB rather than the intended bluetooth target platform (but it will get there!). The most useful bit at the moment are probably the serial read and write routines which you can use to send more than 8 bits at a time over SPI from Arduino – I found the example implementation to be a little inadequate for the 24 bit registers I need to fill on the ADE7753 so I wrote a bit extra in there to suitably fill them. Hopefully things go in and come out in the right order!

So the best bits are the write_to_eeprom(int EEPROM_address, long write_buffer, int bytes_to_write) sub-routine and the read_eeprom(int EEPROM_address, int bytes_to_read) sub-routine for mutli-byte SPI transfers from Arduino to whatever..

Here’s the source:

//registers on ADE7753  
#define WAVEFORM 0x01
#define AENERGY 0x02
#define RAENERGY 0x03
#define LAENERGY 0x04
#define VAENERGY 0x05
#define LVAENERGY 0x06
#define LVARENERGY 0x07
#define MODE 0x09
#define IRQEN 0x0A
#define STATUS 0x0B
#define RSTSTATUS 0x0C
#define CH1OS 0x0D
#define CH2OS 0x0E
#define GAIN 0x0F
#define PHCAL 0x10
#define APOS 0x11
#define WGAIN 0x12
#define WDIV 0x12
#define CFNUM 0x14
#define CFDEN 0x15
#define IRMS 0x16
#define VRMS 0x17
#define IRMSOS 0x18
#define VRMSOS 0x19
#define VAGAIN 0x1A
#define VADIV 0x1B
#define LINECYC 0x1C
#define ZXTOUT 0x1D
#define SAGCYC 0x1E
#define SAGLVL 0x1F
#define IPKLVL 0x20
#define VPKLVL 0x21
#define IPEAK 0x22
#define RSTIPEAK 0x23
#define VPEAK 0x24
#define RSTVPEAK 0x25
#define TEMP 0x26
#define PERIOD 0x27
#define TMODE 0x3D
#define CHKSUM 0x3E
#define DIEREV 0x3F
  
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO 
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

//SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); //set clock rate to 1/16th system


byte eeprom_output_data;
byte multi_byte_data[3];
byte eeprom_input_data=0;
long long_eeprom_data = 0;
byte clr;
int address=0;
//data buffer
char buffer [128];

void fill_buffer()
{
  for (int I=0;I<128;I++)
  {
    buffer[I]=I;
  }
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

void setup()
{
  Serial.begin(115200);

  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0);
  SPSR = (0<<SPI2X);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  Serial.println("init complete");
  delay(1000);
  
  
  
  //testrun starts here
  
  //utils
  //read_eeprom(address value, how many bytes)
  //write_to_eeprom(target, values, bytes to write)
  
  //read what is there right now
  //address = LINECYC;
//  Serial.print(address,HEX);
 // eeprom_output_data = read_eeprom(STATUS,2);
  
  //long TestWrite;
  //TestWrite = 0xABCD;
  //write_to_eeprom(address, TestWrite, 2);
// Serial.println(eeprom_output_data, BIN);
  //eeprom_output_data = read_eeprom(address, 2);
  //Serial.println("Completed basic read write test");
  
  

}



void write_to_eeprom(int EEPROM_address, long write_buffer, int bytes_to_write)
{
  //Serial.print("Multiwrite ops to addr>");
  //Serial.println(EEPROM_address, HEX);
  //set write mode
  byte make_write_cmd = B10000000;
  byte this_write = B00000000;
  EEPROM_address = EEPROM_address|make_write_cmd;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer((char)(EEPROM_address));      //send address
  
  //here there should be a t7 delay, however long that is
  for (int i = 0; i<bytes_to_write; i++){
  //Serial.println(i);
  this_write = byte(write_buffer>>(8*((bytes_to_write-1)-i)));
  //Serial.println(this_write, HEX);
  spi_transfer((char)(this_write));      //send data byte
  }
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
}

long read_eeprom(int EEPROM_address, int bytes_to_read)
{
  //Serial.print("Multi-read to addr>");
  //Serial.print(EEPROM_address, HEX);
  Serial.println(" Data starts:");
  long data = 0;
  byte reader_buf = 0;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer((char)(EEPROM_address));      //send LSByte address
  for (int i = 1; i <= bytes_to_read; i++){
    reader_buf = spi_transfer(0xFF); //get data byte
    Serial.println(i);
    Serial.println(reader_buf, BIN);
    
    data = data|reader_buf;
    if (i< bytes_to_read) {
      data = data<<8;
    }
    }
  Serial.print("completed. data was>");
  Serial.println(data, BIN);
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
  return data;
}

void loop()
{
  
    eeprom_output_data = read_eeprom(STATUS,2);
   Serial.println("STATUS CHECK");
   Serial.println(eeprom_output_data, BIN);
   Serial.println(eeprom_output_data, HEX);
   delay(1000);
   eeprom_output_data = read_eeprom(LINECYC,2);
   Serial.println("LINECYC CHECK");
   Serial.println(eeprom_output_data, BIN);
   Serial.println(eeprom_output_data, HEX);   
   
   
 
  
}
 

Creative Commons License

Power Meter Shield for Arduino by James Devine is licensed under a Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License.

Advertisements

5 thoughts on “Some Sauce..

  1. AlexLeo123 says:

    Hi James,

    I came across your arduinopower project via the openenergymonitor website.

    I’m looking to implement something very similar and just wanted to find out if you’ve been able to get a fully working solution in place yet?

    • pingu98 says:

      Nope sorry – didn’t quite get there before moving to Geneva! I’ve handed to project over to one of my old colleagues, so hopefully he can finish it off. In the meantime, you might want to look at Plogg (http://www.plogginternational.com/) as they can now do most things (with the exception of turning on and off) that I set out to do with arduinopower.

  2. Sathe says:

    Hi,
    Thank you very much for this code. It helped me a lot for my project. I have some problem so just curious to know whether you can help me regarding the problem or not. I have to show the active and reactive energy every 15 sec (which will be read from the register through SPI communication). I don’t know how to develop that. What I have done, I just made a while loop for 15 times and read the aenergy and vaenergy register for 15 times with 1sec delay each time. That’s how I made the loop, though I know it’s not the perfect way.

    I have to calculate the power factor also (PF=ACTIVE POWER/ APPARENT POWER). I really don’t know how to do that.

    The last problem is the values are not showing perfectly, so it’s obvious that my callibration is not perfect. I read the datasheet, but i really don’t understand how to implement this thing. It would be great if u can give some idea regarding this.

    Thanks

  3. vass says:

    Hello there,

    i am an Arduino user and i have some problems with a similar project i have to accomplish

    my project’s idea is to create a zigbee network over 2 Arduino boards and a Plogg Device

    and at first get the results from the device and then upload them as a pachube feed on a pachube account.

    The problem is that i am unable to communicate directly from the Arduino to the Plogg and i cannot understand why..

    i am using xbee shield XB24-B and i do all neccessary actions that a Telegesis USB stick does

    Looking at the Arduino Forum i couldn’t get something usefull because people don’t know very much about Plogg Devices..

    I would be very glad if you could give me some help here

    Thanks

    • pingu98 says:

      Sorry no ideas about Xbee’s or ploggs specifically. Can you strap a serial debugger to the Plogg to see what it’s doing? If there’s no responses at all sounds like you have a basic comms problem.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: