NordicOffGrid´ Logo
Off-grid solcellssystem.
I Nordiskt klimat!
 by Bosse
By AutonomTech.se Frittliv webbplats

 Webbsidan är senast uppdaterad:  

Batterimonitor

NordicOffGrid Ultra-precise Battery System Monitor
Batterimonitor för driftsövervakning av off-grid solcellssystem

Webbsidan skapad 2022-04-10
Synchronous buck converter
Charging Graph for 3-stage lead-acid battery charging (IUoU charger). CC BY-SA 4.0

Batterimonitor typ "tankmätare" för batterier där man summerar ström / effekt till batteribanken över tid till Ah/Wh urladdad status från 100% SOC fulladdat. Utifrån känd C20-batterikapacitet kan man då även försöka ange en relevant SOC-status för laddnivån som 0-100% SOC.
Är en väldigt viktig grundläggande funktion i ett off-grid solcellssystem för batteridriften!
NordicOffGrid Batterimonitor övervakar många fler parameterar för driften än Ah/Wh så utgör en driftsövervakning av off-grid solcellssystemet, med även historisk data och statistik!
Gör även om rå mätdata till information, s.k. aggregerad data, med mer info över driften.
Det jag gör här blir mer som en "Battery System Monitor" (BSM) än en ren batterimonitor, med autonom proaktiv förbrukarstyrning för skonsam hantering av batteridriften!
Batterimonitorn används i projektet: PWM-solladd­regulator
Kommer uppdatera här efterhand som jag utvecklar Batterimonitorn.

Beskrivning av grundfunktion:

Genom att mäta den ström / effekt som laddas ur/i batterierna över tiden fås den strömmängd som påverkar hur mycket av batterikapaciteten som för tillfället lånats ur batterierna. Med 1A ström urladdning under 1h har 1Ah laddats ur batterierna, och motsvarande med 12W effekt urladdning under 1h har 12Wh laddats ur. Men då strömmen normalt varierar mycket över tid måste den mätas väldigt ofta och för varje sådant kort tidsintervall summeras ihop till den totala strömmängden.
För att få en bra noggrannhet över lite längre tid så måste både ström / effekt mätas väldigt noga och med stort dynamiskt omfång samt de korta tidsintervallen måste också kunna mätas med hög precision. Stort dynamiskt omfång betyder att man måste både kunna mäta väldigt små strömmar och de stora som systemet är max dimensionerat för, då även väldigt små strömmar blir en signifikant strömmängd över en längre tid.
En ström på bara 10mA (0,010A) blir på en vecka till 1,7Ah.
Sedan tillkommer problem med att batteri­verknings­graden är lägre än 100%, att den varierar med hur fulladdade batterierna är samt med om driften hela tiden växlar mellan kortare ur/i-laddningar eller längre kontinuerliga ur/i-laddningar. Samt verknings­graden påverkas även av hur hög ström ur/i-laddningen sker med, det som kallas för Peukert´s law, och batterier har en viss självurladdning också. Detta är även olika för olika batterityper, där vanliga blybatterier har rätt stor inverkan av detta, blykol-batterier betydligt mindre och LiFePO4 ännu mindre.
Så för en bra batterimonitor-funktion bör det tas hänsyn till dessa förluster samt man måste även ha en väldigt stabil bra synkronisering mot 100% SOC fulladdad batteribank för att mot fulladdad batteribank kalibrera bort den drift / onoggranhet som ofrånkomligen summeras över tid.
Det enda säkra tillståndet att nollställa / kalibera batterimonitorn mot är 100% SOC fulladdade batterier! Så är en oerhört viktig funktion att få stabil med hög noggrannhet, som även sköter sig helautomatiskt själv utan inställningar av användaren.
Idealet för en batterimonitor är att den själv kan utvärdera dessa olika parametrar dynamiskt under drift, då de varier över dels tid, dels med temperatur samt dels med hur driften är. Så för bra noggrann långtidsstabil drift kan man inte ha fasta inställningsvärden för dessa, värden som dessutom är svåra för användaren att avgöra!
Så min ambition är att försöka utveckla en batterimonitor som hanterar detta själv, sedan får vi se hur långt jag lyckas nå med det. Är svårt så hela vägen når jag nog inte!
Mina analyser visar att batterimonitorn då måste ha tillgång till information om hur solladdregulatorn arbetar för stunden med batteriladdningen, direkt från regulatorn. Är inget som den själv kan utvärdera tillräckligt bra via sina egna mätvärden. Så jag tänker bygga en hybrid PWM-solladdregulator med integrerad batterimonitor. (Och solladdregulatorn i sin tur behöver veta strömmen in-/ut-ur batteribanken för bäst laddstyrning, så en hybrid är välmotiverat.)
2022-10-26
En frågeställning är dock hur får man till allt helt rätt när man har både sol och andra laddare samtidigt?

Peukert´s Law: 2022-10-14

I denna batterimonitor kommer jag inte alls ha med Peukert´s law för Ah- och SOC-beräkningar, samt kommer som första början räkna mot blybatteriernas nominella C20-kapacitet så får resten bara bli en extra marginal för åldrande vid moderata strömuttag.
Jag och en del andra som tittat rätt mycket på detta med batterimonitor är inne på att för batterimonitor i ett off-grid solcellssystem bör man inte alls ta med Peukert´s law så för SOC-beräkningarna, då det blir ett missbruk av den och Peukert´s law inte alls beskriver det driftsfallet eller en verklig förlust av batterikapacitet vid sådan växlande battericykling!

Växlande urladdning Peukert´s law
Växlande urladdning blybatteri, Peukert´s law

Peukert´s law gäller bara för en urladdning med konstant ström i ett svep från 100% SOC till "0% SOC" som bestäms av att urladdningen avbryts vid 10,5V batterispänning för 12V blybatteri. Så Peukert´s law gäller inte alls när man som i ett off-grid solcellssystem har ständigt växlande laddning / urladdning som det blir där!
Därmed är det väldigt osäkert vad den bidrar till i en batterimonitor? Bör ge helt fel resultat!
Är väldigt svårt att hitta kunskap kring hur blybatterier beter sig ur Peukert´s law synvinkel med en växlande daglig laddning från solceller och urladdning där emellan.
Peukert´s relation describes how the capacity is related to the total time to discharge the battery to 10.5 volts. Simply put, the reason you get less amp hours out when the amps are higher is that the higher amps drag down the volts more than a lower amp load, so the 10.5 volts endpoint is reached sooner. It is not because some of the electrons [capacity] in the battery get lost or wasted when you draw current out faster. [källa]
Så Peukert´s Law beskriver inte en förlust i batterikapacitet, utan bara hur mycket av kapaciteten som kan urladdas i ett svep för olika strömmar innan man når 10,5V batterispänning!
Vilket då är helt ointressant för en batterimonitor, inte minst i ett off-grid solcellssystem!
Handlar om tillfälliga polarisations-effekter som sänker batterispänningen under urladdning, mer vid högre ström, som återställs vid vila eller minskar signifikant vid låg ström, mer ju lägre!

Växlande urladdning Peukert´s law
Växlande urladdning blybatteri, Peukert´s law

Som exempel, låter man ett blybatteri som laddats ur till 0% SOC enligt Peukert´s law vila 24h så hämtar det sig och är inte längre urladdat till 0% SOC, utan en signifikant del av kapaciteten återkommer igen under vilan.
Och det är ju precis så driften sker i off-grid solcellssystem, där solcellsladdning i detta sammanhang kan ses som "supervila" för blybatterierna! Så vid ständig växlande laddning / urladdning får man inte alls de förluster i kapacitet som Peukert´s law beskriver när ett blybatteri laddas ur helt i ett svep!
It is a common misunderstanding that the energy not delivered by the battery due to Peukert´s law is "lost" (as heat for example). In fact, once the load is removed, the battery voltage will recover and more energy can again be drawn out of the battery. This is because the law applies specifically to batteries discharged at constant current down to the cutoff voltage. The battery will no longer be able to deliver that current without falling below the cutoff voltage, so it is considered discharged at that point, despite significant energy still remaining in the battery.
What happens is that the chemical process (diffusion) responsible for transporting active chemicals around the battery progresses at a finite rate, so draining the battery quickly causes the voltage to reach the cutoff level prematurely before all the active material in the battery is used up. Given time, the active material will diffuse through the cell (for example, sulfuric acid in a lead-acid battery will diffuse through the porous lead plates and separators) and be available for further reaction.
What Peukert really meant: When energy is drawn, battery voltage falls. As an example were a battery able to sustain 5 amps for 20 hours (before falling below 10.6 volts) it can be rated as being 100 amp hours.
When a heavier load (say 50 amps) is connected across that battery, its voltage falls more rapidly. After (say) 60 minutes, it is likely below 10.6 volts. The battery is consequently unable to sustain that discharge rate. But its energy has been depleted by 50 amp hours. No more – nor less.
A lead acid battery reacts very slowly. Once that 50 amp load is removed it slowly recovers. Off-load voltage will be 12.2-12.3 volts. It may still be able to supply 50 amps, but this time for only 30 minutes. Delivered available capacity is now 75%. The 25% remaining is still available, but now at five or so amps.
So, what Peukert really meant is that rate of discharge does not affect overall capacity. That which it affects is only its usable capacity when loaded above its rated current. In other words its rated capacity (energy) is still available, but only at its intended (rated) current. Some see that as "available capacity".
[källa]

Växlande urladdning Peukert´s law
Blybatterikapacitet 5dygns dålig-väder-reserv.
Ger medelurladdningsström 0,8A/100Ah (C20).
Discharge Rate = 20h / (5 * 24h) = 0.167
Peukert´s k=1.25 är högt för AGM & BlyKol.
Peukert Kalkylator1 / Peukert Kalkylator2

Men riktigt vad man får tillgång till för extra kapacitet vid moderata urladdningsströmmar vet jag inte, då jag hittat absolut noll kunskap kring det för denna växlande driften i ett off-grid solcellssystem. Så i ett senare skede ska jag troligen försöka utvärdera det ur blybatterispänningen vid lägre SOC när strömmen är som lägst nattetid utan solcellsladdning. Men då främst för åldrandet.

2023-08-02
Beräknat för 5 dygns dåligt-väder-reserv (C120) medelström skulle man då ur 100Ah C20 blybatterikapacitet kunna ladda ur 156Ah vid Peukerts exponent 1.25, vilket känns helt orealistiskt mycket! Det skulle innebära att vid C20´s 20h urladdning skulle bara 64% av det aktiva elektrodmaterialet delta i omvandlingen från laddat till urladdat kemiskt tillstånd, vilket känns helt osannolikt lite! Beskrivs även i en forskningsrapport: "The classical Peukert´s equation is not applicable at small discharge currents as according to this equation, at the discharge current decrease, the capacity released by the cells tends to infinity."
En annan forskningsrapport tittar på "Adapting the Peukert Equation to Batteries Discharged at Pulse Currents" och kom fram till "Therefore, the methodology proposed here may extend Peukert´s law to batteries in which the discharge current is not constant."
"Peukert´s law has always been applied to the discharge of batteries at constant currents. Today, however, there are more and more applications in which batteries are used with pulse currents (e.g. wireless sensors, electric vehicles, [off-grid PV-systems])."
Dvs Peukert´s law gäller inte för urladdning med varierande strömstyrka eller vid ständig växling mellan laddning och urladdning i solcellssystem (precis som jag bedömt).
En person med Victron SmartShunt batterimonitor tyckte den visade 76% SoC med Peukert exponent 1.25 kändes hög, då urladdade Ah motsvarade 50% SoC räknat mot fritidsblybatteriernas C20-kapacitet. Så han provade att ändra till Peukert exponent 1.00 och då visade SmartShunt 50% SoC. Ändrad tillbaka till 1.25 visades åter 76% SoC! Så Victron SmartShunt använder Peukert exponent för att räkna ut användbar batterikapacitet vs strömbelastning, vilket då vid låga strömmar (<C20-urladdning) blir en högre kapacitet än blybatteriets C20-kapacitet!
I detta fallet med 50Ah urladdat / 100Ah C20 har Victron SmartShunt för den låga strömbelastningen räknat fram 208Ah användbar kapacitet ur 100Ah C20-kapacitet, vilket är helt orimligt att det skulle stämma med verkligheten bedömer jag! Den ovan nämda forskningsrapportet säger samma: "The classical Peukert´s equation is not applicable at small discharge currents"!
De 208Ah ur 100Ah/C20 i SmartShunt-fallet motsvarar en Discharge Rate = 0.053 i Peukert-beräkningen dvs C20 / 0.053 = C377 urladdning i snitt (typ 15 dygns dåligt-väder-reserv).
Detta stärker också min bedömning att inte använda Peukert´s Law i batterimonitorer!
Även Mastervolt använder Peukert´s Law i sina batterimonitorer: "Peukert´s Law describes the effect of different discharge values on the capacity of a battery, i.e. that battery capacity is reduced at higher discharge rates. All Mastervolt battery monitors take this equation into account so you will always know the correct status of your batteries."
Balmar SG200 batterymonitor använder Peukert´s Law, men bara för Time-To-Go beräkningarna: "Changing the PEUKERT Value will not effect Charge Termination, only TIME REMAINING Calculations".
Simarine verkar också använda sig av Peukert´s Law via: "The nominal battery capacity for the next C ratings: C/20, C/10, and C/5. If you don´t know all the ratings, fill in just those ratings that you know. It is highly recommended to fill at least two C ratings (one is not enough for precise calculations).
Studer Battery Status Processor BSP 1200 använder också Peukert´s Law: "The capacity varies according to the discharge current. With this parameter one can set the Peukert exponent that goes along with the nominal capacity and nominal discharge time."
Trots detta är det min övertygelse att Peukert´s Law inte är tillämpbar för en batterimonitor, speciellt inte i ett off-grid solcellssystem! Finns tillräckligt med vetenskapliga rapporter och fakta som stödjer att Peukert´s Law inte gäller för fluktuerande strömurladdningar samt inte beskriver några kapacitetsförluster för kvarvarande batterikapacitet efter viss urladdning, anser jag!
Vid lite efterforskning finns det en Kinetic Battery Model (KiBaM) för drift i typ off-grid solcellssystem. Det finns en ur KiBaM vidareutvecklad modell "addressing four characteristics of operation: charging, discharging, rest after charge, and rest after discharge" Comprehensive Model for Real Battery Simulation Responsive to Variable Load (4-KiVM) som såifall kanske kunde användas i en batterimonitor i motsats till Peukert´s law. Referens till "The KiBaM battery model" finns i Wikipedia artikeln Recovery effect.
Mer: Battery Aging, Battery Charging and the Kinetic Battery Model: A First Exploration
A realistic model for battery state of charge prediction in energy management simulation tools, baserad på the Kinetic Battery Model.
HOMER uses the Kinetic Battery Model to determine the amount of energy that can be absorbed by or withdrawn from the storage bank each time step. (Visualiserar principen!)

Jag har av dessa anledningar inte heller med Peukert´s law i min Kalkylator små Solelsystem II då jag under min drift sedan 2007 i mitt off-grid solcellssystem inte kunnat se någon inverkan av det som Peukert´s law beskriver!
Jag hade med den från början men har under åren verkligen letat väldigt noga efter inverkan av Peukert's law i min off-grid drift och inte kunnat hitta några spår av den. Då har jag i och för sig rätt måttliga strömmar, men ska man klara 5dygns dåligt-väder-reserv kan höga urladdningsströmma bara förekomma väldigt korta tider av den totala driftstiden, så bör vara i stort samma för alla. Precis under en kortvarig hög urladdningsström borde man kunna notera en effekt av Peukert´s law, men sedan hämtar sig blybatterierna från den s.k "Recovery effect" / "Relaxation effect" (i stort helt vid driften i ett off-grid solcellssystem vad jag kunnat få fram).

Bogart Engineering med sin TriMetric batterimonitor beskriver tydligt varför de inte använder Peukert´s law i sin batterimonitor, och det utifrån över 25 års erfarenhet av att utveckla batterimonitorer.
När jag läser på Victrons webbsida om Peukert exponent för deras BMV 700-serie batterimonitorer får jag uppfattningen att Victron till stor del har missförstått vad Peukert´s Law står för och vad för effekt i blybatterier den beskriver då Victron bl.a. skriver "The capacity of a battery depends on the rate of discharge. The faster the rate of discharge, the less capacity will be available.", vilket känns lite märkligt ihop med batterimonitor i off-grid solcellssystem (även om Peukert´s Law missuppfattas rätt ofta, så förståeligt om även deras ingenjörer gjort så)!
Peukert´s exponent ökar även med blybatteriernas åldrande, så den kommer ju aldrig vara korrekt över tid, och som sagt beskriver inget fenomen användbart för en batterimonitor så som jag och en del andra uppfattat det. Samt den är många gånger svår att få tag på för sina blybatterier, men går att räkna fram om de har minst två kapaciteter angivna typ C5 / C10 / C20 / C100.
De delar av Peukerts effekt som eventuellt påverkar lite även vid cyklisk drift kommer då till stor del med som del av den utvärderade batteriverkningsgraden i batterimonitorn. Så med sådan funktion kan jag verkligen inte se något behov av Peukert´s exponent i batterimonitorn!

Utökad funktion: 2022-06-30 / 2023-04-18

För oss lite mer intresserade kunde det vara intressant med mer information än bara Ah och SOC från en batterimonitor, typ hur mycket ström som använts direkt från solcellerna och hur mycket som plockats ur batteribanken. Hur mycket av strömförbrukning som just nu kommer från solcellerna respektive batteribanken samt ström / effekt ut till utgående förbrukning.
Och vid off-grid för fritidsboende att man kunde nollställa och mäta för en boendeperiod där hur mycket av strömmen som solcellerna resp. batteribanken levererat samt systemet förbrukat, både för boendeperioden och senaste dygnet (24h). Ur det kunde systemet även mer smart beräkna hur länge till batteribankens dåligt-väder-reserv räcker utifrån senaste 24h drift.
Har man 5 dygns dåligt-väder-reserv i batteribanken och solcellerna levererar 75% av förbrukad ström i molnig väder så räcker den reserven då i 20 dygn som exempel.
Kanske även en prognos baserat på senaste timmens förbrukning, men baserat på momentan förbrukning som flera batterimonitorer idag gör känns rätt meningslöst.
Bra att få info om, men lite krävande att själv försöka uppskatta!
Även detta görs lättas genom en samverkan mellan solladdregulator och batterimonitor.
Jag tänker även försöka lagra data kortare tid lokalt i ESP32 (typ 24h till 7? dygn, samt viss nyckeldata kanske ett år och annan 30dygn) samt regelbundet koppla upp den mot egen webbplats inhyrd på webbhotell och lagra långtidsdata där. Så kan jag hålla koll på batteridriften även via Internet varifrån jag vill. Får se under utvecklingen hur mycket sparad data som verkar vettigt!
Sedan hade även någon form av "Battery state of health estimation (SOH)" varit bra, som även kunde larma om något batteri börjar bli dåligt, men får nog ses som överkurs.
Har dock lite funderingar på att övervaka float-ström när solladdregulatorn reglerar den, hålla koll på lägsta batterispänning nattetid samt kanske mäta batteribankens impedans när PWM-regulatorn strömpulsar fulladdad batteribank. Bör kunna ge viss insikt om batteribankens status om någon av de börjar avvika från de normalt uppmätta värdena över lite längre tid!
Även kanske jämföra olika tidsfiltrerade batteriverkningsgrads-mätningar, typ 1/1, 1/10, 1/100 & 1/1000 och se om det blir en tydlig plötslig förändring i batteriverkningsgrad över tid som då kan indikera utvecklingen av problem i blybatterierna! Borde kunna vara ett bra mått!

Hårdvara att bygga på:

Har nu detaljstuderat databladen för INA260 (datasheet) och INA226 (datasheet) och de har verkligen flera riktigt bra funktioner för att kunna bygga en batterimonitor med hög precision! Mer om INA260/INA226.
Dels kan man sätta ADC (Analogue to Digital Converter) conversion time till mellan 140µs och 8.244ms där längre tid ger en mer exakt avläsning, dels kan man låta dem beräkna medelvärdena för mellan 1 till 1024st mätningar, vilket också ger möjlighet till noggrannare mätning av ström och effekt. INA226 använder extern strömshunt med mätområdet ≤36V, ±81,9mV, 16-bit, som då ger möjlighet till externt RC-filter av signalen från strömshunten så ingen data missas mellan samplingarna typ kraftiga korta strömpulser. INA260 har intern 2mΩ strömshunt för ±15A och ≤36V 16-bit mätområde inom -40°C to +85°C. The device operates from a single 2.7V to 5.5V supply, drawing 310 µA (typical), så är strömsnåla också!
Innebär att med maxvärdena 8.244ms och 1024st mätningar fås nya exakta medelvärdesbildade aggregerade data 1ggr/8,64s och som snabbast ca 1ggr/140µs, som INA260/226 då arbetar självständigt med att samla in. Kretsarna har även en signalutgång som indikerar exakt när nya aggregerade mätvärden är tillgängliga, så man kan synka av läsningen av ström/effekt från INA260/226 hos ESP32-mikro-processorkortet med den, vilket görs via s.k. interrupt.
Den utsignalen skulle under långvarig standby-drift även kunna användas till att väcka upp ESP32 mikroprocessorkortet (källa2) ifrån strömsnål light-sleep och läsa av strömförbrukningen med upp till 1ggr/8,64s intervall och vara i light-sleep däremellan, som strömsnål batterimonitor! Men 2x (U+I) 1.1ms conversion time och 1024 averages, 1ggr/2,25s, är nog vettigt så kan responstiden på knapptryckning under light-sleep bli max 2,25s. Då borde kanske ca 22ms RC-filter bli lagom? Typ 4,12kΩ * 4,7µF, R82 50V (RC=19ms), så bör INA226´s 830kΩ ingångsresistans inverka minimalt på mätresultaten.
2023-02-16
Är bara INA226 spänningsmätning VBUS som har 830kΩ ingångsresistans, strömmätningens ingångar IIN+/IIN- har en Input bias current på typ 10µA, men uppmätt ca 35µA i drift!
Så går inte att göra en RC-filtrering på samma lätta sätt där som för VBUS!
Med 4,7µF/4,2kΩ (20ms RC) fick jag 341mA mätt med 500mA genom strömshunten! Utan 4,2kΩ mättes 501,7mA genom 60A/60mV shunten (LSB=1,8mA / 2,5µV).

