산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

9V NiMH 충전식 배터리 V1용 지능형 충전기

구성품 및 소모품

Arduino UNO
× 1
SparkFun I2C DAC 브레이크아웃 - MCP4725
× 1
출력 조절이 가능한 선형 조정기
× 1
Texas Instruments 범용 이중 연산 증폭기
× 1
저항 6.8k 옴
× 2
저항 3.3k 옴
× 1
저항 5.1k 옴
× 1
저항 1k 옴
× 1
저항 10옴
× 1
릴레이(일반)
× 1
저항 20k 옴
× 1
SparkFun 브레드보드 전원 공급 장치 5V/3.3V
× 1
전원 공급 장치 17V
× 1
YwRobot I2C 직렬 LCD 1602 모듈
× 1

이 프로젝트 정보

몇 시간 만에 9V NiMH 배터리를 충전할 수 있는 스마트 충전기 채팅을 찾았지만 찾지 못했습니다. 게다가 내가 찾은 모든 충전기는 정말 "바보"였습니다. 충전 전류를 알 수 없으며 배터리가 완전히 충전된 후 충전을 종료하는 기능이 없습니다. 배터리를 과충전하여 수명을 크게 단축시킬 수 있는 충전기의 문제입니다. 그래서 "스마트" 충전기를 만들기로 결정했습니다.

첫 번째 버전은 단순하게 유지하기 위해 정전류 충전, 배터리 완전 충전 후 자동 충전 종료, 세류 충전, 배터리로 전달된 전하 측정과 같은 기본 기능을 허용합니다.

다음 버전에서는 방전, 용량 측정, 사이클링과 같은 몇 가지 유용한 기능을 추가할 예정입니다.

경고:높은 전류로 배터리를 충전하면 배터리 폭발이나 화재가 발생할 수 있습니다. 충전기를 방치하지 마십시오. 또한 알카라인으로 충전할 예정이 아닌 배터리를 충전하지 마십시오. 이 충전기는 NiMH 배터리로만 테스트되었습니다(그래도 여전히 귀하의 책임하에 사용하고 있으며 설계 또는 코드의 버그로 인해 발생한 손상에 대해 저는 절대 책임을 지지 않습니다). 다른 유형의 배터리를 사용하려면 코드 수정이 필요합니다.

이론

충전기의 필수 매개변수를 이해하는 데 도움이 되는 기억해야 할 몇 가지 유용한 사실입니다.

C - 배터리의 공칭 용량과 동일한 전류

C rate로 충전하면 단일 셀 전압이 1.6V에 도달할 수 있습니다. 이 전압은 오래된 배터리의 경우 더 높을 수 있습니다.

단일 셀의 공칭 전압은 1.2V이지만 완전히 충전된 셀은 최대 1.5V의 개방 회로 전압을 갖습니다.

배터리가 완전히 충전된 후 0.025C(C/40) 미만의 세류 충전 속도를 권장합니다.

일반적으로 NiMH 배터리를 충전하는 방법은 두 가지입니다.

1. 빠른 충전. 충전 전류 0.5C-1C. 충전 상태는 dV/dt(전압 변화율) 또는 dT/dt(온도 변화율)로 모니터링 및 종료되어야 합니다.

2. 느린 충전. 충전 전류 0.1C. 충전 시간 14-16시간. 타이머에 의한 충전 종료. 낮은 전류에서는 dT/dt 충전 종료가 불가능합니다. dV/dt 종단은 문헌에 따라 0.5C 미만의 전류에서 신뢰할 수 없을 수 있습니다.

충전 회로의 기본 매개변수

9V 배터리에는 일반적으로 7개의 직렬 연결된 셀이 있지만 경우에 따라 6개 또는 8개의 셀이 있을 수 있습니다. 전압 조정기는 최소 8*1.6=12.8V까지 충전 전압을 제공할 수 있어야 합니다. LM317 레귤레이터의 드롭아웃 전압은 최대 2V이므로 공급 전압은 ~15V여야 합니다(이는 전류 감지 저항기의 전압 강하를 고려하지 않음).

