Lettura contatore GSE con arduino

Sistemi elettronici di controllo e monitoraggio, Arduino, Rasberry ecc.

Moderatori: gasala50, FabioR

Jekterm
Messaggi: 906
Iscritto il: gio mag 27, 2010 3:05 pm

Re: Lettura contatore GSE con arduino

Messaggioda Jekterm » mer dic 14, 2011 5:27 pm

Bello!!!
Così hai una lettura istantanea e reale della produzione!

Ciao

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » gio dic 15, 2011 8:38 am

Ho fatto qualche acquisto e sono in attesa della merce. Avrò da giocare un po' sotto Natale :mrgreen:

Per ora mi sto facendo aiutare da un amico per la sezione di alimentazione. Trasformatore toroidale 220v-12v con raddrizzatore e regolatore che alimenta arduino tramite il plug di alimentazione.
Prima del regolatore prendo la corrente e tramite alcune resistenze la porto a circa 2.5v
In questo modo la posso dare in pasto ad un ingresso analogico di arduino e, dopo opportuna calibrazione, ottenere la lettura della tensione reale, che userò poi per calcolare la potenza.
Adesso è tutto su breadboard. Appena ho lo stampato faccio qualche foto.

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » ven dic 16, 2011 11:11 am

Oggi ho provato il display del nokia 3310: con 8 € un display grafico e retroilluminato controllato via seriale. Lo metterò sulla scatola che contiene arduino, nel locale tecnico e gli farò mostrare in tempo reale i valori di potenza prodotta e potenza consumata.

Sto poi assemblando la barra led che andrà al centralino del primo piano. Ho modificato leggermente il progetto originale, interponendo un po' di cavo piatto fra scheda e led (120 saldature :shock: ) per posizionare più agevolmente i led sul frontale del centralino, dove taglierò un'apposita feritoia.

Avatar utente
fcattaneo
Site Admin
Messaggi: 1608
Iscritto il: mar nov 27, 2007 7:44 pm
Contatta:

Re: Lettura contatore GSE con arduino

Messaggioda fcattaneo » sab dic 17, 2011 8:34 am

FabioR ha scritto:

sto pensando che potrei far calcore ad arduino i millisecondi fra un lampeggio e l'altro, facendoli calcolare la potenza istantanea ad ogni lampeggio
poi integro il dato facendo la media sul minuto e lo scrivo su db



Secondo me questa soluzione potrebbe essere la migliore..
Provo a ragionarci appena ho tempo.

Ciao,
F.

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » dom dic 18, 2011 9:27 am

Alla fine ho deciso che ad un arduino faccio contare solo i lampeggi ed estraggo solo il dato di energia.
Mentre all'altro progetto che sto facendo faccio trattare la potenza.
Alcune foto del work in progress
http://goo.gl/k4mGB

Il codice è a buon punto, ma manca ancora il circuito per le sonde di corrente e la sonda di tensione

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » dom dic 18, 2011 12:06 pm

Ecco il codice
viene compilato correttamente e funzionano il display e la barra led.
Mancando ancora le sonde, calcola correttamente potenze nulle.

Codice: Seleziona tutto

/*

 Photovoltaic & Home Energy Monitor V 0.1
 Fabio Roverso 16/12/11
 
 based on:
 
 //Basic energy monitoring sketch
 //Authors: Trystan Lea, Eric Sandeen
 
 //Licenced under GNU General Public Licence more details here
 // openenergymonitor.org
 
 //Sketch measures voltage and current.
 //and then calculates useful values like real power,
 //apparent power, powerfactor, Vrms, Irms.
 
 */

#include <SPI.h>
#include <Ethernet.h>
#include <SFEbarGraph.h>

// debug switch
boolean blndebug=true;

/*
########################### LED BARGRAPH #########################
 */
// create a bargraph object
SFEbarGraph BG;
unsigned int LED;
boolean BLINK=true;

/*
########################### ENERGY MONITOR #########################
 */
//Used to convert integer to char for LCD
char chvalue [10];

//Setup variables
int numberOfSamples = 3000;

//Set Voltage and current input pins
int inPinV = 1;
int inPinI_FV = 2; //Photovoltaic
int inPinI_HO = 3; //Home

//Sanity check calibration method thanks to Eric Sandeen http://sandeen.net/wordpress
//See discussion here: http://openenergymonitor.org/emon/node/59
//Enter the values of your setup below

// Voltage is reduced both by wall xfmr & voltage divider
#define AC_WALL_VOLTAGE 230
#define AC_ADAPTER_VOLTAGE 9
// Ratio of the voltage divider in the circuit
#define AC_VOLTAGE_DIV_RATIO 11
// CT: Voltage depends on current, burden resistor, and turns
//Using SCT-013-030 reference sheet
#define CT_BURDEN_RESISTOR 62
#define CT_TURNS 1800

//Calibration coeficients
//These need to be set in order to obtain accurate results
//Set the above values first and then calibrate futher using normal calibration method described on how to build it page.
//double VCAL = 0.88928678;
//double ICAL = 0.069565217;
double VCAL = 1.0;
double ICAL_FV = 1.0;
double ICAL_HO = 1.0;
double PHASECAL = 2.3;

// Initial gueses for ratios, modified by VCAL/ICAL tweaks
#define AC_ADAPTER_RATIO (AC_WALL_VOLTAGE / AC_ADAPTER_VOLTAGE)
double V_RATIO = AC_ADAPTER_RATIO * AC_VOLTAGE_DIV_RATIO * 5 / 1024 * VCAL;
double I_RATIO_FV = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL_FV;
double I_RATIO_HO = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL_HO;

//Sample variables
int lastSampleV,
lastSampleI_FV,
lastSampleI_HO,
sampleV,
sampleI_FV,
sampleI_HO;

//Filter variables
double lastFilteredV,
lastFilteredI_FV,
lastFilteredI_HO,
filteredV,
filteredI_FV,
filteredI_HO;
double filterTemp;

//Stores the phase calibrated instantaneous voltage.
double shiftedV;

//Power calculation variables
double sqI_FV,
sqI_HO,
sqV,
instP_FV,
instP_HO,
sumI_FV,
sumI_HO,
sumV,
sumP_FV,
sumP_HO;

//Useful value variables
double realPower_FV,
realPower_HO,
balancePower,
apparentPower_FV,
apparentPower_HO,
powerFactor_FV,
powerFactor_HO,
Vrms,
Irms_FV,
Irms_HO;

/*
########################### NETWORK #########################
 */

byte mac[] = {
  0x90, 0xA2, 0xDA, 0x00, 0x65, 0xAB }; //Arduino MAC address
byte ip[] = {
  192, 168, 1, 179 }; //Arduino IP address
byte gateway[] = {
  192, 168, 1, 250 }; //Network gateway
byte subnet[] = {
  255, 255, 255, 0 }; //Network subnet mask

//Web client stuff
byte server[] = {
  192 ,168 ,12 ,8 }; //Web server address
unsigned int port = 82; //Web server http port (usually 80)
Client client(server, port); //Creates an http client handle

// On the Ethernet Shield, CS is pin 4.
const int chipSelect = 4;

/*
########################### LCD MONITOR #########################
 */
