De Ultieme Multi Power Module - Deel 2

In het vorige deel hebben we kennis gemaakt met een stroomsensor, de INA3221. Een kant en klaar boardje waar deze chip op zit kunnen we goed gebruiken voor onze experimenten. Helaas moet het board wat worden aangepast om het bruikbaar te maken om drie werkelijk onafhankelijke spannings-kanalen of -bussen te monitoren.

In dit vervolg heb ik de schakeling ontworpen, het schema getekend en een testopstelling met de aangepaste module gemaakt, zodat we kunnen gaan testen met stroom- en spanningsmetingen.

Video : toestemming voor cookies nodig
Instellingen
INA3221

De INA3221 stroomsensor

Een bruikbare SMD chip om de spanning en stroom te monitoren is de INA3221 [info & datasheet]. Deze chip communiceert via de I2C bus en maakt het mogelijk om drie onafhankelijke spannings-kanalen te monitoren. Door het voltageverschil per kanaal over een (bekende, 0.1Ω) shunt-weerstand te meten, kunnen de afgenomen stroom en het vermogen worden bepaald.

Het mooie is dat de chip niet alleen via de I2C bus uitgelezen kan worden, maar dat we de chip ook kunnen configureren door in bepaalde registers te schrijven. De INA3221 kan vervolgens signaleren of de gemeten waarden binnen instelbare grenswaarden blijven en een signaal afgeven als bijvoorbeeld de stroom boven een ingestelde waarde komt. Dit maakt het mogelijk de chip een klein relais te laten bedienen dat als een instelbare automatische zekering kan werken. De module is dan goed beveiligd tegen (oververhitting door) te hoge stromen. Handig tijdens het testen en experimenteren!

Zowel de ‘Warning’ als ‘Critical’ drempelwaarden kunnen hierdoor vanuit het programma in de chip geprogrammeerd worden over de I2C bus. Dit maakt het mogelijk de module uiteindelijk dus via knopjes op het front configureerbaar te maken. Een optie om deze maximaal toelaatbare stroom per bus in de EEPROM van de Arduino op te slaan, zou vanzelfsprekend prettig zijn. Daardoor zouden deze instellingen in de module behouden blijven en hoeft deze niet voor elk gebruik te worden geconfigureerd.

Het prettigst zou zijn als de nieuwe voedingsmodule dezelfde vormfactor heeft als de Zauberling. Hierdoor ligt het voor de hand ook nu de schakeling onder te brengen op een 'sandwich' van twee printplaten. Om deze reden is het schema ook in twee stukken geknipt.

De onderste printplaat ligt onderin de behuizing, maakt de diverse voltages uit de binnenkomende 12 volt van de DC-adaptor, en verzorgt de metingen met de INA-chip. Ook het relais dat zo meteen als automatische zekering dienst kan doen, is hierop ondergebracht.

Op de bovenste printplaat kunnen de diverse connectoren, drukknoppen, LEDs en het kleine schermpje een plekje vinden. Ook zal hier, hangend op de kop, de Arduino Pro Mini nog moeten worden ondergebracht. Om beide zijden van beide printplaten optimaal te gebruiken, zal voor (bijna) alle onderdelen SMD montage worden gekozen.

UMPM - Lower PCB

De onderste printplaat

Via een DC-connector komt de 12 volt van de externe DC-adaptor de behuizing zometeen binnen. Na een fysieke zekering en de aan/uit knop, wordt er op dezeprintplaat 9 volt van gemaakt voor het systeem. Deze spanning loopt niet over de contacten van het relais, dat de automatische zekering vormt. Deze 9 volt gaat straks door naar printplaat 2, waar er op het Arduino Pro Mini board 5 volt van wordt gemaakt. Deze 5 volt gebruikt de microcontroller op de andere printplaat zelf, maar deze komt ook terug zodat de INA-chip er mee gevoed kan worden.

Er worden uit de binnenkomende 12 volt, die over het normally-closed contact van het relais loopt, drie spanningen gemaakt. De 3.3 volt loopt simpelweg door naar de andere printplaat, de bovenste printplaat in de behuizing met de connectoren, het display en de knoppen op het front. De andere drie spanningen lopen over de overeenkomstige meetkanalen van de INA-chip waarna ze via een verbindingsconnector naar de bovenste printplaat gaan waar ze uiteindelijk op het front ter beschikking staan.