최대 충전 전류 200mA 및 전류 감지 저항 10 Ohm의 경우 전류 감지 저항의 추가 강하는 2V이므로 17V 공급 전압이 필요합니다.

완전히 방전된 셀은 매우 낮고 심지어 음의 전압을 가질 수 있습니다. 레귤레이터의 최소 전압은 이상적으로는 0이어야 하지만 LM317을 사용하면 1.2V까지 낮아질 수 있습니다.

회로

회로 설명

기본 아이디어는 충전 전류를 측정하고 원하는 전류에 도달할 때까지 레귤레이터의 전압을 조정하는 것입니다. 전류 감지 저항 R5의 전압 강하를 측정하여 측정한 전류입니다. I=V/R.

SparkFun I2C DAC 브레이크아웃 - MCP4725 - 전압 제어에 사용되는 12비트 디지털-아날로그 변환기. 출력 전압 캠은 0과 5V 사이에서 I2C를 통해 구성됩니다. DAC의 출력 전압을 증폭하는 데 사용되는 0에서 15V 연산 증폭기 LM358까지 더 넓은 범위에서 전압을 조정할 수 있어야 하기 때문입니다. 저항 R4 및 R3에 의해 설정된 연산 증폭기의 증폭. Gain=1+R4/R3=1+6800/3300=3.06이므로 연산 증폭기의 출력 전압은 약 0~15V입니다.

LM358의 최대 출력 전류는 50mA이므로 LM317 가변 전압 레귤레이터는 더 높은 전류를 제어하는 ​​데 사용됩니다. LM317의 ADJ 단자에 연결된 연산 증폭기의 출력. LM317은 ADJ와 OUT 단자 사이에 1.2V를 유지하므로 배터리의 실제 전압은 1.2~16.2V 사이에서 구성할 수 있습니다. LM317은 레귤레이션을 유지하기 위해 최소 3.5mA 전류가 필요합니다. 따라서 배터리가 연결되지 않은 경우 레귤레이션을 보장하기 위해 1kOhm 저항 R6이 사용됩니다. 출력 전압을 필터링하고 LM317의 안정성을 향상시키는 데 사용되는 커패시터 C1.

서로 다른 두 지점에서 측정된 전압입니다.

1. 저항 R5는 Arduino의 핀 A2에 연결됩니다. 측정된 저항의 전압 및 Icharging=V/R

로 계산된 충전 전류보다

2. 배터리의 전압은 최대 16.2V일 수 있으므로 저항 분배기 R1, R2는 Arduino에서 허용하는 5V 미만으로 전압을 가져오는 데 사용됩니다. Arduino의 핀 A0에 연결된 분배기의 출력입니다. R1=5.1k Ohm 및 R2=20kOhm Vout=Vin/(20000+5100)*5100=0.2의 경우 배터리 전압을 5로 나눈 값입니다.

충전 회로에서 배터리를 분리하는 데 사용되는 릴레이. 기존에 사용하던 포토릴레이를 보시면 알겠지만 일반적으로 5V 제어가 가능한 릴레이라면 아무거나 사용하셔도 됩니다. 릴레이의 접점이 정상적으로 열린 상태로 배터리를 연결하는 것이 더 안전합니다.

충전기의 상태를 표시하기 위해 YwRobot I2C SERIAL LCD 1602 MODULE를 사용했지만 다른 I2C 제어 LCD 모듈을 사용할 수 있습니다. YwRobot LCD 모듈이 표준 LiquidCrystal_I2C 라이브러리에서 지원되지 않는 것 같아서 New LiquidCrystal 라이브러리를 사용했습니다. 다른 LCD 모듈을 사용하는 경우 이 줄을 변경해야 합니다.

<사전><코드>LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, 양수); // 16자 및 2줄 표시를 위해 LCD 주소를 0x27로 설정

디지털-아날로그 변환기 및 LCD에 전원을 공급하기 위해 SparkFun Breadboard 전원 공급 장치 5V/3.3V를 사용했습니다. 아두이노 보드에서 5V를 사용해도 괜찮을 것 같습니다.