Multiple INA226´s with INA226_WE library (limit: 4 INA226).
Kanske kan kombinera interrupt med ISR och light sleep wakeup på samma GPIO?
Låter möjligt: ESP32 using interrupt to momentarily wake from Light Sleep - bug?
Går att göra via ONLOW_WE / ONHIGH_WE attachInterrupt(pin, ISR, ONLOW_WE); där WE=Wakeup Enabled, dvs Interrupt och Wakeup från sleep på samma digitala ingång.
Kan göras som deferred interrupt via Queue API med tidsstämpling på 1µs upplösning för effektiv interrupt-hantering och exakt Ah-/Wh-summering / integrering.
Och ESP32 i sin tur har en 64-bitars tidmätning som mäter tiden med 1µs upplösning (0,000001s) och som bara startar om (overflow) 1ggr/292år så man kan mäta tiden mellan ström- och effekt-mätningarna med riktigt hög precision, vilken används för att summera ihop ström (A) och effekt (W) till Ah och Wh för värdena i batterimonitorn.
Ihop med batterier som trivs/tål att float-laddas 100% SOC längre tid (typ blybatterier) kan jag då även göra så batterimonitorn regelbundet automatisk nollströmskalibrerar sig under drift, vilket också ökar långtidsstabiliteten och precisionen. Har jag inte sett någon batterimonitor nu på marknaden har (möjligen BALMAR SG200). Kanske nollströmskalibrera sig mot den ström som är självurladdningen, då det egentligen är en strömförbrukning som inte ström­shunten kan registrera och inte bör komma med i ∑Ah / ∑Wh.
Ska bli spännande det här!

Mobil 4G Router Teltonika RUT241: 2022-07-30

Teltonika RUT241
Teltonika RUT241

Införskaffat den 4G-router jag ska använda för att överföra driftsdata från off-grid sol­cells­systemet till min webbplats server. Valet föll på en Teltonika RUT241 4G/LTE(Cat 4), 3G, 2G industriell router med bra rykte om stabil till­för­lit­lig drift, med bra temperatur­drifts­om­råde på -40°C - +75°C, drifts­spänning 9VDC - 30VDC samt chassit är i aluminium för bästa värme­över­föring och kylning. Drar uppkopplad mot 4G utan datatrafik 1,2W matad från 12V enligt wiki, <2,5Ah/dygn. Har rimligt pris för prestandan tycker jag!
"RUT241 is an excellent fit in various IoT and M2M solutions that require easy setup, reliable network, and remote accessibility.
Kommer använda extern rundstrålande puck-antenn placerad uppe i takluckan i husvagnen, då alla väggar av aluminiumplåt skärmar av rätt mycket där det är dålig mottagning.
RUT241 är en ny version av RUT240, beskriven som: "Teltonika RUT241 är en ny uppgraderad version av den klassiska industriella LTE-routern RUT240. De är nära identiska förutom styrkretsen som uppgraderats till Mediatek MT7628 som har väsentligt bättre tillgänglighet och något snabbare prestanda [580MHz vs 400MHz]." Samt dubbelt så mycket RAM-minne som RUT240, så plats för uppgradering till mer krävande OS i framtiden.

Teltonika RUT241 vs RUT240
Teltonika RUT241 vs RUT240

ESP32 WIFI uppkopplad till RUT241: 2022-08-03

Har kopplat upp RUT241 här hemma nu och tycker WIFI känns helt OK! Har placerat RUT241 ute i köket med en armerad betongvägg i vägen in till vardagsrummet där jag sitter längst in nu. Får full signalstyrka på mobilen där ifrån RUT241 samt min ESP32 som är lite kinkig kopplade upp och synkade med tidsserver på Internet utan problem via RUT241 här längst in i vardagsrummet vid datorn.
ESP32 kopplar upp snabbare till RUT241 än till min bredbands-router som finns i hallen precis utanför dörröppningen in till vardagsrummet och således med bättre kontaktväg så utan armerad betongvägg i vägen. Och den är ändå bra.
I mobilen får inte min bredbands-router riktigt full signalstyrka hela tiden här inne i vardagsrummet, så RUT241 verkar ge något bättre WIFI. Här är ändå 14st andra routrar från grannar som sänder ut WIFI jag ser i mobilen, så är väl ingen perfekt miljö här precis tänker jag.
Har låtit ESP32 koppla upp och synka mot tidsserver via RUT241 8-9ggr nu och fungerar bra hela tiden. 2022-12-16 Nu har min ESP32 bootat och hämtat tid från NTP-server >1000ggr!
Så känns riktigt lovande för husvagnen och mitt kommande PWM-regulator + batterimonitor ESP32 projekt.
Lär ju få tillgång till WIFI även utanför husvagnen, vilket blir som en extra bonus då jag är fullt nöjd med bra Internet inne i husvagnen.
Jag får nu WIFI-signalstyrka RSSI -59dBm i ESP32, vilken anses som:
-50 to -67dBm – At Good signal strength for Web browsing, voice/video calls.
Wireless dBm table

Teltonika RUT241 4G-router i glesbygd: 2022-08-28

Teltonika RUT241
Teltonika 4G Signal strength 3(5)

Tog med Teltonika RUT241 till husvagnen för test av funktion där. Är en ofta svag långsam intermittent mobil-uppkoppling där via mobilen, så en bra referensplats för funktion i bergig skogig Östgötsk glesbygd. Testade även hur ESP32 kan koppla upp och synka sin RTC mot tidsserver på Internet via RUT241´s wifi, och det skedde fint stabilt samt snabbt!

Teltonika RUT241
Teltonika 4G Signal strength

Fick -81dB signalstyrka med puck-antenn på soffbordet där nära mobilen samt pendlade mellan 2-3 (5) streck på RUT241´s indikator. Uppe i taklucka låg den på 3 streck signalstyrka större delen av tiden. Samt fick ned 4-8Mbit/s och upp 0,5-2Mbit/s med snitt runt 6Mbit/s ned och 0,7Mbit/s upp, en 5-10ggr snabbare än med mobilen direkt mot 4G! Är ofta låg kapacitet så hos basstationer ute i glesbygd, som brukar vara rätt hårt belastade så här vid 17:30-tiden på dygnet. Men den mest avgörande skillnaden var att RUT241 behöll sin uppkoppling stabilt med 2-3 streck i signalstyrka, där mobilen tappar den av och till lite längre perioder.
Och wifi räckte bra långt utanför husvagnen med bra signalstyrka 8-10m bort, trots husvagnens utsida av Al-plåt. Så jag känner mig helt nöjd med funktionen, som känns bättre än en del framhållit på Internet för föregångaren RUT240!

Adafruit Proto-Screwshield Arduino R3: 2022-12-01

Proto-Screwshield R3
Adafruit Proto-Screwshield Arduino R3

Lödde ihop ett Proto-Screwshield R3 för utvecklingsfasen när jag testar fram funktionen. Är smidigt och enkelt att arbeta med, att slippa löda in anslutningstrådar från givare, strömförsörjning, etc. till WeMOS ESP32 D1 R32 Uno.
"The next generation Proto-ScrewShield is a dual-purpose prototyping shield. Not only does it have a large 0.1" grid prototyping area but it also extends the Arduino pins to sturdy, secure, and dependable screw terminal blocks. You even get a few bonus terminals for extra GND and four ´free´ terminals for whatever connections you wish! New! As of June 23, 2014 we now have an R3 update to this design - we now have a stacking header for the ICSP 2x3 pins and breakout the SCL and SDA pins. It now works much better with R3 UNO´s, Mega, Leonardo, as well as stacking nicely with any shield.
The stack-able wing design allows you slip this under any shield and still get easy access to the "analog" & "digital" ports of the Arduino. The ScrewShield can be stacked above or below pretty much every other shield.
"

Solid-state relay AC/DC: 2022-12-04

För att styra strömmatningen till Teltonika RUT241 4G Router behöver jag solid-state-relay / load-switch / power-switch funktion som kan styra strömmen ON/OFF på high-side med 3.3V signal från ESP32. Hittade denna hos Electrokit, men finns nog billigare: LCA717 DIP-6 Solid-state relay AC/DC.
What is a Load Switch?
Load switches (TI)
Load switches Low quiescent current, 0-3A (TI)

Batteriverkningsgrad: 2022-12-11

Lite idéer / tankar dök upp kring hur den ska mätas / utvärderas... Kanske som funktion av hur djup en battericykling varit (max DOD) samt kanske hur lång tid den varat innan 100% SOC fulladdat igen? Kan den även vara beroende av batteritemperatur? Får mäta och se när jag har batterimonitorn i skarp drift med den första inledande funktionen för batteri­verkningsgrad och coulomb­verkningsgrad.
Är nog en sådan funktion som kunde använda ML (machine learning) i framtiden?
ML | What is Machine Learning?, GeeksForGeeks
Se även TinyML ESP32 Arduino, TensorFlow.

Grundkoden med menyer & NTP tid klar: 2022-12-13

Blev idag klar med grundkoden för alla menyer, WiFi samt för synkning av RTC (Real Time Clock) med NTP tidsserver på Internet. Sparade en kopia av den som bas för framtida ESP32-projekt. Detta är en mycket stor del av den totala kodningen men bara så viktig med det smidiga användargränssnitt den ger via 16x2 LCD displayen. Samt välutvecklat i FreeRTOS så det med väldigt lite kodning lätt läggs till nya menyer, både som editerar dataparameterar samt som visar driftsdata eller Datum / Tid från RTC, etc.
Har även varit ett lärosteg för mig att börja använda FreeRTOS för effektiv realtidsfunktion! Så hela funktionen är uppbyggd kring ett antal FreeRTOS-tasks, och Arduino loop() raderad.

ID för varje ESP32, macAdress: 2022-12-14

När driftsdata ska skickas till en webbserver på Internet kan ESP32´s MAC-adress användas som ID för respektive ESP32, då det ska vara unikt för varje individ. Så kan data skickas från flera olika ESP32-batterimonitorer utan risk att blandas ihop!

ESP32 Async web server SSE: 2022-12-18

ESP32 Async webbserver (SSE)
ESP32 Async webbserver (SSE), mobil.
Flyttar senare Grafisk dashboard överst.
När all ESP32 funktion är på plats.

Nu kodat färdig för en Async Webbserver med webbsida i ESP32 som skickar datauppdateringar direkt till webbsidan via Server-Sent Events (SSE). SSE är effektivt, strömsnålt och elegant!
Har använt infon och en del kod från: ESP32 Web Server using Server-Sent Events.
Samt från ESP32 WiFiMulti: Connect to the Strongest Wi-Fi Network (from a list of networks)
Med biblioteket: ESPAsyncWebServer-esphome installerat inifrån PlatformIO, ett "Asynchronous HTTP and WebSocket Server Library for ESP8266 and ESP32".
ESPAsyncWebServer-esphome Readme user manual!!!
Var förvånadsvärt enkelt och smärtfritt samt gick mycket snabbare än jag hade förväntat mig! Fungerade direkt.
Är lite snabbt kodat så är inte slutligt utförande / design, samt skickar just nu bara fuskade slumtalsvärden för att se funktionen.
Fungerar jättebra mot wifi-routern här hemma samt mot Teltonika RUT241! ESP32 skickar webbsidan via wifi till routern som i sin tur skickar den vidare via sin wifi ut till mobil / dator.
Så på plats i ett off-grid boende / husvagn kan man kolla sin solcells-batteri driftsstatus inom hela området som routerns wifi når, vilket bör bli ett större områden än för en app via Bluetooth.
ESP32 skickar först hela webbsidan till webbläsaren och sedan bara den data som uppdateras där direkt till webbsidan via Server Sent Events (SSE), vilket är jätteeffektivt och strömsnålt även när flera olika enheter är uppkopplade mot webbsidan samtidigt.
Jag har valt att skicka nya data 1ggr/s så upplevs visningen stabil.
I mobilen kan man välja fullskärmsläge som då ser ut precis som en app, så blir lika snyggt med webbsidan på så sätt utan något beroende av någon extern tjänst eller kontakt med mobilnätet.
Jag väljer att använda en webbsida istället för app, dels för att jag redan har bra kunskap i att koda webbsidor, dels att driftsdatan då kan visas på en mängd olika enheter med webbläsare.
Så vill man ha en stor display kan man bara köpa en billig enkel surfplatta och montera hos sig, samt går ju även att visa på en smart-TV om man har en sådan.
Ska senare koda den som en progressive web app! (Web app manifests | Installing web apps)
Och smidigt att visa driftsdata så direkt från ESP32 mikrokontrollern!
Ska visas mer info där efterhand som projektet framskrider, som en dashboard.
Men nästa steg är att skriva koden för ström-energi-sensorn INA226 och koppla in den mot mitt lilla experimentella off-grid solcellssystem här hemma är tanken. Ska bli intressant!
ESP32 Useful WiFi Library Functions, Arduino
Espressif: ESP32 WiFi API Reference, Networking APIs
HTML vs Body: How to Set Width and Height for Full Page Size
HTML vs Body in CSS (2018)

ESP32 Async webbserver (SSE)
ESP32 Async webbserver (SSE), dator.
Ska bli en till canvas grafisk dashboard.
När full funktion så flyttas de överst.
Ser liknande ut på liggande mobilskärm.

ESP32 Async web server kraschar: 2022-12-21

Har nu kört med ESP32 Async web server SSE några dagar och det visar sig att ESP32-koden kraschar oregelbundet rätt glest (typ 5-10min) när en eller flera webbläsare är uppkopplad aktivt mot ESP32-webbservern och får Server Side Events skickade till sig. Bara då!
ESP32 bootar då om i en oändlig loop utan att lyckas starta om, förutom typ efter 80st gånger som vid debug-utskriften nedan (ResetBootCountRTC in RTC memory: 80).
Trodde först de orsakades av lite svag strömmatning via USB då LCD-displayens LED-bakgrundsbelysning blinkar lite när WiFi kortvarigt drar lite högre ström.
Men dels får jag Reset reason: 4, ESP_RST_PANIC, vilket inte är orsakat av spänningsmatning, dels blev det ingen skillnad när jag monterade in en kondensator för stabilisering av 5V på ESP32!
Och sedan hittad jag hur det gick att få ut mer debug-info i serial-monitor.
Så får där nu följande när det händer:
-------
Reset reason: 4, ESP_RST_PANIC
ResetBootCountRTC in RTC memory: 80
Total booting / resets: 2855

assert failed: tcpip_api_call IDF/components/lwip/lwip/src/api/tcpip.c:497 (Invalid mbox)
(Ser ut som ett av Espressiv-IDF biblioteken är orsak - kan det då fixas med någon inställning för webbservern, eller annat kodmässigt?)

Backtrace:0x40083b71:0x3ffb4c700x4008dadd:0x3ffb4c90 0x40093119:0x3ffb4cb0 0x400fadf1:0x3ffb4de0 0x401493f1:0x3ffb4e10 0x40149c15:0x3ffb4e50 0x400e095e:0x3ffb4e90 0x400d476b:0x3ffb4eb0 0x400d4854:0x3ffb4f20

ELF file SHA256: 0000000000000000

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
-------
Så får dels läsa på mer i ESPAsyncWebServer-esphome Readme user manual, dels se om jag kan få felutskrift för heap corruption diagnostics, om det kan vara en orsak.
Espressif: Heap Memory Debugging
Samt i övrigt gå igenom min kod mer grundligt, ihop med att leta lite mer info på Internet.
Har sett indikation på lösning med att skicka SSE lite mer sällan än nuvarande 1ggr/s?
Vad jag förstått körs allt ESP32-internt kring WiFi / Bluetooth stöd i Core0, så att jag lagt mina funktioner för ESP32-webbserver också i Core0 kanske leder till någon krock av något slag, så får även testa att byta till Core1!

Efter att slagit på mer debug-info kom följande fram:
> assert [RX:' '] [RX:'failed: tcpip_api_call IDF/comp'] failed: tcpip_api_call IDF/comp [RX:'o'] o [RX:'nents/lwip/lwip/src/api/tcpip.c'] nents/lwip/lwip/src/api/tcpip.c [RX:':'] : [RX:'497 (Invalid mbox)\r\n
> \r\n
> \r\n
> Backtra'] 497 (Invalid mbox)

Så problemet ligger tydligen i tcpip...
Edit: Det mesta pekar på att det var ett spänningsfall av strömspik när SSE-data skickas via WiFi / Webbserver, då en 470µF kondensator kopplad till 3,3V på ESP32-kortet för att buffra för dessa fick kodkrasher med det felmeddelandet att försvinna!
Därmed är per se inte min kod det direkta problemet, men får testa ändå med att koda om lite för bättre mer renodlad kod samt lägga i Core1 och se om det kan påverka. Har ändrat så SSE bara exekveras 1ggr/3s (från 1ggr/s) och det verkar lite stabilare!
Samt även läsa på mer i ESPAsyncWebServer-esphome Readme user manual för att se om det är saker i min kod som kan förbättras för ESP32-webbservern. Kanske typ finns någon buffert man kan dimensionera upp?
2022-12-22
Testat en del olika samt läst på nu och blivit något klokare.
Provade att lägga in en vTaskDelay() på 2ms mellan varje av de 11st events.send(), men det gjorde ingen skillnad.
Provade att ändra frekvensen för SSE från 1ggr/s till 1ggr/3s och det blev märkbart stabilare men kraschade ändå någon gång per timme.
Provade att bara låta sända 4st events.send() data mot 11st hittills och då fick jag ingen krasch under flera timmar.
Provade då att öka till 6st events.send() data och då fick jag en krasch under drygt två timmar, när jag hade webbsidan aktiv i två olika webbläsare samtidigt som SSE-data skickades till.
Har något luddigt minnesfragment av att jag läst att vid behov av många datavärden bör man välja att skicka dessa i en JSON fil istället, så ska nog prova det som alternativ.
Även mätt tiden det tog att skicka de 11st events.send() data och blev 12-20ms, så tänkte att med id = millis() fanns risken att två kunde få samma id och det kanske krashade då. Så även provat med id=micros() för att utesluta det, men blev ingen skillnad.
Men jag kan med 6st events.send() data gå vidare nu och koda för energi/ström-sensorn INA226 och installera den mot blybatteriet för lite riktiga mätvärden. Är så nyfiken på att få den sensor i drift och känna pulsen på den!
Och därefter koda om för data via JSON-fil.
Funderar även på ESP32 Webbserver byggt på WebSocket för att kunna få en tvåvägskommunikation så jag kan justera inställningsvärden från webbsidan och aktivera funktioner i ESP32, via Remote Control.
2022-12-22
Kört i flera timmar med bara 6st events.send() data skickade samt ett webbläsarfönster anslutet till ESP32 utan någon krasch!
2022-12-23
Provade att flytta de 11st events.send() data från den Deferred-Interrupt-Task med höga FreeRTOS Priority=7 där jag lagt dem tillfälligt till en nykodad Task_WebServerESP32 med låga FreeRTOS Priority=2 i Core0 som tänkt, och då med den lägre prioriteten fungerade det mycket stabilare.
Så sannolikt krockar en så hög FreeRTOS prioritet för webb-/WiFi-kommunikation med Espressif-IDF bibliotekskods prioritet i core0! Men måste ändå vara en bug/svaghet där, då den kraschar så hårt att ESP32 fastnar i en ändlös reboot och kräver manuell fysisk reset.

Canvas dashboard sneak-peek
ESP32 Async webbserver (SSE) webbsida
Canvas dashboard sneak-peek

Kunde köra två webbläsarfönster anslutna till ESP32-webbservern som uppdaterades med 11st events.send() data under ett par timmar utan krasch. Och med två datorer + en mobil med total 4st webbläsarfönster mot ESP32-webbservern klarade den drygt 15min innan krasch, vilket inte gick alls tidigare. Syns även på RAM-minnes hanteringen som ser mer stabil ut nu!
Så är på rätt spår. Har även checkat att det inte är något minnesläckage!
Sedan flyttade jag allt eget med wifi / webbserver till core1 så blev det ytterligare stabilare samt några andra småmodifieringar.
Så tydligt krockade den hög task-prioriteten med de task Espressif lagt för wifi i core0 så webbservern blockerade det. Har även prova att lägga in en 100ms vTaskDelay() efter hälften av events.send() som delegerar processorkraften i FreeRTOS till andra uppgifter de 100ms.
Har även tittat över alla ESP32 FreeRTOS Task stack size för mina kodade Tasks och optimerat dem.
Nu även kopplat den SSE-skickade datan till den canvas-grafik dashboard jag har på ESP32-webbsidan så mätvärden och mätare uppdateras där, vilket känns riktigt häftigt och coolt! Visar en sneak-peek av dashboard-grafiken och kommer visa hela när jag har den i full drift.
De två olika felmeddelande jag får vid krasch nu är:
assert failed: tcpip_api_call IDF/components/lwip/lwip/src/api/tcpip.c:497 (Invalid mbox)
Guru Meditation Error: Core 0 panic´ed (LoadProhibited). Exception was unhandled.
Där "LoadProhibited" = The error LoadProhibited means that the CPU tried to load a variable form an illegal address.
2022-12-28
Ändrade alla globala variabler till static typedef så de bara blir globala inom min fil, vilket är det normala inom C/C++ för att slippa namnkrock med variabler i inlänkade bibliotek. Verkar som det löste mina misstankar om en klassisk C/C++ bug typ pekarefel eller dylikt som jag hade isolerat till att finnas i en av mina Task. Har i vart fall inte fått något mer sådant felmeddelande.
Men får ändå enstaka glesa kraschar så inte helt stabilt ännu, även om jag oftast kan exekvera fler timmar i sträck.
Ska kolla upp att jag verkligen använder Mutex för exklusiv åtkomst till data / resurser på alla ställen i koden det behövs för att undvika krockar mellan min olika asynkront exekverande FreeRTOS-Tasks! Och om jag inte hittar något där så ta bort alla String-class variabler jag använt (Php-kodvana) och ersätta med klassisk C/C++ char[]-array istället, vilket är mycket effektivare samt antytts någon stans att String kan vålla dessa krascher ihop med webbserver-biblioteket ESPAsyncWebServer-esphome jag använder. Så hoppas få det helt stabilt så!
Lite intressant läsning kring C++ kodning:
Static local variables, Learn C++
Sharing global constants across multiple files (using inline variables)
Why (non-const) global variables are evil
2022-12-29
Fick "Guru Meditation Error: Core 1 panic´ed (LoadProhibited). Exception was unhandled." igen när jag aktiverade en av tryckknapparna, och misstänker det har något att göra med missad Mutex kring min DisplayHandler(), Task_DisplayViewHandler() samt Task_LCDButtonsHandler(), eller Mutex kring Serial.print() då det händer när jag aktiverar menyn för att Serial.printa info om FreeRTOS Task stack size!
Nya versioner av espressif/arduino-esp32 (ESP32 Arduino 2.0.6 based on ESP-IDF 4.4.3) och av platformio/platform-espressif32, 5.3.0 med bl.a. "Fixed issue where esp32 won´t reconnect to WiFi AP if the AP was restarted." som jag tackar för just nu när jag håller på med WiFi och async webbserver!
Har även upptäckt att med PlatformIO längre tid passiv i bakgrunden med öppen Serie-Monitor ansluten till ESP32 så kraschar ESP32-webbservern ibland, men stänger jag Serie-Monitor så undviks det! Verkar som Serie-Monitor blir inaktiv då.

ESP32 Async webbserver (SSE) + LCD
ESP32 Async webbserver (SSE), mobil.
Fullskärmsläge på mobilen liknar en App.
LCD-display på ESP32 med driftsdata.

2022-12-31
Har nu fin långtidsstabilitet med ESP32-webbservern med en uppkopplad webbläsare / webbsida samt med att jag sänkt uppdateringsfrekvensen till 1ggr/2s. Den sänkta uppdateringsfrekvensen beror troligen på att mitt Olimex LCD-shield arbetar så enormt långsamt då det saknar en buffert för inkommande texter så min kod får vänta på den riktigt långsamma skrivning av varje tecken till själva displayen med drygt 640ms för att skriva alla de 2x16 tecknen (20ms/tecken) vid I2C busshastighet 80kHz som är max den klarar.
Vid data till flera webbläsarfönster får jag fortfarande krascher med felmeddelandet: "assert failed: tcpip_api_call IDF/components/lwip/lwip/src/api/tcpip.c:497 (Invalid mbox)". Nämns dock något om ESP32 reset WiFi stack samt How can I increase wifi task stack size?, ESP32: Increase wifi task stack size to support advanced logging, 4WAY_HANDSHAKE_TIMEOUT.
Espressif: Optimization of Internal RAM, Fatal Errors, Guru Meditation Errors
Verkar vara någon buffert / stack size som inte räcker till, men inte lyckats hitta någon bra info om det trots mycket sökande på Internet!


2023-01-18
Har nu hittat både CONFIG_ASYNC_TCP_STACK stack-size och CONFIG_ASYNC_TCP_QUEUE_SIZE event-queue-size för AsyncTCP.cpp i AsyncTCP-esphome-biblioteket:
me-no-dev / AsyncTCP
Sending big blocks of data triggers async_tcp task watchdog, i AsyncTCP.cpp:
event-queue-size:
static inline bool _init_async_event_queue(){
  if(!_async_queue){
    _async_queue = xQueueCreate(512, sizeof(lwip_event_packet_t *)); // 32 default
    if(!_async_queue){
    return false;
    }
  }
  return true;
}
Att öka event-queue-size från default 32 till 512 gjorde att jag kunde öka gränsen för antal events.avgPacketsWaiting() jag tillåter samt köra det helt stabilt även när jag hetsar med 5ggr snabbare sändningsfrekvens via SSE till webbsidorna, även när jag uppdaterar mot två samtidiga webbsidor! Kan med interrupt via tryckknapp uppdatera ca 5ggr/s och fungerar ändå stabil!
Kanske inte skulle behöva kö-övervakningen alls nu, men när jag nu kodat den funktionen känns den bra att ha där. Nu med ökad gräns behöver den i stort aldrig ingripa.
Beskrivs även här: AsyncWebServer giving wdt reset.
Där tipsas även om EspExceptionDecoder för felsökning.
Är ju synd bara att de inte kodat en funktion i AsyncTCP.cpp så man kan justera både dess stack-size och event-queue-size inifrån sin egen kod!
Och i AsyncTCP.h #define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2, som jag även ska prova att öka.
Ökade till 16384 * 2 men det tar mycket RAM-minne, så går tillbaka igen till default. Märkte ingen skillnad vid en snabb test.
Lite mer att läsa:
Using server.serveStatic causes WDT crashes
ESPAsyncWebServer Fork
The combination I currently using Wenserver

Känns inuitivt som att det skulle fixa sig genom att gå över till WebSocket istället för nuvarande SSE med den datamängd jag skickar!
Eller annars använda antingen JSON-data eller Protocol Buffers (Protobuf) (is a free and open-source cross-platform data format used to serialize structured data) för datan.
Går vidare med att koda för och koppla in INA226 energi-/ström-sensorn nu, så får test med WebSocket komma senare. Blir en intressant start på nya året!
2023-01-01
Har haft problem med ESPAsyncWebServer template processing engine då den ersätter template-namn mellan två %-tecken, typ %VOLTAGE% med datan från en C/C++-variable i ESP32-koden. Blir problem dels när man använder % som längdmått i CCS typ width=100%;, samt dels även som enhet i sin html-text! Har ägnat flera dagar åt att hitta en möjlig fix till detta och löste det idag äntligen :-)
Provade att införa #define TEMPLATE_PLACEHOLDER '$' i min kod, men fungerade inte då det inte rår på ESPAsyncWebServer biblioteket.
Hittade tips om att build_flags = -TEMPLATE_PLACEHOLDER='$' i platformio.ini filen skulle fixa det, men inte!
Infogade #define TEMPLATE_PLACEHOLDER '$' i min kod så fick jag upp ett felmeddelande om att symbolen i WebResponseImpl.h var redefinierad och kunde då klicka upp den filen där den ursprungliga #define fanns, så editerade jag den där till #define TEMPLATE_PLACEHOLDER '$'! Och det fungerade!
Där finns även #define TEMPLATE_PARAM_NAME_LENGTH 32, så default kan max 32 tecken användas.
Och även där är en allvarlig bug i denna kodfunktionen, för den tar inledande %-tecken och de följande 32 tecknen och ersätter fast inte hittat avslutande %-tecken. Egentligen är det nog huvudproblemet, och ett grovt kodningsfel tycker jag!
Genom att behålla #define TEMPLATE_PLACEHOLDER '$' i min kod så kommer jag bli uppmärksam på ny uppdatering av ESPAsyncWebServer / WebResponseImpl.h vid kompilering och får då editera där igen. Men oförändrad blir det inga felmeddelande så.
Känns rätt klantigt att använda "%"-tecken för denna funktion, liksom att inte infört ett lätt sätt att själv i sin kod kunna välja lämpligt tecken! Jag provad även att i den egna processor() funktion man gör för utbytet att returnera den var-String man får där ihop med %-tecken, så skulle ju det vid width=100%; ersättas med ursprunglig kod och ingen skada skedd, men då reprocessar den hela den koden från början för varje template-name-processing så hamnade då i en oändlig loop! Också rätt märklig kodfunktion som slösar processorkraft! Borde ju fungerat!
Han som kodat detta bad redan 2018 om ursäkt för den funktionen, men ändå är det nu drygt 4 år senare inte åtgärdat! Ger ett lite dåligt intryck av biblioteket som trots det är det mest använda och mest aktuellt uppdaterade Async Web Server SSE bibliotekt vad jag ser.
Ska senare kolla in WebSockets och då även kanske testa PlatformIO biblioteket WebSocket Server and Client for Arduino ESP32.
2023-01-03
Har nu visat driftsdata (slumptals-fejkade än så länge) från min ESP32 batterimonitor (och blivande PWM-regulator) aktivt uppdaterat via WiFi mot mobilen två timmar i ett streck med stabil funktion från webbservern i ESP32 mikrokontrollern!
Så känns tillräckligt stabilt nu för att gå vidare med att koppla in energi-/ström-sensorn INA226 och fixa programkoden för den samt ansluta till min lilla experiments-solcellsanläggning här hemma.
Server Side Events (SSE) är en elegant smidig teknik, men med detta kodbiblioteket känns den inte riktigt stabil för en "större" datamängd som här, så ska senare testa med WebSockets istället. Men går nu först vidare med att koppla in INA226!
Är så jäkla nyfiken på att testa den smarta INA226: 36V, 16-bit, ultra-precise I2C output current / voltage / power monitor w/alert!