#define PIN_SCE 7 // LCD CS .... Pin 3
#define PIN_RESET 6 // LCD RST .... Pin 1
#define PIN_DC 5 // LCD Dat/Com. Pin 5
#define PIN_SDIN 2 // LCD SPIDat . Pin 6
#define PIN_SCLK 3 // LCD SPIClk . Pin 4
// LCD Gnd .... Pin 2
// LCD Vcc .... Pin 8
// LCD Vlcd ... Pin 7

#define LCD_C LOW
#define LCD_D HIGH

#define LCD_X 84
#define LCD_Y 48
#define LCD_CMD 0

int a,b;

static const byte ASCII[][5] =
{
  {
    0x00, 0x00, 0x00, 0x00, 0x00   }// 20
  ,{
    0x00, 0x00, 0x5f, 0x00, 0x00   }// 21 !
  ,{
    0x00, 0x07, 0x00, 0x07, 0x00   }// 22 "
  ,{
    0x14, 0x7f, 0x14, 0x7f, 0x14   }// 23 #
  ,{
    0x24, 0x2a, 0x7f, 0x2a, 0x12   }// 24 $
  ,{
    0x23, 0x13, 0x08, 0x64, 0x62   }// 25 %
  ,{
    0x36, 0x49, 0x55, 0x22, 0x50   }// 26 &
  ,{
    0x00, 0x05, 0x03, 0x00, 0x00   }// 27 '
  ,{
    0x00, 0x1c, 0x22, 0x41, 0x00   }// 28 (
  ,{
    0x00, 0x41, 0x22, 0x1c, 0x00   }// 29 )
  ,{
    0x14, 0x08, 0x3e, 0x08, 0x14   }// 2a *
  ,{
    0x08, 0x08, 0x3e, 0x08, 0x08   }// 2b +
  ,{
    0x00, 0x50, 0x30, 0x00, 0x00   }// 2c ,
  ,{
    0x08, 0x08, 0x08, 0x08, 0x08   }// 2d -
  ,{
    0x00, 0x60, 0x60, 0x00, 0x00   }// 2e .
  ,{
    0x20, 0x10, 0x08, 0x04, 0x02   }// 2f /
  ,{
    0x3e, 0x51, 0x49, 0x45, 0x3e   }// 30 0
  ,{
    0x00, 0x42, 0x7f, 0x40, 0x00   }// 31 1
  ,{
    0x42, 0x61, 0x51, 0x49, 0x46   }// 32 2
  ,{
    0x21, 0x41, 0x45, 0x4b, 0x31   }// 33 3
  ,{
    0x18, 0x14, 0x12, 0x7f, 0x10   }// 34 4
  ,{
    0x27, 0x45, 0x45, 0x45, 0x39   }// 35 5
  ,{
    0x3c, 0x4a, 0x49, 0x49, 0x30   }// 36 6
  ,{
    0x01, 0x71, 0x09, 0x05, 0x03   }// 37 7
  ,{
    0x36, 0x49, 0x49, 0x49, 0x36   }// 38 8
  ,{
    0x06, 0x49, 0x49, 0x29, 0x1e   }// 39 9
  ,{
    0x00, 0x36, 0x36, 0x00, 0x00   }// 3a :
  ,{
    0x00, 0x56, 0x36, 0x00, 0x00   }// 3b ;
  ,{
    0x08, 0x14, 0x22, 0x41, 0x00   }// 3c <
  ,{
    0x14, 0x14, 0x14, 0x14, 0x14   }// 3d =
  ,{
    0x00, 0x41, 0x22, 0x14, 0x08   }// 3e >
  ,{
    0x02, 0x01, 0x51, 0x09, 0x06   }// 3f ?
  ,{
    0x32, 0x49, 0x79, 0x41, 0x3e   }// 40 @
  ,{
    0x7e, 0x11, 0x11, 0x11, 0x7e   }// 41 A
  ,{
    0x7f, 0x49, 0x49, 0x49, 0x36   }// 42 B
  ,{
    0x3e, 0x41, 0x41, 0x41, 0x22   }// 43 C
  ,{
    0x7f, 0x41, 0x41, 0x22, 0x1c   }// 44 D
  ,{
    0x7f, 0x49, 0x49, 0x49, 0x41   }// 45 E
  ,{
    0x7f, 0x09, 0x09, 0x09, 0x01   }// 46 F
  ,{
    0x3e, 0x41, 0x49, 0x49, 0x7a   }// 47 G
  ,{
    0x7f, 0x08, 0x08, 0x08, 0x7f   }// 48 H
  ,{
    0x00, 0x41, 0x7f, 0x41, 0x00   }// 49 I
  ,{
    0x20, 0x40, 0x41, 0x3f, 0x01   }// 4a J
  ,{
    0x7f, 0x08, 0x14, 0x22, 0x41   }// 4b K
  ,{
    0x7f, 0x40, 0x40, 0x40, 0x40   }// 4c L
  ,{
    0x7f, 0x02, 0x0c, 0x02, 0x7f   }// 4d M
  ,{
    0x7f, 0x04, 0x08, 0x10, 0x7f   }// 4e N
  ,{
    0x3e, 0x41, 0x41, 0x41, 0x3e   }// 4f O
  ,{
    0x7f, 0x09, 0x09, 0x09, 0x06   }// 50 P
  ,{
    0x3e, 0x41, 0x51, 0x21, 0x5e   }// 51 Q
  ,{
    0x7f, 0x09, 0x19, 0x29, 0x46   }// 52 R
  ,{
    0x46, 0x49, 0x49, 0x49, 0x31   }// 53 S
  ,{
    0x01, 0x01, 0x7f, 0x01, 0x01   }// 54 T
  ,{
    0x3f, 0x40, 0x40, 0x40, 0x3f   }// 55 U
  ,{
    0x1f, 0x20, 0x40, 0x20, 0x1f   }// 56 V
  ,{
    0x3f, 0x40, 0x38, 0x40, 0x3f   }// 57 W
  ,{
    0x63, 0x14, 0x08, 0x14, 0x63   }// 58 X
  ,{
    0x07, 0x08, 0x70, 0x08, 0x07   }// 59 Y
  ,{
    0x61, 0x51, 0x49, 0x45, 0x43   }// 5a Z
  ,{
    0x00, 0x7f, 0x41, 0x41, 0x00   }// 5b [
  ,{
    0x02, 0x04, 0x08, 0x10, 0x20   }// 5c ¥
  ,{
    0x00, 0x41, 0x41, 0x7f, 0x00   }// 5d ]
  ,{
    0x04, 0x02, 0x01, 0x02, 0x04   }// 5e ^
  ,{
    0x40, 0x40, 0x40, 0x40, 0x40   }// 5f _
  ,{
    0x00, 0x01, 0x02, 0x04, 0x00   }// 60 `
  ,{
    0x20, 0x54, 0x54, 0x54, 0x78   }// 61 a
  ,{
    0x7f, 0x48, 0x44, 0x44, 0x38   }// 62 b
  ,{
    0x38, 0x44, 0x44, 0x44, 0x20   }// 63 c
  ,{
    0x38, 0x44, 0x44, 0x48, 0x7f   }// 64 d
  ,{
    0x38, 0x54, 0x54, 0x54, 0x18   }// 65 e
  ,{
    0x08, 0x7e, 0x09, 0x01, 0x02   }// 66 f
  ,{
    0x0c, 0x52, 0x52, 0x52, 0x3e   }// 67 g
  ,{
    0x7f, 0x08, 0x04, 0x04, 0x78   }// 68 h
  ,{
    0x00, 0x44, 0x7d, 0x40, 0x00   }// 69 i
  ,{
    0x20, 0x40, 0x44, 0x3d, 0x00   }// 6a j
  ,{
    0x7f, 0x10, 0x28, 0x44, 0x00   }// 6b k
  ,{
    0x00, 0x41, 0x7f, 0x40, 0x00   }// 6c l
  ,{
    0x7c, 0x04, 0x18, 0x04, 0x78   }// 6d m
  ,{
    0x7c, 0x08, 0x04, 0x04, 0x78   }// 6e n
  ,{
    0x38, 0x44, 0x44, 0x44, 0x38   }// 6f o
  ,{
    0x7c, 0x14, 0x14, 0x14, 0x08   }// 70 p
  ,{
    0x08, 0x14, 0x14, 0x18, 0x7c   }// 71 q
  ,{
    0x7c, 0x08, 0x04, 0x04, 0x08   }// 72 r
  ,{
    0x48, 0x54, 0x54, 0x54, 0x20   }// 73 s
  ,{
    0x04, 0x3f, 0x44, 0x40, 0x20   }// 74 t
  ,{
    0x3c, 0x40, 0x40, 0x20, 0x7c   }// 75 u
  ,{
    0x1c, 0x20, 0x40, 0x20, 0x1c   }// 76 v
  ,{
    0x3c, 0x40, 0x30, 0x40, 0x3c   }// 77 w
  ,{
    0x44, 0x28, 0x10, 0x28, 0x44   }// 78 x
  ,{
    0x0c, 0x50, 0x50, 0x50, 0x3c   }// 79 y
  ,{
    0x44, 0x64, 0x54, 0x4c, 0x44   }// 7a z
  ,{
    0x00, 0x08, 0x36, 0x41, 0x00   }// 7b {
  ,{
    0x00, 0x00, 0x7f, 0x00, 0x00   }// 7c |
  ,{
    0x00, 0x41, 0x36, 0x08, 0x00   }// 7d }
  ,{
    0x10, 0x08, 0x08, 0x10, 0x08   }// 7e ?
  ,{
    0x00, 0x06, 0x09, 0x09, 0x06   }// 7f ?
};

