KPOP sprzeżony z INA3221 - rejestruje urządzenie - ale sypie błędami

Fryga
Posts: 136
Joined: Tue Oct 13, 2020 5:57 pm
Location: Mińsk Mazowiecki

Post

Tworzę Suplowe urządzenie do pomiaru prądu w 3 obwodach zasilających. Musze monitorować maksymalny prąd sumaryczny bo zasilacz tylko 3A

chciałem:
1. zastosować INA3221 do pomiaru 3 prądów i stworzyć 4 KPOPy - możliwość podłączenia do 3 INA.
2. niestety wywala się - wzorowałem się na przykładach, ale nie podoba pewnie się sposób inicjacji KPOP w zależności od wykrytych INA adresów na i2c..

@klew pomożesz?

Code: Select all

// ===== ESP32-C3 mini/esp8266 + auto-discovery INA3221 (1..3 szt.) + KPOP =====

//Użycie biblioteki Wire w wersji 1.0 z folderu: C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\Wire 
//Użycie biblioteki Adafruit INA3221 Library w wersji 1.0.3 z folderu: C:\Users\Grzeg\OneDrive\Dokumenty\Arduino\libraries\Adafruit_INA3221_Library 
//Użycie biblioteki Adafruit BusIO w wersji 1.17.2 z folderu: C:\Users\Grzeg\OneDrive\Dokumenty\Arduino\libraries\Adafruit_BusIO 
Użycie biblioteki SPI w wersji 1.0 z folderu: //C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SPI 
Użycie biblioteki SuplaDevice w wersji 25.2 z folderu: C:\Users\Grzeg\OneDrive\Dokumenty\Arduino\libraries\SuplaDevice 
Użycie biblioteki ESP8266WiFi w wersji 1.0 z folderu: //C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WiFi 
Użycie biblioteki ESP8266WebServer w wersji 1.0 z folderu: //C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266WebServer 
Użycie biblioteki ESP8266HTTPUpdateServer w wersji 1.0 z folderu: //C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPUpdateServer 
Użycie biblioteki EEPROM w wersji 1.0 z folderu: //C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\EEPROM 
Użycie biblioteki LittleFS w wersji 0.1.0 z folderu: //C:\Users\Grzeg\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\LittleFS 
#include <Wire.h>
#include <Adafruit_INA3221.h>

#include <SuplaDevice.h>
#include <supla/network/esp_wifi.h>
#include <supla/sensor/general_purpose_measurement.h>

// ---------- I2C / PŁYTKA ---------- pod esp8266
#ifndef SDA_PIN
#define SDA_PIN 4 
#endif
#ifndef SCL_PIN
#define SCL_PIN 5
#endif

// Potencjalne adresy INA3221 (A0/A1 konfiguracja)
const uint8_t INA_ADDRS[] = {0x40, 0x41, 0x42, 0x43};
const size_t  INA_ADDRS_CNT = sizeof(INA_ADDRS)/sizeof(INA_ADDRS[0]);

// Rezystory bocznikowe (Ω) kanałów 0..2 — wpisz realne!
const float SHUNT_OHMS[3] = {0.01, 0.01, 0.01};