ESP32 Async webbserver (SSE) + LCD
ESP32 Async webbserver (SSE), mobil.
Fullskärmsläge på mobilen liknar en App.
LCD-display på ESP32 med driftsdata.

2023-01-05
Nu verkar jag fått min ESP32-webbserver att arbeta helt stabilt utan kodkrascher, både med 1ggr/s uppdateringfrekvens av SSE-data till webbsidan och av LCD-displayen, genom fem ytterligare åtgärder. Har även provat med 2st webbsidor på datorn och 1st i mobilen nu.

  1. Införde en Mutex för DisplayHandler-funktionen så bara en instans av den kan vara aktiv åt gången via anrop från olika FreeRTOS Tasks. Fast den i sig utnyttjar Mutex för I2C-seriebussen så belastar det RAM-minnet med flera aktiva instanser av DisplayHandler inlästa där helt i onödan, samt tar även processorkraft. Syntes tydligt på heap-minnet!
  2. Införde adaptiva funktioner i koden som minskar uppdateringsfrekvensen av SSE-skickade data till webbsidan samt av uppdateringen av LCD-displayen så fort det blir för mycket kö i de Queue-dataflödena. Gjorde stor märkbar skillnad, samt innebär att jag nu normalt kan uppdatera båda 1ggr/s, som väldigt glest tillfälligt görs långsammare individuellt för de olika enheterna. För SSE-skickade data var detta extra kritiskt när en nedstängd webbserver väcks upp igen!
  3. Ändrade WiFi.useStaticBuffers(true); till true (set the buffers memory allocation to dynamic = false), då dynamisk minnesbuffert verkade fragmentera heap-minnet och efter lång driftstid kraschade exekveringen med felmeddelande att heap-allocation inte gick.
  4. Bytte ut den 10µF kondensator jag kopplat till 3,3V på ESP32-kortet till en 470µF kondensator för att buffra för de korta lite högre strömspikar WiFi-kommunikationen drar, vilket gjorde stor skillnad. Nu försvann helt det väldigt glesa kodkrascherna när jag hade ett webbläsarfönster öppet mot ESP32-webbservern, och de mer frekventa krascherna vid 2-3 uppkopplad webbläsarfönster försvann också, så var helt klart spänningsdippar som störde mikroprocessorn! Det luriga är att jag fick inga Brownout-resets utan ESP_RST_PANIC (Panic Handler), så Brownout´s detekterar tydligen inte så korta spänningsdrop!
  5. I min Task där jag skickar alla SSE-data events.send() till webbsidan införde jag ckeck för events.avgPacketsWaiting() så inte de köar upp för mycket väntande Packets i webbservern utan väntar då med att skicka nya, vilket även skonade RAM/Heap-utnyttjandet signifikant. Med events.count() får man även antal webbsidor som servas för stunden!
    Var ett litet dektivjobb att hitta, då det inte tas med i de enkla exemplen för webbserver-kod till ESP32 jag hittat på Internet!
    Har testat vid svag WiFi-signal och arbetar helt stabilt nu även när det kan ta 10-15s mellan att SSE-data via events.send() når webbläsaren! Tidigare kraschade kod-exekveringen då!
    Köandet ökar inte vid 3st anslutna webbläsarfönster mot 1st, så är inte skickad datamängd som ger kö utan tydligen antal anrop till events.send(). Har läst att vid större mängd data blir det bättre att packa in dem i en JSON-fil och skicka med ett anrop till events.send(), så ska prova det senare. Även sett info om att WebSockets skulle vara bättre / effektivare vid denna typ av dataskickande till webbsida, bl.a. för att den kan även skicka binär data (typ float/int tal) mot SSE som bara tar textsträngar, så även det ska jag prova senare.
    Men då jag fått det stabilt nu installerar jag först effekt/ström-sensor INA226 så jag får igång riktig mätning mot batteriet i mitt lilla experiment off-grid solcellssystem här hemma!
2023-01-07
Har lagt in en WiFi.onEvent() som aktiverar server.begin() så att webbservern helt säkert återstartas direkt när WiFi har återanslutit och fått IP efter varit nedkopplad. Tidigare kunde webbserverns återstartande vara lite segt, som ibland t.o.m. kraschade kodexekveringen.
Gör att även efter automatisk WiFi-Reconnect med WiFi.setAutoReconnect(true) så återstartas webbservern direkt!
WiFi.onEvent() är riktigt snabb så WiFi.onEvent(ARDUINO_EVENT_WIFI_STA_GOT_IP); aktiveras innan wifiMulti.run() exekverat färdigt med sin anslutning till WiFi! Märks även när jag nu testat med att min ESP32-kod fått stänga ned WiFi och sedan återstarta en mängd gånger, att webbservern återansluter väldigt snabbt och SSE-data kan uppdateras direkt i webbläsaren efter WiFi-Reconnect! Samt har varit 100% stabilt!
Så ytterligare en pusselbit i att få en riktigt långtidsstabil ESP32 webbserver kod-funktion.
Info och kodtips från: Reconnect to Wi-Fi Network After Lost Connection (Wi-Fi Events)
ESP32 C/C++ kod:
WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info){
  server.begin();
}

Funktionens parametrar: ESP32 Arduino: Getting WiFi Event information.
2023-01-11
Mätt upp via oscilloskop hur snabbt jag kan växla en GPIO-utgång 1-0-1 på mitt ESP32-kort. Är förberedelse inför att kunna utvärdera en Deferred interrupt processing jag snart ska implementera för INA226. Tog 100ns (10MHz), vilket jag är nöjd med!
Så kan göra sådana utvärderingar då med 100ns upplösning!
När jag sedan mäter med interrupt så måste jag göra det via oscilloskop såhär, då signalen kommer utifrån från INA226.
Gör detta med direkt portmanipulation:
GPIO.out_w1tc = ((uint32_t)1 << 18); // Set PIO 18 to 0
GPIO.out_w1ts = ((uint32_t)1 << 18); // Set PIO 18 to 1
GPIO.out_w1tc = ((uint32_t)1 << 18); // Set PIO 18 to 0

Mätte även upp hur exakt den FreeRTOS-Task jag exekverar 1ggr/1000ms blir i sin frekvens samt den tid själva Task-exekveringen tar varje gång. Styrs då av vTaskDelayUntil( &xLastWakeTime, 1000 / portTICK_PERIOD_MS ) samt exekveringen innefattar bl.a. 2st xQueueSend() som initierar exekvering av två andra Task.
Den önskade 1ggr/1000ms exekveringsfrekvensen mäts till 1ggr/1000,01ms stabilt med Std-Dev 4,78µs över 50 mätningar, så det är ju imponerande bra!
Oscilloskopet mäter upp en exekveringsfrekvens på 999,99mHz!

Samt själva exekveringen tar 0,6 - 0,7ms, så xQueueSend()-data till andra Task är också snabbt, då jag gör lite andra småsaker också under Task-exekveringen. Detta går ju att mäta inne i koden också med microsekund-upplösning. Men man ser tydligare hur tiden varierar på oscilloskopet.
Så en duty-cycle för exekveringen på 0,06% - 0,07% i denna Task!
Inte så hård belastning på processorn precis :-)
Gör detta för att få insikt i hur exekveringen och koden arbetar, för eventuellt senare optimering om det behövs! Ökar även min kunskap om hur det jag gör verkligen fungerar.

ESP32 PIO portmanipulation
ESP32 PIO portmanipulation
ESP32 Task frekvens & exekvering
ESP32 Task frekvens & exekvering
ESP32 Task frekvens & exekvering
ESP32 Task frekvens & exekvering

2023-01-16
Kodat Interrupt och WakeUp från light sleep på samma GPIO:
För INA226 effekt/ström-sensorn så dess Alert-interrupt signal både kan indikera nya mätvärden att läsa av samt samtidigt väcka upp ESP32 via GPIO från light sleep när i energisparläge. Görs med attachInterrupt(19, ISR, ONLOW_WE);, där WE=WakeUp Enabled. Var svårt att hitta info om, men nu fungerar det emulerat via en tryckknapp på bread-board. Så nästa steg är att koppla ihop med INA226!
2023-01-18
Har nu hittat både CONFIG_ASYNC_TCP_STACK stack-size och CONFIG_ASYNC_TCP_QUEUE_SIZE event-queue-size för AsyncTCP.cpp i AsyncTCP-esphome-biblioteket:
me-no-dev / AsyncTCP
Sending big blocks of data triggers async_tcp task watchdog, i AsyncTCP.cpp:
event-queue-size:
static inline bool _init_async_event_queue(){
  if(!_async_queue){
    _async_queue = xQueueCreate(512, sizeof(lwip_event_packet_t *)); // 32 default
    if(!_async_queue){
    return false;
    }
  }
  return true;
}
Att öka event-queue-size från default 32 till 512 gjorde att jag kunde öka gränsen för antal events.avgPacketsWaiting() jag tillåter samt köra det helt stabilt även när jag hetsar med 5ggr snabbare sändningsfrekvens via SSE till webbsidorna, även när jag uppdaterar mot två samtidiga webbsidor! Kan med interrupt via tryckknapp uppdatera ca 5ggr/s och fungerar ändå stabil!
Kanske inte skulle behöva kö-övervakningen alls nu, men när jag nu kodat den funktionen känns den bra att ha där. Nu med ökad gräns behöver den i stort aldrig ingripa.
Beskrivs även här: AsyncWebServer giving wdt reset.
Där tipsas även om EspExceptionDecoder för felsökning.
Är ju synd bara att de inte kodat en funktion i AsyncTCP.cpp så man kan justera både dess stack-size och event-queue-size inifrån sin egen kod!
Och i AsyncTCP.h #define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2, som jag även ska prova att öka.
Ökade till 16384 * 2 men det tar mycket RAM-minne, så går tillbaka igen till default. Märkte ingen skillnad vid en snabb test.
Lite mer att läsa:
Using server.serveStatic causes WDT crashes
ESPAsyncWebServer Fork
The combination I currently using Wenserver
2023-01-20

Nedladdningsprestanda webbsida
Document, html, överfört 41,23 kB, storlek 41,12kB, 266ms

Har nu kodat ett menysystem färdigt till 5st webbsidor i ESP32, så nu är där en hel webbplats. Huvud­webbsidan är nu 41,23 kB i överförd storlek som tar ca 150-300ms att ladda ned för webbläsaren. Jag tycker det är imponerande hanterat av ESP32 prestandamässigt!
Är gjort som en modern s.k. "responsive hamburger menu" med en inline <svg></svg> hamburger-icon kod från CSS-Tricks.
Har delat upp webbkoden i separata CSS, JavaScript & Html char-variabler kodblock som är gemensamma för alla webbsidorna, som kopieras in via processor-funktionen i ESPAsyncWebServer-esphome. Sparar på så sätt flash-minne samt slipper redundant kod så blir enklare att uppdatera koden för webbsidorna.
Är fortfarande gott om plats i ESP32 där kompilatorn rapporterar:
RAM: [= ] 14.4% (used 47196 bytes from 327680 bytes)
Flash: [=== ] 28.9% (used 908177 bytes from 3145728 bytes)
Samt i aktiv drift mäter jag i ESP32:
FreeSketchSpace(%): 75
FreeHeap(%): 57 (52% när SSE skickas till webbsida)
SdkVersion: v4.4.3
ChipModel: ESP32-D0WDQ6
ChipRevision: 1
Har även lagt in <svg></svg> för en icon för aktivering av full-screen mode uppe till höger.
Koden hämtad från Arrows fullscreen Icon Svg Code. Finns även Arrows Maximize Icon SVG.
Här är alla FontAwesomeIcons SVG Icons | SVG Code Generator.

Har även lagt till en SVG-FavIcon: Use inline SVG as favicon där <svg></svg>-koden URL-encodes via URL-encoder for SVG.
Nu som första start använder jag Speedometer2 SVG Icon Code men tänker senare skapa en egen SVG-FavIcon.
Html-kodas såhär i <head>-sektionen:
<link rel="icon" href="data:image/svg+xml,[YOUR URL-ENCODED SVG HERE]" type="image/svg+xml" />

Meny ESP32 Async webbserver (SSE)
Meny ESP32 Async webbserver (SSE), mobil.

2023-01-21
Har kopplat in INA226 till ESP32 med INA226_WE biblioteket och dess Conversion-Ready-Alarm Interrupt signal triggar min ISR och dess deferred interrupt processing Task med en väldigt hög repetitiv precision på 1129695±2µs! Mätt via 64-bit esp_timer_get_time()!
En otrolig tidsnoggrannhet upplever jag, men kommer ändå summera Ah med den mätta tiden!
Har då satt INA226 till 1.1ms conversion time och 512 samples för medelvärdesbildning och det är spänning + ström som läses av så 1,1ms * 512 * 2 = 1126ms mellan att INA226 ska ha färdiga nya mätvärden att läsa av, plus ca 4ms overhead på det tydligen.
INA226 mäter därmed ström och spänning 512ggr/1,129695s dvs 453ggr/s, 1ggr/2,2ms!
Ihop med 19ms RC-filter fångas även de allra snabbaste och korta pulser upp i mätningarna!
Så INA226 styr på så sätt nu "pulsen" för min kods exekvering.

Har ingen ström ansluten till INA226 ännu så den mäter nu 3,286V, 0,000A & 0,000W, då spänningsmätningen är kopplad till 3,3V matningsspänningen. Mätdatan 3,286V ligger exakt stabilt på den spänningen och strömmen är 0,000A hela tiden, riktigt imponerande!
Mätt med min digitala multimeter får jag 3,285V.
Ser ut att bli riktigt bra förutsättningar för en hög noggrannhet i batterimonitorn med detta!
Så stämmer med hur jag noga valt komponenter.

Att medelvärdesbilda så här över 1,1s ger väldigt stabila värden att visa och att reglera på!
Blir spännande att se hur stabila mätvärden jag får inkopplat mot blybatteriet senare.
Är möjligt sedan när jag ska reglera laddningen att jag behöver läsa av strömmen lite oftare, men får prova då. Med 588µs conversion time och 256 samples får jag 0,588ms * 256 * 2 = 301ms intervall, som nog kan vara bra att sikta mot om jag behöver snabbare respons för strömmen.
Men samtidigt är den medelvärdesbildade strömmätningen så extremt stabil brusfri att man kan göra en snabbare och mer exakt reglering på den, så tror ändå det räcker med 1ggr/1,1s avläsning. Vid en linjärt förändrad ström över tid så skulle man kunna ta 2ggr förändringen sedan senaste medelvärdesbildade mätvärde, då det skulle motsvara nuvarande momentant värde, så kan experimentera med att ta 1,5-2ggr strömförändringen så i PWM-regleringen. Sedan är en ren PWM-reglering smidig då en ändring i duty-cycle / pulskvot direkt motsvarar en strömändring, så går att matematiskt räkna fram väldigt nog hur mycket pulskvoten behöver ändras för att justera en viss avvikelse i strömregleringen! Och strömreglering i sig mot blybatterier har mycket snabbare respons än spänningsreglering, så det blir en bra bas för regleringen.
Kan se att min nuvarande rent spänningsreglerande PWM-regulator agerar rätt långsamt pga det för stabil reglering mot blybatterierna, då de är rätt spänningströga!
Ska även ha en ström+ reglering för extra snabb noggrann laddreglering, min specialare.

Fri SRAM ligger fortfarande kvar på 52% under aktiv exekvering med SSE-data till webbsida, så en försumbar inverkan på ESP32 prestandan liksom en minimal försumbar tid att hämta mätvärden över I2C. Totala aktiva exekveringstiden för mina FreeRTOS Task´s är kvar på ca 1%.