void LcdCharacter(char character)
{
  LcdWrite(LCD_D, 0x00);
  for (int index = 0; index < 5; index++)
  {
    LcdWrite(LCD_D, ASCII[character - 0x20][index]);
  }
  LcdWrite(LCD_D, 0x00);
}

void LcdClear(void)
{
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(LCD_D, 0x00);
  }
}

void LcdInitialise(void)
{
  pinMode(PIN_SCE, OUTPUT);
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC, OUTPUT);
  pinMode(PIN_SDIN, OUTPUT);
  pinMode(PIN_SCLK, OUTPUT);

  digitalWrite(PIN_RESET, LOW);
  // delay(1);
  digitalWrite(PIN_RESET, HIGH);

  LcdWrite( LCD_CMD, 0x21 ); // LCD Extended Commands.
  LcdWrite( LCD_CMD, 0xBf ); // Set LCD Vop (Contrast). //B1
  LcdWrite( LCD_CMD, 0x04 ); // Set Temp coefficent. //0x04
  LcdWrite( LCD_CMD, 0x14 ); // LCD bias mode 1:48. //0x13
  LcdWrite( LCD_CMD, 0x0C ); // LCD in normal mode. 0x0d for inverse
  LcdWrite(LCD_C, 0x20);
  LcdWrite(LCD_C, 0x0C);
}

void LcdString(char *characters)
{
  while (*characters)
  {
    LcdCharacter(*characters++);
  }
}

void LcdWrite(byte dc, byte data)
{
  digitalWrite(PIN_DC, dc);
  digitalWrite(PIN_SCE, LOW);
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
  digitalWrite(PIN_SCE, HIGH);
}

// gotoXY routine to position cursor
// x - range: 0 to 84
// y - range: 0 to 5

void gotoXY(int x, int y)
{
  LcdWrite( 0, 0x80 | x); // Column.
  LcdWrite( 0, 0x40 | y); // Row.

}

void drawLine(void)
{
  unsigned char j;
  for(j=0; j<84; j++) // top
  {
    gotoXY (j,0);
    LcdWrite (1,0x01);
  }   
  for(j=0; j<84; j++) //Bottom
  {
    gotoXY (j,5);
    LcdWrite (1,0x80);
  }   

  for(j=0; j<6; j++) // Right
  {
    gotoXY (83,j);
    LcdWrite (1,0xff);
  }   
  for(j=0; j<6; j++) // Left
  {
    gotoXY (0,j);
    LcdWrite (1,0xff);
  }

}

//millis
unsigned long time;
unsigned long savetodb;

/*
###########################################################
 ########################### SETUP #########################
 ###########################################################
 */
void setup(void)
{

  //start LCD
  LcdInitialise();
  LcdClear();

  //define ethernet CS
  pinMode(10, OUTPUT);

  //start Ethernet
  Ethernet.begin(mac, ip, gateway, subnet);

  //start serial
  Serial.begin(9600);

  // Let's initialize the bargraph library!
  BG.begin(9,1);

  // Turn all LEDs on then off using BG.paint()
  for(LED=0;LED<(1*30);LED++) // Increment through all the LEDs from 0 to as many as we have
  {
    BG.paint(LED,HIGH); // Turn LED on
    BG.send(); // Send the canvas to the bargraph
    delay(50);
  }

  for(LED=0;LED<(1*30);LED++) // Increment through all the LEDs from 0 to as many as we have
  {
    BG.paint(LED,LOW); // Turn LED off
    BG.send(); // Send the canvas to the bargraph
    delay(50);
  }
  delay(500);

  //Millis
  time = millis();
  savetodb = millis();
}

/*
###########################################################
 ########################### LOOP ##########################
 ###########################################################
 */
