1. Prezentare generală
RTD Master Pro este o aplicație desktop profesională proiectată pentru conversii precise de temperatură folosind atât senzori RTD (Resistance Temperature Detector) cât și termocuple, conform mai multor standarde internaționale.
Senzori RTD
Dispozitive de măsurare precisă a temperaturii care exploatează schimbarea previzibilă a rezistenței electrice a metalelor pure cu temperatura.
Termocuple
Senzori de temperatură care generează tensiune electrică bazată pe efectul Seebeck, ideali pentru temperaturi extreme și răspuns rapid.
Aplicația implementează ecuațiile și coeficienții standardizați definiți de organizațiile internaționale de metrologie (IEC, NIST, ASTM, GOST).
2. Standarde internaționale
2.1 IEC 60751:2008
| Câmp | Valoare |
|---|---|
| Titlu | Termometre cu rezistență din platină industriale și senzori de temperatură din platină |
| Organizație | Comisia Electrotehnică Internațională |
| Domeniu temperatură (Pt) | –200°C … +850°C |
| Coeficient principal | α = 0.00385 Ω/Ω/°C (Pt385) |
| Clase de toleranță | AA, A, B, C |
| Valori standard | Pt100, Pt500, Pt1000 |
B = −5.775 × 10⁻⁷ °C⁻²
C = −4.183 × 10⁻¹² °C⁻⁴ (doar pentru T < 0°C)
2.2 GOST 6651-2009
| Câmp | Valoare |
|---|---|
| Organizație | Consiliul Interstate pentru Standardizare (țările CSI) |
| Domeniu temperatură (Pt) | –200°C … +600°C |
| Coeficient principal | α = 0.00391 Ω/Ω/°C (Pt391) |
| Materiale suplimentare | Cupru (Cu426), Nichel |
B = −5.847 × 10⁻⁷ °C⁻²
C = −4.35 × 10⁻¹² °C⁻⁴
2.3 ASTM E1137/E1137M-20
Standard nord-american pentru RTD-uri din platină industriale. Coeficientul α = 0.00385 Ω/Ω/°C (identic cu IEC 60751). Toleranțe: Grad A (echiv. Clasa A) și Grad B (echiv. Clasa B). Domeniu: –200°C … +850°C.
2.4 Standard Legacy US
Standard american istoric (pre-aliniere ASTM). Coeficient α = 0.00392 Ω/Ω/°C (Pt392). Domeniu: –200°C … +850°C.
B = −5.870 × 10⁻⁷ °C⁻²
C = −4.40 × 10⁻¹² °C⁻⁴
3. Materiale RTD și specificații
3.1 RTD-uri din platină
Cel mai comun și stabil material RTD. Linearitate și stabilitate excelente. Domeniu tipic: –200°C … +850°C (unele până la +1000°C).
| Tip | R₀ (0°C) | Aplicații comune |
|---|---|---|
| Pt100 | 100 Ω | Industrial, HVAC, control proces |
| Pt500 | 500 Ω | Laborator, măsurători de înaltă precizie |
| Pt1000 | 1000 Ω | Automotive, automatizare clădiri |
Coeficienți de temperatură:
- α₃₈₅ = 0.00385 Ω/Ω/°C — IEC 60751, ASTM E1137, DIN 43760
- α₃₉₁ = 0.00391 Ω/Ω/°C — GOST 6651
- α₃₉₂ = 0.00392 Ω/Ω/°C — Legacy US
3.2 RTD-uri din cupru
Cost redus, linearitate bună, domeniu limitat de temperatură: –50°C … +150°C (oxidare peste 150°C).
| Tip | R₀ (0°C) | Aplicații comune |
|---|---|---|
| Cu50 | 50 Ω | Monitorizare temperatură înfășurări |
| Cu100 | 100 Ω | Monitorizare motoare și transformatoare |
Coeficienți: α₄₂₆ = 0.00426 (GOST) · α₄₂₇ = 0.00427 (IEC) · α₄₂₈ = 0.00428 (producători)
3.3 RTD-uri din nichel
Sensibilitate ridicată, non-linear, domeniu moderat: –60°C … +180°C.
| Tip | R₀ (0°C) | α | Aplicații |
|---|---|---|---|
| Ni100 | 100 Ω | 0.00617 | HVAC, uz general |
| Ni120 | 120 Ω | 0.00672 | HVAC european |
| Ni1000 | 1000 Ω | 0.00618 | Automotive, electrocasnice |
4. Metode de calcul și ecuații
4.1 Ecuația Callendar-Van Dusen (RTD platină)
Metoda acceptată internațional pentru calcularea rezistenței RTD din platină în funcție de temperatură.
Pentru T < 0°C: R(T) = R₀[1 + AT + BT² + C(T − 100)T³]
Unde: R(T) = rezistența la T [Ω], R₀ = rezistența nominală la 0°C [Ω], A,B,C = coeficienți CVD
Pentru R < R₀ (T < 0°C) — ecuație cubică rezolvată iterativ Newton-Raphson, toleranță convergență: 10⁻⁶ °C
4.2 Aproximare liniară (cupru și nichel)
Calcul invers: T = (R − R₀) / (R₀ × α)
5. Specificații de toleranță
5.1 Clase de toleranță IEC 60751 (Platină)
| Clasă | Formulă toleranță | La 0°C | La 100°C | La 200°C |
|---|---|---|---|---|
| AA (max. precizie) | ±(0.1 + 0.0017|t|) °C | ±0.10°C | ±0.27°C | ±0.44°C |
| A (standard) | ±(0.15 + 0.002|t|) °C | ±0.15°C | ±0.35°C | ±0.55°C |
| B (uz general) | ±(0.3 + 0.005|t|) °C | ±0.30°C | ±0.80°C | ±1.30°C |
| C (precizie redusă) | ±(0.6 + 0.01|t|) °C | ±0.60°C | ±1.60°C | ±2.60°C |
5.2 Toleranță rezistență la 0°C — Pt100
| Clasă | Toleranță rezistență |
|---|---|
| AA | ±0.04 Ω |
| A | ±0.06 Ω |
| B | ±0.12 Ω |
| C | ±0.24 Ω |
6. Domenii de temperatură
6.1 Domenii pe standard și material
| Standard | Platină | Cupru | Nichel |
|---|---|---|---|
| IEC 60751 | –200 … +850°C | –50 … +150°C | –60 … +180°C |
| GOST 6651 | –200 … +600°C | –50 … +150°C | –60 … +180°C |
| ASTM E1137 | –200 … +850°C | –50 … +150°C | –60 … +180°C |
| Legacy US | –200 … +850°C | –50 … +150°C | –60 … +180°C |
6.2 Valori rezistență Pt100 (Pt385)
| Temperatură | Rezistență Pt100 |
|---|---|
| –200°C | 18.52 Ω |
| –100°C | 60.26 Ω |
| 0°C | 100.00 Ω |
| 100°C | 138.51 Ω |
| 200°C | 175.86 Ω |
| 400°C | 247.09 Ω |
| 600°C | 316.16 Ω |
| 850°C | 390.48 Ω |
7. Funcționalități program
7.1 Capabilități de bază
- Conversie bidirecțională Temperatură ↔ Rezistență
- Suport pentru 4 standarde internaționale
- 3 tipuri de materiale RTD (Platină, Cupru, Nichel)
- Coeficienți alpha multipli per material
- 4 clase de toleranță (AA, A, B, C) cu calcul în timp real
- Ajustare dinamică a domeniului bazată pe standard și material
7.2 Interfață utilizator
- Design modern cu secțiuni codificate color
- Fonturi mari lizibile (11–14pt)
- Selectoare dropdown intuitive
- Afișare toleranță evidențiată
- Suport multi-limbaj (Engleză, Română, Germană)
8. Implementare tehnică
8.1 Arhitectură software
| Componentă | Detalii |
|---|---|
| Limbaj | C++17 |
| Framework GUI | Qt 5.x / 6.x |
| Sistem build | qmake |
| Platforme | Windows, Linux, macOS |
8.2 Precizie calcul
- Aritmetică virgulă mobilă dublu-precizie (IEEE 754)
- Precizie numerică: ~15–17 cifre semnificative zecimale
- Toleranță de convergență Newton-Raphson: 1×10⁻⁶ °C
9. Referințe — Partea I
- [1] IEC 60751:2008 — Termometre cu rezistență din platină industriale și senzori de temperatură din platină. Comisia Electrotehnică Internațională, 2008.
- [2] GOST 6651-2009 — Termometre cu Rezistență, Senzori de Rezistență Termică. Consiliul Interstate pentru Standardizare, 2009.
- [3] ASTM E1137/E1137M-20 — Specificație Standard pentru Termometre cu Rezistență din Platină Industriale. ASTM International, 2020.
- [4] DIN EN 60751:2009-05 — Termometre cu rezistență din platină industriale (IEC 60751:2008). Institutul German pentru Standardizare, 2009.
- [5] H.D. Burns & M. Scroger — Ecuația Callendar-Van Dusen și Aplicarea Sa. Notă Tehnică NIST, 1988.
- [6] Nicholas, J.V., White, D.R. — Traceable Temperatures: O Introducere în Măsurarea și Calibrarea Temperaturii. John Wiley & Sons, 2001.
10. Termocuple — Prezentare generală
10.1 Ce sunt termocuplele?
Termocupla este un senzor de temperatură care generează o tensiune electrică (forță electromotoare termoelectrică) proporțională cu diferența de temperatură între două joncțiuni de metale diferite. Se bazează pe efectul Seebeck, descoperit în 1821 de Thomas Johann Seebeck.
- Două fire din metale diferite sunt unite la un capăt (joncțiunea de măsurare)
- Celălalt capăt este la o temperatură de referință (joncțiunea rece)
- Diferența de temperatură generează o tensiune mică (µV–mV)
- Tensiunea este direct proporțională cu temperatura măsurată
10.2 Comparație RTD vs Termocuplă
| Caracteristică | RTD | Termocuplă |
|---|---|---|
| Principiu | Rezistență electrică | Tensiune termoelectrică |
| Semnal output | Ω (Ohm) | mV (milivolt) |
| Domeniu temperatură | –200 … +850°C | –270 … +1820°C |
| Precizie | ±0.001 … ±0.1°C | ±0.5 … ±2°C |
| Răspuns | Lent (secunde) | Rapid (milisecunde) |
| Stabilitate | Excelentă | Bună (derivă în timp) |
| Cost | Mai mare | Mai mic |
| Alimentare | Necesară (curent) | Auto-generare |
| Linearitate | Bună | Non-liniară |
11. Tipuri de termocuple și specificații
11.1 Type K — Chromel-Alumel
Cel mai comun tip pentru uz general și industrial. Standarde: IEC 60584, ASTM E230.
| Parametru | Valoare |
|---|---|
| Material (+) | Chromel (90% Ni, 10% Cr) |
| Material (–) | Alumel (95% Ni, 2% Mn, 2% Al, 1% Si) |
| Domeniu temperatură | –270°C … +1372°C |
| Sensibilitate la 0°C | ~41 µV/°C |
| Cod culoare | Galben |
- + Domeniu larg de temperatură, cost redus, disponibil larg
- – Derivă magnetică peste 800°C, nepotrivit pentru atmosfere reducătoare
11.2 Type J — Iron-Constantan
Termocupla pentru industria fierului/oțelului și atmosfere reducătoare.
| Parametru | Valoare |
|---|---|
| Material (+) | Fier (Fe) |
| Material (–) | Constantan (55% Cu, 45% Ni) |
| Domeniu temperatură | –210°C … +1200°C |
| Sensibilitate la 0°C | ~52 µV/°C |
| Cod culoare | Negru |
- + Sensibilitate ridicată, cost foarte redus
- – Oxidare rapidă peste 540°C, nu pentru atmosfere oxidante
11.3 Type T — Copper-Constantan
Termocupla pentru criogenie și aplicații de laborator. Excelent pentru temperaturi joase.
| Parametru | Valoare |
|---|---|
| Material (+) | Cupru (Cu) |
| Material (–) | Constantan (55% Cu, 45% Ni) |
| Domeniu temperatură | –270°C … +400°C |
| Sensibilitate la 0°C | ~41 µV/°C |
| Cod culoare | Albastru |
- + Excelent pentru temperaturi joase, linearitate bună, rezistent la umiditate
- – Domeniu limitat (max 400°C), cuprul oxidează peste 400°C
11.4 Type E — Chromel-Constantan
Termocupla cu cea mai mare sensibilitate (output maxim ~61 µV/°C). Domeniu: –270°C … +1000°C. Cod culoare: Violet.
11.5 Type N — Nicrosil-Nisil
Termocupla modernă cu stabilitate îmbunătățită la temperaturi înalte. Înlocuitor superior pentru Type K. Domeniu: –270°C … +1300°C. Sensibilitate: ~27 µV/°C. Cod culoare: Portocaliu.
11.6 Tipuri S, R, B — Metale nobile (Platină)
Termocuple din platină pentru temperaturi foarte înalte și precizie maximă. Cost extrem de ridicat.
| Tip | Materiale | Domeniu | Sensibilitate |
|---|---|---|---|
| Type S | Pt / PtRh10% | –50 … +1768°C | ~6 µV/°C |
| Type R | Pt / PtRh13% | –50 … +1768°C | ~6 µV/°C |
| Type B | PtRh30% / PtRh6% | +200 … +1820°C | ~1 µV/°C |
12. Calcule termocuple și ecuații
12.1 Polinoame NIST ITS-90
Standardul NIST definește polinoame de înaltă precizie pentru conversia temperatură ↔ tensiune.
V = tensiune [mV], T = temperatură [°C]
Type K (0°C … 1372°C) — primii 5 coeficienți: c₀ = −0.176004136860 × 10⁻¹
c₁ = 0.389212049750 × 10⁻¹
c₂ = 0.185587700320 × 10⁻⁴
c₃ = −0.994575928740 × 10⁻⁷
c₄ = 0.318409457190 × 10⁻⁹
… plus termen exponențial
12.2 Compensarea joncțiunii reci (CJC)
Termocuplele măsoară diferența de temperatură între cele două joncțiuni. Pentru temperatura absolută, trebuie compensată temperatura joncțiunii reci.
Metode CJC: (1) baie de gheață la 0°C (laborator), (2) senzor RTD/termistor la joncțiune (industrial), (3) compensare electronică. În RTD Master Pro valoarea implicită este 25°C.
12.3 Calcul invers (Tensiune → Temperatură)
2. T₀ = 0°C
3. T_(n+1) = T_n − [V(T_n) − V_compensat] / [dV/dT(T_n)]
4. Repetă până la convergență |T_(n+1) − T_n| < toleranță
13. Utilizare termocuple în RTD Master Pro
13.1 Selectare mod termocuplă
- Deschide RTD Master Pro
- În secțiunea „Measurement Mode", selectează „Thermocouple"
- Interfața se va schimba pentru a afișa controale specifice termocuplei
13.2 Conversii suportate și exemple
| Mod | Input | Output | Exemplu Type K |
|---|---|---|---|
| T → V | Temperatură [°C] | Tensiune [mV] | 500°C → 20.644 mV |
| V → T | Tensiune [mV] | Temperatură [°C] + CJC | 20.644 mV → ~500°C |
Exemplu practic: Tensiune măsurată 35.2 mV, termocuplă Type K, joncțiune rece 23°C → Temperatură calculată ≈ 852°C.
Anexa A — Formule de referință RTD
Cu100 (Cu427): 0°C → R = 100.00 Ω R = 100 × (1 + 0.00427·T)
Ni100 (Ni617): 0°C → R = 100.00 Ω R = 100 × (1 + 0.00617·T)
Anexa B — Formule de referință termocuple
Type J: V(T) ≈ 0.05 mV/°C × T → 100°C ≈ 5.0 mV
Type T: V(T) ≈ 0.04 mV/°C × T → 100°C ≈ 4.0 mV
Notă: Acestea sunt aproximări liniare. Pentru precizie maximă, aplicația folosește polinoamele complete NIST ITS-90.
Referințe — Partea II
- [7] IEC 60584-1:2013 — Termocuple — Partea 1: Tabele de referință EMF. Comisia Electrotehnică Internațională, 2013.
- [8] ASTM E230/E230M-17 — Specificație Standard și Tabele Temperatură-EMF pentru Termocuple Standardizate. ASTM International, 2017.
- [9] NIST ITS-90 Thermocouple Database — National Institute of Standards and Technology
- [10] ASTM MNL 12, 4th Ed., 1993 — Manual on the Use of Thermocouples in Temperature Measurement.
14. Principiu de funcționare
Elementele primare de presiune diferențială (diafragme, duze, tuburi Venturi) se bazează pe principiul Bernoulli: la o constricție a secțiunii transversale a conductei, viteza fluidului crește iar presiunea statică scade. Diferența de presiune măsurată între secțiunea amonte și gâtul constricției este proporțională cu pătratul debitului.
unde: p₁, p₂ = presiuni statice [Pa], ρ = densitate [kg/m³], v₁, v₂ = viteze [m/s]
Deoarece în practică apar pierderi prin frecțiune și efecte de vena contracta, se introduce coeficientul de debit C care corectează debitul teoretic. Valoarea C depinde de geometria elementului, numărul Reynolds și tipul prizelor de presiune.
15. Standardul ISO 5167
ISO 5167 este standardul internațional pentru măsurarea debitului de fluide cu ajutorul dispozitivelor de presiune diferențială. Este structurat în mai multe părți, fiecare acoperind un tip de element primar.
| Parte | Titlu |
|---|---|
| ISO 5167-1 | Principii generale și cerințe |
| ISO 5167-2 | Diafragme (plăci cu orificiu) |
| ISO 5167-3 | Duze și tuburi Venturi-duză |
| ISO 5167-4 | Tuburi Venturi |
Standardul se aplică exclusiv curgerii monofazice în conductă plină, în regim staționar sau cvasistaționar, cu număr Reynolds ≥ 5000. Fluidul poate fi gaz sau lichid.
16. Tipuri de elemente primare
| Element | Descriere | C tipic | Pierdere ΔP permanentă |
|---|---|---|---|
| Diafragmă (Orifice plate) | Placă plană cu orificiu central cu margini ascuțite, montată perpendicular pe conductă | 0.59 – 0.65 | Mare (40–80%) |
| Duză ISA 1932 | Profil convergent ISA 1932, fără divergent | 0.95 – 0.99 | Medie (30–50%) |
| Duză rază lungă | Profil cu rază mare de curbură (ASME) | 0.95 – 0.99 | Medie |
| Duză Venturi | ISA 1932 + difuzor conic de recuperare | 0.97 – 0.99 | Mică (10–20%) |
| Tub Venturi | Convergent 21° + cilindru + difuzor 7–15° | 0.98 – 0.995 | Minimă (5–15%) |
17. Raportul beta (β) și limitele geometrice
Raportul beta este parametrul geometric fundamental al unui element primar, definit ca raportul dintre diametrul orificiului/gâtului (d) și diametrul interior al conductei (D).
| Element | Interval β recomandat | Observații |
|---|---|---|
| Diafragmă | 0.20 – 0.75 | Optim 0.3–0.6 |
| Duze ISA 1932 / rază lungă | 0.20 – 0.80 | ReD ≥ 10⁴ – 2×10⁴ |
| Tub Venturi / Duză Venturi | 0.30 – 0.75 | Lungimi drepte mai mari amonte |
Valoarea β influențează direct sensibilitatea: un β mai mic generează o diferență de presiune mai mare (semnal mai bun) dar crește pierderea de presiune permanentă.
18. Tipuri de prize de presiune (tapping)
Localizarea prizelor de presiune amonte și aval influențează coeficientul de debit. ISO 5167 definește trei configurații standard pentru diafragme.
| Tip prize | Poziție amonte | Poziție aval | Caracteristici |
|---|---|---|---|
| Prize colț | La fața diafragmei | La fața diafragmei | Uzuale pentru D mic |
| Prize flanșă | 25.4 mm (1″) de la fața diafragmei | 25.4 mm (1″) de la fața diafragmei | Cel mai răspândit |
| D – D/2 taps | 1D amonte | D/2 aval | Mai puțin sensibil la asimetrie |
19. Coeficienți de debit (C)
Coeficientul de debit C corectează debitul teoretic față de debitul real, ținând cont de contracția vena contracta, pierderile prin frecare și distribuția vitezei. Depinde de Re_D și de β.
19.1 Diafragmă — Corelația Reader-Harris/Gallagher
unde: β = d/D, Re_D = numărul Reynolds raportat la D
Corecții suplimentare în funcție de tipul prizelor de presiune:
D – D/2 taps: c₂ = 0.09 · (25.4/D_mm) · β⁴/(1 − β⁴) − 0.0337 · β³ · 25.4/D_mm
C_total = C_baza + c₂
19.2 Duza ISA 1932
19.3 Duza Venturi și Tubul Venturi
Tubul Venturi: C ≈ 0.990 − 0.005·(10⁶/Re_D)⁰·⁰⁵
Coeficientul α este legat de C prin relația α = C/√(1−β⁴), incluzând factorul de viteză de abordare E = 1/√(1−β⁴).
20. Factorul de expandabilitate ε (gaze)
La curgerea fluidelor compresibile (gaze), densitatea variază de la secțiunea amonte la gât. Factorul de expandabilitate ε < 1 corectează această variație.
unde: Δp = presiunea diferențială [bar], p₁ = presiunea absolută amonte [bar], κ = cp/cv
Condiție: 0 ≤ ε ≤ 1. Pentru lichide: ε = 1.
| Fluid | κ (cp/cv) | Observații |
|---|---|---|
| Aer (20°C) | 1.40 | Gaz biatom. Referință standard. |
| Gaz natural (metan) | 1.31 | Variabil cu compoziția. |
| Abur supraîncălzit | ~1.30 | Depinde de T și p. |
| Lichide | — | ε = 1.0 |
21. Ecuația de debit și calculul invers
21.1 Calcul direct (β și Δp cunoscute → Q)
Debitul masic: ṁ = Q · ρ [kg/s]
unde: α = C/√(1−β⁴), ε = factor expandabilitate, Δp [Pa], ρ [kg/m³]
Deoarece C depinde de Re_D, iar Re_D depinde de Q, calculul se face iterativ prin aproximații succesive (5–20 iterații).
21.2 Calcul invers — determinarea dimensiunii (Q dat → β)
Dată o țintă de debit Q și o diferență de presiune Δp, se caută β astfel încât ecuația de debit să fie satisfăcută. PDIM folosește metoda bisecției pe intervalul [0.10 … 0.80].
2. Caută β_low, β_high astfel că f(β_low)·f(β_high) < 0
3. β_mid = (β_low + β_high) / 2
4. Repetă până la convergență (|β_high − β_low| < 10⁻⁶)
21.3 Numărul Reynolds Re_D
unde: ρ [kg/m³], v = viteza în gât [m/s], d = diametrul gâtului [m], μ [Pa·s]
22. Implementare software — PDIM
PDIM este o aplicație de calcul rescrisă în C++17 ca reinterpretare modernă a programului original Turbo Pascal. Folosește ecuațiile ISO 5167 și unități SI.
22.1 Date de intrare
| Parametru | Simbol | Unitate | Descriere |
|---|---|---|---|
| Diametru interior conductă | D | mm | Diametrul interior al conductei |
| Raportul beta (mod rating) | β | — | d/D; utilizat în modul de calcul Q(β) |
| Densitate amonte | ρ | kg/m³ | Densitatea fluidului la condițiile amonte |
| Vâscozitate dinamică | μ | Pa·s | Utilizată la calculul Re_D |
| Raport călduri specifice | κ (kappa) | — | cp/cv; numai pentru gaze |
| Presiune absolută amonte | p₁ | bar | Utilizată la calculul ε |
| Presiune diferențială | Δp | bar | Diferența de presiune între prize |
| Temperatură | T | K | Informativ |
22.2 Date de ieșire
| Parametru | Simbol | Unitate |
|---|---|---|
| Raportul beta calculat | β | — |
| Diametrul orificiului/gâtului | d | mm |
| Numărul Reynolds | Re_D | — |
| Coeficientul de debit | C | — |
| Factorul de expandabilitate | ε (epsilon) | — |
| Coeficient alfa | α = C/√(1−β⁴) | — |
| Debit volumetric | Q | m³/s |
| Debit masic | ṁ | kg/s |
| Presiune diferențială (confirmare) | Δp | bar |
22.3 Moduri de calcul
| Mod | Input principal | Output principal |
|---|---|---|
| Dimensionare | Q țintă [m³/s] + Δp | β, d [mm], C, ε, α |
| Evaluare debit | β cunoscut + Δp | Q [m³/s], ṁ [kg/s], Re_D, C, ε |
Arhitectură software: C++17, g++ -std=gnu++17 -O2. Calcul iterativ pentru convergența coeficienților Re-dependenți; bisecție pentru β în modul de dimensionare. Toleranță: 10⁻¹² m³/s / 10⁻⁶ β.
Anexa C — Formule de referință rapidă: elemente primare ΔP
Coeficient α: α = C / √(1 − β⁴)
Factor expandabilitate (gaze): ε = 1 − (0.351 + 0.256·β⁴ + 0.93·β⁸) · Δp/(κ·p₁)
C diafragmă (ISO 5167-2): C = 0.5959 + 0.0312·β²·¹ − 0.184·β⁸ + 0.0029·β²·⁵·(10⁶/Re_D)⁰·⁷⁵
C duza ISA 1932: C = 0.99 − 0.2262·β⁴·¹ − (0.00175·β² − 0.0033·β⁴·¹⁵)·(10⁶/Re_D)¹·¹⁵
Re_D: Re_D = ρ · v · d / μ
Anexa D — Cod sursă: diafragme.cpp
Fişierul diafragme.cpp conține rescrierea modernă C++17 a programului original Turbo Pascal PDIM.PAS pentru dimensionarea și evaluarea elementelor primare de presiune diferențială (diafragme, duze ISA 1932, duze rază lungă, duze Venturi, tuburi Venturi) conform ISO 5167.
001// pdim_modern.cpp
002// Modern C++17 console rewrite of the Turbo Pascal "diafragme" program.
003// Focus: sizing and performance of primary differential-pressure flow elements (orifice plates, nozzles, Venturi).
004// The code uses ISO 5167-style formulae (as reflected in the Pascal source) and SI units.
005//
006// NOTE:
007// - This is a faithful *engineering* rewrite of the core calculations. The original Pascal program
008// had a large DOS GUI with graphics/printer and many fluid presets via a custom "udim" unit.
009// Here we provide a clean, portable console tool with explicit inputs.
010// - If you share the original udim unit (fluid properties), we can add a library of fluids.
011//
012// Build: g++ -std=gnu++17 -O2 -o pdim_modern pdim_modern.cpp
013//
014// DISCLAIMER: Verify against your standards (ISO 5167 parts) and your original program outputs.
015// Small differences may exist due to rounding, fluid property source, or tap corrections.
016
017#define _USE_MATH_DEFINES
018#include <cmath>
019#include <cstdint>
020#include <iomanip>
021#include <iostream>
022#include <limits>
023#include <optional>
024#include <stdexcept>
025#include <string>
026#include <tuple>
027#include <algorithm>
028
029// ---------- Types & helpers ----------
030
031enum class PrimaryElement {
032 Orifice, // sharp-edged orifice plate
033 ISA1932Nozzle, // ISA 1932 nozzle
034 LongRadiusNozzle, // long-radius nozzle
035 VenturiNozzle,
036 VenturiTube
037};
038
039enum class Tapping {
040 Corner, // corner taps
041 Flange, // flange taps
042 DD2 // D and D/2 taps
043};
044
045struct Inputs {
046 // Pipe & orifice
047 double D_mm; // pipe internal diameter [mm]
048 double beta; // d/D (ignored in "size-by-flow" mode)
049 // Process
050 double rho; // upstream density [kg/m^3]
051 double mu; // dynamic viscosity [Pa·s]
052 double kappa; // cp/cv (for gases). Use 1.0 for liquids.
053 double p1_bar; // upstream absolute pressure [bar]
054 double dp_bar; // differential pressure across primary element [bar]
055 double T_K; // temperature [K] (optional usage)
056 // Target / known flow (volumetric @ upstream conditions)
057 double Q_m3s; // volumetric flow rate [m^3/s]
058 // Selections
059 PrimaryElement elem;
060 Tapping taps;
061 bool isGas; // true for compressible expansibility; false for liquids
062};
063
064static inline double sqr ( double x ) {
065 return x * x;
066}
067static inline double pow4 ( double x ) {
068 x = x * x; return x * x;
069}
070
071// ISO 5167 alpha = C / sqrt(1 - beta^4). Some Pascal code used alfa = C * E where E = 1/sqrt(1 - beta^4).
072struct Coeff {
073 double C; // discharge coefficient
074 double eps; // expansibility (compressibility) factor (1 for liquids)
075 double alpha; // C / sqrt(1 - beta^4)
076};
077
078// ---------- Correlations from Pascal code (seen in PDIM.PAS) ----------
079// These were visible in the source you provided (e.g. 0.5959 + 0.0312*b^2.1 - 0.184*b^8 + 0.0029*b^2.5*(1e6/Re)^0.75)
080// and different c2/tapping corrections.
081Coeff orifice_coeff ( double beta, double ReD, double D_mm, Tapping taps, bool isGas, double dp_bar, double kappa, double p1_bar ) {
082 const double b = beta;
083 double C = 0.5959 + 0.0312 * std::pow ( b, 2.1 ) - 0.184 * std::pow ( b, 8.0 )
084 + 0.0029 * std::pow ( b, 2.5 ) * std::pow ( 1e6 / ReD, 0.75 );
085
086 // Tap-specific correction terms observed in PDIM.PAS
087 // (These approximate flange, corner, D-D/2 effects.)
088 double c2 = 0.0;
089 switch (taps) {
090 case Tapping::Corner:
091 c2 = 0.039 * ( pow4 ( b ) / ( 1.0 - pow4 ( b ) ) ) - 0.0337 * std::pow ( b, 3.0 ) * 25.4 / ( D_mm * 1000.0 );
092 break;
093 case Tapping::Flange:
094 c2 = 0.0; // often absorbed in the base correlation; keep zero unless we later refine
095 break;
096 case Tapping::DD2:
097 c2 = 0.09 * ( 25.4 / ( D_mm * 1000.0 ) ) * ( pow4 ( b ) / ( 1.0 - pow4 ( b ) ) ) - 0.0337 * std::pow ( b, 3.0 ) * 25.4 / ( D_mm * 1000.0 );
098 break;
099 }
100 C += c2;
101
102 const double E = 1.0 / std::sqrt ( 1.0 - pow4 ( b ) );
103
104 // Expansibility factor ε for gases. In PDIM, several forms appear; here we use a common ISO-like form.
105 double eps = 1.0;
106 if (isGas) {
107 // Use ISO-like expansibility; p1_bar, dp_bar in bar
108 const double beta4 = pow4 ( b );
109 const double term = 0.351 + 0.256 * beta4 + 0.93 * beta4 * beta4; // β^8 coefficient
110 eps = 1.0 - term * ( dp_bar / ( kappa * p1_bar ) );
111 if (eps < 0.0) eps = 0.0;
112 if (eps > 1.0) eps = 1.0;
113 }
114 return { C, eps, C * E };
115}
116
117// ISA 1932 nozzle (from PDIM patterns): C ≈ 0.99 - 0.2262 β^4.1 - (...) (1e6/Re)^1.15
118Coeff isa1932_coeff ( double beta, double ReD, bool isGas, double dp_bar, double kappa, double p1_bar ) {
119 const double b = beta;
120 double C = 0.99 - 0.2262 * std::pow ( b, 4.1 )
121 - ( 0.00175 * sqr ( b ) - 0.0033 * std::pow ( b, 4.15 ) ) * std::pow ( 1e6 / ReD, 1.15 );
122 const double E = 1.0 / std::sqrt ( 1.0 - pow4 ( b ) );
123 double eps = 1.0;
124 if (isGas) {
125 // PDIM had variants like (0.484+1.54*β^4)*dp/(k*p1). Use a robust ISO-like form for nozzles as well.
126 const double term = 0.351 + 0.256 * pow4 ( b ) + 0.93 * pow4 ( b ) * pow4 ( b );
127 eps = 1.0 - term * ( dp_bar / ( kappa * p1_bar ) );
128 eps = std::clamp ( eps, 0.0, 1.0 );
129 }
130 return { C, eps, C * E };
131}
132
133// Long-radius nozzle (simplified; many implementations reuse ISA 1932 with different constants).
134// Here we reuse ISA 1932 correlation as a placeholder; adjust if you have the exact PDIM constants.
135Coeff long_radius_nozzle_coeff ( double beta, double ReD, bool isGas, double dp_bar, double kappa, double p1_bar ) {
136 return isa1932_coeff ( beta, ReD, isGas, dp_bar, kappa, p1_bar );
137}
138
139// Venturi nozzle (placeholder: often C ~ 0.985 to 0.995 with weak Re dependence)
140Coeff venturi_nozzle_coeff ( double beta, double ReD, bool isGas, double dp_bar, double kappa, double p1_bar ) {
141 const double b = beta;
142 double C = 0.985 - 0.01 * std::pow ( 1e6 / ReD, 0.05 );
143 const double E = 1.0 / std::sqrt ( 1.0 - pow4 ( b ) );
144 double eps = 1.0;
145 if (isGas) {
146 const double term = 0.351 + 0.256 * pow4 ( b ) + 0.93 * pow4 ( b ) * pow4 ( b );
147 eps = 1.0 - term * ( dp_bar / ( kappa * p1_bar ) );
148 eps = std::clamp ( eps, 0.0, 1.0 );
149 }
150 return { C, eps, C * E };
151}
152
153// Venturi tube (classical: C ~ 0.99 ...)
154Coeff venturi_tube_coeff ( double beta, double ReD, bool isGas, double dp_bar, double kappa, double p1_bar ) {
155 const double b = beta;
156 double C = 0.99 - 0.005 * std::pow ( 1e6 / ReD, 0.05 );
157 const double E = 1.0 / std::sqrt ( 1.0 - pow4 ( b ) );
158 double eps = 1.0;
159 if (isGas) {
160 const double term = 0.351 + 0.256 * pow4 ( b ) + 0.93 * pow4 ( b ) * pow4 ( b );
161 eps = 1.0 - term * ( dp_bar / ( kappa * p1_bar ) );
162 eps = std::clamp ( eps, 0.0, 1.0 );
163 }
164 return { C, eps, C * E };
165}
166
167Coeff coeffs ( const Inputs &in, double beta, double ReD ) {
168 switch (in.elem) {
169 case PrimaryElement::Orifice: return orifice_coeff ( beta, ReD, in.D_mm, in.taps, in.isGas, in.dp_bar, in.kappa, in.p1_bar );
170 case PrimaryElement::ISA1932Nozzle: return isa1932_coeff ( beta, ReD, in.isGas, in.dp_bar, in.kappa, in.p1_bar );
171 case PrimaryElement::LongRadiusNozzle: return long_radius_nozzle_coeff ( beta, ReD, in.isGas, in.dp_bar, in.kappa, in.p1_bar );
172 case PrimaryElement::VenturiNozzle: return venturi_nozzle_coeff ( beta, ReD, in.isGas, in.dp_bar, in.kappa, in.p1_bar );
173 case PrimaryElement::VenturiTube: return venturi_tube_coeff ( beta, ReD, in.isGas, in.dp_bar, in.kappa, in.p1_bar );
174 }
175 throw std::runtime_error ( "Unknown primary element" );
176}
177
178// ---------- Flow relations ----------
179
180struct Result {
181 double beta;
182 double d_mm;
183 double ReD;
184 Coeff cf;
185 double Q_m3s; // volumetric flow [m^3/s]
186 double m_kg_s; // mass flow [kg/s]
187 double dp_bar; // differential pressure [bar]
188};
189
190// Compute flow for a given beta and dp
191Result compute_flow ( const Inputs &in, double beta, double dp_bar_override = -1.0 ) {
192 const double D = in.D_mm / 1000.0; // [m]
193 const double d = beta * D; // [m]
194 const double A = M_PI * d * d / 4.0; // [m^2]
195
196 const double dp_bar = ( dp_bar_override > 0.0 ? dp_bar_override : in.dp_bar );
197 const double dp_Pa = dp_bar * 1e5;
198
199 // We will iterate because Re depends on Q (unknown). Use a fixed-point on velocity.
200 double ReD = 1e6; // initial guess for Re used in correlations
201 Coeff cf = coeffs ( in, beta, ReD );
202
203 // Fixed-point iteration on Q
204 double Q = 0.0;
205 for (int it = 0; it < 20; ++it) {
206 cf = coeffs ( in, beta, ReD );
207 const double alpha_eps = cf.alpha * ( in.isGas ? cf.eps : 1.0 );
208 // Q = (alpha*beta^2*eps) * A_pipe * sqrt(2*dp/rho) ?
209 // From PDIM snippet: deb = (alpha * beta^2 * eps) * (pi*d2^2/4) * sqrt(2*rho*dp)
210 // Interpreting d2 as pipe diameter; here we use orifice throat area A and upstream rho.
211 const double rec = cf.alpha * beta * beta * ( in.isGas ? cf.eps : 1.0 );
212 const double Q_new = rec * ( M_PI * D * D / 4.0 ) * std::sqrt ( 2.0 * dp_Pa / in.rho );
213 // Update Re using throat velocity based on Q through orifice area
214 const double v = Q_new / A;
215 ReD = in.rho * v * d / in.mu;
216 if (std::abs ( Q_new - Q ) < 1e-12) {
217 Q = Q_new; break;
218 }
219 Q = Q_new;
220 }
221
222 const double m = Q * in.rho;
223 return { beta, d * 1000.0, ReD, cf, Q, m, dp_bar };
224}
225
226// Solve for beta (size) given target Q and dp using bisection
227Result size_by_flow ( const Inputs &in, double Q_target, double bmin = 0.20, double bmax = 0.75 ) {
228 auto f = [&] ( double b ) {
229 return compute_flow ( in, b ).Q_m3s - Q_target;
230 };
231 double lo = bmin, hi = bmax;
232 double flo = f ( lo ), fhi = f ( hi );
233 if (flo * fhi > 0.0) {
234 // Try to expand the bracket a bit
235 lo = 0.10; hi = 0.80;
236 flo = f ( lo ); fhi = f ( hi );
237 if (flo * fhi > 0.0) {
238 throw std::runtime_error ( "Unable to bracket solution for beta. Check inputs." );
239 }
240 }
241 for (int it = 0; it < 80; ++it) {
242 const double mid = 0.5 * ( lo + hi );
243 const double fmid = f ( mid );
244 if (std::abs ( fmid ) < 1e-12 || ( hi - lo ) < 1e-6) {
245 return compute_flow ( in, mid );
246 }
247 if (flo * fmid <= 0.0) {
248 hi = mid; fhi = fmid;
249 }
250 else {
251 lo = mid; flo = fmid;
252 }
253 }
254 return compute_flow ( in, 0.5 * ( lo + hi ) );
255}
256
257// Pretty print
258void print_result ( const Result &r ) {
259 std::cout << std::fixed << std::setprecision ( 6 );
260 std::cout << "beta : " << r.beta << "\n";
261 std::cout << "orifice d : " << r.d_mm << " mm\n";
262 std::cout << "Re_D : " << r.ReD << "\n";
263 std::cout << "C : " << r.cf.C << "\n";
264 std::cout << "epsilon : " << r.cf.eps << "\n";
265 std::cout << "alpha : " << r.cf.alpha << "\n";
266 std::cout << "Q : " << r.Q_m3s << " m^3/s\n";
267 std::cout << "m_dot : " << r.m_kg_s << " kg/s\n";
268 std::cout << "dp : " << r.dp_bar << " bar\n";
269}
270
271// ---------- CLI ----------
272
273int main () {
274 std::cout << "Differential-Pressure Flow Primary (modern rewrite of PDIM.PAS)\n";
275 std::cout << "Units: D in mm, p in bar, mu in Pa·s, rho in kg/m^3, Q in m^3/s, T in K.\n\n";
276
277 Inputs in{};
278 int elemChoice = 1, tapChoice = 2, mode = 1;
279 std::cout << "Primary element [1=Orifice, 2=ISA1932 nozzle, 3=Long-radius nozzle, 4=Venturi nozzle, 5=Venturi tube]: ";
280 std::cin >> elemChoice;
281 in.elem = ( elemChoice == 1 ? PrimaryElement::Orifice :
282 elemChoice == 2 ? PrimaryElement::ISA1932Nozzle :
283 elemChoice == 3 ? PrimaryElement::LongRadiusNozzle :
284 elemChoice == 4 ? PrimaryElement::VenturiNozzle : PrimaryElement::VenturiTube );
285
286 if (in.elem == PrimaryElement::Orifice) {
287 std::cout << "Tapping [1=Corner, 2=Flange, 3=D & D/2]: ";
288 std::cin >> tapChoice;
289 in.taps = ( tapChoice == 1 ? Tapping::Corner : tapChoice == 3 ? Tapping::DD2 : Tapping::Flange );
290 }
291 else {
292 in.taps = Tapping::Flange;
293 }
294
295 std::cout << "Is the fluid a gas? [1=yes, 0=no]: ";
296 int gasInt; std::cin >> gasInt; in.isGas = ( gasInt != 0 );
297
298 std::cout << "Pipe inner diameter D [mm]: ";
299 std::cin >> in.D_mm;
300
301 std::cout << "Upstream density rho [kg/m^3]: ";
302 std::cin >> in.rho;
303
304 std::cout << "Dynamic viscosity mu [Pa*s]: ";
305 std::cin >> in.mu;
306
307 if (in.isGas) {
308 std::cout << "Heat capacity ratio kappa = cp/cv [-]: ";
309 std::cin >> in.kappa;
310 }
311 else {
312 in.kappa = 1.0;
313 }
314
315 std::cout << "Upstream absolute pressure p1 [bar]: ";
316 std::cin >> in.p1_bar;
317
318 std::cout << "Differential pressure dp [bar]: ";
319 std::cin >> in.dp_bar;
320
321 std::cout << "Temperature T [K] (enter, used only for info): ";
322 std::cin >> in.T_K;
323
324 std::cout << "\nMode: 1) Size by target flow (compute beta,d) 2) Rate given beta (compute Q)\nSelect 1/2: ";
325 std::cin >> mode;
326
327 if (mode == 1) {
328 std::cout << "Target volumetric flow Q [m^3/s]: ";
329 std::cin >> in.Q_m3s;
330 // Solve for beta
331 try {
332 Result r = size_by_flow ( in, in.Q_m3s );
333 std::cout << "\n--- RESULT (size by flow) ---\n";
334 print_result ( r );
335 }
336 catch (const std::exception &e) {
337 std::cerr << "ERROR: " << e.what () << "\n";
338 return 1;
339 }
340 }
341 else {
342 std::cout << "Given beta d/D [-]: ";
343 std::cin >> in.beta;
344 Result r = compute_flow ( in, in.beta );
345 std::cout << "\n--- RESULT (rate given beta) ---\n";
346 print_result ( r );
347 }
348 return 0;
349}