Och jag lyckas få ihop detta med använt I2C Olimex Shield-LCD 16x2 som har svårt att samsas med annan enhet på samma I2C. Har gjort lite smart kodande där som adaptivt håller koll på detta och skyddar och optimerar Olimex Shield-LCD´s I2C-kommunikation.
Och det går inte ut över INA226´s I2C-kommunikation, så känner mig väldigt nöjd så!
2023-01-22
Testad att sätta ESP32 i light-sleep strömsparläge mellan varje INA226-avläsning, som väcks upp av interrupt från INA226 för ny avläsning av mätdata och sedan light-sleep igen. Nu med 1,1s cykeltid får jag då 10% aktiv drift (för uppdatering av LCD med nya datan) och 90% light-sleep energisparläge. I light-sleep drar ESP32 ca 15mA från 5V USB, samt ca 52mA i aktiv drift utan WiFi och med WiFi i snitt runt 75mA grovt. Fungerade jättebra!
I sådan drift blir strömförbrukning ca 19mA i snitt, vilket känns rätt OK. Vid drift från 12V via DC-DC-konverter bör det bli lägre, beroende på effektiviteten hos DC-DC-konvertern.
2023-01-23
Gjort nu att i strömsparläge med light-sleep så väntar koden adaptivt in en uppdatering av LCD, vilket då tar 2-5% av cykeltiden. Så medelströmförbrukningen då blir vid 5% 0,05x52mA + 0,95x15mA = 17mA från 5V USB. Samt lagt in att när någon av de fyra tryckknapparna är nedtryckt går den ur strömsparläge. Fungerar bra.
It is common to use the idle hook function to place the microcontroller CPU into a power saving mode. The Idle Task Hook - får titta in på detta för light-sleep strömsparfunktion!

INA226 breakout-boardet har en 100mOhm strömshunt, så ställt in INA226 för 100mOhm och 1A mätområde nu under inledande testande. Då mäter den med 0,00125V / 0,00003A upplösning (1 LSB step size). Med ström via 1k+3,3V matningsspänning mäter den då stabilt 3,28625V, 0,00366A samt 0,012W, utan att siffrorna ändras sig alls, dvs utan något som helst brus! Någon gång glest ibland växlar den till 3,28750V dvs 1 LSB upp. Mätvärdena är då medelvärdena av 512st avläsningar av strömshunten, spänningen samt effekten under 1,1s. Medelvärdesbildningen i INA226 så ger väldigt stabila mätvärden samtidigt som avläsning 512ggr/1,1s internt i INA226 fångar upp snabba förändringar i batteribankens ström / spänning för noggrann Ah/Wh-mätning!
Håller jag med två fuktiga fingrar över 1k-motståndet ökar strömvärdet till 0,00369A med just +0,03mA minsta mätsteget (1 LSB step size).
Så med 100A 0,5mOhm strömshunt blir mätupplösningen 3mA i mitt off-grid solcellssystem!
Senare ska jag ta bort strömshunten på INA226 breakout-boardet och koppla mot extern strömshunt 60A / 60mV som jag har i mitt lilla experiment off-grid solcellssystem här hemma.

Mätt med digitalt minnes-oscilloskop för: Interrupt → ISR → ISR Deferred Handling Task

ESP32 deferred interrupt processing
ESP32 deferred interrupt processing
With: I2C Wire.setClock(80000); (Hz)
The I2C LCD-display sets this limit in speed
Only latency that vary is the Mutex lock I2C
due to interference with I2C LCD-display communication
ESP32 deferred interrupt processing
ESP32 deferred interrupt processing
Interrupt frequency (INA226): 1/1129695±2µs (1/1,1s)

Finns lite att läsa på hos espressif kring snabbheten för Interrupt och kod:
High-Level Interrupts
Interrupt allocation
Maximizing Execution Speed

ESP32 Interrupt - ISR latency
ESP32 Interrupt → ISR latency är ca 1,82µs
Rätt långsamt för en 240MHz 32-bit processor
Men väldigt stabil tidsmässigt

Med portYIELD_FROM_ISR() / taskYIELD_FROM_ISR() context switch (ger samma funktion) i ISR fås en bra realtidsfunktion med extremt liten variation i de ca 25µs Deferred ISR Interrupt Latency, ESP32 Interrupt ISR → Deferred Task interrupt processing latency! En extrem skillnad mot utan Yield() då latencyn varierar slumpmässigt ≤1ms!
Mätt med digitalt minnes-oscilloskop för: Interrupt → ISR → ISR Deferred Handling Task.
void IRAM_ATTR ISR_INA226Batt(void)
{
 auto InterruptTime = esp_timer_get_time();
 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 xQueueSendToBackFromISR(DeferredInterruptQueue, &InterruptTime, &xHigherPriorityTaskWoken);
 if( xHigherPriorityTaskWoken )
 {
  portYIELD_FROM_ISR(); // same as taskYIELD_FROM_ISR()
 }
}
Beskrivning av ISR context switch samt FreeRTOS: Why to call taskYIELD_FROM_ISR() method within the isrHandler. "Calling either xQueueSendFromISR() or xQueueReceiveFromISR() within an interrupt service routine can potentially cause a task to leave the Blocked state which then necessitates a context switch if the unblocked task has a higher priority than the interrupted task.
A context switch is performed transparently (within the API functions) when either xQueueSend() or xQueueReceive() cause a task of higher priority than the calling task to exit the Blocked state. This behavior is desirable from a task, but not from an interrupt service routine. Therefore, xQueueSendFromISR() and xQueueReceiveFromISR(), rather than performing the context switch themselves, instead return a value indicative of whether a context switch is required. If a context switch is required, the application writer can use taskYIELD_FROM_ISR() to perform the context switch at the most appropriate time, normally at the end of the interrupt handler.
"
Utan Yield() varierar ESP32 Interrupt ISR → Deferred Task interrupt processing latency mellan 52µs till 900µs.
Beror troligen på att FreeRTOS portTICK_PERIOD_MS är 1ms i ESP32, dvs FreeRTOS tick rate = 1000Hz som är så ofta FreeRTOS kan växla mellan Task under sin Preemptive Multitasking. Min ISR Deferred Interrupt Task har här priority 7 (medelhög).
ESP32 FreeRTOS max Task priority är: 24. Low priority numbers denote low priority tasks. The idle task has priority zero (tskIDLE_PRIORITY).
Max latency utan Yield() för ISR → deferred interrupt processing kan därmed sannolikt bli ≤1000µs = portTICK_PERIOD_MS för en deferred Task med högre prioritet än övriga Tasks.

ESP32 ISR - deferred interrupt processing  latency, Min
ESP32 Interrupt ISR → Deferred Task interrupt processing latency, Minimum ca 25µs

ESP32 deferred interrupts processing
ESP32 deferred interrupt processing - time to sent data to INA226

ESP32 deferred interrupts processing
ESP32 deferred interrupt processing - time reading 4x data from INA226

2023-01-28
Har idag kodat in en finite-state machine i form av en C++ class i mitt ESP32 batterimonitor / PWM-regulator hobbyprojekt. Blev riktigt bra och trevlig!

Styr och håller koll på vilka driftslägen den arbetar i samt sköter om växlingen mellan olika driftslägen på ett strukturerat robust sätt, så jag smidigt kan sköta det från en central kod-funktion.
Blir nu mycket tydligare i programkoden vad som görs samt väldigt mycket enklare att implementera en avancerad robust funktion kring detta! Som att stänga ned i light-sleep kräver att det görs i ett antal steg för bra stabil funktion i mitt projekt, och då tar finite-state machinen hand om den processen bl.a. att stänga ned WiFi först.
Och behöver jag framöver optimera en sådan process eller föra in nya driftslägen så blir det väldigt smidig med en gemensam central kod / class som tar hand om det.

Nu har jag för WiFi / Webbserverns drift samt för CPU-diftsläge / strömsparläge med olika CPU-klockning samt light-sleep. Kommer senare även att ha för PWM-regulatorn och dess olika laddfaser för blybatterierna.
Kan då även från olika delar i koden fråga finite-state machinen om aktuellt driftsläge för de olika funktionerna.

Är väl något man gjort intuitivt förut också, men inte såhär formaliserat och tydligt, vilket blev mycket bättre och kraftfullare :-)
Så känns som detta projektet tog ett tydligt steg framåt idag!
Även lagt in ny LCD-meny för dels att nolla datan för ESP32 Hard- / WDT-resets, dels för Ah/Wh.
Samt lött in en 470µF/16V/105°C och en 2.2µF/50V R82 kondensator mot den pyttelilla som finns invid ESP32-shipets 3,3V matning, för att hantera när ESP32 sänder data via WiFi.
2023-01-29
Nu summerar ESP32 Ah/Wh både vid CPU 240MHz och i Light-Sleep energisparläge. Lagt in en Serial.print() som visar miljarddelar av en Ah/Wh för att lätt kunna följa summeringen över tid där med den lilla 0,00366A ström (1kΩ) 3,28500V jag mäter just nu.
Får utskrivet vid Light-Sleep / 240MHz typ:
Serial.print(): INA226 Interrupt Time: 45232715734µs, TimeDiff (µs): 2261571 / 1129689, 0.046016466Ah, 0.153235674Wh, 99.959991% vid ström 0,00366A och spänning 3,28500V.
Ger 0.046016466Ah / 0,00366A = 12,57h samma som 45232,715734s / 3600 = 12,57h så OK!
Har då infört en C++ BatteriMonitor class som tar hand om denna loggning.
Har även optimerat funktionen vid drift med Light-Sleep så INA226 växlar till AVERAGE_1024 från AVERAGE_512 annars som ihop med 1,1ms conversion-time ger 2,2s resp. 1,1s cykeltid, samt gjort lite annan kod tydligare. Med 2,2s cykeltid blir Light-Sleep driften extra strömsnål.
Processorn väcks upp ur Light-Sleep via INA260-interrupt och efter avlästa mätvärden, uträknade Ah/Wh och uppdaterad LCD sätts i Light-Sleep igen. Så är då i Light-Sleep >95% av tiden när i energisparläge typ nattdrift, där den då drar 15mA från 5V USB.
2023-01-30
Mätte med ESP32+INA226 i frysen (-18°C) och då blev 0,00000A i rumstemperatur -0,00012A nedkyld vid 1A mätområde, så en hyfsat liten inverkan. Mätningen strulade lite så vet inte hur säkert resultatet blev. Motsvarar då -12mA vid 100A mätområde, ca 2Ah/vecka i felvisning så ifall. Men jag har tänkt att automatiskt regelbundet nollström-kalibrera mot aktiv float-laddström vid 100% SOC fulladdat så även batteribankens självurladdning kommer med, så då blir påverkan försumbar.
Är tänkt att göra en förenklad ML (Machine Learning) hur det varierar med batteritemperaturen, en sorts kalibreringstabell-funktion vs batteritemperatur, för extra precision i Ah-räknandet. Senare kanske via TinyML / Tensorflow om det verkar kunna ge någon fördel.
Även tänkt utvärdera batteriverkningsgrad på liknande sätt, vs temperatur, urladdningsdjup, tid sedan senaste fulladdat, etc.
2023-01-31
Köpt DollaTek 10st MP1584EN ultra liten DC-DC 3A ström step-down omvandlare efter tips om att DC-DC-omvandlare baserade på MP1584 har låg tomgångsström (quiescent current). Testat nu och utan utgående ström drar de låga 0,24mA matad med 12,5V, och ut 7,03V belastade med 22Ω / 0,304A drar den 0,182A. Blir 7,03 x 0,304 / (12,5 x 0,182) = 0,94 dvs 94% verkningsgrad vid så låg belastning! Känns lovande för låg strömförbrukning för ESP32 i drift matad via denna! Bör kunna bli ca 10mA i strömsparläge typ nattdrift med bara loggning av strömförbrukning från/till batterierna aktiv med >95% i light-sleep som drar 15mA från 5V USB. Målet har varit <15mA för strömsnål vinterdrift. Får se hur den och ESP32 trivs ihop.
Driftstemperatur: -45°C till 85°C, Storlek: 22mm gånger 17mm.
Finns även hos svenska Invize: Spänningsomvandlare step-down 3A MP1584
2023-02-01
Ändrat så vid night-mode strömsparläge med light-sleep sänks CPU-frekvensen från 240MHz till 80MHz. Med 10, 20 & 40MHz fungerade inte Serial.print() OK, troligen för ESP32 inte hinner skriva databuffertern innan satt i light-sleep. Övriga koden fungerade helt OK även vid 10MHz!
Men är OK med 80MHz som då ger omkring 0,05x40mA + 0,95x15mA = 16mA från 5V USB. Bör kunna bli ca 10mA i snitt via DC-DC-konverter från 12V, klart under målet <15mA.
Har mätt nu och drar ca 11mA från 12,5V vid 7,0V ut vid night-mode strömsparläge med light-sleep, så är nöjd med det! Går kanske att trimma ned till 6,5-6V, men får bli senare testande vart den gränsen går.
Kodat så bara de ändrade mätvärdena skickas över via SSE (Server Side Events) till webbsidan, vilket både belastar SSE mindre samt gav lägre strömförbrukning. Då även kodat in en liten punkt som blinkar på webbsidan i takt med uppdateringarna, så man ser att SSE är aktiv även om inga siffervärden ändras. Den punktens events() uppdaterar även canvas-grafiken.
2023-02-03
Kodat in att menyinställningarna för strömshunt (mV/A, typ 60mV/60A) nu även ändrar inställningarna i INA226 via ina226.setResistorRange(Ω,A), så därmed kodmässigt klart för inkoppling mot blybatteriet i mitt lilla experiment off-grid solcellssystem.
Även installerat breadboard och ESP32 på en gemensam bottenplatta med fasta kopplingsplintar för att säkert kunna dra elledningarna till batteriet. Blir inte så bra direkt från breadboard!
2023-02-04
Kört och loggat min lilla testström lite längre idag, här i strömsparläge / light-sleep:
INA226 Interrupt Time: 26808049418, TimeDiff (us): 2262446, -2.735489130Ah, -8.853511810Wh, SOC 97.621315%. Kodfunktionen för Ah / Wh & SOC är på plats!
2023-02-05
Optimerat Task_LCDbuttonsHandler() för snabbare respons på knapptryckning samt mindre inverkan på övrig kodexekvering. Blev även en renare, tydligare och kortare kod kring I2C.
2023-02-16
Är bara INA226 spänningsmätning VBUS som har 830kΩ ingångsresistans, strömmätningens ingångar IIN+/IIN- har en Input bias current på typ 10µA, men uppmätt ca 35µA i drift!
Så går inte att göra en RC-filtrering på samma lätta sätt där som för VBUS!
Med 4,7µF/4,12kΩ (20ms RC) fick jag 341mA mätt med 500mA genom strömshunten! Utan 4,2kΩ mättes 501,7mA genom 60A/60mV shunten (LSB=1,8mA / 2,5µV).
Missat där så blev lite feltänk! Få fundera på hur jag kan göra istället för att inte missa strömmätningen mellan 2,2ms samplings intervallen! Vill få med även korta strömspikar!
Har nu 22Ω och 4,7µF för strömingångarna som skydd, vilket bara ger 0,10ms tidskonstant.
2023-02-20
Kopplat in min ESP32-batterimonitor till mitt lille experiment off-grid solcellssystem här hemma i lägenhet nu i testdrift.
Så jag kan testa i riktigt driftsmiljö och utveckla den vidare mot färdig funktion med verklig driftsdata för mer skarp drift.
Visar sig då ett elektriskt fenomen som gör att de snabba superkorta strömpulserna från min Battery Reconditioner (9kHz, >50A) ger fel strömvärden vid avläsning av spänningsfallet över 60A/60mV strömshunten. Det då även en så grov strömshunt innehar lite induktans så spänningen vid snabba strömpulser visar inte bara den resistiva spänningen över shunten utan en induktiv sådan också som blir som en falsk strömsignal! Så kondensatorn i strömmätningens RC-filter på 22Ω / 4,7µF laddas upp så det vid strömmar på 100-200mA fås 5-10ggr högre mätt ström, samt vid 800mA ca 2ggr högre!
Utan djupare analys trodde jag att de skulle ta ut sig över en cykel med inverkan av den mikroinduktansens strömtröghet, men gör uppenbarligen inte så!
Så ska försöka få lite hjälp med mer djup kunskap kring det från folk som kan elteorier mer på djupet än jag kan och kanske få tips eller tankar som gör att jag kan arbeta vidare med att nå en lösning även på det. Men kändes lite motigt tillfälligt nu.
Funderar lite kring om LC- eller LRC-lågpassfilter skulle kunna lösa det?
Men känns ändå jäkla skoj att kommit såhär lång nu!
Vid kontinuerlig jämn DC-ström mäter den med väldig hög precision!
Lite input kring detta:
- Kalkylator för låg-/högpassfilter
- LC Filter Calculator – How LC filters work
- LC low pass calculator
- Basic Knowledge of LC Filters
- Transient Robustness for Current Shunt Monitor, Tips?
- TI: INA226 - pulse current measurement
- INA226: 1uA measure current resolution for INA226
- INA226: Measurement resolution and ADC error, 1 LSB Shunt Voltage: 2.5µV
- INA226: Current measurement error with PWM motor driver
- INA240 -4 to 80V, bidirectional, ultra-precise current sensor with enhanced PWM rejection
- ESP32 corrupt heap when handling multiple simultaneous requests, Websockets has been updated / fixed, but SSE (which has similarities with websockets) not. As stated I use Server Sent Events so possible an issue still exists in SSE. (2018, ESPAsyncWebServer)
2023-02-23
Mätt upp strömförbrukningen till: 35mA/12,5V WiFi/webbserver + LCD-bakgrundsbelysning + ESP32 240MHz awake, 33mA vid 1/3-del "Soft" LCD-bakgrundsbelysning mode.
Drar 9mA i snitt med Wifi-OFF, släckt LCD-bakgrundsbelysning, ESP32 80MHz samt light-sleep som väcks upp av INA226-interrupt bara för att kort läsa av nya mätvärden och uppdatera LCD-display 1ggr/2,2s, vid 7,0V från DC-DC omvandlaren. Under själva light-sleep drar den 7mA.
Känner mig nöjd med 9mA då det är <<15mA som var målet!
2023-02-26
Mätt upp strömvärden i off-grid solcellsdrift via de tre olika källorn PWM-display / DMM (True RMS spänning över strömshunt) & INA226 (över strömshunt 60A/60mV), när PWM-regulatorn strömpulsar med drygt 8A pulser 30Hz (ca 7% duty-cycle) samt en Battery Reconditioner strömpulsar >50A 9kHz extremt korta strömpulser genom strömshunten in i blybatteriet:
Mätn1: PWM: 0,3A / DMM: 0,55A / INA226: 1,483A
Mätn2: PWM: 0,2A / DMM: 0,48A / INA226: 1,459A
Vid Batteri: 13,87V = PV Throttle, INA226 mätt ca 20W.
Så är något i min mättekniska utformning kring INA226 som måste fixas för att hantera sådan kraftigt strömpulsad mätning OK!
När ingen strömpulsning förekommer mäter alla tre källorna lika strömvärde!
OBS! PWM-regulatorns egen strömmätning från solpanelen visar också stort fel gentemot DMM True RMS mätvärdet, och då inkluderar det även ESP32´s egenförbrukning på 9mA samt Battery Reconditioner´s på ca 20mA!

Canvas dashboard sneak-peek
ESP32 Async webbserver (SSE) webbsida.
PV off-grid Operational status dashboard sneak-peek.

2023-03-02
Fått strömmätningen med kraftiga strömpulser att fungera nu genom att spänningen över 60A/60mV strömshunten filtreras i ett LRCL-filter vid ingångarna till INA226. Nu stämmer strömvärdena från INA226 med DMM True RMS spänningsmätningar (mV med 2 decimaler) över strömshunten. Ska utvärdera och analysera mätningarna mer noga framöver. Jag kan inte ännu riktigt förklara el-teoretiskt varför det fungerar så och därmed inte heller optimera komponentvärdena för det. Men troligen är det inte mer känsligt än för ett RC-filter, då det ser ut att visa rätt med båda de helt olika strömpulserna! Har gått på min analyserande intuition vad som borde kunna fixa detta!
Visar en liten sneak-peek från mitt grafiska dashboard för "PV off-grid Operational status" i verkligt drift nu i mitt lilla experimentella off-grid solcellssystem vid mobil-laddning.

2023-03-07
Presentation av projektstatus i ett par Facebook-grupper:


Nu har jag mitt ESP32-mikrokontroller baserade batterimonitor projekt i drift sedan en dryg vecka här hemma i mitt lilla experiment off-grid solcellssystem i lägenheten :-)
Känns riktigt skoj att kommit så långt, men är lite svårare än jag tänkt och tar rätt mycket tid att utveckla!
Laddar mobilen här 9 månader/år för att få lite verklig drift, övrig tid på vintern räcker inte strömmen till. Så är mobil-säsong nu igen.
Skoj då att kunna följa driften så detaljerat nu :-)

Med 60A/60mV strömshunt här kan den mäta med en upplösning på 1,8mA (LSB). Med 100A/50mV strömshunt i mitt riktiga off-grid solcellssystem blir det med 3,0mA LSB, så bra precision.
Med INA226 "ultra-precise I2C output current / voltage / power monitor" med väldigt hög precision samt hög noggrannhet över lång tid och stort temperaturområde (så jag inte trodde det var tekniskt möjligt med den prestandan) så bör jag få en riktigt fin precision hos batterimonitorns mätningar, även över hyfsat lång tid.

INA226 får göra upprepat i kontinuerlig följ 512st mätningar av spänning / ström / effekt under 1,1s som den då medelvärdesbildar och sätter en interruptsignal till ESP32 att det finns nya mätvärde att hämta från dess buffert. Så ESP32 hämta varje 1,1s nya sådana fint aggregerade data till sina beräkningar. Får på så sätt både väldigt stabila data som ändå tar med snabba förändringar i ström / spänning 512ggr/1,1s!
I ESP32 mäter jag tid med 1µs upplösning, så beräkningen / summering av Ah och Wh sker med väldigt hög precision så också.

Jag har en Battery Reconditioner till batteriet som via strömshunten strömpulsar med väldigt korta skarpa pulser på >50A i 9kHz för att motverka sulfatering samt PWM-regulatorn strömpulsar med >8A 30Hz när den begränsar laddströmmen för att anpassa laddningen till batteriet.
Jag har nu lyckats få till att jag ändå kan mäta så små strömmar som några mA utan att mätningen störs ut av de höga strömpulserna, och samtidigt mäta strömmängden de höga strömpulserna ger. Ska senare utvärdera lite bättre hur bra det blivit, men ser så här långt riktigt bra ut. Min NASA BM1 batterimonitor jag har i mitt off-grid solcellssystem idag störs helt klart av det strömpulsandet och mäter inte riktigt rätt då. Samt den är inte riktigt temperaturstabil eller långtidsstabil heller, men har ändå haft väldigt bra nytta av den under många år.

