G2025_廃品リチウム電池の放電実験
2025年11月1日
6:22
G2025_lpc812_junk_lithium_battery_discharge
改良中ですが、最新のプロジェクトです LPC812_LIT_DISC.zip
Version:0.9 StartHTML:00000000 EndHTML:00000000 StartFragment:00000000 EndFragment:00000000 解凍してLPC812フォルダの中に保存する

概要
放電の基本回路














放電回路のテスト
電圧モニタ回路の考察

2.558 / 10000 = 0.0003
1.418 / 0.0003 = 4,726.6667
並列で 4.717KΩ
1/R = 1/R2 + 1/R3 -> 1/R3 = 1/R - 1/R2
1/4717 = 0.0002
1/10000=0.0001
0.0002 - 0.0001 = 0.0001
1/0.0001 = 10,000.0
AD変換の内部抵抗は 10KΩかもしれない

根本的なミス
放電測定のプロジェクトを作成ます


モニタ用の初期コード
///////////////////////////////////////////////////////
//
// LPC812 LIT_DISC
// 2025.11.05 水曜 goma0099 リチウム電池放電特性の測定
///////////////////////////////////////////////////////
#include "LPC8xx.h" //ヘッダファイルの読み込み
#include "\LPC\LPC812\KYO\type.h"
#include "stdlib.h" // atoi()
#include "string.h" // memcpy()
//#include "gpio.h"
// 改造された共用関数を一箇所にまとめて最新がインクルードされるように
#include "\LPC\LPC812\KYO\lpc8xx_uart.h"
#include "\LPC\LPC812\KYO\lpc8xx_uart.c"
#include "\LPC\LPC812\KYO\lpc8xx_i2c.h"
#include "\LPC\LPC812\KYO\lpc8xx_i2c.c"
#include "\LPC\LPC812\KYO\lpc812_kyo.h"
#include "\LPC\lpc_kyo.h"
void SwitchMatrix_Init()
{
/* Enable SWM clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7);
/* Pin Assign 8 bit Configuration */
/* U0_TXD */
/* U0_RXD */
LPC_SWM->PINASSIGN0 = 0xffff0004UL;
/* I2C0_SDA */
LPC_SWM->PINASSIGN7 = 0x11ffffffUL;
/* I2C0_SCL */
LPC_SWM->PINASSIGN8 = 0xffffff0dUL;
/* Pin Assign 1 bit Configuration */
/* RESET */
LPC_SWM->PINENABLE0 = 0xffffffbfUL;
}
// インターバル割り込み関数を msec 待ち時間関数に活用しています
void SysTick_Handler(void)
{
if(--Goma_msec_wait_cnt == 0)
{ NVIC_DisableIRQ(SysTick_IRQn); // 割り込み無効
}
}
// ばらつき対策のため平均値を計算します
int16_t av_get(int8_t prm_cs_pin,int8_t prm_ch,int8_t prm_av_max)
{
uint32_t i;
uint32_t ad_dat = 0;
uint32_t gokei = 0;
uint32_t av_max = prm_av_max;
if(av_max <= 0) av_max = 1; // 補正
if(100 < av_max) av_max = 100;
for(i=0 ; i<av_max ; i++)
{
gokei += mcp3208_read(prm_cs_pin,(uint8_t)prm_ch);
wait_sec('m',10);
}
ad_dat = gokei / av_max;
return((uint16_t)ad_dat);
}
int main(void)
{
uint32_t cnt;
uint16_t ad_dat[2];
int8_t cs_pin; // PIOの定義忘れがあり時間ロスしました
// 忘れ防止の為、明示的にします
// スイッチ・マトリックス設定
SwitchMatrix_Init();
SPI_CLK_pin = 6;
SPI_SOMI_pin = 7;
SPI_MOSI_pin = 8;
cs_pin = 9;
//ポートの方向決定
pin_set_output(SPI_CLK_pin); // MCP3208 CLK
pin_set_input(SPI_SOMI_pin); // MCP3208 OUTPUT
pin_set_output(SPI_MOSI_pin); // MCP3208 INPUT
pin_set_output(cs_pin); // MCP3208 CS 定義忘れがあり時間ロスしました
//////////////////////////////////////
// 周期割り込みの初期化
//////////////////////////////////////
SystemCoreClockUpdate();
SysTick_Config( SYSTICK_DELAY );
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
UARTInit(LPC_USART0,115200); // UART初期化関数( bpsに設定)
// i2c通信は未使用なので、初期化は省いています
//UART_puts("speed 115200 \r\n");
while(1)
{
wait_sec('m',2000);
for(cnt=0 ; cnt<2 ; cnt++)
{
// ばらつきを補正するため 10 回測定して平均します
ad_dat[cnt] = av_get(cs_pin,cnt,10);
}
// 放電対象の電池が未接続の場合はモニタしない
if(100 < ad_dat[0])
{
UART_puts("V=");
UART_putdec(ad_dat[0]);
UART_puts(" ");
UART_puts("A=");
UART_putdec(ad_dat[1]);
UART_puts("\r\n");
}
}
}
解放電圧4.25 電池のモニタ結果


