Files
L'électron rare f55093d6fe
ESP-IDF CI / Host Tests (Unity) (push) Successful in 1m8s
CI / firmware-native (push) Successful in 2m57s
Rust Protection Tests / Cargo test (host) (push) Failing after 3m21s
ESP-IDF CI / ESP-IDF Build (v5.4) (push) Failing after 6m55s
ESP-IDF CI / Memory Budget Gate (push) Has been skipped
qa-cicd-environments / qa-kxkm-s3-build (push) Successful in 8m53s
qa-cicd-environments / qa-sim-host (push) Successful in 2m2s
qa-cicd-environments / qa-kxkm-s3-memory-budget (push) Successful in 11m17s
chore: import KXKM Batterie Parallelator
Context: the project archive (KXKM_Batterie_Parallelator-main) had
no git history locally; a fresh repository is needed to host it on
git.saillant.cc (electron/KXKM_Batterie_Parallelator).

Approach: initialize a new repo on branch main, stage the archive
content, and harden .gitignore before the first commit.

Changes:
- Import the full project tree: firmware/, firmware-idf/,
  firmware-rs/, iosApp/, kxkm-bmu-app/, kxkm-api/, hardware/,
  docs/, specs/, scripts/, models/, tests/
- Keep project dotfiles tracked despite the trailing '.*' ignore
  rule: .github/, .claude/, .superpowers/, .gitattributes,
  .markdownlint.json
- Extend .gitignore: firmware/src/credentials.h (local secrets,
  template kept), kxkm-bmu-app/**/build/ (66 MB compiled iOS
  framework), .remember/ (session data)

Impact: the project can now be maintained on the self-hosted Gitea
forge with a clean, secret-free initial history.
2026-07-04 12:32:28 +02:00

193 lines
11 KiB
Arduino