Har även en webbserver kodad i ESP32 med webbsidor som visar driftsdata, statistik och info på fem olika webbsidor, som jag då via WiFi kan se i webbläsaren på mobilen eller på en dator, som man ser i mobilen på fotot.

Men är rätt mycket jobb kvar ändå till helt färdigt.
Att göra en egen batterimonitor såhär innebär att jag kan visa precis den driftsdata och statistik jag vill se, samt som det ser ut nu kan jag få en väldigt hög precision i mätningarna.
Ska senare även försöka att skicka data via WiFi / Internet till en webbsida jag har på webbhotell, där jag kan samla driftsdata över längre tid, samt som jag då kan se hemifrån eller vart jag än befinner mig.

Men några gånger har jag nästan varit på väg att ge upp då det dykt upp svårigheter som kändes omöjliga att lösa för mig, men jag lyckats med till slut ändå :-)
Samt är mycket nytt att lära för mig, då detta är mitt första ESP32-projekt samt första gången jag använder FreeRTOS i kodandet! Tror dock jag tagit mig igenom de värsta svårigheterna så nu...

Jag gör detta som ett hobbyprojekt till mig själv för bättre funktion i mitt off-grid solcellssystem i husvagnen och är bara självlärd inom elektronik, C++ kodning samt ESP32-mikrokontroller.
Samt gör det även lite för att ha något tekniskt att engagera mig i och få stimulans från som pensionär.
För de som är nyfikna kan man se mer på min webbsida för projektet:
https://www.nordicoffgrid.se/datalogging/batterymonitor.php

ESP32 batterimonitor - utvecklingsplattform
ESP32 batterimonitor - utvecklingsplattform i off-grid solcellssystem skarp drift.

2023-03-08
Texas Instruments benämner sin sensor INA226 jag använder för "ultra-precise I2C output current / voltage / power monitor". Så ihop med den precision jag kan får ut ur ESP32 så får jag kanske då en ultra-precise batterimonitor som kan mäta sig väl mot de som finns på marknaden.

Det jag via min ESP32-batterimonitor nu följt laddningen i mitt 44Ah blykolbatteri här hemma senaste dygnet är riktigt intressant, där -2Ah urladdat (95% SOC) återladdades igår via bulk-, absorptions- och float-laddning i fullt solsken under dagen ger en väldigt detaljerad info om laddförloppet.
PWM-regulatorn skiftade från kontinuerlig float-laddning till bulk- / absorptions-laddning, då batterispänning sjönk till ca 12,3V vid mobilladdning, under <12,4V som är gränsen för det. Är det initiala spänningdroppet "coup de fouet" man får vid riktigt 100% SOC fulladdade blybatterier i bra kondition, så strömpuls-laddningen har verkligen hunnit fräschat upp blybatteriet efter ca 2,5 vintermånader utan att nått 100% SOC full laddnivå!
Riktigt skoj att kunna följa det så noga, vilket även gav mig ett par nya intressanta kunskaper kring blybatteriladdning.

Kunde bl.a. bekräfta ett antagande jag gjort utifrån ett flertal olika källor om nivån på 0,015C / 1,5% tail-current (1,5A/100Ah) som gräns där absorptions-laddningen bör avbrytas för optimal laddning, så man låter blybatterierna själva tala om när de fått lagom med absorptions-laddning.
Så kommer använda det i min egna PWM-solladdregulator.
Strömmen under 3h absorptions-laddning gick ned till <0,44A/44Ah (0,01C / 1%) utan tvekan där, så blir bra marginaler!
Samt vid 13,8V float-laddning stabiliserade sig den pulsade laddströmmen på ca 200mA (för högt). När solen sedan började gå ned så solcellsströmmen sjönk långsamt och stabilt så blev strömmen vid 13,4V ca 35mA, vilket känns mer lagom för standby-laddning.
Är så grovt och primitiv att köra med en fast tidsgräns för absorptions-laddning, och även med en adaptiv tidsfunktion mot batterispänningen precis när laddningen startar på morgonen blir en grov osäker styrning av blybatteriladdningen, om än något bättre.

Senare ska jag koda lite mer analytisk funktion så jag får ut än mer intressant data från den, som även ska kunna styra laddförloppet bättre.
Jag tycker hela den här branschen med 12/24/48V off-grid solcellssystem är lite seg i att utnyttja den moderna tekniken och skapa lite aktivare smartare laddhantering.
När man gick från oreglerad laddning till s.k. smarta batteriladdare för blybatterier var det ett stort steg, men lite synd utvecklingen verkar ha stannat där känner jag!
Man verkar helt ha nöjt sig med vanlig flerstegsladdning med fasta gränser!

På kvällen uppdaterades de grundbibliotek från Espressif man använder för ESP32 kodning inkl. Arduino v2.0.7, och var några buggfixar där som eventuellt åtgärdar några saker jag haft lite problem kring med WiFi / Webbservern.
Har även gjort lite code refactoring så jag nu fått in i stort all driftsstyrning via en Finite-State Machine (FSM) och därmed en bättre tydligare funktion. Innebär att alla de olika driftslägena, "states", nu styrs och växlas mellan av StateMachine-koden, så allt det är samlat på en plats och det blir inte redundant kod. Blir även mycket enklare att underhålla den delen av funktionaliteten samlad centralt på så sätt, samt mindre risk för buggar.
En tydlig förbättring blev att jag införde en Task_StateMachine() för asynkron växling av driftsläge, så t.ex. inte aktivering av WiFi / Webbserver blockerar responsen hos tryckknapparna. Task_StateMachine() kommunicerar med class StateMachine som har en synkron funktion.
Idag 14 Mars när jag aktiverade ESP32-batterymonitorn med en knapptryckning på morgonen kopplade den upp snabbt smidigt mot WiFi, vilket efter en natts drift tidigare ofta varit trögt och ibland misslyckats. Om det håller i sig är det ett signifikant framsteg mot stabil 24/7/365 drift!
Jag hade en svag intuitiv känsla att en asynkron Finite-State Machine (FSM) funktion skulle kunna ha den inverkan, så håller tummarna för det!
Förfinade även ESP32-webbsidornas meny-funktion lite, med att när man tryckt på ett menyval så fälls meny in snyggt mjukt igen tills webbläsaren hinner växla webbsida.
2023-03-15

Canvas dashboard sneak-peek
ESP32 Async webbserver (SSE) webbsida.
PV off-grid Operational status dashboard sneak-peek.

Även idag startade ESP32-batterymonitor upp WiFi snabbt och smidigt vid knapptryckning!
Samt flera gånger under gårdagen och kvällen.
Kan även se att när WiFi / Webbserver stängs ned frigör mycket SRAM nu (52% till 76% ledigt), vilket inte skett tidigare, så indikerar också tydliga förändringar i kodens funktion som känns positiva. Samt lägsta ledigt SRAM nu 129204b under dessa dygn och största allokerbart heap block 110580b stabilt. Är ca 161970b vid 52% ledigt SRAM.
Är stabilaste drift hittills under flera dygn såhär! Känns riktigt lovande!
Aktiv WiFi, webbserver och SSE-data till webbsida drar ca 35mA för sin drift, så rätt måttligt.
2023-03-16
Helt stabil snabb smidig uppkoppling mot WiFi nu tredje morgonen (24/3-drift) i drift också, när aktiverad med knapptryckning! Riktigt upplyftande, känns att jag går i mål med detta nu.
Samma många gånger under hela gårdagen, så ett riktigt bra framsteg för 24/7/365-drift!
Är sannolikt en kombination av WiFi-buggfixar i Platform-espressif32 v6.1.0 / ESP-IDF v5.0.1 / Arduino v2.0.7 samt min dynamiska Task_StateMachine() ihop med min code refactoring!
2023-03-17
Har två gånger fått kod-krascher när jag aktiverat WiFi / Webbserver med felmeddelandet:
"Guru Meditation Error: Core 0 panic´ed (IntegerDivideByZero). Exception was unhandled."
Har lite snabbt sökt men inte hittat orsaken i min kod. Ska göra det noggrannare senare!
Men ESP32 fixar Rebooting snabbt och bra direkt efter det, så inget som direkt påverkar stabil 24/7/365-drift annat än att <15min (<2hr) data förloras!
2023-03-18

24hr running statistics
Latest 24hr running statistics - Current

Har kodat "Senaste 24-timmars löpande stati­stik" för ström­men, med Akuell-, Medel­värd­es-, Max­värd­es- & Min­värd­es-ström över sen­as­te 24 timmarna löpande. Ska bli för de andra mätvärdena också. Får här tränga djupare in i C++, klasser och objektorientering m.m.!
Ger en bra överblick över senaste dygnets drift i off-grid solcellssystemet.
ESP-batterimonitorn fortsätter att arbeta stabilt över dygnet.
2023-03-19

24hr running statistics
Latest 24hr running statistics - Current

Hade haft Nordic­Off­Grid Batteri­mon­itorn i drift i dryga 24h när skärm­dumpen från mobilen togs idag. De senaste 24h har medel­ström­men då varit -5mA i det väldigt gråmulna vädret, samt Max +73mA och Min -82mA. Max ladd­ström mitt lilla ex­peri­ment sol­cells­sy­stem ger är ca 1A i bra soligt väder, så idag ca 7% av det som mest. Är mätt med en 60A/60mV ström­shunt.

Det löpande ström­medel­vär­det för 24h är beräknat på ca 80.000 ström­värd­en hanterade i ESP32 från INA226-sensorn, som i sin tur skapar varje sådant strömvärde som medelvärdet under 1,1s för 512st strömmätningar.
Så totalt baseras det löpande 24h strömmedelvärdet på ca 40.000.000 strömmätningar, vilket ger bra precision! Liknande gäller för Max- och Min-värdena. Max- och Min-värdena bygger på de under 1,1s medelvärdesbildade mätvärdena från 512st mätningar i INA226, så korta irrelevanta strömspikar filtreras bort på så sätt. Blir samma för batterispänning och övriga datamätvärden också.
Med så många mätvärden blir det viktigt med en bra effektiv algoritm för hur man hanterar det i programkoden, och jag har fixat en som både är väldigt snål på minne och CPU-belastning.

Med strömmedelvärdet för senaste 24h kommer jag göra en bra tidsprognos för hur länge kvarvarande batterikapacitet bör räcka, något helt annat än den prognos baserad på momentan-strömmen min NASA BM1 ger idag. Baserat på momentanström fås olika tidsprognos när 12V kylskåpskompressorn arbetar eller pausar i sin drift, helt oanvändbart! Med 24h tas även den lägre strömförbrukningen under natten med i prognosen.
Ger en bra överblick över senaste dygnets drift i off-grid solcellssystemet.
Blir mer som driftsövervakning av off-grid solcellssystemet än bara batterimonitor!
Ger på så sätt en tydligare överblick över driften av min Victron blykolbatteribank, samt kommer bättre kunna planera aktiv drift i lite längre dåligt solcellsväder.
Känns roligt med en batterimonitor med bra precision och bra info via aggregerad data :-)
2023-03-24

Time To Go
Time To Go för 24hr och 1hr medelström.
Time To Go
Time To Go för 24hr och 1hr medelström.
Time To Go
Time To Go för 24hr och 1hr medelström.
Stabila värden trots korta solglimtar!
Time To Go
Time To Go för 24hr och 1hr medelström.

Har idag kodat en "Time To Go" panel för en bra tidprognos över hur länge kvarvarande batterikapacitet bör räcka för driften vid urladdning, eller tid till fulladdat när solcellerna laddar upp batteribanken. Upp↑/ned↓-pilar visar laddning/urladdning.
Visar bara i hela dagar och timmar, då minuter blir för precist i förhållande till den långtidsprecision man får i ett sådant här system anser jag, och kanske än mer till hur noga man rent tekniskt kan synkronisera 100% SOC med verkligt fulladdad batteribank. Blir då inom ±30min som ↑↓1hr visas avrundat.
Tidprognosen visas dels för senaste löpande 24hr strömmedelvärde, dels för senaste 1hr strömmedelvärde. På så sätt får man en stabil bra uppfattning över hur man ligger till med driften av batteribanken och off-grid socellssystemet oavsett lite varierande ström över dygnet eller från kylskåpskompressors drift ON/OFF, från korta solglimtar, etc. "Time To Go" baserat på momentanström är värdelös!
Kanske blir det senare någon form av adaptiv funktion för 1hr visningen, som någon gav förslag på för anpassning till hur aktuell drift är.

24hr Average, Max & Min Current
Present, 24hr Average, Max & Min Current
24hr & 1hr running Average Current
24hr & 1hr running Average Current

Idag är det väder med ständigt korta solglimtar, men får då ändå en stabil fin prognos för hur lång återladdningstid som är kvar, istället för att den hoppar kraftigt fram och tillbaka efter hur den momentana strömmen är i systemet!
Strömmen varierade då 400-500% till 1000% snabbt upp och ned, så blir svårt att bilda sig en uppfattning på det momentana strömvärdet / tidsprognosen, men med 1hr medelvärde får man ändå stabila fina värden både för strömmen och återstående laddtid! Riktigt häftigt!

Ska även bli löpande 7dygns statistik och troligen även 30dygns, för än bättre info, insikt och överblick det ger över off-grid-systemets drift. I ett sunt dimensionerat off-grid solcellssystem med ≥5dygns dåligt-väder-reserv (Days Of Autonomy) utjämnar batteribanken normalt variationer i strömproduktion av verkligt väder över minst 1-2 veckors tid, så 7dygns strömstatistik är värdefullt i sådan drift.
Min vision med detta är även ett system som helt autonomt smart kan styra laster efter hur mycket ström den utvärderar att det finns att utnyttja över tid, typ 4G router, fläkt, belysning, etc.

2023-03-27

Upptid, datum/tid ESP32 / Client
Upptid samt datum/tid ESP32 / Client.

Skapat en TIME-panel för dels ESP32 Uptime, dels för datum/tid för ESP32 RTC samt Client tid, så kan se hur länge ESP32 varit igång sedan senaste bootning samt kan jämföra hur ESP32 RTC-tiden håller sig och är uppdaterad.
Har efter det fått ett par panic-reboot med felmeddelandet: "Guru Meditation Error: Core 0 panic´ed (LoadProhibited). Exception was unhandled.", som jag får felsöka!
The error LoadProhibited means that the CPU tried to load a variable form an illegal address.
Do you use String Class and do a lot off String constructions with String c = "a" + "b", or are you creating char arrays on the fly e.g. char d[ ] = "efg".
Arduino: ESP32 - Guru Meditation Error: Core 1 panic´ed (LoadProhibited): "My guess is that "lastData" returnedData = int(lastData[7]); has not been set and is still a null (0) pointer. You get an error when you try to read address 7."

Har lagt in att alla class StateMachine´s public variabler initieras i dess Constructor StateMachine(), kanske en möjlig orsak? En variabel, ESP_Time_us, som jag missat där används tidigt för just Uptime, kanske innan den hade initierats med något värde!

Optimerat för detta när bara IP förloras, så WiFi nu ska startas om och återansluta IP:
15:32:02.824 > INA226 Interrupt Time: 144809137, TimeDiff(us): 4592239, -0.038083Ah, 0.596590Wh, 99.913%, 0.96/0.52W
15:32:05.962 > [157673][V][WiFiGeneric.cpp:374] _arduino_event_cb(): STA IP Lost
15:32:05.968 > [157674][D][WiFiGeneric.cpp:931] _eventCallback(): Arduino Event: 9 - STA_LOST_IP
15:32:05.973 > WiFi.onEvent(): No WifiConnect, Event: 9
15:32:05.975 >
15:32:07.851 > INA226 Interrupt Time: 150549432, TimeDiff(us): 5740295, -0.038016Ah, 0.598343Wh, 99.914%, 1.10/0.54W
OBS! WiFi.status() != WL_CONNECTED blir nog inte True då, vilket jag nog förutsatt!?
Får fundera mer på det och söka kunskap om! Inträffar så väldigt sällan, så svårt att ha tur och fånga upp meddelandet såhär.Har modifierat nu så det bör återansluta WiFi / IP!
Hanterar nu dessa WiFi.onEvent(): RDUINO_EVENT_WIFI_STA_DISCONNECTED || ARDUINO_EVENT_WIFI_STA_LOST_IP || ARDUINO_EVENT_WIFI_STA_STOP för anrop av WiFiReconnect(), samt har tagit bort villkoret WiFi.status() != WL_CONNECTED för återanslutning.

2023-03-29
Har problem med att sällsynt ibland (typ <1ggr/dag) så blir det kodexekveringsfel, men bara med WiFi / webbserver ingång vad jag kan se. I nattmode med nedsläckt LCD-display och WiFi / webbserver har jag aldrigt noterat det, så minskar ned koden jag behöver leta i. Samtidgt vet jag då inte om det är min kod eller Espressif system-kod för WiFi eller webbserver-biblioteket?
Skulle jag kunna använda IDF Monitor ihop med Espressif Arduino-framework så skulle jag få ut det radnummer det inträffar vid samt i vilken kod-fil! Då hade det genast blivit mycket lättare att hitta och åtgärda (om det är i min kod-fil), så får söka efter om det är möjligt på något sätt!

Felmeddelande jag får i Verbose mode (DCORE_DEBUG_LEVEL=5):
Guru Meditation Error: Core 0 panic´ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x40094090 PS : 0x00060233 A0 : 0x80094506 A1 : 0x3ffe1c10
A2 : 0x3ffb8014 A3 : 0x3ffb8e1c A4 : 0xabba1234 A5 : 0x00000010 A6 : 0x00000003 A7 : 0x00000003 A8 : 0x00000003 A9 : 0x00000002
A10 : 0x3ffb8e18 A11 : 0x0000003c A12 : 0x00000059 A13 : 0x3ffb8e14
A14 : 0x3ffb8e48 A15 : 0x00000000 SAR : 0x0000001d EXCCAUSE: 0x0000001d
EXCVADDR: 0xabba1240 LBEG : 0x4008be5d LEND : 0x4008be6d LCOUNT : 0xfffffffe

Guru Meditation Error: Core 0 panic´ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400ded89 PS : 0x00060030 A0 : 0x800deded A1 : 0x3ffe1d80
A2 : 0x3ffb85d4 A3 : 0xbaad5678 A4 : 0x3ffb85e0 A5 : 0x3ffb93c8
A6 : 0x0a0d0a0d A7 : 0x32343031 A8 : 0x800ded85 A9 : 0x3ffe1d60
A10 : 0x00000000 A11 : 0xbaad5678 A12 : 0x00000000 A13 : 0x3ffb857c
A14 : 0x00000000 A15 : 0x74000a0d SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0xbaad567c LBEG : 0x4008a530 LEND : 0x4008a546 LCOUNT : 0xffffffff

Här finns felbeskrivning av LoadProhibited, StoreProhibited:
"These CPU exceptions happen when an application attempts to read from or write to an invalid memory location. The address which has been written/read is found in the EXCVADDR register in the register dump. If this address is zero, it usually means that the application has attempted to dereference a NULL pointer. If this address is close to zero, it usually means that the application has attempted to access a member of a structure, but the pointer to the structure is NULL. If this address is something else (garbage value, not in 0x3fxxxxxx - 0x6xxxxxxx range), it likely means that the pointer used to access the data is either not initialized or has been corrupted."
Så antagligen försöker min C++ programkod läsa/skriva till en variabel som inte längre existerar (ett klassiskt C++ kodfel), som kanske skulle behöva göras static för att behållas i programminnet typ Local variable scope.
Eftersom exekveringsfelet inträffar i Core 0 (där Espressif WiFi systemkod ligger, ihop med en del av mina FreeRTOS Task) skulle jag som felsökning kunna flytta alla mina Task till Core 1 temporärt. Följer då felet med till Core 1 så är det någon av mina Task. Då kan jag flytta en Task i taget tillbaks och när felet följer med tillbaka till Core 0 så vet jag vilken Task som orsakar det. Men hade varit lättare om det inträffade oftare!
Verkar dock som jag lyckats skapa något pekar- eller variable scope-fel i min senare kodning nu! Känns bara lite konstigt att det inträffar så sällan med många timmar emellan!
Nu senast LoadProhibited med EXCVADDR: 0x00000005.
Får även senare framöver titta på Get started with Arduino and ESP32-DevKitC: debugging and unit testing!
Även kanske om problemen fortsätter: Please build project in debug configuration to get more details about an exception, ihop med PlatformIO meny: PROJEKT TASKS - wemos_d1_uno32 - General - Monitor (kan det vara "IDF Monitor"?).
2023-03-30
Man ska inte använda färdiga kopplingssladdar till breadboards för strömförsörjningen till sin ESP32!
Har nu lokaliserat ett problem jag fick efter den senaste större kodförändringen till dålig kontakt och glappkontakt i just en sådan som går mellan min DC-DC-konverter och ESP32! Trodde naturligtvis jag fått till någon dum bugg i min kod, men hittade glappkontakt och sannolikt även dålig kontakt i den kopplingstråden. Sedan är det nog även något typ pekarfel i min C++ kod!
Samt efter de senaste kodförändringarna har ESP32 fått svårt att återansluta till WiFi / Webbserver, så något blev inte bra där!
Backar därför till senaste version jag märkt OK (2023-03-14), och där fungerar det bra igen. Så blir att återinföra förändringar sedan dess en i taget och checka när problemet uppstår. Går lätt via "Compare Selected" i PlatformIO / VSCode där jag får upp de två filer jag jämför sida vid sida med alla skillnader utmärkta, så bara kopiera kod mellan dem steg för steg via den pil-icon-kopieringsfunktionen som finns där. Blev två steg fram ett tillbaka nu, som det blir ibland!

VSCode "Compare Selected"
VSCode "Compare Selected"

