Due met 4xINA219 op I2C werkt maar een paar seconden op een Uno werkt het wel

Hallo,

Ik heb een vreemd probleem.

Ik het een programma gemaakt om 4 power sensoren (INA219) uit te lezen. Dit werkt goed op een Uno. Alleen omdat het straks op een Due moet draaien had ik hetzelfde programma op een Due gezet en dan werkt deze maar een paar seconden.

Ik kom er niet uit en heb geen idee waar ik dit moet zoeken.

Moet je voor I2C nog iets extra's doen op een Due?

Hieronder staat me code:

#include <Wire.h>
#include <Adafruit_INA219.h>

Adafruit_INA219 SensorU24; //0x40
Adafruit_INA219 SensorU12(0x41);
Adafruit_INA219 SensorU5(0x44);
Adafruit_INA219 SensorU3(0x45);

void setup(void) 
{
  Serial.begin(115200);
  while (!Serial) {
      // will pause Zero, Leonardo, etc until serial console opens
      delay(1);
  }

  uint32_t currentFrequency;
    
  Serial.println("Hello!");
  
  // Initialize the INA219.
  // By default the initialization will use the largest range (32V, 2A).  However
  // you can call a setCalibration function to change this range (see comments).
  
  if (! SensorU24.begin()) {
    Serial.println("Failed to find SensorU24");
  }
 
  if (! SensorU12.begin()) {
    Serial.println("Failed to find SensorU12");
  }
 
  if (! SensorU5.begin()) {
    Serial.println("Failed to find SensorU5");
  }
 
  if (! SensorU3.begin()) {
    Serial.println("Failed to find SensorU3");
  }
 
  // To use a slightly lower 32V, 1A range (higher precision on amps):
  //ina219.setCalibration_32V_1A();
  // Or to use a lower 16V, 400mA range (higher precision on volts and amps):
  //ina219.setCalibration_16V_400mA();

  Serial.println("Measuring voltage and current with INA219 ...");
}