또한 충전 회로에 17V를 공급해야 합니다. 전원 공급 장치가 없는 경우 다음과 같이 조정 가능한 DC/DC 변환기를 사용할 수 있습니다.

http://www.ebay.com/itm/DC-DC-Adjustable-Step-up-boost-Power-Converter-Module-XL6009-Replace-LM2577-/310717070508

기능

많은 전선을 원하지 않았기 때문에 충전을 구성하는 버튼이 없었습니다. Chagrin 전류는 코드에서만 구성됩니다. Charger.ino에서 원하는 충전 전류를 설정해야 합니다.

//****************************** 충전 매개변수 ************* *************************//******************** ************************************************** ******************* float target_current_mA=30; //충전 전류 mAfloat battery_nominal_capacity_mA=170; //배터리의 공칭 용량 mAfloat max_time_for_trickle_charge=6; //최대 세류 충전 시간(분)//**************************************** *****************************************************/ /**************************************************** **************************************** 

target_current_mA - 일정한 충전 전류

max_time_for_trickle_charge - 세류 충전을 위한 최대 시간(분), 최대 600(10시간)까지 설정할 수 있습니다.

battery_nominal_capacity_mA - 세류 전류를 계산하는 데 사용되는 배터리 용량

일반적으로 충전 전류는 최대 공칭 용량일 수 있습니다. 공칭 용량이 170mAh인 배터리의 경우 최대 충전 전류는 170mA입니다. 최소 충전 전류는 일반적으로 170mAh 배터리의 경우 C/10 - 17mA입니다.

전원이 켜진 후 충전기는 배터리가 연결되었는지 확인합니다. 배터리가 연결된 경우 배터리는 완전히 충전될 때까지 구성된 정전류로 충전됩니다. 5분 동안 음의 dV/dt를 감지하여 충전이 종료되었습니다. 충전이 완료된 충전기는 현재 C/40으로 세류 충전으로 전환됩니다. 최대 세류 충전 시간이 경과하면 충전기가 배터리에서 자동으로 분리됩니다.

1 - dV/dt

2 - 충전 시간(분)

1 - 충전 시간

2 - 충전이 배터리로 전송됨

NiMH 배터리에 대한 추가 정보:

1. http://data.energizer.com/PDFs/nickelmetalhydride_appman.pdf

2. http://batteryuniversity.com/learn/article/charging_nickel_metal_hydride

<섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

코드