2023-03-31
Haft version 2023-03-14 i drift idag i drygt 8h med aktiv WiFi / Webbserver utan något problem. Har då modifierat koden så jag på Serial.print bara får ut debug- och felinformation, så det är lätt att följa vad som händer. Så denna versionen verkar helt OK och stabil!
Är inget minnesläckage heller under den tiden med: Fri SRAM 52% (161660b), Lägst ledig heap: 135324b samt Största allokerbara heap 110580b.
Så noga under så lång tid har jag inte följt upp kodexekveringen förut, även om jag haft igång den i flera dygn tidigare. Men ville nu vara säker på att jag utgår från en stabilt fungerande kod för felsökningen av senare tillagd kod!
Känns skönt, för då ska det lättare gå att hitta buggen / buggarna i den kod jag successivt återinför steg för steg nu igen.
Även om det känns lite märkligt att ett typ pekarfel kan inträffa så glest som 3-4h eller längre tid med programkoden exekverandes 1ggr/1,1s! Men är delvis asynkrona kodloopar med FreeRTOS Task ihop med att lite olika kod exekveras beroende på mätt batteriström, så kanske någon kombination kan uppstå så sällan då? Samt har bara hänt när WiFi / Webbservern är aktiva, så är i någon kod som bara exekveras då så har mina aningar var jag ska se upp lite extra när koden återinförs steg för steg! Detta är lärpengar som ny på objektorienterad C++ kodning!
Får läsa på lite mer om det, som typ: Grundläggande objektorienterad programmering i C++: Klasser och objekt, Creating a class object in C++, References to the class object. Access to a class object by reference., DuckDuckGo: C++ "class" "object" new pointer vs reference, DuckDuckGo: C++ new reference "class" "object", Static Objects in C++, Static Members of a C++ Class.
Ser ut som att jag missuppfattat någon nyans där och bör modifiera min C++ OOP-kod?
W3school testing C++ OOP coding.
2023-04-01
Justerade C++ OOP-koden för alla class-object så den säkert inte allokeras i stack-minnet utan i heap, men blev samma kodkrascher ändå med koden för class RingBuffer24hr:
[746963][D][WiFiGeneric.cpp:931] _eventCGuru Meditation Error: Core 0 panic´ed (IntegerDivideByZero). Exception was unhandled.
Guru Meditation Error: Core 0 panic´ed (LoadStoreAlignment). Exception was unhandled. EXCVADDR: 0x401057be LBEG
Vid aktivering av strömsparläge light-sleep?
[747746][D][WiFiGeneric.cpp:931] _eventGuru Meditation Error: Core 0 panic´ed (IntegerDivideByZero). Exception was unhandled.
Kom efter: Uptime: 00y00m00d 00:12:26, med 12 minuters tid till aktivering av strömsparläge light-sleep!
2023-04-02

Upptid, datum/tid ESP32 / Client
Upptid samt datum/tid ESP32 / Client.

Återinförde all kod utom den som gör statistiska beräkningar inom class RingBuffer24hr och då fungerar det stabilt inklusive Time-displayen med Uptime och datum! Så kodbuggen finns i den koden för statistiska beräkningarna inom class RingBuffer24hr eller dess SSE-skickande till webbsidan. Så får gå igenom koden för varje sådan statistikdata där och införa en och en tills jag hittat kodfelet. En hyfsat rimlig uppgift!
Skönt jag fått stabil drift igen så långt med koden!
Konstaterar samtidigt så tomt det känns med bara rå mätdata med frånvaro av den omgjord till information s.k aggregerad data! Så min vision kring detta är helt rätt och värt arbetet!
Och efter Uptime: 00y00m00d 01:35:34 kom det igen:
Guru Meditation Error: Core 0 panic´ed (LoadProhibited). Exception was unhandled. EXCVADDR: 0x00000005 LBE
Kommer så jäkla sällan, så svårt att veta vilken kodförändring som orsakar det!

2023-04-03
Ska nog bara ha egen kod i Core 1 då man dels annars drabbas av komplexiteten av "ESP32 inter-processor communication" vad det gäller access till globala variabler med konflikt om man inte skapar exklusiv access via Semaphore-Mutex, dels kör Espressif all systemfunktion med WiFi på Core 0 som man riskerar att störa. Är risk det är bl.a. detta jag har haft problem med!
Provar nu att köra alla mina Task på Core 1.
Har tänkt att float- och int-variabler accessas inom en klockcykel så ingen risk för kollision där, men kan ju bli det när en global sådan variabel accessas samtidigt från de två olika CPU-kärnorna! Så ett lite feltänk pga oerfaren inom Multitasking- / Mulitecore-kodande!
Samt får nog även kolla att jag ger exklusiv access till globala double-variabler då de tar två klockcykler att accessa, samt troligen samma till alla class-object instanser (eller bara dess funktioner()?) i min Multitasking-koddrift!
2023-04-04

Time To Go för 24hr och 1hr medelström.
Time To Go för 24hr och 1hr medelström.
Uptime 2023-04-07.
Uptime 2023-04-07.

Nu har jag återställt all kod samt, fixat några små buggar, optimerat lite kod samt gjort lite Code refactoring, ihop med att all min kod nu körs på Core 1. Och nu ser det ut att arbeta stabilt och bra utan kodkrasch, i vart fall i ett par 3-4 timmar pass.
Har även omprövat min tidigare åsikt och redovisar nu "Time To Go" antingen som ddhh eller hhmm, dvs gått ifrån att visa timme som minsta mått utan tar även minuter så man får lite mer upplösning på det. Man får se det som tid kvar till att batterimonitorn når 100% SOC, vilket kan skilja något från batteribankens verklighet.
Kommer framöver för 24hr Time-To-Go statistiskt analysera hela dess datamängd och få en lite bättre prognos som aldrig bör komma fram till en fulladdad tid mitt i natten! Blir även senare liknande för löpande 7 dygns statistik!

2023-04-07
Har fått in lite mer 24hr data, samt framförallt kunnat kör 1dygns och 17h stabil drift nu. Här ser man tydligt nyttan av 24hr Time-To-Go prognos över 1hr Time-To-Go prognos tidig morgon med bara en ytterst svag laddström ännu. Samt jag tycker det är smidigt med "24hr ΔCHARGE" som visar hur laddningen i batteribanken har förändrats under senast 24 timmarna, så man själv inte behöver memorera något sådant eller läsa av ur diagram. Ger en bra bild över utvecklingen av batteribankens laddstatus så man speciellt i sämre väder kan planera sin drift bättre.
Denna 24hr statistik baseras på 40.000.000 mätvärden / dygn av spänning, ström och effekt till/från batteribanken, så fångar även upp snabba förändringar för hög precision.
Är det VOLTAGE, POWER, DISCHARGE & SOC som också ska få sina 24hr data, vilket den mesta C++ OOP-koden redan är kodad för.
Ska senare bli en lika dan dashboard för "Latest 7days running statistics"!

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Latest 24hr running statistics

2023-04-10

Upptid, datum/tid ESP32 / Client
Upptid & datum/tid ESP32 / Client.

Har nu passerat 5 dygns uptime, när detta skrivs 00y00m05d 06:43:11. Så det visar på hög exekveringsstabilitet. Det motsvar ca 412.000 programloopsexekveringar, så alla kombinationer borde ha hunnit uppstå då som kan leda till kodkrasch tänker jag.
Är lite av en milstolpe för 24/7/365-drift känner jag!
Är bara att koda vidare för att VOLTAGE, POWER, DISCHARGE & SOC också ska få sina 24hr data, vilket den mesta C++ OOP-koden redan är kodad för.

2023-04-12
Nu är "Dashboard - Latest 24hr running statistics" färdigkodad och i drift, vilket känns skoj! Hann dessförinnan nå drygt 7 dygns kontinuerlig drift som är rekordet hittills.
Kan även konstatera att objektorinterad programmering (OOP) är bara så bra och smidigt, samt att jag trivs bra med att koda i C/C++ som ger väldigt snabb prestanda och minnessnål kod!
I Computer Sweden´s De 10 mest populära programmeringsspråken i april 2023 ligger C på 2:a och C++ på 4:e plats i populäritet, så är populära hos många.

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Latest 24hr running statistics

2023-04-16
Fick tips om IoTPlotter som "is a service which collects data from your IoT devices for long-term graph plotting and storage, completely free" där jag enkelt skulle kunna komma igång snabbt med att få upp data i diagram som jag når ifrån hela Internet. Som ett första steg innan jag kodat eget till mina egna webbsidor på Internet.
Men ska först göra ett snabbt test om jag inte lite enkelt kan skicka data till min egna webbsite.
Även fått tips att använda Grafana på egen server hemma för att visa aggregerad mätdata i olika dashboards som är lätta att tyda. Får kolla upp om det även går på min webbplats inhyrd på webbhotell! Grafana ser fint ut och har spanat in det för rätt länge sedan då Grafana kan ge fina grafiska dashboards.
Samt en som via Zabbix gjort egen monitoring från Victron-enheter i sin båt.
Själv skulle jag i framtiden vilja använda MQTT med en tidsdatabas typ InfluxDB + MQTT.
Samt för egen grafisk display ser LVGL - Light and Versatile Graphics Library trevligt ut.
2023-04-17
Testkört min kod som utvärderar batteribankens Coulomb(Ah) och Energy(Wh) verkningsgrad i batterimonitorn. Än så länge med manuell aktivering för fulladdat batteri vid en "Tail current" på ca 0,005C (0,5%) laddström vid 13,8V aktivt reglerad float-laddning.
Vid cykling 100%-98%-100% SOC blir Coulomb(Ah)-verkningsgraden 48% för mitt gamla blykol-startbatteri jag använder i experiment solcellssystemet här hemma. Utgör den cykling min mobil-laddning ger.
Är betydligt bättre verkningsgrad än jag trodde för den lilla marginella cyklingen. Vid automatisk mätning av verkningsgraden senare ska det bara göras för de urladdningscykler som batteriet nått <90% SOC för att ge vettiga värden är tanken.
Denna aktuella verkningsgradssiffra kommer jag använda på ett smart sätt i batterimonitorn för att få riktigt bra precision i dess mätningar, vilket då sker med en ständigt uppdaterad aktuell verkningsgradssiffra för batteribanken.
Ska bli spännande att mäta på mina Victron lead-carbon batterier i mitt riktiga off-grid solcellssystem inom några veckor!
Här med laddströmmen 0,157A för 44Ah batteriet under aktiv float-laddning är det 0,0036C dvs ca 1,4ggr marginal mot 0,005C för Tail current! Är också något jag kunde övervaka för stabil robust funktion / drift, och till en början följa upp när i skarp drift. Nu under några dygn mätt till >1,5ggr lägsta ström vid aktiv float-laddning!
Inspiration / referens:
AI-felsökning i 5G-mobilnätet med maskininlärning visar hur analys av stora datamängder ger fördel!
Batteribolaget: "Tur-och-retur-verkningsgrad (urladdning från 100% till 0% och tillbaka till 100% laddning) hos det genomsnittliga blybatteriet är 80%. Motsvarande för ett LFP-batteri (LiFePO4) är 92%. Laddningsprocessen hos bly-syra batterier blir särskilt ineffektivt när 80% laddningstillståndet har uppnåtts, vilket resulterar i 50% effektivitet eller till och med mindre i solcellssystem där flera dagars reservenergi krävs (batteritid i 70% till 100% laddat tillstånd)."
TAO Performance: A complete Energy Management System
UPS VRLA lead acid battery predictive maintenance.

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Operational data
OBS! EFFIENCY siffrorna (99) & (97) är bara fake ännu.

2023-04-21
Nu vid 17-tiden blev en ny laddcykel klar vid Tail-current <0,005C (0,5%) och aktiv float-laddning i mitt gamla 44Ah blykol-startbatteri jag har i mitt lille experiment solcellssystem. Urladdade till 96% SOC laddnivå denna gången igår kväll vid laddning av urladdad mobil.
Fick då mätt av min ESP32 batterimonitor batteriverkningsgrad 75% nu mot 48% när jag cyklade till 98% SOC, vilket är riktigt bra för så minimal 4% DOD cykling. Det blykol-startbatteriet är från 2016, så indikerar att det är rimligt fräscht fortfarande märkligt nog men naturligtvis krävs det djupare urladdning för att avgöra det mer säkert.
Energiverkningsgraden 58% är inte helt OK mätt ännu, då jag har någon överledning / störning i hårdvaran vid låga effekter så den mäter fel där. Men vet ungefär vad jag ska ändra på hårdvarumässigt, dock valt att få programkoden rimligt färdig först.
Men programkoden verkar fungera fint som tänkt i att utvärdera batteriverkningsgrad!
(Siffrorna (99) / (97) är bara fake ännu, men ska bli något medelvärde över tid.)
Nästa steg är att lyckas koppla upp mot befintlig PWM-regulator så jag får en automatisk detektering av Tail-current 0,005C vid aktiv float-laddning för synkning mot 100% SOC fulladdad blybatteribank.

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Operational data
OBS! EFFIENCY siffrorna (99) & (97) är bara fake ännu.

2023-04-27
Infört en synkningsrutin för 100% SOC mot fulladdad batteribank vid grundare urladdningar där inte batteriverkningsgrad beräknas. Kom på en smart algoritm där som ger en noggrann synkning av 100% SOC mot fulladdad batteribank, utan några kepiga svåra inställningar! Får fundera på om den kunde användas för all 100% SOC synkning?
Utvärdering av batteribankens coulomb-verkningsgrad (Ah) är intressant data att ta del av, men främst är det viktig data för hög precision i batterimonitorns mätning av SOC/Ah-laddningsnivå status i batteribanken! Coulomb-verkningsgraden blir löpande utvärderad så den fås för aktuellt driftsmönster och batteritemperatur för bästa precision. På så sätt får man hela tiden aktuell batteriverkningsgrad för den typ av drift / cykling man har för sin blybatteribank samt för batteritemperatur och inverkan från åldrande batterier.
För att kunna mäta batteriverkningsgrad rimligt exakt krävs det att batterimonitorn har en bra precision i att kunna synkronisera sitt 100% SOC fulladdat mätvärde med verkligt 100% SOC fulladdat batteri, och där har jag fått till bra funktion nu.
Samt under de första tio cyklingarna kalibrerar sig batterimonitorn mot batteribanken!
Blir en helt annan precision än om man som användare ska försöka mata in ett fast sådant värde själv för batteriverkningsgrad som inställning!
Ska man uppnå en bra långtidsstabiltet i mätningarna av batteribankens SOC/Ah-laddstatus vid längre tids partiell (PSOC) cykling krävs ett bra verkligt värde för batteriverkningsgraden för att det inte ska driva iväg, så en viktig funktion för det. Med båda LiFePO4 och AGM-blykol (lead-carbon) som tål mycket PSOC-cykling blir detta mer viktigt hos en batterimonitor än tidigare!
2023-05-08
I förrgår natt hade jag 230V 100W växelriktaren igång för att ladda ur lite så kom ned på 96% SOC laddnivå, och igår hann solen ladda det fullt igen. Hamnade då på 70,3% Coulomb­verknings­grad, vilket är jäkla bra för bara 4% DOD urladdning. I en vetenskaplig noggrann rapport mätte de upp ca 50% verkningsgrad vid cykling med 15-20% urladdning, och än sämre vid ännu grundare urladdningar hos ett fint kvalitetsblybatteri.
Så måste vara kombinationen blykolbatteri (mitt gamla Tudor High Tech Carbon Boost 2.0 startbatteri) och strömpulsad laddning från PWM-regulatorns som ger den bra verkningsgraden.

Är skoj att mäta upp och få data på, men den riktiga vinsten är i att med den datan kunna mäta urladdningsnivån (SOC / Ah-urladdning) i blybatteriet med högre precision då jag använder verkningsgraden i beräkningarna där! Här systemdata jag får ut (dock alla datavärden inte helt korrekt där då jag flera gånger laddat upp ny programkod som då stört mitt i mätningar).

Igår kväll/inatt laddade jag ur till 93% SOC så blev absorptions-laddning idag. Då denna PWM-regulator har en fast 3h absorptionstid så kom laddströmmen ned ända till 350mA (0,008C) innan växling till float-laddning, vilket är betydligt lägre än den 0,015C (1,5%, 0,66A/44Ah) Tail-current som är lämplig gräns att avbryta absorptions-laddningen vid för växling till float-laddning.
Om växling skett vid 0,015C Tail-current hade laddnivån då varit någon stans mellan 99,5-100% SOC, så absorptions-laddningen hade kommit väldigt nära 100% SOC fulladdat och bara några få 1/10-dels procent återstått att ladda via float-laddning!
Så blev en bra kvittens på att 0,015C (1,5%) Tail-current är en bra säker gräns att avbryta absorptions-laddningen vid, med god marginal mot hur låg laddströmmen kan bli under absorptions-laddningen. Visar även att 0,015C Tail-current hade avbrutit denna absorptions-laddning signifikant tidigare än dess nu fasta 3h gräns som ger lite onödig överladdning!
Ger ny intressant kunskap med en batterimonitor som mäter med så hög precision!
Så ger bra input till laddcykelstyrningen hos Nordic PV-controller.

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Operational data.
Uppmätta verkningsgrader vid grund urladdning 1,5-7% DOD.
NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Latest running 24hr statistics.
Absorptions-laddning - Volt, Amp & SOC / Discharge stämmer med varandra vid 100% SOC batteri!
Tail-current 0,015C (1,5%) 44Ah = 0,66A då Absorptions-laddning ska avbrytas.
Här kör PWM-regulatorn med fast 3h absorptions laddtid så laddar onödigt länge.

2023-05-12
Är inte bara för mig det tar tid att utveckla mjukvaran / programkoden och testa av den noga för denna batterimonitorn!
I höst skulle Volvos nya elbil EX90 börja produceras, men så blir det inte:
"– Volvo Cars behöver ytterligare tid i mjukvaruutveckling och testning och justerar den planerade produktionsstarten. Produktionen beräknas nu påbörjas under första halvåret 2024, uppger bolaget i ett pressmeddelande.
Även andra tillverkar har haft kraftiga förseningar pga tid som mjukvaruutvecklingen tar!
Nu har jag inför fälttest i mitt riktiga off-grid solcellssystem kvar att införa en meny för reset av statistikdata, två mindre funktioner som behöver en lätt optimering samt att skapa det elektriska informationsutbytet mellan befintlig PWM-regulators driftsmode och batterimonitorn. Så förhållandevis lite kvar :-)
Och även att bygga ett exemplar till av hårdvaran, men det går rätt fort!
Mätningen / utvärderingen av batteriverkningsgrad fungerar bra nu:

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Operational data.
Uppmätta verkningsgrader vid grund urladdning 1,5-7% DOD.

Hittade intressant data om nominal float-laddström för AGM-blybatterier hos Float Current Monitoring: a complete overview "Remote monitoring expertise for over four decades", samt även en lista med "Float Current behaviors to monitor"!
A good rule of thumb for VRLA is 10mA of float current for each 100Ah capacity (float at 13,5V). Vid 13,8V och +25°C gäller enligt dem:
Nominal AGM Float-current = 1.6mA/Ah ±33%, så 160±53mA/100Ah.
Eftersom AGM-blykol har något lägre laddspänning så gäller det nog för lite lägre float-spänning hos dem.

Även hittat en Ultra-High Precision Coulometry för cyklisk mätning / utvärdering av battericeller. What Coulombic Efficiency (CE) measurements mean and how they can be used to quantify cell performance.
Exploring Coulombic Inefficiency Per Hour (CIE/HR): "There´s no denying the usefulness and importance of Coulombic Efficiency. However, when comparing cells cycled under different conditions, to have a direct comparison, there´s a few things that must be considered since cell degradation depends on both time and cycle number. Things like reactions of electrolyte components will occur even if a cell is sitting on a shelf not being cycled.
The time dependence of reactions within a lithium-ion cell are challenging for meaningful comparisons of CE – which measures these reactions – where cycles take a different amount of time to complete; cells with cycles that take more time will experience more reactions per cycles. In this way, CE is understood to be a function of both cycle number and time.
"

Ger mig en tanke att jag kanske skulle addera till en antagen (uppmätt?) självurladdning för en bättre långtidsstabilitet i mätningen av SOC/Ah-laddnivå i batteribanken? Men utvärderar först från lite testdrift i mitt riktiga off-grid solcellssystem. Jag har inte någon data på blybatteriers cykliska drift från en ultra-precis batterimonitor och ej hittat någon sådan data på Internet.
Eller fångas det upp rimligt bra av mätningen av batteriverkningsgraden?
Båda dessa ger en kvittens på att jag är rätt på det med tankar kring att utvärdera olika dynamiska driftsparametrar för att få en indikation på när något blybatteri i batteribanken börjar få problem i sin batterikemi!

2023-05-16
Två intressanta rapporter som ger lite mer kunskapsinsikt kring blybattericykling i off-grid solcellssystem, samt kring hur valet av blybatteriverkningsgrad i batterimonitorn är beroende av ens egen battericykling i ett solcellssystem för att få en noggrann visning i batterimonitorn.
Dels: "Superkondensatorer kombinerat med blybatterier" (vilket man även har integrerat i blykol-batterikemin) som även har en del resonemang kring batteriverkningsgrad och Peukerts effekt.
Dels den jag läste redan för något år sedan och som även refereras till i rapporten ovan, där Trojan djupurladdnings flooded kvalitetsblybatterier cyklas med strömbelastningar aktuella i off-grid solcellssystem (C/30): "A Study of Lead-Acid Battery Efficiency Near Top-of-Charge and the Impact on PV System Design"

Det verkar vanligt att man anger 85% blybatteriverkningsgrad i en batterimonitor men för den typiska cyklingen i ett sunt dimensionerat off-grid solcellssystem blir det ofta signifikant fel enligt dessa rapporter!
"Notice also that the overall efficiency shows high values, with full charge represented by approximately 85% efficiency, a commonly used value for battery charge efficiency. More importantly, notice the dramatically lower efficiencies for the increments above about 80% state of charge, where most values are below 60% efficiency, and full charge is represented by less than 50% efficiency."
Så har man då den typiska grunda blybattericyklingen det blir i ett sunt dimensionerat off-grid solcellssystem så är 85% verkningsgrad på tok för högt för batterimonitorn, som med den då ger felvisning.
Nu tror jag att AGM-blybatterier är något lite bättre än öppna flooded blysyrabatterier på detta, men har inte sett några fakta på det.

Verkningsgraden hos ett blysyrabatteri varierar väldigt mycket beroende på omständigheterna.
Tre viktiga variabler är urladdningsdjup (DoD), temperatur och strömbelastning, men även typ av laddning har stor inverkan samt även åldrande.

Enligt rapporten ger en grund cykling på 3-4% DOD en blybatteriverkningsgrad (Ah) på 45-50% bara! När jag nu cyklat mitt gamla blykol-startbatteri i mitt lilla experiment solcellssystem med 3-4% DOD har min batterimonitor mätt upp en batteriverkningsgrad (Ah) på 70-73%! Dvs ca 1,55ggr / 55% bättre batteriverkningsgrad!
Sannolikt är det från kombinationen strömpulsad laddning via PWM-regulator (som är förstärkt av mig) samt att det är blykol-batteri. Men jag tror att det är den strömpulsade laddningen som bidrar mest till den bra blybatteriverkningsgraden!
Vid sådan grund blybattericykling ger strömpulsad laddning markant bättre batteriverkningsgrad, så det enligt mina erfarenheter i stort uppväger att PWM-regulatorn inte kan utnyttja de extra 15-25% ström som en MPPT-regulator får ut från solpanelerna under bulk-laddfasen då den typiska battericyklingen sker inom 70-100% SOC i ett off-grid solcellssystem.