De afbeelding hiernaast komt uit de datasheet van de stroomsensor en toont het principe van de meting. Aan de linkerkant zijn de drie shunt-weerstanden waarover de meting plaatsvindt zichtbaar. Deze zijn op het sensorboard als zware 2 Watt SMD weerstanden (met R2512 behuizing) uitgevoerd. Deze weerstanden staan telkens in serie met de 'load'; de aangesloten verbruiker. De afwisselend gemeten waarden van elke bus, worden bemonsterd door een AD-converter (ADC, midden) en worden in registers van de chip geplaatst die via de I2C bus opvraagbaar zijn (rechts). Aan deze interface-kant ook de verschillende stuur- en alarmsignalen van de chip. Voor dit project wordt alleen het 'Critical' signaal gebruikt om de automatische zekering te activeren als de geconfigureerde grenswaarde voor de afgenomen stroom wordt overschreden.

INA3221 application

Ook kunnen we via de I2C bus configureren bij welke stroom het het ‘Critial’ signaal van de betreffende bus actief moet worden. Dit signaal wordt ingelezen op ingang D8 van de Arduino (zie schema PCB 2 hieronder). Zodra het actief is, kan via uitgang D9 dan het 'Fuse' signaal gegeven worden om via een transistor het relais te bekrachtigen. Hierdoor vallen onmiddelijk alle spanningen aan de uitgangen weg en is de module tegen te hoge stromen, zoals door kortsluiting, beschermd.

De systeemspanning van 9 volt en de 3.3 volt uitgang kunnen door SMD types spanningsregulatoren van maximaal 100 mA worden verzorgd, voor de 9 en 5 volt spanningsregulatoren van de uitgangsspanningen is het verstandiger zwaardere types zoals de 78S05 (tot max. 2A) te kiezen. Om de 12 volt ingangsspanning van de DC-adaptor die op het front van de module, maar ook achterop op de twee door te lussen spanningsuitgangen, doorloopt hoeven we ons niet te bekommeren. Daar geldt de maximale stroom die de adaptor kan leveren. Vanzelfsprekend zal deze wel binnen grenzen van de fysieke zekering moeten liggen. Als we de printplaat ontwerpen met '1 ounce' koperdikte en een koperspoor-breedte van 1,5mm, zal deze een stroom tot 1,5 Ampère zonder problemen aankunnen. Wie meer wil zal de PCB met dikker koper moeten laten fabriceren of de sporen kunnen vertinnen.

UMPM - Upper PCB

De bovenste printplaat

Hierboven het schema van de printplaat die bovenin de behuizing, onder het frontdeksel, zit. Deze printplaat geeft plaats aan het display en de aansluitingen op het front voor de diverse spanningen van 3.3, 5, 9 en 12 volt.
 
Het belangrijkste onderdeel is hier vanzelfsprekend de Arduino Pro Mini, die vanaf de andere printplaat wordt gevoed en de 5 volt die hij maakt weer aan printplaat 1 ter beschikking stelt voor de INA-chip. Het ‘Critial’ signaal van deze stroomsensor komt hier binnen, en als de automatische zekering moet ingrijpen kunnen we hier het ‘Fuse’-signaal terugsturen zodat het relais en daarmee de automatische zekering worden bekrachtigd. Op zo'n moment gaat tevens de ‘Overload’ LED aan.
 
Er zijn knopjes om door de verschillende kanalen of bussen te lopen op het beeldschermpje. Dit kleine SSD1306 display loopt via dezelfde I2C bus waarover de INA-chip over wordt uitgelezen. Met LEDs wordt aangegeven welke spanning wordt weergegeven op het scherm. Er is een ‘Clear’ knopje om de op het display weergegeven stroompieken te resetten. En er is een knopje om de configuratie-modus te bereiken zodat we de stroomdrempel per bus kunnen configureren. Deze kunnen dan desgewenst in de EEPROM van de Arduino worden opgeslagen door het drukken van de 'Store'-knop.
 