void loop(void) 
{
  float U24_shuntvoltage = 0;
  float U24_busvoltage = 0;
  float U24_current_mA = 0;
  float U24_loadvoltage = 0;
  float U24_power_mW = 0;
  
  float U12_shuntvoltage = 0;
  float U12_busvoltage = 0;
  float U12_current_mA = 0;
  float U12_loadvoltage = 0;
  float U12_power_mW = 0;

  float U5_shuntvoltage = 0;
  float U5_busvoltage = 0;
  float U5_current_mA = 0;
  float U5_loadvoltage = 0;
  float U5_power_mW = 0;

  float U3_shuntvoltage = 0;
  float U3_busvoltage = 0;
  float U3_current_mA = 0;
  float U3_loadvoltage = 0;
  float U3_power_mW = 0;
  
  U24_shuntvoltage = SensorU24.getShuntVoltage_mV();
  U24_busvoltage = SensorU24.getBusVoltage_V();
  U24_current_mA = SensorU24.getCurrent_mA();
  U24_power_mW = SensorU24.getPower_mW();
  U24_loadvoltage = U24_busvoltage + (U24_shuntvoltage / 1000);
  
  U12_shuntvoltage = SensorU12.getShuntVoltage_mV();
  U12_busvoltage = SensorU12.getBusVoltage_V();
  U12_current_mA = SensorU12.getCurrent_mA();
  U12_power_mW = SensorU12.getPower_mW();
  U12_loadvoltage = U12_busvoltage + (U12_shuntvoltage / 1000);
  
  U5_shuntvoltage = SensorU5.getShuntVoltage_mV();
  U5_busvoltage = SensorU5.getBusVoltage_V();
  U5_current_mA = SensorU5.getCurrent_mA();
  U5_power_mW = SensorU5.getPower_mW();
  U5_loadvoltage = U5_busvoltage + (U5_shuntvoltage / 1000);
  
  U3_shuntvoltage = SensorU3.getShuntVoltage_mV();
  U3_busvoltage = SensorU3.getBusVoltage_V();
  U3_current_mA = SensorU3.getCurrent_mA();
  U3_power_mW = SensorU3.getPower_mW();
  U3_loadvoltage = U3_busvoltage + (U3_shuntvoltage / 1000);
  
  Serial.println("===========================================================");
  Serial.println("POWER 24V:   ");
  Serial.print("Bus Voltage:   "); Serial.print(U24_busvoltage);   Serial.println(" V ");
  Serial.print("Shunt Voltage: "); Serial.print(U24_shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(U24_loadvoltage);  Serial.println(" V ");
  Serial.print("Current:       "); Serial.print(U24_current_mA);   Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(U24_power_mW);     Serial.println(" mW");
  
  Serial.println("===========================================================");
  Serial.println("POWER 12V:   ");
  Serial.print("Bus Voltage:   "); Serial.print(U12_busvoltage);   Serial.println(" V ");
  Serial.print("Shunt Voltage: "); Serial.print(U12_shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(U12_loadvoltage);  Serial.println(" V ");
  Serial.print("Current:       "); Serial.print(U12_current_mA);   Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(U12_power_mW);     Serial.println(" mW");
  
  Serial.println("===========================================================");
  Serial.println("POWER 5V:   ");
  Serial.print("Bus Voltage:   "); Serial.print(U5_busvoltage);   Serial.println(" V ");
  Serial.print("Shunt Voltage: "); Serial.print(U5_shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(U5_loadvoltage);  Serial.println(" V ");
  Serial.print("Current:       "); Serial.print(U5_current_mA);   Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(U5_power_mW);     Serial.println(" mW");
  
  Serial.println("===========================================================");
  Serial.println("POWER 3V:   ");
  Serial.print("Bus Voltage:   "); Serial.print(U3_busvoltage);   Serial.println(" V ");
  Serial.print("Shunt Voltage: "); Serial.print(U3_shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(U3_loadvoltage);  Serial.println(" V ");
  Serial.print("Current:       "); Serial.print(U3_current_mA);   Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(U3_power_mW);     Serial.println(" mW");



  delay(2000);
}

heb je aan allebei de kanten netjes de weerstanden gezet en die ook aangesloten?
in de eerste regel staat een default, maak daar eens een normale zin van
die declaraties mag ook in een zin.

Nee, ik heb geen weerstand aangesloten. Ik heb gegoogled maar vind niet echt 1 waarde hier voor.

Ik heb 5V en 3V3. Heb je hier nog andere waardes nodig?

Wel bijzonder dat het bij de uno wel werk dan.

Adafruit_INA219 SensorU24; //0x40

Stndaard stond het adres niet genoemd als je een jumper niet dicht soldeer. Ik heb hem er meer zelf bijgezet zodat ik geen dubbele adressen gebruikt.

Bedoel je nu dat ik de eerste regel net zo neet moet zetten als de volgende 3, met het adres er in?

ja dus adres 40 netjes benoemen ipv dat er de default waarde staat.
en ik bedoelde de afsluitweerstanden van I2C die zijn inderdaad verschillend voor 3 en 5 Volt.
wel 1 voltage gebruiken voor het geheel. I2C is normaal 5 Volt, dus het kan zijn dat het met de Due (3.3 Violt niet meer werkt door het verschil in werkspanning.

Oke, zal het adres toevoegen.

Met die weerstanden vind ik nog wel lastig wat ik moet kiezen. Voor 5 V zie je al een hele hoop verschillende waardes, en voor 3V3 kan ik dit moeilijk vinden. Heb jij ervaring met deze weerstand te kiezen?

De INA219 is geloof ik wel geschikt voor 3V3. Dit staat op de achterzijde (zie foto bijlage)

INA219.PNG

Volgens I2C is de maximum stroom 3 mAdus bij 3 Volt 10 kiloohm minimum. Maar vaak zet je het dubbele erin zoals 20kohm of 22 omdat dat goedkope weerstanden zijn. zo belangrijk is het niet.
dus een pullup van 16 kohm is minimaal om zowel op 3 als op 5 Volt te kunnen werken.
De INA mag beide zijn voltages hebben.
de verschillende waardes is heel normaal heeft te maken met ruis en stroomverbruik, techniek is niet zo exact als vaak wordt gedacht.

Kun je een link geven naar de INA219 modules die je gebruikt (graag een link naar waar je het hebt gekocht).
Hoe heb je ze aangesloten ?
Hoe lang zijn de draden van SDA en SCL ? Gebruik je een kabel ?

Zoals shooter en rainman al schreven: de INA219 is geschikt voor 3.3V en 5V. Maar geef de INA219 5V op een 5V board zoals de Arduino Uno, en geef de INA219 3.3V als het samen met een 3.3V board gebruikt wordt zoals de Due. Op die manier werken de I2C signalen op de juist voltages.

De Arduino Uno heeft een input-filter en een uitgang-slew-rate-limiter voor de I2C bus. De signalen zijn dus veel vriendelijker dan bij een Arduino Due.

Helaas is de Due een board met meerdere problemen. Het grootste probleem is de I2C bus. Als je zoekt in dit forum, dan kom je heel vaak problemen met de Due en I2C tegen. Er zitten namelijk verkeerde pullup weerstanden op het Due board. Op de gewone SDA and SCL zitten weerstanden van 1k5 naar 3.3V en soms zitten er zelfs 1k weerstanden op gesoldeerd. De andere I2C bus (SDA1 en SCL1) hebben helemaal geen pullup weerstanden.

Normaal gesproken worden er geen of anders 10k pullup weerstanden gebruikt, maar de Due blijven ze verkopen met de verkeerde pullup weerstanden.

Je kunt die weerstanden er af halen, met een flinke druppel soldeer over het hele smd onderdeel.

Kun je een ander board nemen ? Bijvoorbeeld een SAMD ARM M0+, zoals bij de Arduino Zero en veel MKR boards.

@ shooter

Ik heb een weerstand nu van 1,6k gekozen. Deze heb ik berekend volgens een youtube link: Calculating the Correct Pull-up Resistor Value in I2C Bus Applications - YouTube

Het werkt helaas nog niet. Het gaat wel langer goed, qua tijd dan.

@ koepel

Ik heb de INA219 hier gekocht: https://nl.aliexpress.com/item/32859078202.html?spm=a2g0s.9042311.0.0.27424c4dRs6uQg

De draden zijn 30cm (standaard 4 polig dupont verlengkabel), stuks. Op de print zijn het korte sporen. De externe pullup weerstand heb ik aan het einde gezet.

In de bijlage (ina219.zip) zitten de foto's. Het is een hoofdprint print die 24V schakelt met een meeting er op. En daarna zijn het 3 dezelfde prints met een DC/DC converter met een meeting er op. De ingestelde voedingen zijn 12V, 5V en 3V3.

Bedankt voor de tip van de Due. Ik had dit niet gevonden, maar het is soms lastig zoeken op het forum.

Dus de weerstanden er niet afhalen, maar kortsluiten? Of haal je er af door een druppel er op te doen?

Ik had eerst een mega en deze was te klein qua geheugen. daarom ben ik een due gaan gebruiken. Vind het wel lastig sowieso want ik moet naar de 3V3 terwijl ik alles op 5V heb uitgelegd.

Een bijkomend groot voordeel is een tweede I2C bus omdat ik veel dubbele adressen heb.

Ik heb me nog niet verdiept in de andere boards.

Het probleem is dat ik van huis uit een PLC programeur ben (structed text) en dat ik C me eigen aanleer. Het probleem is daar ook om de code compact te houden, maar ook begrijpbaar (voor mij dan :wink: )

Ik gebruik de Due om via RS232 request en status signalen naar andere Mega's (of nano's) te zenden en ontvangen. De mega (of nano) lost local ook een deel van de besturing op. Ook zijn de Mega (of nano) ook gelijk de i/o binnen halen of aansturen.

Dus ik weet niet welk board dan een goed keuze is.

ina219.zip (593 KB)

Het was beter geweest dat je die video niet had gezien. Er worden allerlei aannames gedaan, en de belangrijke dingen zitten verborgen in de berekening. Die berekening gaat uit van een capaciteit op de SDA en SCL lijn van 200 pF. Jij hebt geen 200 pF, dus is die berekening niet voor jou :frowning:

Voor sensoren is een 3.3V Arduino beter, omdat je dan gewoon de 3.3V sensoren kunt aansluiten.
Hoe verbindt je de 3.3V Due met de 5V Mega en Nano ? Via RX en TX ? Je kunt niet zomaar een signaal van 5V aan de Due voeren. Of via modules naar een echte RS-232 bus ?

Het zwarte blokje met weerstanden kun je er af halen. Niet kortsluiten, want dat is een blokje van 4 weerstanden (waarvan er twee gebruikt worden als pullup weerstand). Met een "flinke druppel soldeer" bedoelde ik dat je dat hele ding kunt opwarmen en van het board af kunt laten vallen of er af wippen.

Laten we eens gaan rekenen:
Stel dat je 1k5 pullup weerstanden op de Due hebt en geen 1k, en dat de interne pullup van de Due 50k is (ik ben vergeten wat de waarde is). Op die INA219 modules zie ik 10k pullup weerstand zitten ("1002"). Dus vier keer 10k. Dan nog jouw 1k6 er bij.
Dan wordt de totale pullup:
1k5 // 50k // 10k // 10k // 10k // 10k // 1k6 = 584 Ω
De sink current (om de SDA of SCL omlaag te trekken) = 3.3V / 584Ω = 5.6 mA
Die mag maximaal 3mA zijn.

Je kunt dat blokje van 1k5 van het Due board afhalen en jouw 1k6 weglaten. Dan zou het moeten werken als er niets anders is aangesloten.

Zonder jouw 1k6 wordt de sink current 3.5 mA. Dat is slechts 0.5 mA over de grens en dat zou gewoon moeten werken. Dus mogelijk is er meer aan de hand. Soms worden 100 Ω weerstanden in de SDA en SCL lijn gezet bij de Due om de steile pieken van de signalen wat te dempen.

De foto's zijn een beetje een zoekplaatje voor mij. De I2C bus heeft drie draden: SDA, SCL en GND. De belangrijkste is vanzelfsprekend de GND. Ik kan moeilijk volgen waar de GND heen gaat, die lijkt een ander pad te volgen.

Wat zet je op de VCC van de INA219 ? Die moet 3.3V zijn als je de 3.3V I2C bus van de Due gebruikt, en die moet 5V zijn als je de 5V I2C bus van de Mega of Nano gebruikt. Ik heb de indruk dat het 5V is en dat die niet van het Arduino board af komt. Dan kloppen de SDA en SCL signalen niet voor de Due.

Ik kan niet zeggen waarom de Mega niet groot genoeg is en welk board je het beste kunt gebruiken. Misschien is je code niet optimaal en zou je 90% op sram kunnen besparen. Misschien ken je "F()" macro en de PROGMEM niet. Misschien wil enorme wiskundige matrix berekeningen doen, dan kun je beter een computer gebruiken (of een Raspberry Pi).

Een project met een Arduino Mega 2560 board is bij mij:
De schets gebruikt 76190 bytes (30%) programma-opslagruimte. Maximum is 253952 bytes.
Globale variabelen gebruiken 2535 bytes (30%) van het dynamisch geheugen. Resteren 5657 bytes voor lokale variabelen. Maximum is 8192 bytes.
De 76190 gebruik van flash memory is niet interressant. De 2535 byte wordt runtime nog een stuk meer, maar nog ruim binnen de 8k sram.

Haal alle I2C weerstanden eraf en zet aan het begin en eind een setje van 10 K dat is hoe het hoort.

@ koepel.

Hier is even snel het schema (zie bijlage). Op de rest kom ik nog terug

In de bijlage zit een foto van de INA219 pcb.

Voor de duidelijkheid, de rood omcirkelde weerstanden zijn de pullup weerstanden voor de bus.

En de oranje omcirkelde weerstanden zijn waarschijnlijk de pullup weerstanden voor de adressen te selecteren

Als ik het logisch bekijk.

@ koepel.

Ik dacht, zoek het eerst zelf uit voordat ik vragen ga stellen.

Wat betreft de RS232.

Ik heb al succes vol een nano aan een Mega gekoppeld en een mega oo kaan een mega met de Easy Transfer library. Werk echt super. Ik heb me niet gerealiseerd dat dit inderdaad niet kan met een due.

Zou het wel lukken met een level shifter

Weerstandje Due
In dat blokje zitten 4 weerstanden en ik moet er twee weg halen, maar ik haal er vier weg. heb ik die andere ook niet nodig voor iets?

En hoe zit het dan met de 2e I2C bus op de Due?

Schema:
Op de foto zitten 4 aders VCC (3V3) + gnd + Scl + Sda. De print heeft ook voeding nodig. Alleen bij de due is de vcc niet gebruikt (zie ook mijn vorige post met het schema/schets

De voeding komt van de laatste DC/DC print die van de 24V een 3V3 maakt. De gnd zijn allemaal gekoppeld met DC/DC print.

Programeren:

Ik programeer zoals ik een plc programeerde in Structed text. En ik heb al gemerkt dat in een plc de ruimte niet echt een probleem is, dus de manier van programmeren die ik ken is minder geschikt voor arduino.

In de plc bouwde ik hele status en commando structuren op die verzonden werden van uit een master controller die alles regelde en aanstuurde. De ontvangen zijde van deze commando verwerkte dit local en deden hun acties en stuurde de status terug. Het idee zou wel kunnen werken maar de manier hoe je dit programmeer kan in een arduino niet zoals op een plc. Ik ben steeds aan het leren hoe C werkt en hoe een arduino werkt. maar soms wat frustrerend.

Ik ben recentelijk helemaal opnieuw begonnen met me project met een andere aanpak.

Ik heb nu eerst een goed debug programma geschreven waar ik bepaalde onderdelen in debug zet zodat de arduino er weinig last van heb. En nu ben ik delen eerst lokaal aan het testen (enkelvoudig op een losse UNO, als dat werkt het programma opslaan en eventueel de meervoudige varianten testen (zoals hier met meerdere INA219's). Ook appart opslaan als het werkt en daarna pas inplemeteren in het eigelijke project. Zo hoop ik me code en programma netjes te houden.

Ik ken inderdaad de "F()" macro en de PROGMEM niet. Er zitten (nog geen) grote wiskundige berekeningen in. Het is nu meer input inlezen, verwerken (omschalen en binnen de gestelde grenzen houden), output aansturen. Alleen de input kan op een andere arduino board zitten als de output.

Ok eerlijk de zijn had ik de due gekozen omdat deze dezelfde board layout heeft als de mega en heel veel ruimte heeft. Ook voor de CAN, maar dat wordt niet ondersteund had ik gevonden op internet. Wilde dit gebruiken ipv RS232. Minder storing gevoelig en sneller

@ shooter (Paul)

Dus van alle INA219's de weerstanden af halen en dan ook van de due.

Kan 4 weerstanden pakken van 10k

2 weerstanden daarvan samen met de draden naar het eerste INA219 aan de due I2C headers drukken met de andere kant aan de 3V3

De andere 2 aan het einden op de I2C pinnen zetten en aan de 3V3

@ koepel, is dit ook een goed idee

Het is namelijk erg veel werk, Ik moet de INA219 los solderen van mijn gemaakte print om er bij te kunnen.

Hierbij een paar losse antwoorden, en nu maar hopen dat het ook wat duidelijker wordt ::slight_smile:

Je mag die 10k op de INA219 modules laten zitten. Dat is slechts 10k en je gebruikt vier modules. Dat is te overzien.
Stel dat je soms één sensor-module gebruikt en soms 10 sensor-modules. Dan wil je natuurlijk de I2C bus hetzelfde houden, en dan is het beter om vaste externe pullup weerstanden te gebruiken en ze van alle modules weg te halen. Bij jouw project hoeft dat niet.

De Due is de Master en de 3.3V pin van de Due is om sensoren van power te voorzien. Dan zou ik graag zien dat er vier draden vanuit de Due gaan (SDA, SCL, GND, 3.3V) en dat naar alle INA219 modules. Die draden nergens anders mee verbinden. Als je iets anders met de GND of de 3.3V van de Due wilt verbinden, dan dat bij/op het Due board doen, maar laat die vier draden naar de sensoren met rust.
Op je tekening kan ik niet overzien of er veel storing tussen de verschillende dingen zou kunnen staan.

Een TTL-level seriële of UART of USART of RX/TX verbinding is géén RS-232.
Ik denk dat de term "seriële verbinding" het meest wordt gebruikt.
Om een 5V board met een 3.3V board te verbinden kun je die level shifters gebruiken. Dan wordt het signaal echter wel een stuk zwakker :frowning:

Dat blokje van 4 weerstanden gebruikt er maar 2 voor de I2C bus. De andere twee worden niet gebruikt :o
De SDA1 en SCL1 hebben helemaal geen pullup weerstanden. Helaas is het vaak lastig om een bestaande library om te zetten naar "Wire1".

Je kunt je sketch laten zien. Waarschijnlijk heb je alle text in sram staan, terwijl die ook in Flash geheugen kan.
Ik ben benieuwd naar wat de compiler zegt over jouw geheugengebruik. Ik bedoel dat stukje dat ik liet zien dat begint met: "De schets gebruikt 76190 bytes (30%) programma...".

Heeft de Due geen support voor CAN ? Dat is balen. Er zijn wel modules en libraries voor CAN. Die heb ik zelf niet geprobeerd.