// ---------- SUPLA ----------
Supla::ESPWifi wifi("UUU", "UUUUU);

// Losowe GUID/AUTHKEY (16 bajtów)
char GUID[SUPLA_GUID_SIZE] = {
 UUUUUUUUUU
};
char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {
UUUUUUUUUUUUUUUUUUU
};

// ---------- MAX 3 szt. INA3221 ----------
struct INAEntry {
  uint8_t addr;
  Adafruit_INA3221 dev;
  bool     ok = false;
} ina[3];   // zainicjujemy dynamicznie wg liczby wykryć INA

uint8_t ina_found = 0;

// ---------- KPOP: do 10 kanałów (3/6/9 prądów + 1 suma) ----------
static const uint8_t MAX_KPOP = 10;
Supla::Sensor::GeneralPurposeMeasurement* KPOP[MAX_KPOP] = {nullptr};
uint8_t kpop_cnt = 0;  // ile faktycznie utworzono
int sum_idx = -1;      // index kanału sumy

// Etykiety
String chTitle(uint8_t idx) {
  // idx 0..(3*ina_found-1): przeliczymy na (ina#, ch#)
  uint8_t ina_idx = idx / 3;
  uint8_t ch = idx % 3; // 0..2
  return "INA" + String(ina_idx+1) + "_CH" + String(ch+1);
}

void addKPOP(const String& title, const char* unit="A", uint8_t prec=3) {
  if (kpop_cnt >= MAX_KPOP) return;
  KPOP[kpop_cnt] = new Supla::Sensor::GeneralPurposeMeasurement();
  KPOP[kpop_cnt]->setDefaultUnitAfterValue(unit);
  KPOP[kpop_cnt]->setDefaultValuePrecision(prec);
  KPOP[kpop_cnt]->setInitialCaption(title.c_str());
  kpop_cnt++;
}

void setup() {
  Serial.begin(115200);
  delay(200);
  Wire.begin(SDA_PIN, SCL_PIN);

  // --- Skan/Initialize INA3221 (max 3 sztuki) ---
  for (size_t a = 0; a < INA_ADDRS_CNT && ina_found < 3; ++a) {
    uint8_t addr = INA_ADDRS[a];

    // szybki ping I2C (opcjonalnie)
    Wire.beginTransmission(addr);
    uint8_t err = Wire.endTransmission();
    if (err != 0) continue;

    // próbujemy .begin()
    INAEntry &slot = ina[ina_found];
    slot.addr = addr;
    if (slot.dev.begin(addr, &Wire)) {
      for (uint8_t ch=0; ch<3; ch++) slot.dev.setShuntResistance(ch, SHUNT_OHMS[ch]);
      slot.ok = true;
      ina_found++;
      Serial.printf("INA3221 #%u OK @0x%02X\n", ina_found, addr);
    }
  }

  if (ina_found == 0) {
    Serial.println("Nie znaleziono INA3221 na I2C (0x40..0x43).");
  }

  // --- KPOP: 3/6/9 prądów + 1 suma (1→4, 2→7, 3→10) ---
  uint8_t wanted = (ina_found * 3) + (ina_found ? 1 : 0);
  if (wanted > MAX_KPOP) wanted = MAX_KPOP;

  // prądy
  for (uint8_t i = 0; i < ina_found*3 && i < MAX_KPOP-1; ++i) {
    addKPOP(chTitle(i)); // jednostka "A", prec 3
  }
  // suma
  if (ina_found > 0 && kpop_cnt < MAX_KPOP) {
    addKPOP("INA_total");
    sum_idx = kpop_cnt - 1;
  }

  // --- SUPLA start ---
  SuplaDevice.begin(GUID, "svrUU.supla.org", "[email protected]", AUTHKEY);

  Serial.printf("Znaleziono INA: %u, utworzono KPOP: %u (sum_idx=%d)\n",
                ina_found, kpop_cnt, sum_idx);
}

void loop() {
  SuplaDevice.iterate();

  static uint32_t t = 0;
  if (millis() - t < 1000) return;
  t = millis();

  if (ina_found == 0) return;

  // odczyt prądów i publikacja
  double sum = 0.0;
  uint8_t out_idx = 0;

  for (uint8_t n = 0; n < ina_found; ++n) {
    INAEntry &e = ina[n];
    if (!e.ok) continue;

    for (uint8_t ch = 0; ch < 3; ++ch) {
      if (out_idx >= kpop_cnt || (sum_idx >= 0 && out_idx == sum_idx)) break;
      double amps = (double)e.dev.getCurrentAmps(ch);
      if (amps < 0) amps = 0;              // obcięcie szumu ujemnego
      if (out_idx < MAX_KPOP) {
        KPOP[out_idx]->setValue(amps);
      }
      sum += amps;
      out_idx++;
    }
  }

  if (sum_idx >= 0 && sum_idx < kpop_cnt && KPOP[sum_idx]) {
    KPOP[sum_idx]->setValue(sum);
  }

  //  Serial diagnostyka
  Serial.print("I: ");
  for (uint8_t i = 0; i < kpop_cnt; ++i) {
    // wypisz wszystkie
    Serial.print(i == 0 ? "" : ", ");
    if (i == sum_idx) Serial.print("SUM");
    else Serial.print(chTitle(i));
  }
  Serial.print(" | suma=");
  Serial.println(sum, 3);
}
[email protected]
Posts: 1585
Joined: Mon Feb 06, 2023 8:56 am
Has thanked: 18 times
Been thanked: 26 times

Post

A jak się wywala? jakieś logi?

Return to “Pomoc”