Helemaal rechts worden de FTDI programmeersignalen doorgezet naar een connector op deze print om de Arduino te kunnen programmeren via de USB-bus. Omdat de module slechts sporadisch van nieuwe firmware hoeft te worden voorzien, is deze connector niet naar buiten uitgevoerd en onder het deksel van de module bereikbaar.

Testopstelling

Hiernaast is de schakeling op een breadboard gezet. Linksboven de twee grotere voltage regulators, met daaronder de kleinere 3.3 volt en 9 volt regulatoren voor de systeemspanning. Ook het relais en de stuurtransistor voor de 'automatische zekering' zijn geplaatst en aangesloten.

De witte drukknoppen kunnen voor het kiezen van de uitlezing op het scherm worden gebruikt. De blauwe drukknop om naar de instelmodus voor de stroomdrempel te gaan. Deze knop kan ook gebruikt worden om de vastgehouden piekstroom melding op het scherm te resetten. Met de rode knop tenslotte kan de ingestelde waarde in EEPROM worden opgeslagen.

INA3221 breadboard

De oranje knop is tijdelijk. Hiermee kan, ter test, een 100Ω vermogensweerstand aan een uitgang worden aangesloten om te kunnen spelen met stroomvariaties en de zekering te testen. Met de hardware aldus opgesteld, werd het tijd om een Arduino Sketch te schrijven om een en ander eens te kunnen gaan uitproberen.

De INA3221 uitlezen en configureren

Ik vond voor communicatie met de INA-chip een software bibliotheek van SwitchDoc Labs. Helaas was deze nogal rudimentair en konden er alleen meetwaarden uit registers van de chip mee worden gelezen. Er waren nog geen routines om via de I2C bus configuratiewaarden naar registers van de chip te schrijven. Dit is vanzelfsprekend wel iets dat noodzakelijk is als we de hardware monitoring door de chip zouden willen gaan gebruiken. Natuurlijk is het mogelijk de stroomsterkte in de software te monitoren, maar aangezien de chip de mogelijkheid biedt het hardwarematig te monitoren, wilde ik dat graag gebruiken. Daarom breidde ik de library uit zodat ik ook de 'Critical Alert' waarde in de chip kon schrijven voor elke bus.

Hiernaast de Arduino Sketch die ik voor het begeleidende filmpje gebruikte. Deze is, inclusief de aangepaste library, ook te vinden op GitHub.

// Test INA3221
// Whizzbizz.com - Arnoud van Delden - June 2022
// See https://www.whizzbizz.com/en/power-module-part2
//

#include 
#include "SDL_Arduino_INA3221.h"

// Initializing INA3221 
SDL_Arduino_INA3221 ina3221;  // Default address 0x40 on I2C bus

// The three channels/busses of the INA3221
#define VOLTAGE_MAIN_12V 1
#define VOLTAGE_9V 2
#define VOLTAGE_5V 3

// Static calibration offset for current per bus, will be exemplaric...
#define CAL1 0 // 12v bus: Compensate for 9, 5 and 3.3 voltages that are being produced from the fuse-switched measured 12v
#define CAL2 0  // 9v
#define CAL3 0  // 5v

// Define I/O pins
#define BUS1_LED       7
#define BUS2_LED       6
#define BUS3_LED       5
#define READ_CRITICAL  8
#define AUTO_FUSE      9

bool logging = true;      // Serial logging during development...
bool ext_logging = true; // Show all bus values during debugging...

uint16_t binValue;
bool autoFuse = false;

struct INA3221_Bus {
  char* Label;
  uint8_t Channel;
  float shuntvoltage = 0;
  uint16_t shuntvoltage_raw = 0xFF;
  float busvoltage = 0;
  uint16_t busvoltage_raw = 0xFF;
  float current_mA = 0;
  float current_mAMax = 0;
  float currentOffset;
  float loadvoltage = 0;
  uint16_t currentLimit;
  uint16_t currentLimitSaved;
};

INA3221_Bus Bus1, Bus2, Bus3;
INA3221_Bus *currentBus = &Bus1;

