ระบบโซลาร์ที่บ้านผมใช้อินเวอร์เตอร์ Deye SUN-10K-SG02LP1-EU-AM3 ร่วมกับแบตเตอรี่และ Home Assistant ซึ่งมีข้อมูลกำลังผลิต การใช้ไฟ และ Battery State of Charge หรือ SOC อยู่แล้ว

สิ่งที่ผมต้องการเพิ่มคือการควบคุมเพดานกระแสชาร์จตามช่วงการทำงานของแบตเตอรี่:

  • เมื่อโซลาร์เริ่มผลิตในแต่ละวัน ตั้งเพดานกระแสชาร์จเป็น 130A
  • เมื่อ SOC >90% ลดเพดานเหลือ 110A
  • คง 110A ไว้จนถึงการเริ่มผลิตในวันถัดไป
  • ทุกครั้งที่เปลี่ยนค่า ต้องอ่านกลับยืนยันก่อนรายงานว่าสำเร็จ

เป้าหมายของผมคือใช้กระแสชาร์จในระดับค่อนข้างอนุรักษ์นิยม และลดเพดานลงอีกเมื่อแบตเตอรี่ใกล้เต็ม โดยไม่เพิ่มการสื่อสารกับ logger เกินความจำเป็น บทความนี้อธิบายทั้งเหตุผลด้านแบตเตอรี่ การออกแบบระบบควบคุม และข้อจำกัดที่ต้องแยกให้ออกจากผลการทดสอบจริง

1. เริ่มจากความจุแบตเตอรี่และ C-rate

แบตเตอรี่มีสามลูก ต่อขนานกันที่ระดับแรงดันระบบเดียวกัน:

แบตเตอรี่ความจุ
ลูกที่ 1280Ah
ลูกที่ 2280Ah
ลูกที่ 3314Ah
รวม874Ah

C-rate ใช้บอกว่ากระแสชาร์จสูงแค่ไหนเมื่อเทียบกับความจุแบตเตอรี่ วิธีคำนวณคือ กระแสชาร์จ (A) ÷ ความจุตามพิกัด (Ah) แล้วแสดงผลเป็นจำนวนเท่าของ C

สำหรับ bank 874Ah กระแสที่เทียบเท่า 0.2C คือ 0.2 × 874 = 174.8A

เพดานกระแสชาร์จการคำนวณC-rate ของ bank
174.8A174.8 ÷ 8740.200C
130A130 ÷ 874ประมาณ 0.149C
110A110 ÷ 874ประมาณ 0.126C

ทั้ง 130A และ 110A จึงต่ำกว่า 0.2C เมื่อเทียบกับความจุรวมตามพิกัดของทั้งชุด แต่ยังไม่ใช่การยืนยันว่ากระแสที่ไหลเข้าแบตเตอรี่แต่ละลูกมี C-rate เท่ากัน

หากกระแสแบ่งตามสัดส่วนความจุอย่างสมบูรณ์ จะได้ประมาณนี้:

แบตเตอรี่กระแสเมื่อรวม 130Aกระแสเมื่อรวม 110A
280Ah ลูกที่ 141.6A35.2A
280Ah ลูกที่ 241.6A35.2A
314Ah ลูกที่ 346.7A39.5A

ตารางนี้เป็น แบบจำลองเพื่ออธิบาย ไม่ใช่ค่าที่วัดจริง การแบ่งกระแสขึ้นอยู่กับความต้านทานภายใน สาย จุดต่อ SOC และพฤติกรรมของ BMS แต่ละลูกด้วย

เงื่อนไขสำคัญอีกข้อคือ แบตเตอรี่ทั้งสามลูกต้องยังเชื่อมต่อและรับกระแสอยู่ หากเหลือเพียงสองลูกขนาด 280Ah ความจุจะเหลือ 560Ah และ 130 ÷ 560 ≈ 0.232C ซึ่งสูงกว่า 0.2C ทันที

ดังนั้นข้อความว่า “ต่ำกว่า 0.2C” มีเงื่อนไขว่าความจุทั้ง 874Ah ยังอยู่ในระบบและพร้อมรับการชาร์จ ตัวควบคุมรุ่นนี้ยังไม่ได้ตรวจจำนวนแบตเตอรี่ที่ออนไลน์แล้วคำนวณเพดานใหม่อัตโนมัติ

2. ทำไมผมเลือกใช้แนวคิดไม่เกิน 0.2C?

