• Welcome to LusoRobótica - Robótica em Português.
 

SCT-013 + i2c eeprom, Gravar e Ler dados.

Started by dennis_boy, 21 de April de 2018, 11:51

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

dennis_boy

Bom dia.
Estou com um SCT-013.
Já procurei rebusquei tudo no Google.
Gostava de gravar e ler os kwh na memoria mas não sei como.


No projecto que estou a fazer utilizo para a eeprom:
void i2c_eeprom_write_byte ...

byte i2c_eeprom_read_byte ...

jm_araujo

Dás muito pouca informação para que seja possível ajudar-te.
Elabora mais um bocado.

SerraCabo

Pressupondo que calcular os KWh não é o problema, gravar na memória com quê? Arduino?

SC


dennis_boy

Manipulação para o AT24C256 esta complicado.
kwhTotal = kwhTotal + (((Irms*rede)/1000.0) * 1.0/3600.0 * (timems/1000.0));
Ate aqui esta tudo bem.
Pior é gravar o float.
Depois ler.
Tenho ate isto ( dtostrf(kwhTotal,4, 5, outstr) ) para me mostrar mais casas decimais.


desde já obrigado para compreensão.

vasco

Desculpa se a ideia é estúpida, mas porque não gravar a string ?
Certamente que gravar o float ocupa menos bytes, mas se não estiveres aflito de espaço o mais fácil será gravares a string. (penso eu de quê) :-D
Stupid men are often capable of things the clever wouldn't dare to contemplate.

Njay

#5
De uma forma simplificada, precisas de uma função que te grave/leia um nº arbitrário de bytes na EEPROM. Exemplo de cabeça e incompleto para a escrita (não conheço a assinatura das funções de escrita em EEPROM por i2c, terás que adaptar):

static void writeArrayToI2cEeprom (uint8_t i2c_addr, uint16_t eeprom_addr, void* data, int16_t data_size)
{
    uint8_t*  ptr = (uint8_t*)data;
    while (--data_size >= 0)
    {
        i2c_eeprom_write_byte (i2c_addr, eeprom_addr++, *ptr++);
    }
}


Depois já podes gravar o que quiseres, tendo sempre em conta o endereço da EEPROM e se há espaço que chegue. Por exemplo, gravar uma variável float:

float  kwh;
...
writeArrayToI2cEeprom (0x17, 0x01, &kwh, sizeof(kwh));

dennis_boy

Obrigado pela ajuda!! ;)
Hoje tive para aqui a refazer métodos cheguei a este.

#include "Wire.h"
#include "EmonLib.h"

#define disk1 0x50

#define AddressKwhDay 0

EnergyMonitor emon1;

float rede = 230.0;

double kwhTotal;

union kWh_Float_Byte {
   float floatkWh;
   byte  bytekWh[4];
} TOTAL_kWh;


unsigned long ltmillis, tmillis, timems, previousMillis;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
 
  emon1.current(1, 2.7); //760?
 
  if (i2c_eeprom_read_byte(disk1, AddressKwhDay) != 0xFF) {
  for (int i=0; i<4; i++) {
    TOTAL1_kWh.bytekWh[i] = i2c_eeprom_read_byte(disk1, AddressKwhDay+i);
  }
  kwhTotal = TOTAL_kWh.floatkWh;
  }

  previousMillis = millis();
}

void loop()
{
  ltmillis = tmillis;
  tmillis = millis();
  timems = tmillis - ltmillis;

  double Irms = emon1.calcIrms(1484);
  if (Irms < 0.02) Irms = 0;

  kwhTotal = kwhTotal + (((Irms*rede)/1000.0) * 1.0/3600.0 * (timems/1000.0));

  double potencia =  Irms * rede;

  Serial.print("Potencia = ");
  Serial.print(potencia);
  Serial.print("    Irms = ");
  Serial.print(Irms);
  Serial.print("    Kwh = ");
  Serial.print(kwhTotal);
  Serial.print(" ");
  Serial.println();

  if ((millis() - previousMillis)>4000)
  {
  TOTAL1_kWh.floatkWh = kwhTotal;
 
  for (int i=0; i<4; i++) {
   
  i2c_eeprom_write_byte(disk1, AddressKwhDay+i, TOTAL_kWh.bytekWh[i]);
  delay(5);
  }
  previousMillis=millis();
  }

}

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.write(rdata);
    Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
}


Um único problema que encontro é só grava 2 casas decimais e para a continuação da soma fico muito duvidoso que bata certo...

senso

Simplifica a tua formula, porque tens ai montes de divisões enormes que só estão a matar a resolução..
Avr fanboy

dennis_boy

Não sei ao que te referes, este é só teste de bancada porque resultado final é com um LCD.
Como agora estou com um SCT-013 100Amp mas quero comprar um de 20Amp penso ter menos erro nas leituras
como também estou a espera do da voltagem.

senso

(((Irms*rede)/1000.0) * 1.0/3600.0 * (timems/1000.0))

Parece-me estar tudo a multiplicar, logo pode ficar:

Irms*rede*1*timems/(1000*3600*1000)

Faz-me confusão estares a dividir por um valor tao elevado.
Avr fanboy

dennis_boy

eu apanhei este exemplo mas parece estar mais correcto o calculo que estas a dar faz resultados negativo
resultados:
Potencia = 312.10    Irms = 1.36   Kwh = -5.1658263206 (pico da ligação da corrente)
Potencia = 0.00    Irms = 0.00    Kwh = -63.5444564819   (depois desligado)

senso

#11
Porque é que estás a dividir o tempo por 1000, se já está em ms?

O negativo deve ser por teres underflow, é que é uma divisão tão grande.
Avr fanboy

dennis_boy

Obrigado a todos pela participação.
O método para o eeprom esta a registar e a ler bem.
Aprendi com a ( union ) podemos manipular registos era o que pretendia aprender.
Eu Não tenho curso em programação ou frequentei algo do género só que gosto de aprender porque a minha área é electricidade residencial.
Mas como viram não vim aqui pedir códigos mas uma ideia para pegar como cheguei la. ;)