Min batterimonitor jag utvecklar som ett hobbyprojekt utvärderar löpande batteriverkningsgraden vid den aktuella cyklingen man har i sitt batterisystem, så inverkan av olika urladdningsdjup (DoD), temperatur och strömbelastning samt även laddsätt kommer med från den verkliga driften. På så sätt räknar jag med att löpande kunna få riktigt bra precision i den, samt jag slipper en besvärlig inställning.
De delar av Peukerts effekt som eventuellt påverkar lite även vid cyklisk drift kommer då till stor del med som del av den utvärderade batteriverkningsgraden, så även den slipper jag ha som ett inställningsvärde.
Sedan varierar blybatteriverkningsgraden med hur djupt batteribanken cyklas, så är den utvärderad för rätt grund cykling i bra väder så kommer den inte stämma fullt ut för de mer sällsynta djupa urladdningarna i längre dåligt väder. Men bör ändå bli hyfsat bra, speciellt med tanke på att batteriverkningsgraden blir något högre vid djupare urladdningscykel så man kommer då att ha något större marginaler än batterimonitorn visar. Så utvärdering av blybatteriverkningsgraden vid grundare cykling kommer aldrig leda till någon kritisk överraskning för driften vid en mer sällsynt djupare urladdning i längre dåligt väder!
I princip skulle man kunna utvärdera den biten också efterhand som ens blybatteribank cyklas olika djupt, men just nu känner jag mig tveksam till om det är värt att komplicera programkoden med det samt att lägga energi på hur det skulle hanteras.

Incremental charge efficiency
Incremental Ah charge efficiency for Trojan 30XHS 100Ah battery at C/30

2023-05-25
En av marknadens mer avancerade och välutvecklade BMS för LiFePO4 TAO Performance BMS visar också sin driftsdata i en local dashboard via WiFi och webbläsare, precis som jag gör via webbservern i denna batterimonitorn!
Batterimonitorn använder två metoder för att synkronisera 100% SOC fulladdat till verkligt fulladdad blybatteribank, dels via tail-current under aktiv float-reglering, dels en annan speciell utvecklad mätmetod bara utifrån sina egna mätdata som blir lite som en reservmetod.
Denna reservmetod är nu testad en tid och fungerar riktigt bra! Ska optimera den lite ytterligare för att bli mer oberoende av batteribankens kapacitet (Ah) samt av hur aktuell drift är. Ger en hög precision i synkningen samt kräver inga inställningar för aktuell installation!
Tail-current metoden behövs fortfarande för att få en mer likartad utvärdering av batteriverkningsgrad, då det är blybatterierna som direkt själva talar om när de precis är 100% SOC fulladdade.

2023-06-03
Kämpar vidare med att uppnå full 365/7/24 driftsstabilitet!
Har haft fortsatt glesa kodkrascher när jag bläddrar runt aktivt mellan de olika webbsidorna med driftsdata från ESP32, där kodbiblioteket ESP32 ESPAsyncWebServer-esphome kraschar i sin programkod. Men i nattdrift med bara min egen kod i drift är det fullt stabilt!
Känns surt/motigt att det är välrenomerade kodbibliotek jag använder som skapar problem för stabil kodfunktion och inte mitt egna kodande. Interaktionen med kodbiblioteket är väldigt tydligt och rättfram, så känner mig säker på att jag inte gör fel där!
Har ökat CONFIG_ASYNC_TCP_QUEUE_SIZE från 512 till 1024 (från original 32) i AsyncTCP.h, men osäker på om det behövdes. Men har det så en tid nu som test. Gör det i xQueueCreate(1024, sizeof(lwip_event_packet_t *)) i AsyncTCP.ccp.
Har gjort en rutin som aktiverar events.close() på alla de olika instanserna där events.count() == 0 för att säkert stänga ned all SSE-kommunikation som inte är aktiv längre och behövs!
if (eventsStat.count() == 0U)
{
  eventsStat.close();
}
Det verkar göra nytta att rensa upp så! Har inte sett någon kodkrasch sedan dess relaterat till bläddrande bland ESP32-webbsidorna i webbläsaren på datorn! Men hittar inget skrivet alls om detta utan hittade close() när jag studerade alla funktioner som gick att applicera på en events från dess kodbibliotek. Har hört att vid vanlig webbsideskodning med SSE för Internet är det ett problem som uppstår ibland att inte all gammal oanvänd SSE-kommunikation rensas ut så och tillslut leder till kodkrasch då SSE blir överbelastat, att SSE anslutningarna aldrig stängs även när de borde ha stängts.
Events.close() leder till filen AsyncEventSource.cpp och inom webbutveckling finns EventSource close() method: The close() method of the EventSource interface closes the SSE connection, if one is made. Så känns som close() stänger en kvarlämnad SSE-anslutning.
Samt har optimerat free stack space för mina olika FreeRTOS Task så de har lite drygt 2000 bytes free stack under drift. Kör med god marginal nu under utvecklingen men tanken är att gå ned till ca 1000 bytes free stack space senare och slutgiltigt 500 bytes:
Task minimum free stack space (bytes):

1.TaskSetupESP32: (2628)
2.TaskDisplayViewHandler: 2032
3.TaskLCDbuttonsHandler: 2052
4.TaskWebServerESP32: 2080
5.TaskDeferredInterruptINA226: 2040
6.TaskStateMachine: 2072

Samt har även ändrat Task_DeferredInterruptIN226´s xQueueReceive() xTicksToWait från 1500 till 5000ms så den inte aktiveras för en mindre fördröjning av interrupt från INA226 pga eventuell krock med interrupt mot ESPAsyncWebServer. Har haft någon väldigt sällsynt kodkrasch som verkar vara kopplad till Task_DeferredInterruptIN226, typ 1ggr/10dygn när ESP32 webbsida visas med aktiv SSE.
Har även ändrat i TaskWebServerESP32 så att SSE-events bara max får utnyttja 450ms av 1100ms cykeltiden, mot tidigare 750ms. Ger mer ostörd tid för ESPAsyncWebServer, om det kanske är lite av problemet!
Känns dock som ett misstag att jag fortsatte med SSE (Server Side Events) för dataskickandet till webbsidorna så länge för första fälttestet i husvagnen, istället för att byta till WebSockets som jag senare fått uppfattningen är stabilare i sin funktion.
Behöver WebSockets dubbelriktade kommunikation för en webbsida med inställningar samt WebSocket kan skicka binär data.
Så når jag inte full stabiltet med dessa kodrefaktorings så får jag bita i det sura äpplet och byta till WebSockets nu, vilket jag annars gör senare efter lite test och utvärdering!
Är mer hype kring WebSocket så verkar vara mer välutvecklat därför, som bl.a. beskrivs i ESPAsyncWebServer manualen:
Limiting the number of web socket clients:
Browsers sometimes do not correctly close the websocket connection, even when the close() function is called in javascript. This will eventually exhaust the web server´s resources and will cause the server to crash. Periodically calling the cleanClients() function from the main loop() function limits the number of clients by closing the oldest client when the maximum number of clients has been exceeded. This can called be every cycle, however, if you wish to use less power, then calling as infrequently as once per second is sufficient.
void loop(){
  ws.cleanupClients();
}
cleanupClients() finns inte för SSE där!

2023-06-05
Så långt är det stabilt nu med förändringarna beskrivna ovan.
Fångade en komplett battericykling ned till 95% SOC och fick verkningsgrad utvärderad.
Blev hela 81,2% coulomb-verkningsgrad för så grund urladdning, så blykol-batteri ihop med strömpulsad laddning är helt klart en bra kombination. Ytterligare en urladdning till 97,3% SOC gav 73,4% coulomb-verkningsgrad. Jag har fortfarande en hårdvarumässig överhörning vid mätning av låga effekter, så energi-verkningsgraden blir inte rätt ännu.
Men har inte heller försökt att lösa det problemet ännu. Tror det är rätt enkelt.
Övriga data där blir mer intressant med lite fler cyklingar på rad utan kodkrasch!

2023-06-09
Hade återigen en syllsynt kodkrasch (typ <1ggr/vecka) när jag aktivt snabbt bläddrade runt bland webbsidorna från ESP32-webbservern, precis när en ny webbsida skulle visas. Nu efter 6 dygns OK funktion med mycket stresstestande. Finns inget bra sätt att felsöka så sällsynta händelser för mig. Men lite logiskt tänkande ledde till att kanske SSE anslutningen inte stängs korrekt när webbsidan stängs och avslutas, så ESP32-webbservern blir överbelastad av det (att kanske försöka skicka både SSE och ny webbsida samtidigt).
Så provat att lagt in sådan funktion nu i min webbsideskod som avslutar SSE innan webbsidan stängs. Kunde se i "Verktyg för webbutvecklare - Nätverk" i webbläsaren att utan den kodfunktionen kommer det ett Error-meddelande för förra visade webbsidans SSE-events vid sidväxling men nu med detta inlagt så försvinner det Error-meddelandet! Så känns helt rätt och kan nog faktiskt vara en orsak. Men inget jag sett något tips om eller beskrivning av - är så mycket jag själv måste lista ut kring att få SSE att fungera stabilt med webbsidorna och ESP32-webbservern!
Ser även en lite ytterligare distinkt funktion i aktiveringen av SSE på nya visade webbsidan, vilket även skett lite efter de övriga senaste förändringarna. Så en liten indirekt indikation på att kodförbättringen kanske gör nytta.
window.addEventListener("pagehide", (event) => {
  eventsource.close();
},false);
document.addEventListener("visibilitychange", (event) => {
  if (document.visibilityState === "hidden") {
    eventsource.close();
  }
},false);
Page Lifecycle API
Förhoppningsvis är det så stabilt nu att jag med denna koden kan starta fältprov i mitt riktiga off-grid solcellssystem bara jag byggt prototyp 2 färdig. Sedan är det att skicka driftsdata till webbsida på webbhotell samt att börja testa WebSocket som står på tur. Men ska först då vara off-grid aktivt lite och uppleva ESP32-batterimonitorns funktion i skarp drift.
Jag tror starkt på att ersätta SSE (Server Side Events) med WebSocket för mindre problem och mer prestanda i datautbytet mellan webbservern och webbsidan, men återstår att testa!

2023-06-14

TRMS vs Average
TRMS vs Average / Medelvärde - olika kurvform
CF: Crest Factor = Peak-value / RMS-value
D: Duty-cycle (Pulskvot)
TRMS vs Average
TRMS vs Average / Medelvärde - olika kurvform
TRMS vs Average
TRMS vs Average / Medelvärde

Att utvärdera att batterimonitorn mäter rätt strömvärde för ren kontinuerlig jämn DC likström är inte svårt, men vid olika pulsad ström blir det svårare! De mätinstrument jag har mäter TRMS och batterimontorn mäter medelvärde, vilka skiljer sig åt för olika kurvformer. Blir extra tydligt vid låga PWM-pulskvoter från PWM-regulatorn! Ska senare se om mitt digtala oscilloskop kan hjälpa mig där vid en mer slutlig utvärdering.
Men under några timmars mätning vid olika strömpulsande ser batterimonitorn ut att hålla en bra precision i strömmätningarna!
Även effektmätningen har blivit betydligt bättre efter en smärre förändring hårdvarumässigt och räknar med en signifikant förbättring när jag gör om hårdvaru-layouten så överhörning från strömpulsandet minimeras.
Nu när programkoden verkar fungera stabilt och bra fokuserar jag lite på att verifiera och förbättra hårdvaran när jag bygger protyp två nu!
Mer kunskap:
How to derive the RMS value of pulse and square waveforms
Digital Multimeters- Basic Guide, Fluke
Electronic Test Instruments: Measurement Theory

2023-06-16
Nu kört drift stabilt drygt 7dygn och gjort en massa stresstestande med en mängd aktiveringar av WiFi / Webbserver samt bläddrande mellan alla ESP32-webbsidorna! Har inte gått förut!
Så känns riktigt lovande för stabil 24/7/365-drift. Ser även att belastningen av SRAM-minnet är ytterligare stabilare nu under dessa 7+ dygn med 127096 bytes som lägsta ledigt samt i snitt ca 51% ledigt med visad aktiv webbsida!
Har haft problem med funktionen från det välrenommerade ESPAsyncWebServer-esphome biblioteket. Har dels fått hacka det lite, dels fått lista ut en del ej dokumenterade funktioner som krävs, samt fått koda en övervakning och reglering av webbserverns SSE-drift så den inte överbelastas i SSE-kommunikationen till webbsidorna som visar driftsdata.
Verkar som den senaste justeringen nu i webbsideskoden som stänger SSE precis innan webbsidan avslutas var det sista som behövdes för att kunna växla stabilt mellan webbsidorna!

NordicOffGrid™ PV Battery Dashboard
NordicOffGrid™ PV Battery Dashboard - Operational Data

2023-06-18
Fick färdigt den 2:a prototypen av ESP32-batterimonitorn idag som fungerade direkt. Testkört den en del men inte inkopplad i solcellssystem ännu. Är mer noga byggd samt med en bättre hårdvarulayout som bör förhindra överhörning från strömpulsande!
Ska göra en del mer laboratoriemässiga mätningar och analyser på ström- och effekt-mätningen på den först nu.
Sedan provköra i mitt lilla experiment solcellssystem och därefter installera i mitt riktiga off-grid solcellssystem.

ESP32 Ultra-precise Battery System Monitor
Prototyp 2, ESP32 Ultra-precise Battery System Monitor


2023-06-29
För att ytterligare minimera risken för problem mellan ESPAsyncWebServer-esphome biblioteket och min programkod har jag omslutit hela min ISR-funktions kod för INA226´s interrupt med en kritisk sektion portENTER_CRITICAL_ISR(&Mux) / portEXIT_CRITICAL_ISR(&Mux), vilken ger att "inside the critical section interrupts are disabled" källa1, källa2, källa3, källa4, atomic instruction.
Key of a critical section is that it´s not preempted. One will not get a context switch in a critical section with interrupts disabled! Vilket känns viktigt för denna ISR_INA226Batt()!
Critical sections are used as a valid protection method against simultaneous access in FreeRTOS - Critical Sections & Disabling Interrupts.
ESPAsyncWebServer-esphome lär ha interrupts för sin funktion så bör undvika störning av annat samtidigt interrupt på detta sätt, vilket jag sett extremt glesa händelser jag tolkar skulle kunna vara en interrupt "context switch" när min ISR-funktion ISR_INA226Batt() exekverar.
Men då detta har hänt typ 1ggr/2veckor tar det tid att verifiera en förbättring!
Samt det händer bara när ESPAsyncWebServern aktiveras och visar webbsidor.
Kan i vart fall inte se någon negativ effekt av portENTER_CRITICAL_ISR(&Mux) / portEXIT_CRITICAL_ISR(&Mux) i ISR för min kod-funktion!
Läs mer om Deferred interrupt context switch på webbsidan om Arduino ESP32 C/C++ kodning.
Är mycket med kodinteraktionen med RTOS att förstå sig på riktigt djupt och få känsla för!
Men samtidigt intressant och spännande att utforska.

2023-07-03
Gör nu en del mer laboratoriemässiga mätningar och analyser på ström- och effekt-mätningen på min 2:a prototyp. Ser att jag behöver justera hur jag kopplat hårdvaran då det finns lite mätavvikelse vid riktigt låga strömmar. Egentligen borde jag ha strömshunten på high-side (batteri-plus) men min nuvarande batterimonitor i off-grid solcellssystemet har den på low-side (batteri-minus), vilket är det vanliga hos batterimonitorer. Vill helst slippa en ombyggnad i elsystemet så försöker lite till med low-side! INA226 är annars mest anpassade för high-side vid dubbelriktad strömmätning.
Men mäter och provar lite olika små justeringar och lär mig INA226 i mer detalj ett tag. Får jag det tillräckligt bra nu med low-side så monterar jag in den i skarp drift i mitt off-grid solcellssystem, så fortsätter jag att optimera med protyp 1 här hemma i experiment solcellssystemet.

INA226
INA226 High- or- Low-side sensing application

2023-07-04
En liten enkel justering i hårdvarans INA226 inkoppling fixade helt mätavvikelsen vid låga strömmar och mäter nu 100% korrekt, med strömshunten ansluten low-side (batteri minus).
Är intressant att se att medan strömvisningen på labora­torie­nät­aggre­gatet fladdrar mellan 11mA till 24mA så visar ESP32 stabilt -13mA medelström mätt över 2,2s vid nattdrift. Är växlingarna mellan ESP32 light-sleep och kort full drift för avläsning av INA226-sensorn samt en blinkande LED som ger variationerna i strömförbrukning men som ligger absolut stilla som medelvärde!
Ger en väldigt behaglig stabil och precis strömvisning, samt strömvärde för beräkningar!
Har även validerat labora­torie­nät­aggre­gatets strömvisning med en bra multimeter.

2023-07-07
Köpt nytt blybatteri till mitt lilla experiment off-grid solcellssystem hemma i Lägenheten. Ska ersätta mitt gamla utrangerade 44Ah blykol-startbatteri från 2016-01-23, som inte är AGM och jag inte kan kolla syranivån i (så det inte händer en olycka med det). Det beter sig annars spännings-, ström-, laddnings- och verkningsgrads-mässigt väldigt fräscht vid mina grunda cyklingar (≥95% SoC) med värden som i stort hos ett nytt batteri. Strömpulsladdning rocks!
Det nya 12V UPLUS 90Ah Lead-Carbon (Bly-Kol) är ett "true deep cycle AGM technology" som ger ett bra kvalitetsintryck. "UPLUS Bly-Carbon batterier är utvecklade för elfordon och för att användas som ett förbrukningsbatteri i mobila och marina applikationer. Batterierna fungerar dock även bra som ett stand-by batteri." Så ska fungera väldigt bra med min drift här med mest väldigt grunda cyklingar från laddning av mobilen, nästan som standby-drift. Och samtidigt kunna fungera lite som reservkraft vid eventuellt strömavbrott.
Detta UPLUS 90Ah Lead-Carbon höll 12,60V vid leverans, vilket känns helt OK (≈90% SoC).
  • True deep cycle AGM technology-GREEN SOLUTION
  • Over 99.99% virgin lead for grid plate and active material
  • Heavy duty grid/paste design for deep cycle application
  • Maintenance free, non-spillable, valve-regulated
  • Double separator configuration: long cycle life &
    High energy density and super anti-vibration design
  • Low self-discharge for longer shelf life
SellPower Nordic AB som är generalagent för dessa i Sverige ger ett bra, seriöst kunnigt intryck och verkar noga med att bara ha kvalitetsprodukter i sitt sortiment, flera med en grön profil!
Har nu även fått ett par feedback av folk som jobbat med dem eller haft affärer ihop som säger att SellPower är väldigt seriösa och duktiga, vilket bekräftar min analys av SellPower!
Blir även bra att min fortsatta utveckling sker mot ett AGM-blykol batteri för djupurladdning till solcellssystem, så jag har rätt förutsättningar. Utökar även till dubbla solcellseffekten.

2023-07-10
Kopplat in prototyp II på mitt lilla experimentella off-grid solcellssystem i lägenheten och det fungerar fint! Förändringarna i hårdvarans layout för INA226 blev bra.
Känner av när PWM-regulatorn är i aktiv reglermode och PWM-strömpulsar s.k PV Throttle, precis som tänkt. Och i kombination med Tail-current <0,005C (0,5%) så synkar den 100% SoC mot fulladdat batteri bara så fint och exakt. Kan därmed få riktigt bra precision i uppmätning av batteri­verknings­grad och därmed även SoC / Ah-laddnivå! Vid aktiv strömbegränsande reglering ihop med 0,5% Tail-current så talar batteriet själv om när det är fulladdat.
Har därmed fått min PWM-solladdregulator och denna ESP32 batterimonitor att kommunicera med varandra, vilket behövs för riktigt bra funktion hos batterimonitorn.
PV Throttle dektekteringen fungerar från riktigt hög pulskvot, så fångar verkligen direkt PWM-strömpulsandet börjar. Så osäkerheten kring det är helt skingrad nu.
Har gjort lite speciell kodning kring detta som kvalitetssäkrar detekteringen av PV Throttling och 100% SoC fulladdad blybatteribank via Tail-current.
Men är 0,5% Tail-current ett säkert fast värde att gå på som alltid kan nås i ett blybatteri? I mitt nuvarande gamla utrangerade 44Ah blykol-startbatteri från 2016-01-23 här hemma når jag ända ned till åtminstone 0,25% Tail-current, så ger 2ggr säkerhet i detekteringen av 0,5% Tail-current!
Sedan kommer jag bygga in en övervakning av detta, så om den lägsta mätta Tail-current vid PV Throttle börjar närma sig eller överstiger 0,5% så kommer en kodfunktion justera upp den automatiskt för att säkra funktionen. En sorts inbyggd automatisk kvalitetssäkrande funktion.

ESP32 Ultra-precise Battery System Monitor
Prototyp II, Tänd Grön LED = PV Throttle ON
Och Ström < Tail-current => 100% SoC synkat


2023-07-14
Varit flera dygn utan att blivit fulladdat, men så idag blev blybatteriet 100% SoC fulladdat.
Kombinationen PV Throttle = ON och Tail-current <0,005C (0,5%) plus lite kvalitetssäkrande logik ger en riktig fin precision i avkänning av 100% SoC batteriladdnivå! Idag var det växlande soligt med moln så en svår instabil situation att detektera 100% SoC men batterimonitorn gjorde det väldigt stabilt med riktigt bra precision! Är imponerande utan att ha trimmat funktionen!
Så ett första bra steg i valideringen av den funktionen, som är så grundläggande!
Tyvärr blockerar jag utvärderingen av batteriverkningsgrad vid första 100% SoC synkningen, men såg ut att ha blivit väldigt hög verkningsgrad annars. Så är nästa spännande att se.

2023-07-15
Kodat 5st till LCD displayvyer, för SoC-data, TimeToGo 1hr/24hr, 24hr ΔCHARGE (Ah/Wh), Batteriverkningsgrad samt Cycled Discharge. Har nu totalt 21st LCD-displayvyer att bländra runt som en cirkel mellan, både som visar driftsdata och menyer för inställningar.
Kan nu även se den mesta driftsdatan via LCD-displayen av det som visas på webbsidorna.

LCD display views
LCD-display vyer över driftsdata


2023-07-16
Med prototyp II som mäter rätt även för små strömmar samt synkar 100% SoC till fulladdat batteri med hög precision utvärderades en Coulomb(Ah) verkningsgrad på hela 92% för 44Ah bly­kol­start­batteriet från 2016-01-23 strömpuls­laddat med låg ström <1A/44Ah=<0,023C. Är för 1st laddcykel över två dygn med -1,7Ah/44Ah urladdning.
Är sannolikt pga kombinationen blykol-batteri, ström­puls­ladd­ning och låg laddström, men ändå väldigt imponerande för det gamla blybatteriet! Intressant att kunna mäta nu!
Samt mätte en Energi(Wh) verkningsgrad på 87%.
Behövs dock mätningar över flera batteri­cyklingar innan man kan känna sig mer säker på dessa värden, men just nu prioriterar jag den sista justeringen i koden inför att installera i mitt riktiga off-grid sol­cells­system! Var dock skoj att se för en batteri­cykling såhär.