บน nameplate ของแบตเตอรี่ 280Ah ที่ใช้อยู่ ระบุ Normal Charge ที่ 56A ซึ่งเท่ากับ 56 ÷ 280 = 0.2C ผมจึงใช้ 0.2C เป็นจุดอ้างอิง แล้วเลือกเพดานรวมต่ำกว่านั้นอีก คือประมาณ 0.149C ในช่วงแรก และ 0.126C เมื่อ SOC สูง

0.2C เป็นเกณฑ์ออกแบบที่ผมเลือกสำหรับระบบนี้ ไม่ใช่ข้อกำหนดสากลว่า LiFePO₄ ทุกชนิดต้องชาร์จไม่เกิน 0.2C ตัวอย่างเช่น คู่มือ Lithium NG ของ Victron แนะนำกระแส 0.5C สำหรับผลิตภัณฑ์ของตน ค่าที่เหมาะสมจึงต้องอ้างอิงแบตเตอรี่แต่ละรุ่น — Victron Lithium NG: Charging and recommended settings

ในระบบบ้าน ผมไม่ได้ต้องการชาร์จให้เร็วที่สุดตลอดเวลา จึงยอมแลกความเร็วบางส่วนกับการจำกัดกระแสให้มีระยะห่างจากค่าที่สูงกว่านี้ แต่ยังไม่สรุปว่าค่าชุดนี้ทำให้อายุแบตเตอรี่เพิ่มขึ้นกี่เปอร์เซ็นต์ เพราะยังไม่มีข้อมูลระยะยาวรองรับ

3. ลดกระแสแล้วช่วยเรื่องความร้อนอย่างไร?

เมื่อกระแสไหลผ่านส่วนที่มีความต้านทาน เช่น สายและจุดต่อ จะเกิดการสูญเสียเป็นความร้อน หลักการพื้นฐานคือ กำลังสูญเสีย = กระแส × กระแส × ความต้านทาน หรือที่มักเขียนว่า P = I²R

หมายความว่า หากความต้านทานเท่าเดิม ความร้อนส่วนนี้ไม่ได้เพิ่มหรือลดตามกระแสแบบเส้นตรง แต่เปลี่ยนตามกระแสยกกำลังสอง

ลองเทียบกรณีที่กระแสจริงลดจาก 130A เหลือ 110A:

ขั้นตอนผลลัพธ์
กระแสใหม่เทียบกับเดิม: 110 ÷ 130ประมาณ 0.846 เท่า
กำลังสูญเสียเทียบกับเดิม: 0.846 × 0.846ประมาณ 0.716 เท่า
เปลี่ยนเป็นเปอร์เซ็นต์เหลือประมาณ 71.6%
ส่วนที่ลดลง: 100 − 71.6ประมาณ 28.4%

ความหมายคือ ถ้ากระแสจริงลดตามนี้ และความต้านทานเท่าเดิม การสูญเสียแบบ I²R ในส่วนที่พิจารณาจะลดลงประมาณ 28.4% ไม่ได้หมายความว่าอุณหภูมิทั้งแบตเตอรี่ลดลง 28.4% หรืออายุแบตเตอรี่เพิ่มขึ้นในสัดส่วนเดียวกัน

ที่สำคัญ 130A และ 110A ใน controller เป็นเพียง เพดานกระแส หากก่อนปรับ แบตเตอรี่รับกระแสจริงเพียง 60A การลดเพดานจาก 130A เป็น 110A อาจไม่ทำให้กระแสจริงเปลี่ยนเลย จึงยังนำตัวเลข 28.4% ไปอ้างเป็นผลประหยัดหรือผลลดความร้อนของระบบจริงไม่ได้

การประเมินการถนอมแบตเตอรี่ต้องดูร่วมกันทั้งกระแสจริงรายลูก อุณหภูมิ แรงดันเซลล์สูงสุด ความต่างแรงดันระหว่างเซลล์ เวลาที่อยู่ใกล้เต็ม และเหตุการณ์จำกัดหรือตัดชาร์จจาก BMS

4. ใกล้เต็มควรลดกระแส หรือควรลดแรงดัน?

คำว่า “ชาร์จเบาลงเมื่อใกล้เต็ม” ต้องแยกเป็นสองแนวคิดทางไฟฟ้า

ลดเพดานกระแส: นี่คือสิ่งที่ระบบปัจจุบันทำ คือเปลี่ยนจาก 130A เป็น 110A ไม่ได้สั่งเปลี่ยนแรงดันชาร์จ

ปรับแรงดันและระยะเวลาช่วงปลายการชาร์จ: เกี่ยวข้องกับ charge profile เช่น แรงดัน absorption ระยะเวลาคงแรงดัน และแรงดันช่วงหลังจากนั้น รวมถึงเงื่อนไข balancing ของแบตเตอรี่