/*!
*
* @file BackgroundRead.ino
*
* @brief Example program for the INA Library demonstrating background reads
*
* @section BackgroundRead_section Description
*
* Program to demonstrate using the interrupt pin of any INA2xx which supports that functionality.
* It uses a pin-change interrupt handler and programs any INA2xx found to to read voltage and
* current information in the background while allowing the main Arduino code to continue processing
* normally until it is ready to consume the readings.\n\n
*
* The example program uses the Arduino AVR-based interrupt mechanism and will not function on other
* platforms\n\n
*
* Detailed documentation can be found on the GitHub Wiki pages at
* https://github.com/Zanduino/INA/wiki \n\n Since the INA library allows multiple devices of
* different types and this program demonstrates interrupts and background processing, it will limit
* itself to using the first INA226 detected. This is easily changed in the if another device type
* or device number to test is required.\n
*
* This example is for a INA226 set up to measure a 5-Volt load with a 0.1Ohm resistor in place,
* this is the same setup that can be found in the Adafruit INA226 breakout board. The complex
* calibration options are done at runtime using the 2 parameters specified in the "begin()" call
* and the library has gone to great lengths to avoid the use of floating point to conserve space
* and minimize runtime. This demo program uses floating point only to convert and display the data
* conveniently. The INA226 uses 15 bits of precision, and even though the current and watt
* information is returned using 32-bit integers the precision remains the same.\n The INA226 is set
* up to measure using the maximum conversion length (and maximum accuracy) and then average those
* readings 64 times. This results in readings taking 8.244ms x 64 = 527.616ms or just less than 2
* times a second. The pin-change interrupt handler is called when a reading is finished and the
* INA226 pulls the pin down to ground, it resets the pin status and adds the readings to the global
* variables. The main program will do whatever processing it has to and every 5 seconds it will
* display the current averaged readings and reset them.\n
*
* The datasheet for the INA226 can be found at http://www.ti.com/lit/ds/symlink/INA226.pdf and it
* contains the information required in order to hook up the device. Unfortunately it comes as a
* VSSOP package but it can be soldered onto a breakout board for breadboard use. The INA226 is
* quite similar to the INA219 mentioned above, but it can take bus voltages of up to 36V (which I
* needed in order to monitor a 24V battery system which goes above 28V while charging and which is
* above the absolute limits of the INA219). It is also significantly more accurate than the INA219,
* plus has an alert pin.\n The interrupt is set to pin 8. The tests were done on an Arduino Micro,
* and the Atmel 82U4 chip only allows pin change interrupt on selected pins (SS,SCK,MISO,MOSI,8) so
* pin 8 was chosen.
*
* @section BackgroundRead_license GNU General Public License v3.0
*
* This program is free software : you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should
* have received a copy of the GNU General Public License along with this program(see
* https://github.com/Zanduino/INA/blob/master/LICENSE). If not, see
* <http://www.gnu.org/licenses/>.
*
* @section BackgroundRead_author Author
*
* Written by Arnd <[email protected]> at https://www.github.com/SV-Zanshin
*
* @section BackgroundRead_versions Changelog
*
* Version | Date | Developer | Comments
* ------- | ---------- | ----------- | ------------------------------------------------------------
* 1.0.5 | 2020-12-01 | SV-Zanshin | Corrected "alertOnConversion()" call
* 1.0.4 | 2019-02-16 | SV-Zanshin | ifdef so that sketch won't compile on incompatible platforms
* 1.0.3 | 2019-01-09 | SV-Zanshin | Cleaned up doxygen formatting
* 1.0.2 | 2018-12-28 | SV-Zanshin | Converted comments to doxygen format
* 1.0.0 | 2018-06-23 | SV-Zanshin | Cloned and adapted example from old deprecated INA226
* library
*
*/
#if !defined(__AVR__)
#error Example program only functions on Atmel AVR-Based platforms
#endif
/**************************************************************************************************
** Declare all include files **
**************************************************************************************************/
#include <INA.h> // Include the INA library
/**************************************************************************************************
** Declare program Constants **
**************************************************************************************************/
const uint8_t INA_ALERT_PIN = 8; ///< Pin-Change pin used for the INA "ALERT" functionality
const uint8_t GREEN_LED_PIN = 13; ///< Arduino standard green LED
const uint32_t SERIAL_SPEED = 115200; ///< Use fast serial speed
/**************************************************************************************************
** Declare global variables and instantiate classes **
**************************************************************************************************/
INA_Class INA; ///< INA class instantiation
volatile uint8_t deviceNumber = UINT8_MAX; ///< Device Number to use in example
volatile uint64_t sumBusMillVolts = 0; ///< Sum of bus voltage readings
volatile int64_t sumBusMicroAmps = 0; ///< Sum of bus amperage readings
volatile uint8_t readings = 0; ///< Number of measurements taken
ISR(PCINT0_vect) {
/*!
@brief Interrupt service routine for the PCINT0_vect
@details Routine is called whenever the INA_ALERT_PIN changes value
*/
*digitalPinToPCMSK(INA_ALERT_PIN) &= ~bit(digitalPinToPCMSKbit(INA_ALERT_PIN)); // Disable PCMSK
PCICR &= ~bit(digitalPinToPCICRbit(INA_ALERT_PIN)); // disable interrupt for the group
sei(); // Enable interrupts (for I2C calls)
digitalWrite(GREEN_LED_PIN, !digitalRead(GREEN_LED_PIN)); // Toggle LED
sumBusMillVolts += INA.getBusMilliVolts(deviceNumber); // Add current value to sum
sumBusMicroAmps += INA.getBusMicroAmps(deviceNumber); // Add current value to sum
readings++;
INA.waitForConversion(deviceNumber); // Wait for conversion & INA int. flag
cli(); // Disable interrupts
*digitalPinToPCMSK(INA_ALERT_PIN) |=
bit(digitalPinToPCMSKbit(INA_ALERT_PIN)); // Enable PCMSK pin
PCIFR |= bit(digitalPinToPCICRbit(INA_ALERT_PIN)); // clear any outstanding interrupt
PCICR |= bit(digitalPinToPCICRbit(INA_ALERT_PIN)); // enable interrupt for the group
} // of ISR handler for INT0 group of pins
/*!
@brief Arduino method called once at startup to initialize the system
@details This is an Arduino IDE method which is called first upon boot or restart. It is only
called one time and then control goes to the main "loop()" method, from which control
never returns
@return void
*/
void setup() {
pinMode(GREEN_LED_PIN, OUTPUT); // Make the internal LED an output pin
digitalWrite(GREEN_LED_PIN, true); // Turn on the LED
pinMode(INA_ALERT_PIN, INPUT_PULLUP); // Declare pin with internal pull-up resistor
*digitalPinToPCMSK(INA_ALERT_PIN) |= bit(digitalPinToPCMSKbit(INA_ALERT_PIN)); // Enable PCMSK
PCIFR |= bit(digitalPinToPCICRbit(INA_ALERT_PIN)); // clear any outstanding interrupt
PCICR |= bit(digitalPinToPCICRbit(INA_ALERT_PIN)); // enable interrupt for the group
Serial.begin(SERIAL_SPEED);
#ifdef __AVR_ATmega32U4__ // If this is a 32U4 processor, wait 2 seconds for initialization
delay(2000);
#endif
Serial.print(F("\n\nBackground INA Read V1.0.5\n"));
uint8_t devicesFound = 0;
while (deviceNumber == UINT8_MAX) // Loop until we find the first device
{
devicesFound = INA.begin(1, 100000); // +/- 1 Amps maximum for 0.1 Ohm resistor
for (uint8_t i = 0; i < devicesFound; i++) {
/* Change the "INA226" in the following statement to whatever device you have attached
and want to measure */
if (strcmp(INA.getDeviceName(i), "INA226") == 0) {
deviceNumber = i;
INA.reset(deviceNumber); // Reset device to default settings
break;
} // of if-then we have found an INA226
} // of for-next loop through all devices found
if (deviceNumber == UINT8_MAX) {
Serial.print(F("No INA found. Waiting 5s and retrying...\n"));
delay(5000);
} // of if-then no INA226 found
} // of if-then no device found
Serial.print(F("Found INA at device number "));
Serial.println(deviceNumber);
Serial.println();
INA.setAveraging(64, deviceNumber); // Average each reading 64 times
INA.setBusConversion(8244, deviceNumber); // Maximum conversion time 8.244ms
INA.setShuntConversion(8244, deviceNumber); // Maximum conversion time 8.244ms
INA.setMode(INA_MODE_CONTINUOUS_BOTH, deviceNumber); // Bus/shunt measured continuously
INA.alertOnConversion(true, deviceNumber); // Make alert pin go low on finish
} // of method setup()
void loop() {
/*!
@brief Arduino method for the main program loop
@details This is the main program for the Arduino IDE, it is called in an infinite loop. The
INA226 measurements are triggered by the interrupt handler each time a conversion is
ready and stored in variables. The main program doesn't call any INA library functions,
that is done in the interrupt handler. Each time 10 readings have been collected the
program will output the averaged values and measurements resume from that point onwards
@return void
*/
static long lastMillis = millis(); // Store the last time we printed something
if (readings >= 10) {
Serial.print(F("Averaging readings taken over "));
Serial.print((float)(millis() - lastMillis) / 1000, 2);
Serial.print(F(" seconds.\nBus voltage: "));
Serial.print((float)sumBusMillVolts / readings / 1000.0, 4);
Serial.print(F("V\nBus amperage: "));
Serial.print((float)sumBusMicroAmps / readings / 1000.0, 4);
Serial.print(F("mA\n\n"));
lastMillis = millis();
cli(); // Disable interrupts to reset values
readings = 0;
sumBusMillVolts = 0;
sumBusMicroAmps = 0;
sei(); // Enable interrupts again
} // of if-then we've reached the required amount of readings
} // of method loop()