Prototyp II, 1st laddcykel över två dygn
Prototyp II, 1st laddcykel över två dygn -1,7Ah/44Ah => 92% Coulomb(Ah) verkningsgrad!
Samt 87% Energi(Wh) verkningsgrad.

2023-07-18
Har gjort lite kodrefaktoring, optimerat några kodfunktioner samt verifierat programkoden lite mer så den nu bör vara redo för skarpt fältprov i mitt riktiga off-grid solcellssytem! Några små verifieringar ytterligare av hårdvaran också bara samt uppdatering till samma hårdvarulayout i prototyp I som stannar här hemma i experiment off-grid solcellssystemet.
Är lättast att göra det när jag har de två prototyperna anslutna parallellt här hemma så jag kan jämföra mellan dem. Ska se om jag kan förenkla det filter jag har som gör att jag mäter strömmen för kraftigt snabbt strömpulsande rätt. Tror det men ändå lite osäker.
Har ju hittills mest lagt tiden på programkodningen, då det varit huvudutmaningen.

2023-07-19
Är jäkla spännande att få mätt batteriverkningsgraden för sitt blykolbatteri via batterimonitorn för varje battericykel (dock gammalt blykol­start­batteri från 2016-01-23 här hemma just nu)!
Både Coulomb(Ah) och Energy(Wh) verkningsgrad.

Förra battericykeln gav 92,0% Coulomb(Ah)-verkningsgrad cyklad -1,7Ah av 44Ah, till bara 97,7% SoC.
Då skedda återladdningen i bra solsken mot slutet av tiden under de två dygnen.
Återladdat med låg solcellsström <1A / 44Ah = <0,023C och mot slutet när regulatorn begränsar strömmen PWM-strömpuls­laddat.
Återladdningen vid så grund cykling sker i enbart float-laddning med min PWM-regulator.

Batteriet själv talar då om när det är fulladdat vid aktiv float-strömreglering och Tail-current <0,005C (0,5%). Samt ihop med lite kvalitetssäkrande kod så den detekteringen blir robust och stabil även i växlande solsken.
Har sett nu att detta ser ut att ske med riktigt bra repeterbar precision!
Så även batterimonitorns 100% SoC blir väldigt exakt synkad till full blybatteribank.
Här kan man se att Tail-current kommit ned ända på +0,123A vid aktiv PWM-reglering, mot 0,220A som är 0,005C / 0,5% för 44Ah batteriet.

Senaste battericykeln klar nu seneftermiddag återladdad stor del av tiden med riktigt låg ström i varierande väder med mycket molnigt slutade med 98,4% Coulomb(Ah)-verkningsgrad cyklad -1,3Ah av 44Ah, till bara 97,2% SoC.
Jag cyklar här normalt bara med laddning av min mobil.

Vid så grunda cyklingar brukar traditionella blybatterier ha urusel verkningsgrad under 50%!
Att jag får så hög här bör vara kombinationen väldigt låg laddström, PWM-strömpulsladdning och blykol-batteri.
(Samt det kräver egentligen verifiering från lite fler laddcykler för säkra siffror, och blir bättre uppmätt med urladdning <90% SoC.)

Planen är att ha denna batterimonitor inmonterad i mitt off-grid solcellssystem med Victron lead-carbon batterier senast under nästa vecka. Och där kommer då batteriverkningsgrad bara utvärderas för battericykler som går under 90% SoC!
Ska bli väldigt intressant att få mätt Victron lead-carbon´s batteriverkningsgrad under min normala aktiva drift där!
Tyvärr har jag varit rätt sjuk senaste månaderna så är en viss osäkerhet kring det om tidplanen håller.
Men programkoden (firmware) för detta är i alla fall äntligen färdig, debuggad och testad nu.

Prototyp II, 1st laddcykel över två dygn
Prototyp II, 1st laddcykel -1,3Ah av 44Ah => 98,4% Coulomb(Ah) verkningsgrad!
Samt 87% Energi(Wh) verkningsgrad.
Prototyp II, 1st laddcykel över två dygn
Prototyp II, 1st laddcykel -1,3Ah av 44Ah => 98,4% Coulomb(Ah) verkningsgrad!
Samt 87% Energi(Wh) verkningsgrad.

2023-07-21
Senaste laddcykel över ett dygn gav 100% Ah-batteriverkningsgrad (!) för -1,6Ah/44Ah cyklad urladdning och 96,5% SoC. Så antingen någon liten felmätning av pulsad ström eller möjligen att det skett lite ytterligare desulfatering, för 100% verkningrad har det absolut inte. Är extremt känsligt när man mäter såhär väldigt grunda urladdningar, så blir intressantare sedan för drift i mitt riktiga off-grid solcellssystem.
Lägsta Tail-current sjönk något ytterligare ned till omkring 105mA (≈0,0024C), vilket tyder på lite ytterligare gjord desulfatering i batteriet av strömpulsandet.
Är svårt att verifiera att batterimonitorn mäter pulsad ström med tillräckligt bra noggrannhet vid PWM-strömpulsad laddning! Ska se om jag kan verifiera det bättre med mitt digitala oscilloskop som jag tror kan mäta medelspänningen över strömshunten för pulsande ström.
För båda de senaste dygnens kompletta små laddcyklar har medelströmmen under 24h varit +8mA/+9mA, så en väldigt liten mängd "bortslösad" ström som förlust i blykolbatteriet!
Visar att blybatterier kan arbeta betydligt mer effektivt än de allmänt beskrivs som. Innebär sannolikt i stort noll gasning och bara lite ström till desulfatering, cellbalansering och förluster.
Strömpulsladdning ger extremt låg gasning som en av flera fördelar!
Har inget noterbart minnesläckage (memory leak) under 2-3 veckors drift:
ESP.getMinFreeHeap(): 132004 bytes (lägsta sedan start)
ESP.getMaxAllocHeap(): 110580 bytes (största fritt minnesblock)
ESP.getFreeHeap() / ESP.getHeapSize(): 50-51% Wifi+Webserver ON, 74% Wifi+Webserver OFF

2023-07-23
Kodat en adaptiv funktion som hanterar Tail-current gränsvärdet (0,005C / 0,5%) så det vid behov justeras upp automatisk efter blybatteriernas funktion så en robust stabil synkronisering av 100% SoC till fulladdat blybatteri alltid kan göras utifrån Tail-current.
Sedan finns det en reservmetod som också synkroniserar 100% SoC med bra precision, men inte tidsmässigt lika exakt för bra beräkning av batteriverkningsgrad.


2023-07-28
Mätt upp strömförbrukningen för Mobil 4G Router Teltonika RUT241 vid uppkopplad drift, som då drar ≈90mA i snitt från 12,5V. Motsvarar i 24/7-drift ca 2Ah/dygn, vilket känns överkomligt.
Optimerade / förenklade även filtret för strömsignalen för korrekt mätning av pulsad ström. Då jag hade både version I & II inkopplade samtidigt kunde jag jämföra och med modifieringen blev mätningen något lugnare men gav ändå i stort samma strömvärden. Jag bedömmer att det blev något bättre noggrannhet för små strömvärden under ca 150mA för 60A/60mV strömshunten.
Ska senare försöka göra än mer noga utvärdering via digitalt oscilloskop som kan mäta medelvärdet för kontinuerligt pulsande. Men vill komma i provdrift nu i fält!

2023-07-29
Installerat protype II i mitt off-grid solcellssystem i husvagnen för riktig fälttest.
Fungerar väldigt bra och ger en riktigt fin driftsöversikt över AGM-blykol batterierna. Vistades där i två dygn och kunde verifiera att de två olika Time-To-Go prognoserna (från 1hr / 24hr statistik) är riktigt bra och fungerar som tänkt med 12V kylskåpskompressorns intermittenta drift med ca 25% av tiden aktivt igång! Fick fint stabila drifttidsprognoser, både för 24hr dygnsdriftens längre tid och aktuell korttids laddningsprognos baserat på senaste 1hr strömstatistik.
De kompletterar varandra väldigt fint!
Även batterimonitorns 100% SoC synkning till helt fulladdat batteri fungerar med väldigt bra repeterbar precision, så riktigt imponerande! Även vid snabbt växlande soligt / molnigt väder!
Visar nu även i PV Battery Dashboard om PV Throttle är ON/OFF (om aktiv strömbegränsad reglering i solladdregulatorn), via grön färgmarkering (ON) av cirkeldiagrammets centrum där:

PV Throttle ON/OFF indikator
PV Dashboard indikerar om PV Throttle är ON/OFF

2023-08-01
Vid passiv standby-drift i mitt lilla experiment off-grid solcellssystem här hemma med gammalt 44Ah blykolstartbatteri (än så länge) så blir dygnsladdningen för helt fulladdat blybatteri ca +0,140Ah/24h, ca +6mA i medelström. Är baserat på senaste uppmätt 24h medelström.
Är imponerande lite strömförbrukning, speciellt med tanke på att en Battery Reconditioner (9kHz, >50A) hela tiden ligger och pulsar ström in i blybatteriet och laddar upp sig med ström från blybatteriet. Kan finnas ett mindre mätfel för strömmen när PWM-regulatorn strömpulsar, vilket jag ska mäta upp och analysera mer noga senare och så ifall justera filtret för.

2023-08-03
Stämt av att tidmätningen via esp_timer_get_time() 64bit tid internt i ESP32 inte bidrar med en signifikant onoggrannhet till Ah-summeringen från de samplade strömvärdena pga av avvikande CPU-klockfrekvens. Och fick som svar att Industristandard för klockkristallerna är ±20ppm, men idag är kristaller så bra att det är sannolikt inom ±10ppm. Så det är betydligt högre precision än jag får i strömmätningen, så bidrar inte till någon onoggrannhet i Ah-summeringen!
Fick även följdfrågan: "Frågan är väl också hur klockan propagerar internt i processorn? (Både mellan olika delar av hårdvaran men också exekveringstiden för olika instruktioner.)"
Som jag svarade på: Jo det är också en intressant frågeställning.
Men via esp_timer_get_time() får jag tid med µs upplösning, och tar tidsstämplingen via interrupt när INA226-sensorn signalerar att nya mätvärden finns att hämta.
Så tidsstämplingen och mätvärdena får en bra noggrannhet mot varandra.
Sedan skickas de vidare till en Deferred interrupt processing funktion som getts hög prioritet i FreeRTOS, så den exekveringen blir som en direkt förlängning på ISR-funktionen som interruptet triggar. Där hämtar jag strömmätvärdena från en buffert de är lagrade i hos INA226-sensorn, så de påverkas inte av att det tar någon lite tid.
Med µs upplösning har jag goda marginaler för tillräckligt hög tidsprecision samt allt övrigt är kodat så jag inte förstör den precisionen.
Som jag förstått det så tickar inte tiden på från esp_timer_get_time() inne i ISR-funktionen, så jag får verkligen tidsstämplingen för exakt när interruptet triggades.
Har även via 200MHz digitalt minnes-oscilloskop checkat av att interruptet med ISR sker tillräckligt snabbt.
Så jag tror jag har tillräcklig koll på den biten.
Men helt klart en viktig frågeställning också i detta sammanhanget!

2023-08-06
Var och tittade till installationen i off-grid solcellssystemet samt uppdaterade hårdvaran lite enligt det senaste här hemma. Ska ge lite mer exakt mätning av strömpulsandet från PWM-regulatorn vid spänningsreglerad laddning mot blybatteribanken.
De dryga två dygnen jag bodde där nyss när jag installerade ESP32-batterimonitorn där gav lite intressanta första mätvärden och driftsstatistik nu när batteribanken hunnit bli fulladdad igen:
- Senaste lägsta SoC: 75,7% (motsvara ca -51,5Ah)
- Senaste cyklade urladdning: -81,1Ah
- Batteriverkningsgrad Ah: 94,0%
- Batteriverkningsgrad Wh: 88,2%
- Low Tail current: ca 0,14% / 0,0014C
Under de dryga aktiva två dygnen boende blev batteribanken inte fulladdad, men en hel del laddades tillbaka i det växlande solskenet dagtid. Så därför senast lägsta SoC bara motsvarar -51,5Ah urladdat medans "Senaste cyklad urladdning" blev -81,1Ah då den räknar all cyklad urladdning tills fulladdat igen. Är en intressant siffra tycker jag!
Den mätta Batteriverkningsgraden känns bra för några dygns aktiv drift ihop med några dygn till tills fulladdat i det mulna vädret, men de mätningarna kommer troligen påverkas lite av den justering jag gjorde i hårdvaran idag. Samt tror det skiljer lite vid första aktiva drift såhär efter en längre passiv standby-drift mot vid en lite längre aktiv drift med flera fulladdningar under tiden.
Men för blybatteri är de verkningsgraderna riktigt bra vid denna battericyklingen, så märks den är signifikant bättre hos AGM-blykol batterier!

ESP32-batterimonitor driftsstatistik
ESP32-batterimonitor driftsstatistik

2023-08-10
Har förbättrat mätningarna av PWM-solladdregulatorns 30Hz strömpulsade laddning så ESP32 via INA226 nu samplar spänningen över strömshunten i 3,5kHz just när det är PWM-strömpulsning. Det är max vad INA226 kan prestera! Använder då Conversion time 140µs och Averaging 1024 st mätningar. Så 1024st mätningar medelvärdesbildas i INA226 innan interrupt sätts till ESP32 så den hämtar den datan ur bufferten.
Innebär ca 117 samplingar per 30Hz pulsperiod samt medelvärdet för ca 35st 30Hz pulscykler, ihop med en RC-filter tidskonstant på 0,31ms dvs i storlekordning för 1% Duty-cycle.
Så skulle helst velat upp i 2-5ms RC-tidskonstant!
Samplar då kontinuerligt i ca 3,5kHz och mätt att ESP32 hinner med att hantera detta i helt jämn takt med INA226 med nya data var 292:a ms, även när driftsdata förmedlas via ESP32 webbservern via WiFi till webbsida på datorn.
Gör detta bara då ESP32 detekterar att PWM-solladdregulatorn strömpulsar, annars samplas med ca 450Hz dvs blir 7,8ggr oftare såhär.
Jag tycker det märks skillnad, dels så varierade strömvärdet signifikant mer förut (vilket jag trodde var PWM-regulatorn som var lite orolig i regleringen), dels har jag idag haft ett par gånger när solinstrålning minskat långsamt från fullt solsken så PWM-regulatorn växlat mjukt från strömpulsande till jämn DC-ström ut och det har inte gett något synbart hopp i det mätta strömvärdet vid växlingen.
Så känns som det blev bättre såhär med lite mer noggrann mätning av den strömpulsade laddningen. Känns som ett skoj steg framåt!
Impulsen kommer ifrån när jag frågat mer kunniga inom RC-filter / datafiltrering och sampling om råd på Internet. Jag är lite utanför min kunskapszon här!
Ska senare i höst försöka utvärdera det mer nog i mätning via mitt digitala oscilloskop.

2023-08-18
Håller på att i KiCad Spice simulera lite olika filterkonfiguration för strömsignalerna från ström­shunten. För optimering av funktion samt öka kunskapen och insikten kring detta.
Grönt är INA226´s sampling av mätdata ca 3,5kHz, Lila = 1% duty-cycle 30Hz PWM-strömpuls (solladdregulator), Blå = en filterkonfiguration & Röd = en annan filterkonfiguration.
Den röda kurvan sprider ut strömpulsen mjukt över längre tid så den hinner samplas fler gånger för bättre mätprecision. Att den svänger en del gör inget så länge summan (med tecken) av areorna mellan kurvan och 0V X-axeln motsvarar korrekt mätt Ah-summering dvs arean för PWM-strömpulsen, vilket det ser ut att göra. Får ju även medelvärdet för 1024 sådana samplingar som motsvarar ca 35st 30Hz cykler, så svängningen blir helt bortfiltrerad på så sätt.
Skulle vilja ha längre tidskonstant för filtret, men INA226 strömmätingångar får max ha 20-22Ω total filterresistans samt lägsta LSB mätspänning är 2.5µV som gör det svårt ihop!
Men ur detta får jag till lite ytterligare förbättrad mätprecision för strömmen vid aktiv PWM.

KiCad simulering filter
ESP32-batterimonitor KiCad simulering filter

2023-09-02
Simulerat mer med KiCad Spice och utvärderat 3st olika samplingfrekvenser mot det analoga strömsignalfiltret. Ser att den högre ca 3,5kHz samplingen är bra vid PWM-strömpulsladdning samt att en 2ggr högre samplingfrekvens än jag haft hittills samverkar bättre med filtret för mer exakt strömmätning, så ändrat till det för aktiv batteridrift. Behåller den tidigare långsammare samplingen för energisparläge vid nattdrift. Så simuleringarna har därmed hjälpt mig att både optimera programkoden i batterimonitorn och det analoga strömsignalfiltret för ökad mätprecision för strömmen! Så nu analyserar programkoden den momentana batteridriften och växlar mellan tre olika samplingfrekvenser och driftslägen automatiskt. Ser bara så fint ut!
På så sätt utnyttjar jag även INA226-strömsensorns prestanda och möjligheter optimalt.

KiCad simulering filter
ESP32-batterimonitor KiCad simulering filter

Är jäkla intressant med mitt ESP32-baserade "Ultra-precise Battery System Monitor" hobbyprojekt som mäter ström stabilt nere på mA / mAh nivå med bra upplösning!
Så kan väldigt detaljerat följa mitt utrangerade gamla (2016-01-23) startblykolbatteris drift i mitt lilla experiment off-grid solcellssystem här hemma.

Under hela sommaren har lägsta stabil TailCurrent vid fulladdat batteri och aktiv strömbegränsande reglering via PWM-solladdregulatorn sjunkit och är nu nere i ca 110mA dvs 0,25% av de 44Ah i batteriet.
Det bör innebära att PWM-strömpulsladdningen fortsätter att långsamt återbilda gammal sulfatering i blybatteriet, vilket även ström- / spännings-responsen under drift antyder.
Så vid de rätt grunda urladdningar (laddar bara mobilen) så beter sig detta gamla blybatteri som nytt ström- och spännings-mässigt! Laddar väl ur ned till ca 92-93% SoC då och då, mätt mot dess nominella 44Ah C20-kapacitet.
Har inte testat hur det reagerar vid lite djupare urladdning då det är så pass gammalt och inte till för denna typ av drift.
Jag får just nu 100% uppmätt batt­eri­verk­nings­grad vid små urladdningar som jag misstänker beror på små mätfel orsakade av långa signalkablar mellan strömshunt och INA226-sensor i den temporär ex­peri­ment­upp­kopp­ling­en här hemma. Men skulle även delvis kunna bero på att PWM-strömpulsande desulfatera blybatteriet så man via det når TailCurrent lite tidigare.

Jag har byggt ihop en kommunikation mellan min batterimonitor och PWM-solladdregulator, så batterimonitorn får väldigt exakt info om när regulator aktivt PWM-strömpulsar för att begränsa laddströmmen. Indikeras även med grön LED.
Samt använder en TailCurrent < 220mA / 0,5% vid aktiv PWM-pulsreglering som indikering för fulladdat blybatteri, vilket ger väldigt bra precision i 100% SoC synkning till fulladdat blybatteri!
Har därmed en bra marginal mot hur lågt TailCurrent går ned till i aktiv float-laddning som nu de 110mA.
Är 0,5% TailCurrent så vid aktiv strömreglerad float-laddning som indikerar fulladdat blybatteri med bra precision, vilket man inte kan få bara baserat på batterispänning + TailCurrent.

Sägs att lägsta TailCurrent så ökar hos åldrade blybatterier men är inget jag ser här eller heller sett hos min gamla fritidsblybatteribank ens vid 9 års ålder på den. Är kanske pga nyttan PWM-strömpulsladdningen gör?
Men min batterimonitor utvärderar det adaptivt kontinuerligt och anpassar helt automatisk TailCurrent gränsen uppåt för 100% SoC fulladdat blybatteri om det behövs för funktionen.

Har köpt ett nytt AGM-blykol batteri avsett för djupurladdning och solcellsdrift som även klarar av typ längre UPS-standby drift bra med fin livslängd, så bör bli perfekt här hemma.
Så ska snart flytta över mitt hemmasystem till det och får då även som lite mer riktig reservkraft här hemma på 12V 90Ah.
Samt blir lite mer korrekt blybatteridrift för solcellssystemet att utvärdera mot!
Men ser ju även med startblykolbatteriet så intressanta egenskaper blykol ger.

Kom nu vid 17:40-tiden precis ned i ca 90mA / 0,20% TailCurrent vid 5,5% Duty-Cycle PWM-strömpulsande, lägsta hittills :-)
Varit fint soligt hela eftermiddagen.


Idéer: 2023-07-04 / 2023-07-18

  • Logga tid i aktiv PWM-reglering senaste 14 dygnen. Styr 4G-router uppkoppling för datalagring på server så minst 2h/14dygn ∑ PWM-tid uppnås för AGM-blykol batteriers välmående.
    Styr 12V ström till 4G-router via enkel analys över utvecklingen under senaste 14 dygnen.
    Loggas per dygn för de 14 dygnen för att kunna analyseras bra.
    Minimum uppkoppling 1ggr/dygn och max kontinuerligt är tanken.
  • Mäta vid vilken SoC PV Throttle = ON, dvs till hur högt SoC tar batteribanken emot full laddström från solcellerna. Både senaste och som medelvärde.
    Kanske ha två styck olika mätvärden, där den ena bara mäter för en viss minsta laddström?
    Bara mäta för cyklingar <90% SoC?
  • Mätningen av µs i ESP32 är beroende av processorns klockning som kan avvika något från angiven frekven. Man skulle kunna kaliberar den mot RTC-realtid som hämtas från Internet och mäta över lite längre tid. På så sätt skulle man kunna få en kaliberingssiffra för den som kompenserar för dess avvikelse och därmed öka precisionen i summeringen av Ah / Wh över längre tid.
  • Övervaka RAM-minnet för om minnesläckage detekteras som ger kritiskt lite ledigt minne eller för mycket fragmentering av RAM-minnet, och då göra en kontrollerad hard restart där driftsdata sparar så all driftspåverkan undviks?
  • Titta över min strategi för watchdog timer i ESP32-koden:
    A Designer´s Guide to Watchdog Timers , DigiKey
    What is a watchdog timer (WDT)?, ABLIC Inc.
    Watchdog timer, Wikipedia

Länkar: 2023-06-16

Solcellsström vid svagt ljus är ett viktig tillskott!
Webpage: server time: 42.5 ms, (incl. log: 17.0 ms) ||