ในช่วงควบคุมแรงดัน กระแสสามารถค่อย ๆ ลดลงได้โดยไม่ต้องลด voltage setpoint ตาม SOC ทุกครั้ง ส่วนบางระบบลดแรงดันหลังจบ absorption ตามโปรไฟล์ผู้ผลิต คู่มือ Victron อธิบายทั้ง absorption เวลาสำหรับ balancer และการลดแรงดันไป float แต่ค่าของผลิตภัณฑ์นั้นไม่ใช่ค่าที่ควรยกมาใช้กับแบตเตอรี่ของผมโดยตรง — Victron Lithium NG: Charging profile

แนวคิดด้านการถนอมแบตเตอรี่ของผมจึงมีสองระดับ:

  1. ทำแล้ว: ลดเพดานกระแสเมื่อ SOC >90%
  2. ต้องศึกษาเพิ่มเติม: จัดการแรงดันและระยะเวลาช่วงใกล้เต็มให้ตรงสเปกแบตเตอรี่ทุกลูกและ BMS รวมถึงการ balancing

ระบบนี้จึงยังไม่ใช่ “ลดแรงดันชาร์จเมื่อใกล้เต็ม” แต่เป็น ลดเพดานกระแสจากประมาณ 0.149C เป็น 0.126C ส่วน SOC 90% เป็นจุดเปลี่ยนนโยบายที่เลือกใช้ ไม่ใช่เส้นแบ่งทางเคมีของแบตเตอรี่ทุกระบบ

5. Controller นี้อยู่ตรงไหนของระบบ?

ผมออกแบบเป็นชั้นควบคุมนโยบาย หรือ supervisory controller ไม่ได้เข้าไปควบคุมวงจรชาร์จความเร็วสูงภายใน inverter และไม่ได้แทนที่ BMS

ชั้นของระบบหน้าที่
Home Assistantให้ SOC และเหตุการณ์เริ่มผลิต
Charge controllerเลือกเพดานกระแสและจัดการสถานะคำสั่ง
Inverterควบคุมการแปลงพลังงานและการชาร์จตามข้อจำกัด
BMSตรวจและจำกัดการทำงานตามเงื่อนไขแบตเตอรี่

ตัวแปรที่ปรับคือ Max Battery Charging Current เท่านั้น กระแสจริงยังขึ้นอยู่กับพลังงานที่มีให้ชาร์จ โหลด สถานะการชาร์จ และข้อจำกัด inverter/BMS

ก่อนเพิ่มกระแส ระบบตรวจสถานะเครื่อง alarm/fault และ BMS charge-current limit ที่ inverter รายงานด้วย แต่ค่า BMS limit ระดับระบบไม่ใช่หลักฐานว่ากระแสรายลูกอยู่ในขอบเขตที่ต้องการ

6. ใช้การเริ่มผลิตจริงเป็นจุดเริ่มรอบ

ผมใช้เหตุการณ์ “โซลาร์เริ่มผลิต” แทนเวลาพระอาทิตย์ขึ้น Automation เดิมใน HA ตรวจว่า PV เส้นใดเส้นหนึ่งผลิตมากกว่า 10W แล้วบันทึกวันที่ครั้งเดียวต่อวัน จึงใช้ helper เดิมเปิดรอบใหม่

วิธีนี้แยกการเริ่มผลิตวันใหม่ออกจากกำลังผลิตที่กลับมาหลังเมฆบังในวันเดิม มีเพียงกรณีแรกที่เปิดรอบการชาร์จใหม่

เหตุการณ์เป้าหมาย
เริ่มผลิตวันใหม่ และ SOC ไม่เกิน 90%130A
เริ่มผลิตวันใหม่ แต่ SOC เกิน 90% แล้ว110A
ระหว่างวัน SOC เท่ากับ 90% และยังไม่เคยล็อกยังคง 130A
ระหว่างวัน SOC มากกว่า 90%เปลี่ยนเป็น 110A และล็อก
SOC ลดลงภายหลังในวันเดียวกันยังคง 110A
เริ่มผลิตวันถัดไปประเมินเงื่อนไขรอบใหม่

การล็อกสถานะช่วยไม่ให้ SOC ที่ลดลงภายหลังทำให้ระบบกลับไปเพิ่มกระแสในวันเดียวกัน

7. เปลี่ยนจาก polling เป็น event-driven control