void setup(void) {
  if (logging) Serial.begin(115200);
  if (logging) Serial.println(F("Test INA3221"));

  // Set pin-modes...
  pinMode(READ_CRITICAL, INPUT);
  pinMode(AUTO_FUSE, OUTPUT);

  // Initialize busses and INA3221...
  Bus1.Label = "12V";
  Bus1.Channel = VOLTAGE_MAIN_12V;
  Bus1.currentOffset = CAL1;
  Bus2.Label = "9V";
  Bus2.Channel = VOLTAGE_9V;
  Bus2.currentOffset = CAL2;
  Bus3.Label = "5V";
  Bus3.Channel = VOLTAGE_5V;
  Bus3.currentOffset = CAL3;
  ina3221.begin();
  if (logging) {
    Serial.print(F("INA3221 getManufID="));
    Serial.println(ina3221.getManufID());
  }
  delay(200);
}

void loop(void) {
  // Read individual busses
  readBus(Bus1);
  delay(200);
  readBus(Bus2);
  delay(200);
  readBus(Bus3);
  delay(200);

  if (ext_logging) {
    logBus(Bus1);
    logBus(Bus2);
    logBus(Bus3);
  }
  
  delay(1000);
}

void readBus(INA3221_Bus &Bus) {
  Bus.busvoltage = fabs(ina3221.getBusVoltage_V(Bus.Channel));
  Bus.busvoltage_raw = ina3221.getBusVoltage_raw(Bus.Channel);
  Bus.shuntvoltage = fabs(ina3221.getShuntVoltage_mV(Bus.Channel));
  Bus.shuntvoltage_raw = ina3221.getShuntVoltage_raw(Bus.Channel);
  Bus.current_mA = fabs(ina3221.getCurrent_mA(Bus.Channel)-Bus.currentOffset);
  if (Bus.current_mA > Bus.current_mAMax) Bus.current_mAMax = Bus.current_mA;
  Bus.loadvoltage = fabs(Bus.busvoltage + (Bus.shuntvoltage / 1000));
}

void logBus(INA3221_Bus Bus) {
  Serial.print(F("   "));
  Serial.println(Bus.Label); 
  Serial.print(F("   Bus Voltage:       ")); Serial.print(Bus.busvoltage); Serial.println(" V");
  Serial.print(F("   Bus Voltage HEX:   0x")); Serial.println(Bus.busvoltage_raw, HEX);
  Serial.print(F("   Shunt Voltage:     ")); Serial.print(Bus.shuntvoltage); Serial.println(" mV");
  Serial.print(F("   Shunt Voltage HEX: 0x")); Serial.println(Bus.shuntvoltage_raw, HEX);
  Serial.print(F("   Load Voltage:      ")); Serial.print(Bus.loadvoltage); Serial.println(" V");
  Serial.print(F("   Current:           ")); Serial.print(Bus.current_mA); Serial.println(" mA");
  Serial.println("");
}

uint8_t readCriticalStatus() {
  // Reads the mask/enable register of the INA3221 after Critical Warning Alert
  uint16_t binValue;
  ina3221.wireReadRegister(INA3221_MASK_ENABLE, &binValue);
  binValue = (binValue>>7);
  if (binValue==4) {
    currentBus = &Bus1;
    return 1; // Bit2=Bus1
  }
  if (binValue==2) {
    currentBus = &Bus2;
    return 2; // Bit1=Bus2
  }
  if (binValue==1) {
    currentBus = &Bus3;
    return 3; // Bit0=Bus3
  }
  return 0;
}
Silberling Case

De volgende stap...

De volgende stap is de uitdaging bovenstaande schakeling in een 'Silberling'-behuizing te persen. Het is duidelijk dat het dan noodzakelijk wordt het relatief grote sensorboard (bijna twee keer zo groot als de Arduino Pro Mini!) te laten vervallen en te kiezen voor een eigen PCB layout waarop de sensor direct als SMD onderdeel zal worden geplaatst.

In het volgende en laatste deel zullen we eens kijken of ik de twee printplaatjes, de 3D te printen behuizing en het front kan ontwerpen. Ik ga dan de module echt in elkaar zetten en kijken of dat werkt.