AD変換値から電圧、電流を計算します
4200*1000/3814=1101.2061
V = (AD値 *1101) /1000 mV
581*1000/1505=386.0465
A = (AD値*386)/1000 mA



放電タイミングをマイコンから制御します





充電開始制御が完成したので、モニタから調整します

実測 計算値
電流 504mA 319 mA
電圧 3594 mV 3610 mV
下記の換算で、手持ちのB35テスターと適合しました

充電制御回路の為、放電テストの電池を外しても 1733 mV より下がりません
プロジェクトの最新コード

///////////////////////////////////////////////////////
//
// LPC812 LIT_DISC
// 2025.11.05 水曜 goma0099 リチウム電池放電特性の測定
///////////////////////////////////////////////////////
#include "LPC8xx.h" //ヘッダファイルの読み込み
#include "\LPC\LPC812\KYO\type.h"
#include "stdlib.h" // atoi()
#include "string.h" // memcpy()
//#include "gpio.h"
// 改造された共用関数を一箇所にまとめて最新がインクルードされるように
#include "\LPC\LPC812\KYO\lpc8xx_uart.h"
#include "\LPC\LPC812\KYO\lpc8xx_uart.c"
#include "\LPC\LPC812\KYO\lpc8xx_i2c.h"
#include "\LPC\LPC812\KYO\lpc8xx_i2c.c"
#include "\LPC\LPC812\KYO\lpc812_kyo.h"
#include "\LPC\lpc_kyo.h"
void SwitchMatrix_Init()
{
/* Enable SWM clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7);
/* Pin Assign 8 bit Configuration */
/* U0_TXD */
/* U0_RXD */
LPC_SWM->PINASSIGN0 = 0xffff0004UL;
/* I2C0_SDA */
LPC_SWM->PINASSIGN7 = 0x11ffffffUL;
/* I2C0_SCL */
LPC_SWM->PINASSIGN8 = 0xffffff0dUL;
/* Pin Assign 1 bit Configuration */
/* RESET */
LPC_SWM->PINENABLE0 = 0xffffffbfUL;
}
// インターバル割り込み関数を msec 待ち時間関数に活用しています
void SysTick_Handler(void)
{
if(--Goma_msec_wait_cnt == 0)
{ NVIC_DisableIRQ(SysTick_IRQn); // 割り込み無効
}
}
// ばらつき対策のため平均値を計算します
int16_t av_get(int8_t prm_cs_pin,int8_t prm_ch,int8_t prm_av_max)
{
uint32_t i;
uint32_t ad_dat = 0;
uint32_t gokei = 0;
uint32_t av_max = prm_av_max;
if(av_max <= 0) av_max = 1; // 補正
if(100 < av_max) av_max = 100;
for(i=0 ; i<av_max ; i++)
{
gokei += mcp3208_read(prm_cs_pin,(uint8_t)prm_ch);
wait_sec('m',5);
}
ad_dat = gokei / av_max;
return((uint16_t)ad_dat);
}
uint32_t mon_dsp(
uint32_t prm_volt_all,
uint32_t prm_amp_all,
uint32_t prm_volt_dat_all,
uint32_t prm_amp_dat_all
)
{
uint32_t volt;
uint32_t amp;
uint32_t volt_dat;
uint32_t amp_dat;
volt = prm_volt_all / 60;
amp = prm_amp_all / 60;
volt_dat = prm_volt_dat_all / 60;
amp_dat = prm_amp_dat_all / 60;
UART_puts("V=,");
UART_putdec(volt);
UART_puts(",mV ,");
UART_putdec(volt_dat);
UART_puts(",A=,");
UART_putdec(amp);
UART_puts(",mA ,");
UART_putdec(amp_dat);
UART_puts("\r\n");
return(volt);
}
int main(void)
{
uint16_t ad_dat[2];
uint8_t cs_pin; // PIOの定義忘れがあり時間ロスしました
// 忘れ防止の為、明示的にします
uint8_t sw_pin;
uint32_t i;
uint32_t volt;
uint32_t amp;
uint32_t min_cnt;
uint32_t volt_all;
uint32_t amp_all;
uint32_t volt_dat_all;
uint32_t amp_dat_all;
uint32_t volt_end; // 放電終了判定
uint32_t volt_start; // 放電開始基準
uint32_t volt_open; // 解放電圧保持
uint32_t disc_cnt; // 放電持続カウンター
uint8_t disc_mod; // 0:放電前(解放電圧) 1:放電開始 2:放電終了
// スイッチ・マトリックス設定
SwitchMatrix_Init();
SPI_CLK_pin = 6;
SPI_SOMI_pin = 7;
SPI_MOSI_pin = 8;
cs_pin = 9;
sw_pin = 10;
//ポートの方向決定
pin_set_output(SPI_CLK_pin); // MCP3208 CLK
pin_set_input(SPI_SOMI_pin); // MCP3208 OUTPUT
pin_set_output(SPI_MOSI_pin); // MCP3208 INPUT
pin_set_output(cs_pin); // MCP3208 CS 定義忘れがあり時間ロスしました
pin_set_output(sw_pin);
//////////////////////////////////////
// 周期割り込みの初期化
//////////////////////////////////////
SystemCoreClockUpdate();
SysTick_Config( SYSTICK_DELAY );
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
UARTInit(LPC_USART0,115200); // UART初期化関数( bpsに設定)
// i2c通信は未使用なので、初期化は省いています
//UART_puts("speed 115200 \r\n");
pin_out(sw_pin,0,'m',0); // 放電制御OFF
volt_end = 3000; // 放電最終電圧
volt_start = 3800; // 放電開始基準 解放電圧がこれ以上で放電開始します
disc_mod = 0;
while(1)
{
ad_dat[0] = av_get(cs_pin,0,3); // 電圧
ad_dat[1] = av_get(cs_pin,1,3); // 電流
// テスターの誤差にも適合させるため、テスターは固定する必要があります
// 32bit を出来るだけ有効にするため、係数は5桁を利用しています
// この定数は、この電子回路にだけ特化されます 新しい回路では別の調整が必要です
volt = (ad_dat[0]*109490)/100000;
amp = (ad_dat[1]*38250)/100000;
switch(disc_mod)
{
case 0: // 放電前
wait_sec('m',960); // 通常周期
//UART_putdec(volt);
//UART_puts("\r\n");
if(volt_start <= volt)
{
UART_puts("Start Dischage \r\n");
volt_open = volt; // 解放電圧記録
disc_cnt = 0;
min_cnt = 0;
volt_all = amp_all = 0;
volt_dat_all = amp_dat_all = 0;
disc_mod = 1;
pin_out(sw_pin,1,'m',0); // 放電制御ON
}
break;
case 1: // 放電開始
wait_sec('m',960); // 通常周期
++min_cnt;
volt_all = volt_all + volt;
amp_all = amp_all + amp;
volt_dat_all = volt_dat_all + ad_dat[0];
amp_dat_all = amp_dat_all + ad_dat[0];
if(59 <= min_cnt)
{
++min_cnt;
++disc_cnt;
i = mon_dsp(volt_all,amp_all,volt_dat_all,amp_dat_all); // 1分モニタ
if(i < volt_end)
{
UART_puts("Dischage min max =,");
UART_putdec(disc_cnt);
UART_puts("\r\n");
disc_mod = 2;
pin_out(sw_pin,0,'m',0); // 放電制御OFF
}
// 最初の1分
if(disc_cnt == 1)
{
i = volt_open - (volt_all / 60);
UART_puts("Farst Drop Volt =");
UART_putdec(i);
UART_puts(" mV \r\n");
}
min_cnt = 0;
volt_all = amp_all = 0;
volt_dat_all = amp_dat_all = 0;
}
break;
case 2: // 放電終了
wait_sec('m',960); // 通常周期
if(volt < 2000)
{
// 電池が取り外されたと判断し、モードを初期化します
disc_mod = 0;
}
break;
}
}
}
実験途中のモニタ画面と考察

テストを継続する前に、通信モニタプログラムを改造します
goma0099.com/PDF/G3012a_pc_lpc_micon_uart_part_2.htm






管理番号 38 のリチウム電池

管理番号 26 番のリチウム電池


スイッチング 素子 K4017 の電圧降下を改善する
管理番号 13番



マイコンのモニタ書式の変更