เวอร์ชันแรกอ่าน logger ทุกนาที แม้ HA มีข้อมูลจำนวนหนึ่งอยู่แล้ว เมื่อทบทวน ผมพบว่า SOC ใช้จาก HA ได้ ส่วนเพดานกระแสเป็น configuration ที่เปลี่ยนไม่บ่อย

จึงปรับเป็น อ่านข้อมูลตัดสินใจจาก HA และติดต่อ logger เมื่อมีเหตุเปลี่ยนค่าเท่านั้น ช่วง idle ไม่มีการเชื่อมต่อ logger จาก controller นี้

การติดต่อโดยตรงเกิดเมื่อ precheck ก่อนเขียน อ่านกลับยืนยัน หรือจัดการความผิดพลาดและคืนค่า HA integration ยังอ่านตามรอบปกติ การออกแบบนี้ลดเฉพาะการสื่อสารซ้ำที่ controller เพิ่มเข้ามา

8. Write acknowledgement ไม่ใช่ confirmation

สำหรับชุดที่ทดสอบ ผมใช้ local Solarman V5 และ Modbus FC16 เขียน register 210 แบบเลขฐานสิบ ซึ่งเป็นค่ากระแสชาร์จสูงสุดตาม map ที่ใช้ ต้องตรวจ map ตามรุ่นและ firmware ก่อนนำไปใช้กับอุปกรณ์อื่น

ผมแยก acknowledgement หรือคำตอบรับการส่งคำสั่ง ออกจาก confirmation หรือการอ่านกลับแล้วตรงเป้าหมาย หากคำตอบ timeout ก็ยังสรุปไม่ได้ว่าเครื่องไม่ได้รับคำสั่ง

ขั้นตอนคือ:

  1. เป้าหมายเปลี่ยน → ตรวจสถานะเครื่อง fault BMS limit และค่าปัจจุบัน
  2. บันทึก pending ลง disk ก่อนส่งคำสั่ง
  3. ส่ง FC16 แล้วปิด connection
  4. รออย่างน้อย 90 วินาที
  5. อ่านค่ากระแสและสถานะกลับ → ยืนยันเมื่อค่าตรงและสถานะปกติ

90 วินาทีเป็นช่วงหน่วงที่เลือกในเชิงระบบ ไม่ได้อ้างว่าอุปกรณ์ทุกรุ่นจำเป็นต้องใช้ หาก precheck พบว่าค่าจริงตรงเป้าหมายอยู่แล้ว ก็ไม่เขียนซ้ำ

9. Persistent state และการรับมือ restart

สถานะที่เก็บลง disk มีวันที่ของรอบ สถานะล็อก ค่าที่ยืนยันและเวลา คำสั่ง pending เวลาครบกำหนดอ่านกลับ จำนวนครั้งที่ลอง และคิวแจ้งเตือน

การบันทึก pending ก่อนเขียน ช่วยให้หลัง restart ระบบกลับมาอ่านยืนยัน แทนส่งคำสั่งเดิมซ้ำโดยไม่ตรวจสอบ

นี่ไม่ใช่การรับประกัน exactly-once ระหว่างไฟล์กับ inverter เพราะไม่ได้อยู่ใน transaction เดียวกัน หากหยุดหลังบันทึกแต่ก่อนส่งจริง ระบบก็ต้องอ่านกลับแล้วจัดการผลที่พบ หลักการคือกลับมาตรวจสภาพจริงก่อนตัดสินใจต่อ

10. Helper ต้องแสดงค่าที่ยืนยันล่าสุด

Helperความหมาย
Confirmed currentค่าล่าสุดที่อ่านยืนยันแล้ว: 130A / 110A
Statusยืนยันแล้ว / รอยืนยัน / ยืนยันไม่สำเร็จ
Confirmed atเวลาอ่านกลับยืนยันล่าสุด

ขณะเปลี่ยนจาก 130A เป็น 110A ค่า confirmed ยังเป็น 130A และ status เป็น “รอยืนยัน” เมื่ออ่านกลับได้ 110A จึงเปลี่ยนค่าและ timestamp พร้อมแจ้งผล

Helpers เป็นตัวแสดงผล การกด dropdown ไม่สั่ง inverter และไม่ถูกใช้เป็นหลักฐานว่าค่าเครื่องเปลี่ยนแล้ว ประวัติแต่ละครั้งเก็บใน event log แยกจาก timestamp ล่าสุด

11. SOC คงที่ ไม่ได้แปลว่าข้อมูลค้าง

SOC อาจคงค่าเดิมนาน แม้ HA อ่านข้อมูลสำเร็จต่อเนื่อง จึงไม่ใช้เวลาเปลี่ยนค่า SOC เป็นเงื่อนไขความสดเพียงอย่างเดียว