void loop(){

  time=millis();

  for (int n=0; n<numberOfSamples; n++)
  {

    //Used for offset removal
    lastSampleV=sampleV;
    lastSampleI_FV=sampleI_FV;
    lastSampleI_HO=sampleI_HO;

    //Read in voltage and current samples.
    sampleV = analogRead(inPinV);
    sampleI_FV = analogRead(inPinI_FV);
    sampleI_HO = analogRead(inPinI_HO);

    //Used for offset removal
    lastFilteredV = filteredV;
    lastFilteredI_FV = filteredI_FV;
    lastFilteredI_HO = filteredI_HO;

    //Digital high pass filters to remove 2.5V DC offset.
    filteredV = 0.996*(lastFilteredV+sampleV-lastSampleV);
    filteredI_FV = 0.996*(lastFilteredI_FV+sampleI_FV-lastSampleI_FV);
    filteredI_HO = 0.996*(lastFilteredI_HO+sampleI_HO-lastSampleI_HO);

    //Phase calibration goes here.
    shiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);

    //Root-mean-square method voltage
    //1) square voltage values
    sqV= filteredV * filteredV;
    //2) sum
    sumV += sqV;

    //Root-mean-square method current
    //1) square current values
    sqI_FV = filteredI_FV * filteredI_FV;
    sqI_HO = filteredI_HO * filteredI_HO;
    //2) sum
    sumI_FV += sqI_FV;
    sumI_HO += sqI_HO;


    //Instantaneous Power
    instP_FV = shiftedV * filteredI_FV;
    instP_HO = shiftedV * filteredI_HO;
    //Sum
    sumP_FV +=instP_FV;
    sumP_HO +=instP_HO;
  }

  //Calculation of the root of the mean of the voltage and current squared (rms)
  //Calibration coeficients applied.
  Vrms = V_RATIO*sqrt(sumV / numberOfSamples);
  Irms_FV = I_RATIO_FV*sqrt(sumI_FV / numberOfSamples);
  Irms_HO = I_RATIO_HO*sqrt(sumI_HO / numberOfSamples);

  //Calculation power values
  realPower_FV = V_RATIO*I_RATIO_FV*sumP_FV / numberOfSamples;
  realPower_HO = V_RATIO*I_RATIO_HO*sumP_HO / numberOfSamples;
  apparentPower_FV = Vrms * Irms_FV;
  apparentPower_HO = Vrms * Irms_HO;
  powerFactor_FV = realPower_FV / apparentPower_FV;
  powerFactor_HO = realPower_HO / apparentPower_HO;
  balancePower=realPower_FV-realPower_HO;
  //balancePower=-3400;

  //Reset accumulators
  sumV = 0;
  sumI_FV = 0;
  sumI_HO = 0;
  sumP_FV = 0;
  sumP_HO = 0;

  /*
########################### OUTPUT #########################
   */
  if (blndebug){
    //Output to serial
    Serial.print(realPower_FV);
    Serial.print(' ');
    Serial.print(apparentPower_FV);
    Serial.print(' ');
    Serial.print(powerFactor_FV);
    Serial.print(' ');
    Serial.print(Vrms);
    Serial.print(' ');
    Serial.println(Irms_FV);

    Serial.print(realPower_HO);
    Serial.print(' ');
    Serial.print(apparentPower_HO);
    Serial.print(' ');
    Serial.print(powerFactor_HO);
    Serial.print(' ');
    Serial.print(Vrms);
    Serial.print(' ');
    Serial.println(Irms_HO);
  }

  //Ouput Real Power to the LCD
  LcdClear();
  gotoXY(10,0);
  itoa((int)(Vrms), chvalue,10);
  LcdString (chvalue);
  LcdString ("V"); 
  gotoXY(2,1);
  itoa((int)(realPower_FV), chvalue,10);
  LcdString ("FV: ");
  LcdString (chvalue);
  LcdString ("W");
  gotoXY(2,2);
  itoa((int)(realPower_HO), chvalue,10);
  LcdString ("HO: -");
  LcdString (chvalue);
  LcdString ("W");
  gotoXY(0,4);
  LcdString ("- Bilancio -");
  gotoXY(2,5);
  itoa((int)(balancePower), chvalue,10);
  LcdString ("SUM: ");
  LcdString (chvalue);
  LcdString ("W");

  //output to graph bar
  if (balancePower<-3300) {
    for(LED=20;LED<30;LED++)
    {
      BG.paint(LED,BLINK); // Turn LED on
      BG.send(); // Send the canvas to the bargraph
    }
    BLINK=!BLINK;
  }
  else if (balancePower>=-3300 && balancePower<-3083){
    BG.clear(); // Clear the canvas
    BG.paint(29,HIGH);
    BG.paint(28,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-3083 && balancePower<-2866){
    BG.clear(); // Clear the canvas
    BG.paint(28,HIGH);
    BG.paint(27,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-2866 && balancePower<-2648){
    BG.clear(); // Clear the canvas
    BG.paint(27,HIGH);
    BG.paint(26,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-2648 && balancePower<-2431){
    BG.clear(); // Clear the canvas
    BG.paint(26,HIGH);
    BG.paint(25,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-2431 && balancePower<-2214){
    BG.clear(); // Clear the canvas
    BG.paint(25,HIGH);
    BG.paint(24,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-2214 && balancePower<-1997){
    BG.clear(); // Clear the canvas
    BG.paint(24,HIGH);
    BG.paint(23,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-1997 && balancePower<-1779){
    BG.clear(); // Clear the canvas
    BG.paint(23,HIGH);
    BG.paint(22,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-1779 && balancePower<-1562){
    BG.clear(); // Clear the canvas
    BG.paint(22,HIGH);
    BG.paint(21,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-1562 && balancePower<-1345){
    BG.clear(); // Clear the canvas
    BG.paint(21,HIGH);
    BG.paint(20,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-1345 && balancePower<-1128){
    BG.clear(); // Clear the canvas
    BG.paint(20,HIGH);
    BG.paint(19,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-1128 && balancePower<-910){
    BG.clear(); // Clear the canvas
    BG.paint(19,HIGH);
    BG.paint(18,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-910 && balancePower<-693){
    BG.clear(); // Clear the canvas
    BG.paint(18,HIGH);
    BG.paint(17,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-693 && balancePower<-476){
    BG.clear(); // Clear the canvas
    BG.paint(17,HIGH);
    BG.paint(16,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-476 && balancePower<-259){
    BG.clear(); // Clear the canvas
    BG.paint(16,HIGH);
    BG.paint(15,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-259 && balancePower<-41){
    BG.clear(); // Clear the canvas
    BG.paint(15,HIGH);
    BG.paint(14,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=-41 && balancePower<176){
    BG.clear(); // Clear the canvas
    BG.paint(14,HIGH);
    BG.paint(13,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=176 && balancePower<393){
    BG.clear(); // Clear the canvas
    BG.paint(13,HIGH);
    BG.paint(12,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=393 && balancePower<610){
    BG.clear(); // Clear the canvas
    BG.paint(12,HIGH);
    BG.paint(11,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=610 && balancePower<828){
    BG.clear(); // Clear the canvas
    BG.paint(11,HIGH);
    BG.paint(10,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=828 && balancePower<1045){
    BG.clear(); // Clear the canvas
    BG.paint(10,HIGH);
    BG.paint(9,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=1045 && balancePower<1262){
    BG.clear(); // Clear the canvas
    BG.paint(9,HIGH);
    BG.paint(8,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=1262 && balancePower<1479){
    BG.clear(); // Clear the canvas
    BG.paint(8,HIGH);
    BG.paint(7,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=1479 && balancePower<1697){
    BG.clear(); // Clear the canvas
    BG.paint(7,HIGH);
    BG.paint(6,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=1697 && balancePower<1914){
    BG.clear(); // Clear the canvas
    BG.paint(6,HIGH);
    BG.paint(5,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=1914 && balancePower<2131){
    BG.clear(); // Clear the canvas
    BG.paint(5,HIGH);
    BG.paint(4,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=2131 && balancePower<2348){
    BG.clear(); // Clear the canvas
    BG.paint(4,HIGH);
    BG.paint(3,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=2348 && balancePower<2566){
    BG.clear(); // Clear the canvas
    BG.paint(3,HIGH);
    BG.paint(2,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=2566 && balancePower<2783){
    BG.clear(); // Clear the canvas
    BG.paint(2,HIGH);
    BG.paint(1,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=2783 && balancePower<3000){
    BG.clear(); // Clear the canvas
    BG.paint(1,HIGH);
    BG.paint(0,HIGH);
    BG.send(); // Send the canvas to the bargraph
  }
  else if (balancePower>=3000 ){
    for(LED=0;LED<10;LED++)
    {
      BG.paint(LED,BLINK); // Turn LED on
      BG.send(); // Send the canvas to the bargraph
    }
    BLINK=!BLINK;
  }

  //output to DB every minute
  if(time>savetodb+60000){
    WebClient();
    savetodb=millis();
  }

}
void WebClient(){

  if (client.connect()){
    client.flush();
    client.print("GET ");
    client.print("/fv.php?user=user&password=pass&data=");
    client.print(realPower_FV);
    client.print(";");
    client.print(apparentPower_FV);
    client.print(";");
    client.print(powerFactor_FV);
    client.print(";");
    client.print(Irms_FV);
    client.print(";");
    client.print(realPower_HO);
    client.print(";");
    client.print(apparentPower_HO);
    client.print(";");
    client.print(powerFactor_HO);
    client.print(";");
    client.print(Irms_HO);
    client.print(";");
    client.print(Vrms);
    client.println(" HTTP/1.0");
    client.println();
    while(!client.available()){
      delay(1);
    }
    while (client.available()){
      char c = client.read();
      if (blndebug) Serial.print(c);
    }
    if (blndebug) Serial.println();
  }
  else {
    if (blndebug) Serial.println("EXCEPTION: during HTTP GET. Could not connect");
    return;
  }
  while(client.connected()){
    if (blndebug) Serial.println("Waiting for server to disconnect");
  }
  client.stop();

}

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » dom dic 25, 2011 9:04 am

Ho completato il sistema. Il cicuito è assemblato su una millefori e fa un po' schifo a vedersi ma funziona :mrgreen:
Uso un trasformatore a 9V per leggere la tensione di rete.
I dati che ottengo sono potenza reale, potenza apparente, fattore di potenza,
Irms e Vrms
Ho usato una stufa elettrica e un misuratore di consumo simile a quello del lidl per calibrare il sistema e adesso ho letture consistenti.
I valori vengono mostrati in tempo reale sul display lcd e sulla barra led.
Nei prossimi giorni installerò il box principale vicino al centralino di casa, facendo i collegamenti delle sonde. Metterò la barra led al piano di sopra, visibile dalla cucina.

Appena possibile aggiorno l'album fotografico.

Questo è il codice. Dovrebbe funzionare tutto, anche se non ho ancora testato la trasmissione dei dati in rete.
/*

Photovoltaic & Home Energy Monitor V 0.2
Fabio Roverso 21/12/11

based on:

//Basic energy monitoring sketch
//Authors: Trystan Lea, Eric Sandeen

//Licenced under GNU General Public Licence more details here
// openenergymonitor.org

//Sketch measures voltage and current.
//and then calculates useful values like real power,
//apparent power, powerfactor, Vrms, Irms.

*/

#include <SPI.h>
#include <Ethernet.h>
#include <SFEbarGraph.h>

// millis (for db saving)
unsigned long time;
unsigned long savetodb;

// debug output switch
boolean blndebug=true;

// power range for the ledbar
int Max_Production = 3000;
int Min_Production = -3100;
unsigned int lapses = 30;
int increment = (Max_Production - Min_Production) / lapses;

/*
########################### LED BARGRAPH #########################
*/
// create a bargraph object
SFEbarGraph BG;
unsigned int LED;
boolean BLINK=true;

/*
########################### ENERGY MONITOR #########################
*/
//Used to convert integer to char for LCD
char chvalue [10];

//Setup variables
int numberOfSamples = 3000;

//Set Voltage and current input pins
int inPinV = 1;
int inPinI_FV = 2; //Photovoltaic CT
int inPinI_HO = 3; //Home CT

//Sanity check calibration method thanks to Eric Sandeen http://sandeen.net/wordpress
//See discussion here: http://openenergymonitor.org/emon/node/59
//Enter the values of your setup below

// Voltage is reduced both by wall xfmr & voltage divider
#define AC_WALL_VOLTAGE 230
#define AC_ADAPTER_VOLTAGE 9
// Ratio of the voltage divider in the circuit #da verificare#
#define AC_VOLTAGE_DIV_RATIO 11
// CT: Voltage depends on current, burden resistor, and turns
//Using SCT-013-030 reference sheet
#define CT_BURDEN_RESISTOR 62
#define CT_TURNS 1800

//Calibration coeficients
//These need to be set in order to obtain accurate results
//Set the above values first and then calibrate futher using normal calibration method described on how to build it page.
double VCAL = 1.242937853107345;
double ICAL_FV = 0.9931972789115646;
double ICAL_HO = 0.9931972789115646;
double PHASECAL = 2.3;

// Initial gueses for ratios, modified by VCAL/ICAL tweaks
#define AC_ADAPTER_RATIO (AC_WALL_VOLTAGE / AC_ADAPTER_VOLTAGE)
double V_RATIO = AC_ADAPTER_RATIO * AC_VOLTAGE_DIV_RATIO * 5 / 1024 * VCAL;
double I_RATIO_FV = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL_FV;
double I_RATIO_HO = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL_HO;

//Sample variables
int lastSampleV,
lastSampleI_FV,
lastSampleI_HO,
sampleV,
sampleI_FV,
sampleI_HO;

//Filter variables
double lastFilteredV,
lastFilteredI_FV,
lastFilteredI_HO,
filteredV,
filteredI_FV,
filteredI_HO;

double filterTemp;

//Stores the phase calibrated instantaneous voltage.
double shiftedV;

//Power calculation variables
double sqI_FV,
sqI_HO,
sqV,
instP_FV,
instP_HO,
sumI_FV,
sumI_HO,
sumV,
sumP_FV,
sumP_HO;

//Useful value variables
double realPower_FV,
realPower_HO,
balancePower,
apparentPower_FV,
apparentPower_HO,
powerFactor_FV,
powerFactor_HO,
Vrms,
Irms_FV,
Irms_HO;

/*
########################### NETWORK #########################
*/

byte mac[] = {
0x90, 0xA2, 0xDA, 0x00, 0x65, 0xAB }; //Arduino MAC address
byte ip[] = {
192, 168, 1, 179 }; //Arduino IP address
byte gateway[] = {
192, 168, 1, 250 }; //Network gateway
byte subnet[] = {
255, 255, 255, 0 }; //Network subnet mask

//Web client stuff
byte server[] = {
192 ,168 ,12 ,8 }; //Web server address
unsigned int port = 82; //Web server http port (usually 80)
Client client(server, port); //Creates an http client handle

/*
########################### LCD MONITOR #########################

This Code has extra features
including a XY positioning function on Display
and a Line Draw function on Nokia 3310 LCD
It is modded from the original
http://www.arduino.cc/playground/Code/PCD8544
*/
// Mods by Jim Park
// jim(^dOt^)buzz(^aT^)gmail(^dOt^)com
// hope it works for you

#define PIN_SCE 7 // LCD CS .... Pin 3
#define PIN_RESET 6 // LCD RST .... Pin 1
#define PIN_DC 5 // LCD Dat/Com. Pin 5
#define PIN_SDIN 2 // LCD SPIDat . Pin 6
#define PIN_SCLK 3 // LCD SPIClk . Pin 4
// LCD Gnd .... Pin 2
// LCD Vcc .... Pin 8
// LCD Vlcd ... Pin 7

#define LCD_C LOW
#define LCD_D HIGH

#define LCD_X 84
#define LCD_Y 48
#define LCD_CMD 0

static const byte ASCII[][5] =
{
{0x00, 0x00, 0x00, 0x00, 0x00} // 20
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ?
,{0x00, 0x06, 0x09, 0x09, 0x06} // 7f ?
};

void LcdCharacter(char character)
{
LcdWrite(LCD_D, 0x00);
for (int index = 0; index < 5; index++)
{
LcdWrite(LCD_D, ASCII[character - 0x20][index]);
}
LcdWrite(LCD_D, 0x00);
}

void LcdClear(void)
{
for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
{
LcdWrite(LCD_D, 0x00);
}
}

void LcdInitialise(void)
{
pinMode(PIN_SCE, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_DC, OUTPUT);
pinMode(PIN_SDIN, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);

digitalWrite(PIN_RESET, LOW);
// delay(1);
digitalWrite(PIN_RESET, HIGH);

LcdWrite( LCD_CMD, 0x21 ); // LCD Extended Commands.
LcdWrite( LCD_CMD, 0xBf ); // Set LCD Vop (Contrast). //B1
LcdWrite( LCD_CMD, 0x04 ); // Set Temp coefficent. //0x04
LcdWrite( LCD_CMD, 0x14 ); // LCD bias mode 1:48. //0x13
LcdWrite( LCD_CMD, 0x0C ); // LCD in normal mode. 0x0d for inverse
LcdWrite(LCD_C, 0x20);
LcdWrite(LCD_C, 0x0C);
}

void LcdString(char *characters)
{
while (*characters)
{
LcdCharacter(*characters++);
}
}

void LcdWrite(byte dc, byte data)
{
digitalWrite(PIN_DC, dc);
digitalWrite(PIN_SCE, LOW);
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
digitalWrite(PIN_SCE, HIGH);
}

// gotoXY routine to position cursor
// x - range: 0 to 84
// y - range: 0 to 5

void gotoXY(int x, int y)
{
LcdWrite( 0, 0x80 | x); // Column.
LcdWrite( 0, 0x40 | y); // Row.

}

void drawLine(void)
{
unsigned char j;
for(j=0; j<84; j++) // top
{
gotoXY (j,0);
LcdWrite (1,0x01);
}
for(j=0; j<84; j++) //Bottom
{
gotoXY (j,5);
LcdWrite (1,0x80);
}

for(j=0; j<6; j++) // Right
{
gotoXY (83,j);
LcdWrite (1,0xff);
}
for(j=0; j<6; j++) // Left
{
gotoXY (0,j);
LcdWrite (1,0xff);
}

}

/*
###########################################################
########################### SETUP #########################
###########################################################
*/
void setup(void)
{

// start LCD
LcdInitialise();
LcdClear();

// define ethernet SS
pinMode(10, OUTPUT);

// start Ethernet
Ethernet.begin(mac, ip, gateway, subnet);

// start serial
Serial.begin(9600);

// initialize the bargraph library
BG.begin(9,1);

// Turn all LEDs on then off using BG.paint()
for(LED=0;LED<(1*30);LED++) // Increment through all the LEDs from 0 to as many as we have
{
BG.paint(LED,HIGH); // Turn LED on
BG.send(); // Send the canvas to the bargraph
delay(50);
}

for(LED=0;LED<(1*30);LED++) // Increment through all the LEDs from 0 to as many as we have
{
BG.paint(LED,LOW); // Turn LED off
BG.send(); // Send the canvas to the bargraph
delay(50);
}

// initialize timers
time = millis();
savetodb = millis();
}

/*
###########################################################
########################### LOOP ##########################
###########################################################
*/
void loop(){

time=millis();

for (int n=0; n<numberOfSamples; n++)
{

//Used for offset removal
lastSampleV=sampleV;
lastSampleI_FV=sampleI_FV;
lastSampleI_HO=sampleI_HO;

//Read in voltage and current samples.
sampleV = analogRead(inPinV);
sampleI_FV = analogRead(inPinI_FV);
sampleI_HO = analogRead(inPinI_HO);

//Used for offset removal
lastFilteredV = filteredV;
lastFilteredI_FV = filteredI_FV;
lastFilteredI_HO = filteredI_HO;

//Digital high pass filters to remove 2.5V DC offset.
filteredV = 0.996*(lastFilteredV+sampleV-lastSampleV);
filteredI_FV = 0.996*(lastFilteredI_FV+sampleI_FV-lastSampleI_FV);
filteredI_HO = 0.996*(lastFilteredI_HO+sampleI_HO-lastSampleI_HO);

//Phase calibration goes here.
shiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);

//Root-mean-square method voltage
//1) square voltage values
sqV= filteredV * filteredV;
//2) sum
sumV += sqV;

//Root-mean-square method current
//1) square current values
sqI_FV = filteredI_FV * filteredI_FV;
sqI_HO = filteredI_HO * filteredI_HO;
//2) sum
sumI_FV += sqI_FV;
sumI_HO += sqI_HO;

//Instantaneous Power
instP_FV = shiftedV * filteredI_FV;
instP_HO = shiftedV * filteredI_HO;
//Sum
sumP_FV +=instP_FV;
sumP_HO +=instP_HO;
}

//Calculation of the root of the mean of the voltage and current squared (rms)
//Calibration coeficients applied.
Vrms = V_RATIO*sqrt(sumV / numberOfSamples);
Irms_FV = I_RATIO_FV*sqrt(sumI_FV / numberOfSamples);
Irms_HO = I_RATIO_HO*sqrt(sumI_HO / numberOfSamples);

//Calculation power values
realPower_FV = V_RATIO*I_RATIO_FV*sumP_FV / numberOfSamples;
realPower_HO = V_RATIO*I_RATIO_HO*sumP_HO / numberOfSamples;
apparentPower_FV = Vrms * Irms_FV;
apparentPower_HO = Vrms * Irms_HO;
powerFactor_FV = realPower_FV / apparentPower_FV;
powerFactor_HO = realPower_HO / apparentPower_HO;
//Home power balance
balancePower=realPower_FV-realPower_HO;

//Reset accumulators
sumV = 0;
sumI_FV = 0;
sumI_HO = 0;
sumP_FV = 0;
sumP_HO = 0;

/*
########################### OUTPUT #########################
*/
if (blndebug){
//Output to serial
Serial.println("Real_FV Apparent_FV P_Fact_FV I_FV Real_HO Apparent_HO P_Fact_HO I_HO V");
Serial.print(realPower_FV);
Serial.print(' ');
Serial.print(apparentPower_FV);
Serial.print(' ');
Serial.print(powerFactor_FV);
Serial.print(' ');
Serial.print(Irms_FV);
Serial.print(' ');
Serial.print(realPower_HO);
Serial.print(' ');
Serial.print(apparentPower_HO);
Serial.print(' ');
Serial.print(powerFactor_HO);
Serial.print(' ');
Serial.print(Irms_HO);
Serial.print(' ');
Serial.println(Vrms);
}

//Ouput Real Power to the LCD
LcdClear();
gotoXY(2,0);
LcdString ("Vrms: ");
itoa((int)(Vrms), chvalue,10);
LcdString (chvalue);
LcdString (" V");

gotoXY(2,1);
itoa(((int)(realPower_FV/10)*10), chvalue,10);
LcdString ("FV: +");
LcdString (chvalue);
LcdString (" W");

gotoXY(2,2);
itoa(((int)(realPower_HO/10)*10), chvalue,10);
LcdString ("HO: -");
LcdString (chvalue);
LcdString (" W");

gotoXY(0,4);
LcdString ("- Bilancio -");

gotoXY(10,5);
itoa(((int)(balancePower/10)*10), chvalue,10);
//LcdString ("BILANCIO: ");
LcdString (chvalue);
LcdString (" W");

//output to graph bar
if (balancePower < Min_Production - increment) {
for(LED=20;LED<30;LED++)
{
BG.paint(LED,BLINK); // Turn LED on
BG.send(); // Send the canvas to the bargraph
}
BLINK=!BLINK;
}
else if (balancePower >= (Min_Production - increment) && balancePower < Min_Production){
BG.clear(); // Clear the canvas
BG.paint(29,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= Min_Production && balancePower < (Min_Production + 1 * increment)){
BG.clear(); // Clear the canvas
BG.paint(29,HIGH);
BG.paint(28,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 1 * increment) && balancePower < (Min_Production + 2 * increment)){
BG.clear(); // Clear the canvas
BG.paint(28,HIGH);
BG.paint(27,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 2 * increment) && balancePower < (Min_Production + 3 * increment)){
BG.clear(); // Clear the canvas
BG.paint(27,HIGH);
BG.paint(26,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 3 * increment) && balancePower < (Min_Production + 4 * increment)){
BG.clear(); // Clear the canvas
BG.paint(26,HIGH);
BG.paint(25,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 4 * increment) && balancePower < (Min_Production + 5 * increment)){
BG.clear(); // Clear the canvas
BG.paint(25,HIGH);
BG.paint(24,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 5 * increment) && balancePower < (Min_Production + 6 * increment)){
BG.clear(); // Clear the canvas
BG.paint(24,HIGH);
BG.paint(23,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 6 * increment) && balancePower < (Min_Production + 7 * increment)){
BG.clear(); // Clear the canvas
BG.paint(23,HIGH);
BG.paint(22,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 7 * increment) && balancePower < (Min_Production + 8 * increment)){
BG.clear(); // Clear the canvas
BG.paint(22,HIGH);
BG.paint(21,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 8 * increment) && balancePower < (Min_Production + 9 * increment)){
BG.clear(); // Clear the canvas
BG.paint(21,HIGH);
BG.paint(20,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 9 * increment) && balancePower < (Min_Production + 10 * increment)){
BG.clear(); // Clear the canvas
BG.paint(20,HIGH);
BG.paint(19,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 10 * increment) && balancePower < (Min_Production + 11 * increment)){
BG.clear(); // Clear the canvas
BG.paint(19,HIGH);
BG.paint(18,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 11 * increment) && balancePower <- (Min_Production + 12 * increment)){
BG.clear(); // Clear the canvas
BG.paint(18,HIGH);
BG.paint(17,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 12 * increment) && balancePower < (Min_Production + 13 * increment)){
BG.clear(); // Clear the canvas
BG.paint(17,HIGH);
BG.paint(16,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 13 * increment) && balancePower < (Min_Production + 14 * increment)){
BG.clear(); // Clear the canvas
BG.paint(16,HIGH);
BG.paint(15,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 14 * increment) && balancePower < (Min_Production + 15 * increment)){
BG.clear(); // Clear the canvas
BG.paint(15,HIGH);
BG.paint(14,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 15 * increment) && balancePower < (Min_Production + 16 * increment)){
BG.clear(); // Clear the canvas
BG.paint(14,HIGH);
BG.paint(13,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 16 * increment) && balancePower < (Min_Production + 17 * increment)){
BG.clear(); // Clear the canvas
BG.paint(13,HIGH);
BG.paint(12,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 17 * increment) && balancePower < (Min_Production + 18 * increment)){
BG.clear(); // Clear the canvas
BG.paint(12,HIGH);
BG.paint(11,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 18 * increment) && balancePower < (Min_Production + 19 * increment)){
BG.clear(); // Clear the canvas
BG.paint(11,HIGH);
BG.paint(10,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 19 * increment) && balancePower < (Min_Production + 20 * increment)){
BG.clear(); // Clear the canvas
BG.paint(10,HIGH);
BG.paint(9,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 20 * increment) && balancePower < (Min_Production + 21 * increment)){
BG.clear(); // Clear the canvas
BG.paint(9,HIGH);
BG.paint(8,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 21 * increment) && balancePower < (Min_Production + 22 * increment)){
BG.clear(); // Clear the canvas
BG.paint(8,HIGH);
BG.paint(7,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 22 * increment) && balancePower < (Min_Production + 23 * increment)){
BG.clear(); // Clear the canvas
BG.paint(7,HIGH);
BG.paint(6,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 23 * increment) && balancePower < (Min_Production + 24 * increment)){
BG.clear(); // Clear the canvas
BG.paint(6,HIGH);
BG.paint(5,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 24 * increment) && balancePower < (Min_Production + 25 * increment)){
BG.clear(); // Clear the canvas
BG.paint(5,HIGH);
BG.paint(4,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 25 * increment) && balancePower < (Min_Production + 26 * increment)){
BG.clear(); // Clear the canvas
BG.paint(4,HIGH);
BG.paint(3,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 26 * increment) && balancePower < (Min_Production + 27 * increment)){
BG.clear(); // Clear the canvas
BG.paint(3,HIGH);
BG.paint(2,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 27 * increment) && balancePower < (Min_Production + 28 * increment)){
BG.clear(); // Clear the canvas
BG.paint(2,HIGH);
BG.paint(1,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 28 * increment) && balancePower < (Min_Production + 29 * increment)){
BG.clear(); // Clear the canvas
BG.paint(1,HIGH);
BG.paint(0,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 29 * increment) && balancePower < (Min_Production + 30 * increment)){
BG.clear(); // Clear the canvas
BG.paint(0,HIGH);
BG.send(); // Send the canvas to the bargraph
}
else if (balancePower >= (Min_Production + 30 * increment) ){
for(LED=0;LED<10;LED++)
{
BG.paint(LED,BLINK); // Turn LED on
BG.send(); // Send the canvas to the bargraph
}
BLINK=!BLINK;
}

//output to DB every minute
if(time>savetodb+60000){
WebClient();
savetodb=millis();
}

}
void WebClient(){

if (client.connect()){
client.flush();
client.print("GET ");
client.print("/fv.php?user=user&password=pass&data=");
client.print(realPower_FV);
client.print(";");
client.print(apparentPower_FV);
client.print(";");
client.print(powerFactor_FV);
client.print(";");
client.print(Irms_FV);
client.print(";");
client.print(realPower_HO);
client.print(";");
client.print(apparentPower_HO);
client.print(";");
client.print(powerFactor_HO);
client.print(";");
client.print(Irms_HO);
client.print(";");
client.print(Vrms);
client.println(" HTTP/1.0");
client.println();
while(!client.available()){
delay(1);
}
while (client.available()){
char c = client.read();
if (blndebug) Serial.print(c);
}
if (blndebug) Serial.println();
}
else {
if (blndebug) Serial.println("EXCEPTION: during HTTP GET. Could not connect");
return;
}
while(client.connected()){
if (blndebug) Serial.println("Waiting for server to disconnect");
}
client.stop();

}

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » mer dic 28, 2011 8:51 pm

Album aggiornato
http://goo.gl/k4mGB
il sistema è montato e sembra funzionare correttamente. Farò ancora qualche test nei prossimi giorni.
Appena potrò metterò su il sito web con in dati

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » ven gen 27, 2012 9:36 am

Mi sono state poste privatamente delle domande, ma preferisco rispondere sul forum per il beneficio di tutti.

Mi è stato chiesto se mettere il contaimpulsi sul contatore di produzione o su quello di scambio.
Sul contatore di scambio non ha senso perchè gli impulsi contabilizzano sia l'energia prelevata che quella immessa in rete e non è possibile discriminare, se non guardando il simbolo che appare sul display del contatore.

In realtà anche contando gli impulsi del contatore si produzione c'è un piccolissimo errore sistematico, perchè l'autoconsumo dell'inverter preleva una piccola quantità di energia, anche di notte, che viene contabilizzata come consumo. Il GSE la ignora perchè è energia che forniamo noi pagandola noi, ma porduce comunque qualche lampeggio spurio sul contatore.
Nel mio caso ho visto tramite le sonde di corrente che si tratta di un consumo di circa 4/6W. Nei conti che faccio lo tratto come errore sistematico e lo sottraggo al calcolo dell'energia prodotta (ottenuta dai lampeggi)

Avatar utente
fcattaneo
Site Admin
Messaggi: 1608
Iscritto il: mar nov 27, 2007 7:44 pm
Contatta:

Re: Lettura contatore GSE con arduino

Messaggioda fcattaneo » sab gen 28, 2012 12:07 pm

Molto interessante Fabio.

Posso darti l'accesso all'area "autocostruzione" del sito, cosi se vuoi metti sul sito le descrizioni e le foto.

Ciao,
F.

cristianc
Messaggi: 167
Iscritto il: mer dic 07, 2011 8:44 am

Re: Lettura contatore GSE con arduino

Messaggioda cristianc » gio feb 09, 2012 11:21 am

Complimenti Fabio e grazie per la condivisione. Mi sto cimentando da poco anche io
con arduino, vorrei cominciare con il monitoraggio del solare ed ho una domanda
stupida: se l'arduino non è collegato al pc con l'USB ma lo metto in funzione con
un alimentatore, le istruzioni Serial.print o Serial.println bloccano l'esecuzione dello
sketch arduino?

Poi volevo chiederti, per monitorare il consumo di corrente o la produzione si
può utilizzarequesta schedache ho visto casualmente ieri?
Qui il grafico produzione mensile del mio impianto solare. Dettaglio gennaio
Dettaglio Febbraio
Tabella Marzo

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » gio feb 09, 2012 3:03 pm

cristianc ha scritto:Complimenti Fabio e grazie per la condivisione. Mi sto cimentando da poco anche io
con arduino, vorrei cominciare con il monitoraggio del solare ed ho una domanda
stupida: se l'arduino non è collegato al pc con l'USB ma lo metto in funzione con
un alimentatore, le istruzioni Serial.print o Serial.println bloccano l'esecuzione dello
sketch arduino?

no, le ho lasciate attive su tutti gli arduino che ho in produzione senza problemi
Poi volevo chiederti, per monitorare il consumo di corrente o la produzione si
può utilizzarequesta schedache ho visto casualmente ieri?

Quella scheda usa l'effetto hall e produce un'uscita in corrente, che devi trasformare in tensione tramite una resistenza burden (che non so calcolare)

Inoltre ottieni un valore valore sinusoidale che devi campionare e trasformare in valore efficace tramite la media quadratica dei campioni (http://it.wikipedia.org/wiki/Valore_efficace )

Devi poi far sì, con un partitore di tensione, che la tensione oscilli fra 0v e +5v per poterla far leggere da arduino,
Devi anche aggiungere un errore sistematico, con opportuno circuito, per avere solo valori positivi (errore da sottrarre poi via software

Non ottieni informazioni di tensione, che quindi devi inserire come costante. Non riesci nemmeno a misurare lo sfasamento fra corrente e tensione per calcolare la potenza reale (ottieni quindi un valore in VA e non in W)

Guarda anche qua per la teoria sulla misura
http://openenergymonitor.org/emon/node/61
http://openenergymonitor.org/emon/node/62

Non è così semplice, come vedi. Mi ci son dovuto rompere la testa anche io per un po' :mrgreen:

Il codice che io ho preso da openenergymonitor misura 3000 campioni di corrente e tensione e poi calcola i valori efficaci di corrente e tensione.
Dopo di che è anche in grado di calcolare lo sfasamento, la potenza reale e quella apparente.
Con un arduino uno, campionando due sonde di tensione e una di corrente, ottengo circa un valore al secondo, quindi la cpu è abbastanza sotto carico per i calcoli svolti.

cristianc
Messaggi: 167
Iscritto il: mer dic 07, 2011 8:44 am

Re: Lettura contatore GSE con arduino

Messaggioda cristianc » ven feb 10, 2012 4:11 pm

mi hai stordito :)
mi è chiaro che misurare l'energia con quel coso non è banale. Io cercavo
una cosa che mi indicasse solo se c'è corrente, nel mio caso può bastare?
(nel senso lo metto in serie ad un'utenza elettrica e mi interessa sapere
quando l'utenza è attivata).

P.S.
Per il problema dei Serial.print bloccanti mi sono accordo dell'ennesima mia
ca**ata, l'alimentatore non funzionava. Fra l'altro non ho recuperato in casa
un alimentatore adatto, ne ho solo da 5 v o 12v e non vanno bene :x
Qui il grafico produzione mensile del mio impianto solare. Dettaglio gennaio
Dettaglio Febbraio
Tabella Marzo

FabioR
Messaggi: 125
Iscritto il: ven set 30, 2011 8:11 am

Re: Lettura contatore GSE con arduino

Messaggioda FabioR » sab feb 11, 2012 8:10 am

effettivamente mi sono dovuto fare una piccola infarinatura di elettrotecnica per capire come realizzare il mio progetto.
Il problema è che misuri una corrente alternata, quindi anche la corrente ha un andamento sinusoidale. Se non usi un valore medio su un intervallo di tempo puoi avere dei valori di corrente assorbita molto diversi a seconda di dove ti trovi sulla sinusoide nel momento di lettura del segnale.
Poi passo, perchè non è esattamente il mio mestiere, e non conosco bene i sensori di hall.
Ti conviene trovare un elettronico, perchè io sono solo un informatico ;)

PS arduino va anche a 12, anche se il regolatore di tensione scalda un po'
e potrebbe andare anche a 5 (come fa quando è collegato con l'usb) ma dovresti mettere i +5 su un pin +5 di arduino, saltando il regolatore (ma non hai protezioni)

cristianc
Messaggi: 167
Iscritto il: mer dic 07, 2011 8:44 am

Re: Lettura contatore GSE con arduino

Messaggioda cristianc » lun feb 27, 2012 8:38 pm

Ho notato che ne programma originale avevi previsto il salvataggio dei dati sia su mysql che su SD, poi hai
eliminato la parte SD e di gestione dell'ora: hai avuto qualche problema o è stata una scelta?
Qui il grafico produzione mensile del mio impianto solare. Dettaglio gennaio
Dettaglio Febbraio
Tabella Marzo


Torna a “Domotica, monitoraggio e controllo.”



Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite