Jak měřit s SCT013 přes ADS1115

Nedaří se vám s projektem a nenašli jste vhodné místo, kde se zeptat? Napište sem.
Pravidla fóra
Tohle subfórum je určeno pro konzultaci ucelených nápadů, popřípadě řešení komplexnějších projektů, které opravdu není možné rozdělit na menší části.
Většinu problémů jde rozdělit na menší a ptát se na ně v konkrétních subfórech.
Odpovědět
unyhhox
Příspěvky: 41
Registrován: 19 bře 2018, 11:11
Reputation: 0

Jak měřit s SCT013 přes ADS1115

Příspěvek od unyhhox » 08 lis 2022, 08:51

Ahoj,

pracuji na měření a regulaci fotovoltaického systému a nyní řeším rozšíření ADC vstupů u ESP8266, protože jeden je málo. Použil jsem ADS1115. Pokud použiji example kód, tak měření napětí se mi podařilo, ale za boha nemůžu přijít na měření proudu. Používám knihovnu emonlib, tudíž zadávám pin a kalibraci. Nevím ale, jak s připojením senzoru na ADS1115 definuji pin.

Pokud použiju kód ADS uvedený níže, tak měření napětí funguje bez problémů. Ještě aby ne .. je to example kód. Ověřil jsem tim ale to, že ADS není vadný a mohl jsem se posunout dále.

Kód: Vybrat vše

#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

void setup(void)
{
  Serial.begin(9600);
  ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV


  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
}

void loop(void)
{
  int16_t adc0, adc1, adc2, adc3;
  float volts0;

  adc0 = ads.readADC_SingleEnded(0);
  

  volts0 = ads.computeVolts(adc0);

  Serial.print("AIN0: "); Serial.print(adc0); Serial.print("  "); Serial.print(volts0); Serial.println("V");
  
  delay(1000);
}
Zvlášt pro kontrolu funkčnosti jsem použil kód uvedený níže, čímž jsem ověřil funkčnost senzoru proudu a pájeného obvodu. Měření proudu fungovalo až s neuvěřitelnou přesnosti.

Kód: Vybrat vše

#include "EmonLib.h"
EnergyMonitor emon1;

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

  emon1.current(1, 111.1);             // Current: input pin, calibration.
}

void loop()
{
double Irms = emon1.calcIrms(1480);  // Calculate Irms only
  Serial.println(Irms);               // Irms
}
Potom došlo na to, tyto dva kódy dát dohromady, abych mohl měřit proud s tím, že senzor SC013 bude připojený na ADS1115. Kód v setup

Kód: Vybrat vše

emon1.current(1, 111.1); 
dává možnost volbu analogového vstupu a kalibrace. Jak mám ale definovat pin ADS, když k měření vstupu ADS je uvedené jen

Kód: Vybrat vše

ads.readADC_SingleEnded(0)
? Zkusil jsem mnoho kombinací, ale bez úspěchu.

Mnohokrát děkuji za rady. Snad se zase něco přiučím.

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od kiRRow » 08 lis 2022, 15:01

Ten pin na ADS tam nedostaneš. S ADS komunikuješ pomocí sběrnice I2C, ten ti změří napětí na té proudové sondě (to je závislé na měřeném proudu) a pošle ho do ESP32, kde ho už budeš muset sám přepočítat na proud.

unyhhox
Příspěvky: 41
Registrován: 19 bře 2018, 11:11
Reputation: 0

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od unyhhox » 08 lis 2022, 15:19

kiRRow píše:
08 lis 2022, 15:01
Ten pin na ADS tam nedostaneš. S ADS komunikuješ pomocí sběrnice I2C, ten ti změří napětí na té proudové sondě (to je závislé na měřeném proudu) a pošle ho do ESP32, kde ho už budeš muset sám přepočítat na proud.
Principu sondy rozumím, ale nevím právě, jak dostat pin do toho kód z emonlib. Můžeš mi prosím poradit, jak to udělat? nějaký vzorový kód? už jsem z toho na mrtvici. Možná upravit samotnou knihovnu, kde musí být kód pro výpočet a přepsat to na kód měření ADS?

Díky moc.

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od kiRRow » 08 lis 2022, 15:37

Ta knihovna Emon je napsaná aby používala analogový pin procesoru na kterém je spuštěna.


Tohle je ta funkce co vypočítává Irms

Kód: Vybrat vše

//--------------------------------------------------------------------------------------
double EnergyMonitor::calcIrms(unsigned int Number_of_Samples)
{

  #if defined emonTxV3
    int SupplyVoltage=3300;
  #else
    int SupplyVoltage = readVcc();
  #endif


  for (unsigned int n = 0; n < Number_of_Samples; n++)
  {
    sampleI = analogRead(inPinI);

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI-offsetI)/1024);
    filteredI = sampleI - offsetI;

    // Root-mean-square method current
    // 1) square current values
    sqI = filteredI * filteredI;
    // 2) sum
    sumI += sqI;
  }

  double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Irms = I_RATIO * sqrt(sumI / Number_of_Samples);

  //Reset accumulators
  sumI = 0;
  //--------------------------------------------------------------------------------------

  return Irms;
}

tady vidíš, že to čte přímo pin procesoru sampleI = analogRead(inPinI); změř napětí na proudové sondě a přepočti ho na Rms ... to jak to má vyřešené ten výpočet autor knihovny je v kódu

edit - ještě konstruktor ti pošlu ať vidíš kde se berou ty proměnné

Kód: Vybrat vše

void EnergyMonitor::current(unsigned int _inPinI, double _ICAL)
{
  inPinI = _inPinI;
  ICAL = _ICAL;
  offsetI = ADC_COUNTS>>1;
}
když to rozpitváš inPinI tě nezajímá, ICAL je to kalibrační číslo, offsetI je informace o tom kolikati bitový převodník procesor má
edit 2

Kód: Vybrat vše

long EnergyMonitor::readVcc() {
  long result;

  //not used on emonTx V3 - as Vcc is always 3.3V - eliminates bandgap error and need for calibration http://harizanov.com/2013/09/thoughts-on-avr-adc-accuracy/

  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB1286__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  ADCSRB &= ~_BV(MUX5);   // Without this the function always returns -1 on the ATmega2560 http://openenergymonitor.org/emon/node/2253#comment-11432
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);

  #endif


  #if defined(__AVR__)
  delay(2);                                        // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);                             // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = READVCC_CALIBRATION_CONST / result;  //1100mV*1024 ADC steps http://openenergymonitor.org/emon/node/1186
  return result;
  #elif defined(__arm__)
  return (3300);                                  //Arduino Due
  #else
  return (3300);                                  //Guess that other un-supported architectures will be running a 3.3V!
  #endif
}
bez toho to nepoběží

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od kiRRow » 08 lis 2022, 16:20

nedalo mi to... a zkusil jsem to splácat dohromady... nemám to jak otestovat, než tu splácaninu stylem ctrl+c ctrl+v sem hodit...

Kód: Vybrat vše

#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

void setup(void)
{
  Serial.begin(9600);
  ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV

  current(111.1);             // Current: input pin, calibration.

  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
}