ระบบตรวจ SOC ว่าเป็นตัวเลข 0–100%, integration เป็น Connected และเวลาอ่านสำเร็จล่าสุดไม่เกิน 180 วินาที พร้อมตรวจ timestamp ของ heartbeat

หากไม่ผ่าน จะไม่เริ่มคำสั่งใหม่จาก SOC นั้นและแจ้งปัญหา แต่ถ้ามี pending อยู่ ยังต้องอ่านยืนยันจาก logger เพื่อรู้ผลคำสั่งที่เริ่มไปแล้ว

12. Failure handling และข้อแลกเปลี่ยน

การลองใหม่มีขีดจำกัด หากอ่านยืนยันไม่ได้ จะลองอ่านซ้ำก่อนโดยไม่เขียนคำสั่งเดิมซ้ำระหว่างรอ หากเป็นการเพิ่มกระแสและยังยืนยันไม่ได้ครบจำนวนครั้ง จะพยายามคืนค่าเดิมพร้อมอ่านยืนยันการคืนค่า เมื่อถึงเงื่อนไขที่ยืนยันต่อไม่ได้ ระบบหยุดเขียนและแจ้งให้ตรวจสอบ

ข้อแลกเปลี่ยนคือ ไม่ตรวจพบการเปลี่ยนค่าจากหน้าเครื่องหรือแอปทันทีระหว่าง idle confirmed current จึงหมายถึงค่าที่เคยอ่านยืนยัน ไม่ใช่ค่าที่วัดต่อเนื่อง

Notification มี durable outbox แยกผู้รับ แต่ HA รับคำสั่งแล้วไม่ยืนยันว่าโทรศัพท์แสดงข้อความ และหาก host หรือเครือข่ายล่มทั้งหมด ก็แจ้งเหตุทันทีไม่ได้

13. สิ่งที่ยืนยันได้ และสิ่งที่ยังต้องวัด

ฉบับเผยแพร่ ณ วันที่เขียนมี offline tests 30 กรณี ครอบคลุม SOC threshold, latch, freshness, pending, restart, timeout, readback, retry, recovery, dry-run และ helpers ระบบต้นทางเปิดใช้งาน event-only แล้ว และตรวจช่วง idle ได้ว่า controller ไม่เชื่อมต่อ logger เพิ่ม

ผลเหล่านี้ยืนยัน พฤติกรรมระบบควบคุม ไม่ใช่ ผลต่ออายุแบตเตอรี่ หากจะประเมินการถนอมแบตเตอรี่ต่อ ผมต้องการข้อมูลเพิ่ม:

ข้อมูลคำถาม
กระแสจริงรายลูกแต่ละลูกมี C-rate และแบ่งโหลดอย่างไร
อุณหภูมิรายลูกใกล้เต็มแล้วอุณหภูมิเปลี่ยนอย่างไร
Cell maximum / cell deltaเซลล์ใดขึ้นสูงก่อน หรือ balancing ไม่ทันหรือไม่
เวลาที่ SOC สูงค้างใกล้เต็มนานแค่ไหน
BMS limit / protection eventsจำกัดหรือตัดชาร์จบ่อยเพียงใด
เวลาชาร์จและพลังงานที่รับได้ลดเพดานแล้วกระทบพลังงานรายวันเท่าไร

โค้ดและเอกสาร

เปิดโค้ดไว้ที่ GitHub: deye-charge-controller มี configuration, Docker Compose, HA helpers, automation วันที่เริ่มผลิต และคู่มืออัปเกรด ค่าเริ่มต้นเป็น dry-run ซึ่งไม่ติดต่อ logger แม้มี pending เดิม ผู้ติดตั้งต้องกำหนด entity และข้อจำกัดระบบตัวเองก่อนเปิดเขียน

งานนี้เริ่มจากการอยากถนอมแบตเตอรี่ด้วยกระแสค่อนข้างต่ำ แต่ต้องออกแบบความน่าเชื่อถือของการควบคุมควบคู่กัน 130A และ 110A ต่ำกว่า 0.2C ของ bank 874Ah ตามพิกัด แต่ต้องดูการแบ่งกระแส สภาพแบตเตอรี่ และข้อมูล BMS ประกอบ

ส่วน software ต้องแยกเป้าหมาย คำสั่งที่ส่งแล้ว และค่าที่อ่านกลับยืนยันแล้วให้ชัด จึงจะใช้ข้อมูลบนหน้าจอตัดสินใจได้อย่างมีความหมาย