<울>
  • 충전기.이노
  • main.ino
  • hw.ino
  • lcd.ino
  • calculations.ino
  • 이 프로젝트에 사용된 새로운 LiquidCrystal 라이브러리
  • charger.ino아두이노
    메인 파일
    //9V NiMH 배터리 충전용 //배터리는 6,7 또는 8개의 1.25V 셀을 가질 수 있습니다.//이것은 7.5와 10V 사이의 공칭 전압을 만듭니다.#include #include #include  #include #include LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, 긍정적); // 16자 및 2줄 디스플레이의 경우 LCD 주소를 0x27로 설정합니다.//하드웨어 정의#define MCP4725_ADDR 0x60 //DAC 주소#define DAC_REF_VOLTAGE 5.0#define DAC_REF_VOLTAGE 5.0#define CHARGE_RELAY_PIN 2#define DISCONNECT_CONHIENSTOR_#define CURRENT_SENSING_SESISTOR 10.2 //OHm#define BATTERY_VOLTAGE_PIN A0#define R1 5090 //전압 센싱 디바이더의 로우 사이드 저항#define R2 19910//전압 센싱 디바이더의 하이 사이드 저항#define ADC_REF_VOLTAGE 4.89 //Arduino 실제 전압에 대한 적절한 공급 전압 ADC에서 전압으로 변환#define R3 3300.0#define R4 6800.0#define AMP_GAIN (1+R4/R3)//다양한 정의//#define MINIMUM_VOLTAGE 8.1 //레귤레이터 이후의 최소 전압#define BATTERY_GOOD_VOLTAGE_THRESHOLD_define ED_0CULTAGE_THRESHOLD_define 7.0 배터리 전류 mA(하드 컷오프)#define MAXIMUM_BATTERY_VOLTAGE 15.0 //최대 허용 배터리 전압 V(하드 컷오프)#define VOLTAGE_STEP 0.001 //전압 단계 Regulation#define POINTS_FOR_AVERAGING 100 //평균화를 위해 취한 포인트 수#define MEASURE2MEASURE_US 5000 //마이크로초 단위의 측정 간 시간(두 개의 아날로그 읽기 때문에 200보다 커야 함)#define VOLTAGE_LOG_TIME_MIN 30.0을 위해 전압을 저장하려면 분 단위 / DT 차단 # 10 # 15 # 20 # 30 #을 충전 정의합니다 CURRENT_RAMP_UP가 CURRENT_RAMP_DOWN 32 # 정의 정의 BATTERY_VOLTAGE_LOW 정의 35 #은 END_OF_TRICKLE 정의 트리클 정의 5 #가 BATTERY_CONNECTED 정의 NO_BATTERY 정의 5 #가 TRICKLE_CURRENT_RATIO 40은 충전기 # 초기화 0 #을 정의 상태 // 정의 MINUTES_TO_LOG 정의 37 #은 UNEXPECTED_CURRENT_FALL 40 # 70 # 정의 60 #은 FULLY_CHARGED 정의합니다 UNABLE_TO_REACH_CURRENT 정의 정의 CURRENT_TOO_HIGH 80 # REGULATION_FAILED 90 # 과전류 100 # 과전압 101 #이 FINAL_STATE 200 /// 부호의 INT voltage_readings [POINTS_FOR_AVERAGING] current_sensing_resistor_readings [POINTS_FOR_AVERAGING]를 정의하는 정의 정의 정의 averaging_index; //평균화를 위해 unsigned int voltage_sum,current_sum;//평균화합 f loat 레귤레이터_전압_코드,저항_전압,csr_전압_코드,레귤레이터_전압,전류_mA,배터리_전압;//측정플로트 tmp_저항_전압,tmp_current_mA,tmp_regulator_volt,tmp_battery_voltage;int i,j,last_last_2문자열,j,lastr_state;short_string_second_초기호가 없는;문자열 msg,eoc_line1,eoc_line2;unsigned char sec_index,min_index;//long long int charging_started;float sec_log[60],min_log[MINUTES_TO_LOG],last_blf;float trickle_current_mA;int total_minutes_average=0;elapsedMillis_blf;float trickle_current_mA;int total_minutes_average=0;elapsedMilli 0;float last_dac_voltage=0;//Messagesconst char msg_battery_detected[] PROGMEM ="배터리 감지";const char msg_no_battery[] PROGMEM ="배터리 없음";const char msg_battery_ok[] PROGMEM ="배터리 정상"; PROGMEM ="배터리 전압이 너무 낮음";const char msg_voltage_too_low_short[] PROGMEM ="V 배터리 부족";const char msg_ramp_up[] PROGM EM ="상승";const char msg_Charging[] PROGMEM ="충전";const char msg_space[] PROGMEM =" ";const char msg_ramp_down[] PROGMEM ="하강";const char msg_trickle_charge[] PROGMEM ="세류 충전 ";const char msg_no_current[] PROGMEM ="현재 없음";const char msg_current_unreachable[] PROGMEM ="도달할 수 없습니다";const char msg_current_unreachable_long[] PROGMEM ="원하는 전류에 연결할 수 없습니다";const char msg_completed[] PROGMEM ="Completed ";const char msg_charge[] PROGMEM ="충전";const char msg_high_current[] PROGMEM ="고전류"; const char msg_regulation_fault[] PROGMEM ="규제 오류";const char msg_overcurrent[] PROGMEM ="전류가 너무 높음"; const char msg_overvoltage[] PROGMEM ="전압이 너무 높음";const char msg_trickle_completed[] PROGMEM ="세류 완료";//**************************** **** 충전 매개변수 *****************************************//* ************************************************** ************************************** float target_current_mA=30; //충전 전류 mAfloat battery_nominal_capacity_mA=170; //배터리의 공칭 용량 mAfloat max_time_for_trickle_charge=6; //최대 세류 충전 시간(분)//**************************************** *****************************************************/ /**************************************************** ****************************************struct mytime { unsigned char 시간; 서명되지 않은 char 분; unsigned int total_minutes;} elapsed_time;void setup() { pinMode(CHARGE_RELAY_PIN, OUTPUT); 분리_충전_회로(); //배터리에서 충전기 분리 Wire.begin();//I2C dac_write_voltage(0);//가능한 낮은 전류 세트를 확인합니다. Serial.begin(115200); last_second=초(); lcd_last_second=초(); log_last_second=초(); Timer1.initialize(MEASURE2MEASURE_US); //배터리의 전압과 전류(마이크로초)를 측정하는 데 사용합니다. Timer1.attachInterrupt(read_hw); // 타이머 오버플로 인터럽트로 read_hw()를 첨부합니다. averaging_index=0; 초_인덱스=0; 최소 인덱스 =0; Charger_state=0;//상태 머신의 초기 상태 Want_dac_voltage=0;//shure 최소 전압 출력 last_blf=1.0; Trickle_current_mA=battery_nominal_capacity_mA/TRICKLE_CURRENT_RATIO; //ChargingTimeMillis=0; //LCD lcd.begin(16,2); lcd.backlight(); lcd.clear(); update_lcd(F("전원 켜기..."),empty_string); delay(1000);}float log_battery_voltage(){ //(log_last_second==second()) return last_blf인 경우 초당 한 번만 기록합니다. 그렇지 않으면 log_last_second=second(); sec_log[sec_index]=배터리 전압; if (sec_index<59) { sec_index++; } else {//1분이 기록된 경우 //분당 평균 계산 if (min_index>=MINUTES_TO_LOG) min_index=0; 초_인덱스=0; 부동 합계_v=0; (i=0;i<60;i++){ sum_v+=sec_log[i]; } float min_average=sum_v/60.0; for(i=1;i 
    main.ino아두이노
    <사전>무효 루프() { 문자열 msg1; switch(charger_state){ case INITIALIZATION://Initial state disconnect_Charging_circuit();//shure 릴레이 연결을 끊도록 설정 dac_write_voltage(0);//가능한 낮은 전류 설정을 확인합니다. Want_dac_voltage=0;//shure 최소 전압 출력 지연을 설정합니다(100).; read_status(); if (battery_voltage>0.1) { Charger_state=BATTERY_CONNECTED;//배터리 감지 update_lcd(M2S(msg_battery_detected),empty_string); Serial.println(M2S(msg_battery_detected)); 지연(2000); } else {//배터리 없음 Serial.println(M2S(msg_no_battery)); update_lcd(M2S(msg_no_battery),construct_status_string()); Charger_state=NO_BATTERY;//배터리 감지 지연(1000); } 부서지다; case NO_BATTERY://배터리 없음 read_status(); if (battery_voltage>0.1) { Charger_state=BATTERY_CONNECTED;//배터리 감지 Serial.println(M2S(msg_battery_detected)); update_lcd(M2S(msg_battery_detected),construct_status_string()); 지연(1500); } else{ //배터리가 이 상태로 유지되지 않으면 update_lcd(M2S(msg_no_battery),construct_status_string()); 지연(1100); } 부서지다; case BATTERY_CONNECTED://배터리 연결 dac_write_voltage(0);//가능한 더 낮은 전류 설정을 확인합니다.wanted_dac_voltage=0; 지연(100); read_status(); if (battery_voltage>BATTERY_GOOD_VOLTAGE_THRESHOLD){charger_state=CURRENT_RAMP_UP;//충전 전류 램프업 시작 //snprintf(welcome, sizeof(welcome),"펌웨어:V%d.%d%d",ver,ver2,ver3); update_lcd(M2S(msg_battery_ok),construct_status_string()); Serial.println(M2S(msg_battery_ok)); 지연(2000); want_dac_voltage=get_approximated_dac_voltage(battery_voltage);//필요한 레귤레이터 전압 설정 //Serial.println(get_approximated_dac_voltage(battery_voltage)); 연결_충전_회로(); 지연(200); } else { Charger_state=BATTERY_VOLTAGE_LOW;//배터리 전압이 너무 낮습니다. Serial.println(M2S(msg_voltage_too_low)); update_lcd(M2S(msg_voltage_too_low_short),construct_status_string()); 지연(1000); } 부서지다; case BATTERY_VOLTAGE_LOW://배터리 전압이 너무 낮습니다. update_lcd(M2S(msg_voltage_too_low_short),construct_status_string()); Serial.println(M2S(msg_voltage_too_low)); Charger_state=FINAL_STATE;//중단 중단; case CURRENT_RAMP_UP:///Current rampup //if (current_mA<1.0) Charger_state=40;//Current가 예기치 않게 떨어졌습니다 read_status(); update_lcd(M2S(msg_ramp_up),construct_status_string()); 지연(50); if (current_mAMAXIMUM_BATTERY_VOLTAGE ) Charger_state=OVERVOLTAGE;//과전압 if (abs(current_mA-target_current_mA)>0.2){//If (전류가 목표에서 벗어난 경우) 0.01) want_dac_voltage=wanted_dac_voltage-VOLTAGE_STEP; else Charger_state=CURRENT_TOO_HIGH;//전류가 너무 높아서 낮출 수 없음 } } if (abs(current_mA-target_current_mA)>5){//조절 실패, 차이가 너무 높음 충전기_state=REGULATION_FAILED;//조절 오류, 차이가 너무 높음 } dac_write_voltage (wanted_dac_voltage); if (total_minutes_averagetrickle_current_mA) { if (wanted_dac_voltage>VOLTAGE_STEP) {wanted_dac_voltage=wanted_dac_voltage-VOLTAGE_STEP; dac_write_voltage(wanted_dac_voltage); } else Charger_state=CURRENT_TOO_HIGH;//전류를 세류 속도로 줄일 수 없음 } else { charge_state=TRICKLE;//충전 TrickleChargingTimeMillis=0; Serial.println(M2S(msg_trickle_charge)); } 부서지다; case TRICKLE://충전지연(200); read_status(); if (current_mA<0.2) Charger_state=UNEXPECTED_CURRENT_FALL;//Current가 예기치 않게 떨어졌습니다 if (battery_voltage>MAXIMUM_BATTERY_VOLTAGE ) Charger_state=OVERVOLTAGE;//과전압 if (abs(current_mA-trickle_current_mA)>0.2) from (devcurrent_ated target from if current) 0.01) want_dac_voltage=wanted_dac_voltage-VOLTAGE_STEP; else Charge_state=CURRENT_TOO_HIGH;//전류가 너무 높아서 낮출 수 없음 } } if (abs(current_mA-trickle_current_mA)>5){//조절 실패, 차이가 너무 높음 충전기_state=REGULATION_FAILED;//조절 오류, 차이가 너무 높음 } dac_write_voltage (wanted_dac_voltage); //if (total_minutes_averagemax_time_for_trickle_charge) {//최대 허용 세류 충전 update_lcd(eoc_line1,eoc_line2); Charger_state=END_OF_TRICKLE;//disconnect_charging_circuit() 중지; //배터리에서 충전기 분리 } break; 경우 END_OF_TRICKLE:if ((second()%8)<4) update_lcd(M2S(msg_trickle_completed),construct_status_string()); 그렇지 않으면 update_lcd(eoc_line1,eoc_line2); 부서지다; case UNEXPECTED_CURRENT_FALL://전류가 예기치 않게 떨어졌습니다. Serial.println(F("전류가 예기치 않게 떨어졌습니다")); 분리_충전_회로(); 원티드_dac_전압=0; update_lcd(M2S(msg_no_current),construct_status_string()); Charger_state=FINAL_STATE;//지연 정지(1000); 부서지다; case UNABLE_TO_REACH_CURRENT://원하는 현재 Serial.println(M2S(msg_current_unreachable_long))에 연결할 수 없습니다. 분리_충전_회로(); 원티드_dac_전압=0; dac_write_voltage(wanted_dac_voltage); 지연(1000); update_lcd(M2S(msg_current_unreachable),construct_status_string()); Charger_state=FINAL_STATE;//중단 중단; case FULLY_CHARGED://완전 충전 elapsed_time=mills2time(ChargingTimeMillis); int charge_mAh; Charge_mAh=calculate_charge(ChargingTimeMillis); msg =String(M2S(msg_completed)+M2S(msg_space)+construct_time_string(elapsed_time)); msg1=문자열(M2S(msg_charge)+M2S(msg_space)+문자열(충전_mAh)+문자열("mAh")); eoc_line1=메시지; eoc_line2=msg1; update_lcd(msg,msg1); Serial.println(msg); //연결 해제_충전_회로(); //wanted_dac_voltage=0; //dac_write_voltage(wanted_dac_voltage); 지연(3000); Charger_state=CURRENT_RAMP_DOWN;//중단 중단; case CURRENT_TOO_HIGH://전류가 너무 높음 Serial.println(F("목표로 전류를 낮출 수 없습니다.")); 분리_충전_회로(); 원티드_dac_전압=0; dac_write_voltage(0); update_lcd(M2S(msg_high_current),construct_status_string()); 지연(1000); Charger_state=FINAL_STATE;//중단 중단; case REGULATION_FAILED://조절 실패 Serial.println(M2S(msg_regulation_fault)); 분리_충전_회로(); 원티드_dac_전압=0; dac_write_voltage(0); update_lcd(M2S(msg_regulation_fault),construct_status_string()); 지연(1000); Charger_state=FINAL_STATE;//중단 중단; case OVERCURRENT://과전류 연결 해제_충전_회로(); Serial.println(M2S(msg_overcurrent)); 원티드_dac_전압=0; dac_write_voltage(wanted_dac_voltage); update_lcd(M2S(msg_overcurrent),construct_status_string()); 지연(1000); Charger_state=FINAL_STATE;//중단 중단; case OVERVOLTAGE://과전압 연결 해제_충전_회로(); Serial.println(M2S(msg_overvoltage)); 원티드_dac_전압=0; dac_write_voltage(wanted_dac_voltage); update_lcd(M2S(msg_overvoltage),construct_status_string()); 지연(1000); Charger_state=FINAL_STATE;//중단 중단; case FINAL_STATE://지연 정지(10000); 부서지다; 기본값:want_dac_voltage=0; Charger_state=0; } //Serial.println(current_mA); //Serial.print("현재="); //Serial.print(current_mA); //Serial.println("mA"); //Serial.print("DAC 전압"); //Serial.println(dac_voltage); //Serial.print("원하는 DAC 전압"); //Serial.println(wanted_dac_voltage); //Serial.print(current_mA); //Serial.print(" "); //Serial.print(dac_voltage); //Serial.print(" "); read_status(); if (last_second!=second()){ Serial.print(current_mA); Serial.print(","); //Serial.print(resistor_voltage); //Serial.print(","); //Serial.print(dac_voltage); //Serial.print(","); //Serial.print(regulator_voltage); //Serial.print(","); Serial.println(배터리 전압); last_second=초(); }}
    hw.ino아두이노
    float get_approximated_dac_voltage(float vbat){ //float offset_voltage=1.2/R3*(R3+R4); 부동 오프셋_전압=1.2; float adc_voltage=(vbat-offset_voltage)/AMP_GAIN-0.5; if (adc_voltage<0) adc_voltage=0; return adc_voltage;}int voltage_to_code(부동 전압){ int code=4095.0/DAC_REF_VOLTAGE*voltage; 반환 코드;} 무효 dac_write(int 코드){ Wire.beginTransmission(MCP4725_ADDR); Wire.write(64); // cmd를 사용하여 DAC 업데이트 Wire.write(code>> 4); // 최상위 8비트... Wire.write((code &15) <<4); // 4개의 최하위 비트... Wire.endTransmission();}void read_status(){ voltage_sum=0; 현재_합=0; for (i=0;i=POINTS_FOR_AVERAGING) averaging_index=0; if(tmp_battery_voltage>MAXIMUM_BATTERY_VOLTAGE) { 연결 해제_충전_회로(); //배터리에서 충전기 연결 끊기 충전기_state=OVERVOLTAGE; } if (tmp_current_mA>MAXIMIM_ALLOWED_CURRENT ){ 연결 해제_충전_회로(); //배터리에서 충전기 연결 끊기 충전기_state=OVERCURRENT; }}disconnect_charging_circuit(){ digitalWrite(CHARGE_RELAY_PIN,DISCONNECT_CHARGE_RELAY); //배터리에서 충전기 분리}void connect_Charge_circuit(){ digitalWrite(CHARGE_RELAY_PIN,CONNECT_CHARGE_RELAY); //충전기에 배터리 연결}//sec_index=0;//min_index=0;
    lcd.ino아두이노
    무효 update_lcd(문자열 first_line,문자열 second_line){ //Serial.print("update_lcd"); //Serial.print(lcd_last_string2); //Serial.print(" "); //Serial.println(second_line); if (lcd_last_string1!=first_line){ lcd.clear(); lcd.setCursor(0,0); lcd.print(첫줄); lcd_last_string1=첫 번째 줄; lcd.setCursor(0,1); lcd.print(second_line); lcd_last_string2=second_line; } if(lcd_last_second!=second()){ if (lcd_last_string2!=second_line){ lcd.setCursor(0,1); lcd.print(second_line); lcd_last_string2=second_line; } } lcd_last_second=second();}문자열 구성_상태_문자열(무효){ 문자열 v,i; if (battery_voltage<10) v=String(battery_voltage, 2); 그렇지 않으면 v=문자열(배터리 전압, 1); if (current_mA<10) i=String(current_mA, 2); 그렇지 않으면 i=문자열(전류_mA, 1); //Serial.println(v); mytime 경과; 문자열 msg,msg_time; //Serial.print(충전 시작); //Serial.print(" "); //Serial.println(String(millis()-Charging_started)); switch(charger_state){ 케이스 충전:elapsed=mills2time(ChargingTimeMillis); 부서지다; 사례 TRICKLE:elapsed=mills2time(TrickleChargingTimeMillis); 부서지다; } if (charger_state==충전 || Charger_state==TRICKLE){ if (elapsed.total_minutes<10) msg_time=String(elapsed.total_minutes)+" "; else if (elapsed.total_minutes<100) msg_time=String(elapsed.total_minutes)+" "; else msg_time=String(elapsed.total_minutes); } switch(charger_state){ 케이스 충전:msg=v+String(F("V "))+i+String(F("mA"))+" "+msg_time; 부서지다; 경우 트릭:msg=v+String(F("V "))+i+String(F("mA"))+" "+msg_time; 부서지다; 기본값:msg=v+문자열(F("V"))+i+문자열(F("mA")); } msg.replace("-","");//Remove minus sign return msg;}String construct_time_string(mytime timeinfo){ String mystring=String(timeinfo.hours,DEC)+String(F(":"))+String(timeinfo.minutes,DEC); //return String(timeinfo.hours,DEC)+String(F(":"))+String(timeinfo.minutes,DEC); return mystring;}
    calculations.inoArduino
    float best_linear_fit(float y[MINUTES_TO_LOG]){ float sx =0.0, sy =0.0, sxx =0.0, sxy =0.0; //int n =y.size(); for (i =0; i  
    New LiquidCrystal library used for this projectArduino
    미리보기 없음(다운로드만 가능).

    회로도

    charger_AgK96zxw2T.zip

    제조공정

    1. 갈증 경보 식물 알람
    2. 이탈리아어 단어 시계
    3. 4x3 키패드용 핀 3개
    4. Sigfox kWh 미터
    5. 블루투스 온도 모니터
    6. 제스처 제어 잠금
    7. 컴패니언 IC
    8. USB MIDI 어댑터
    9. Arduino용 절연 아날로그 입력
    10. 반응 시간 측정