//--
double ICAL;
double offsetI;
#if defined(__arm__)
#define ADC_BITS    12
#else
#define ADC_BITS    10
#endif
#define ADC_COUNTS  (1<<ADC_BITS)
void current(double _ICAL)
{
  ICAL = _ICAL;
  offsetI = ADC_COUNTS>>1;
}
//--
#ifndef READVCC_CALIBRATION_CONST
#define READVCC_CALIBRATION_CONST 1126400L
#endif
long readVcc() {
  long result;

  //not used on emonTx V3 - as Vcc is always 3.3V - eliminates bandgap error and need for calibration http://harizanov.com/2013/09/thoughts-on-avr-adc-accuracy/

  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB1286__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  ADCSRB &= ~_BV(MUX5);   // Without this the function always returns -1 on the ATmega2560 http://openenergymonitor.org/emon/node/2253#comment-11432
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);

  #endif


  #if defined(__AVR__)
  delay(2);                                        // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);                             // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = READVCC_CALIBRATION_CONST / result;  //1100mV*1024 ADC steps http://openenergymonitor.org/emon/node/1186
  return result;
  #elif defined(__arm__)
  return (3300);                                  //Arduino Due
  #else
  return (3300);                                  //Guess that other un-supported architectures will be running a 3.3V!
  #endif
}
//--
//--------------------------------------------------------------------------------------
int sampleI;
double sqI,sumI,Irms,filteredI;
double calcIrms(unsigned int Number_of_Samples)
{

  #if defined emonTxV3
    int SupplyVoltage=3300;
  #else
    int SupplyVoltage = readVcc();
  #endif


  for (unsigned int n = 0; n < Number_of_Samples; n++)
  {
    sampleI = ads.readADC_SingleEnded(0);

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI-offsetI)/1024);
    filteredI = sampleI - offsetI;

    // Root-mean-square method current
    // 1) square current values
    sqI = filteredI * filteredI;
    // 2) sum
    sumI += sqI;
  }

  double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Irms = I_RATIO * sqrt(sumI / Number_of_Samples);

  //Reset accumulators
  sumI = 0;
  //--------------------------------------------------------------------------------------

  return Irms;
}
void loop(void)
{
  double Irms = calcIrms(1480);  // Calculate Irms only
  Serial.println(Irms);
}
current(111.1); // Current: input pin, calibration. --- už né pin ... jen kalibrační číslo si nastav
sampleI = ads.readADC_SingleEnded(0); --- tady vpašovávám místo analogového čtení z pinu kus kódu z toho adc examplu ... nedávám tam volty, ale to co by ta knihovna normálně četla z toho analogového pinu
..... jsem zvědav co to provede :)

unyhhox
Příspěvky: 41
Registrován: 19 bře 2018, 11:11
Reputation: 0

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od unyhhox » 09 lis 2022, 19:49

kiRRow píše:
08 lis 2022, 16:20
nedalo mi to... a zkusil jsem to splácat dohromady... nemám to jak otestovat, než tu splácaninu stylem ctrl+c ctrl+v sem hodit...

Kód: Vybrat vše

#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

void setup(void)
{
  Serial.begin(9600);
  ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV

  current(111.1);             // Current: input pin, calibration.

  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
}

//--
double ICAL;
double offsetI;
#if defined(__arm__)
#define ADC_BITS    12
#else
#define ADC_BITS    10
#endif
#define ADC_COUNTS  (1<<ADC_BITS)
void current(double _ICAL)
{
  ICAL = _ICAL;
  offsetI = ADC_COUNTS>>1;
}
//--
#ifndef READVCC_CALIBRATION_CONST
#define READVCC_CALIBRATION_CONST 1126400L
#endif
long readVcc() {
  long result;

  //not used on emonTx V3 - as Vcc is always 3.3V - eliminates bandgap error and need for calibration http://harizanov.com/2013/09/thoughts-on-avr-adc-accuracy/

  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB1286__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  ADCSRB &= ~_BV(MUX5);   // Without this the function always returns -1 on the ATmega2560 http://openenergymonitor.org/emon/node/2253#comment-11432
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);

  #endif


  #if defined(__AVR__)
  delay(2);                                        // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);                             // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = READVCC_CALIBRATION_CONST / result;  //1100mV*1024 ADC steps http://openenergymonitor.org/emon/node/1186
  return result;
  #elif defined(__arm__)
  return (3300);                                  //Arduino Due
  #else
  return (3300);                                  //Guess that other un-supported architectures will be running a 3.3V!
  #endif
}
//--
//--------------------------------------------------------------------------------------
int sampleI;
double sqI,sumI,Irms,filteredI;
double calcIrms(unsigned int Number_of_Samples)
{

  #if defined emonTxV3
    int SupplyVoltage=3300;
  #else
    int SupplyVoltage = readVcc();
  #endif


  for (unsigned int n = 0; n < Number_of_Samples; n++)
  {
    sampleI = ads.readADC_SingleEnded(0);

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI-offsetI)/1024);
    filteredI = sampleI - offsetI;

    // Root-mean-square method current
    // 1) square current values
    sqI = filteredI * filteredI;
    // 2) sum
    sumI += sqI;
  }

  double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Irms = I_RATIO * sqrt(sumI / Number_of_Samples);

  //Reset accumulators
  sumI = 0;
  //--------------------------------------------------------------------------------------

  return Irms;
}
void loop(void)
{
  double Irms = calcIrms(1480);  // Calculate Irms only
  Serial.println(Irms);
}
current(111.1); // Current: input pin, calibration. --- už né pin ... jen kalibrační číslo si nastav
sampleI = ads.readADC_SingleEnded(0); --- tady vpašovávám místo analogového čtení z pinu kus kódu z toho adc examplu ... nedávám tam volty, ale to co by ta knihovna normálně četla z toho analogového pinu
..... jsem zvědav co to provede :)
Tak jsem to vyzkoušel a výsledek v serial monitoru je následující

Kód: Vybrat vše

19:47:09.951 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
19:47:09.951 -> 
19:47:09.951 -> load 0x4010f000, len 3460, room 16 
19:47:09.951 -> tail 4
19:47:09.951 -> chksum 0xcc
19:47:09.951 -> load 0x3fff20b8, len 40, room 4 
19:47:09.951 -> tail 4
19:47:09.951 -> chksum 0xc9
19:47:09.951 -> csum 0xc9
19:47:09.951 -> v00043530
19:47:09.951 -> ~ld

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od kiRRow » 09 lis 2022, 20:15

Jak se něco takovýho tam mohlo dostat. Do sériové linky se vypisuje jen Serial.println(Irms); a to že failnul ads při inicializaci. Snad leda by kolidovala proměnná Irms ... pochybuju ale ... zkus nahradit loop tímhle

Kód: Vybrat vše

void loop(void)
{
  double cIrms = calcIrms(1480);  // Calculate Irms only
  Serial.println(cIrms);
}
zatím je to děsná prasárna... pokus jestli to vůbec jde takhle lehce splácnout dohromady

unyhhox
Příspěvky: 41
Registrován: 19 bře 2018, 11:11
Reputation: 0

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od unyhhox » 09 lis 2022, 21:02

kiRRow píše:
09 lis 2022, 20:15
Jak se něco takovýho tam mohlo dostat. Do sériové linky se vypisuje jen Serial.println(Irms); a to že failnul ads při inicializaci. Snad leda by kolidovala proměnná Irms ... pochybuju ale ... zkus nahradit loop tímhle

Kód: Vybrat vše

void loop(void)
{
  double cIrms = calcIrms(1480);  // Calculate Irms only
  Serial.println(cIrms);
}
zatím je to děsná prasárna... pokus jestli to vůbec jde takhle lehce splácnout dohromady
žádná změna. Pořád to háže bordel.
21:01:23.664 -> ets Jan 8 2013,rst cause:2, boot mode:(3,6)
21:01:23.711 ->
21:01:23.711 -> load 0x4010f000, len 3460, room 16
21:01:23.711 -> tail 4
21:01:23.711 -> chksum 0xcc
21:01:23.711 -> load 0x3fff20b8, len 40, room 4
21:01:23.711 -> tail 4
21:01:23.711 -> chksum 0xc9
21:01:23.711 -> csum 0xc9
21:01:23.711 -> v00043530
21:01:23.711 -> ~ld


Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Jak měřit s SCT013 přes ADS1115

Příspěvek od kiRRow » 10 lis 2022, 14:30

Tak to jsi mě dostal. Absolutně nechápu jak se tam tohle bere a odkud. To tam máš snad nahráno něco jiného. Já v podstatě vzal ten ADS example, nakopíroval do něj jen kusy knihovny emon1 které potřebuje ta funkce calcIrms. Čekal jsem že minimálně dostaneš nějaké nepřesné měření...

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 17 hostů