Carregador inteligente para baterias recarregáveis de 9V NiMH V1
Componentes e suprimentos
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Sobre este projeto
Procurei um carregador inteligente que pode carregar uma bateria 9V NiMH em algumas horas e não encontrei um. Além disso, todos os carregadores que encontrei eram realmente "burros". Corrente de carregamento desconhecida e nenhuma função para encerrar o carregamento após a bateria estar totalmente carregada. Problema com tais carregadores que podem sobrecarregar a bateria e reduzir significativamente sua vida útil. Então decidi criar um carregador "inteligente".
Pretendo manter a primeira versão simples, de modo que permite coisas básicas como carregar com corrente constante, término automático do carregamento após a bateria totalmente carregada, carga lenta, medição da carga transferida para a bateria.
Na próxima versão, acrescentarei alguns recursos úteis adicionais, como descarga, medição de capacidade e ciclagem.
Aviso:Carregar a bateria com alta corrente pode causar explosão ou incêndio. Por favor, não deixe o carregador sem supervisão. Além disso, não tente carregar uma bateria que não seja alcalina. Este carregador foi testado apenas com baterias NiMH (e ainda assim você o está usando por sua própria conta e risco e eu não tenho nenhuma responsabilidade se houver algum dano causado por erros no design ou código). O desgosto de outros tipos de baterias exigirá a modificação do código.
Teoria
Alguns fatos úteis para lembrar que ajudarão a entender os parâmetros necessários do carregador.
C - corrente igual à capacidade nominal da bateria
Quando carregada na taxa C, a voltagem de célula única pode chegar a 1,6V. Esta tensão pode ser maior para baterias velhas.
A voltagem nominal de uma única célula é de 1,2 V, mas a célula totalmente carregada tem uma voltagem de circuito aberto de até 1,5 volt.
Recomenda-se uma taxa de carga lenta inferior a 0,025 C (C / 40) após a bateria estar totalmente carregada.
Geralmente, há duas opções para carregar a bateria NiMH:
1. Carregamento rápido. Corrente de carregamento 0,5C-1C. O estado de carga deve ser monitorado e encerrado por dV / dt (taxa de mudança de tensão) ou dT / dt (taxa de mudança de temperatura)
2. Carregamento lento. Corrente de carregamento 0.1C. Tempo de carregamento 14-16 horas. Encerramento de carga por cronômetro. Terminação de carga dT / dt impossível para correntes baixas. A terminação dV / dt pode não ser confiável para correntes abaixo de 0,5C, de acordo com a literatura.
Parâmetros básicos do circuito de carregamento
A bateria de 9 V geralmente tem 7 pontos de venda conectados em série, mas em alguns casos pode ter 6 ou 8 células. O regulador de tensão deve ser capaz de fornecer tensão de carga de pelo menos 8 * 1,6 =12,8V. Tensão de queda do regulador LM317 de até 2 V, então a tensão de alimentação precisa ser ~ 15 V (isso não leva em consideração a queda de tensão no resistor de detecção de corrente).
Para corrente de carga máxima de 200mA e resistor de detecção de corrente de 10 Ohm, a queda adicional no resistor de detecção de corrente é de 2 V, portanto, é necessária uma tensão de alimentação de 17 V.
A célula totalmente descarregada pode ter tensão muito baixa, mesmo negativa. A tensão mínima do regulador idealmente deve ser 0, mas usando o LM317, pode ser tão baixa quanto 1,2V.
Circuito
Explicações do circuito
A ideia básica é medir a corrente de carga e ajustar a tensão do regulador até que a corrente desejada seja alcançada. Corrente medida medindo a queda de tensão no resistor de detecção de corrente R5. I =V / R.
SparkFun I2C DAC Breakout - MCP4725 - conversor digital para analógico de 12 bits usado para controlar a tensão. A tensão de saída pode ser configurada via I2C entre 0 e 5V. Porque precisamos ser capazes de ajustar a tensão em uma faixa mais ampla, de 0 a 15 V amplificador operacional LM358 usado para amplificar a tensão de saída do DAC. Amplificação do amplificador operacional definido pelos resistores R4 e R3. Ganho =1 + R4 / R3 =1 + 6800/3300 =3,06 então a tensão de saída do amplificador operacional é de aproximadamente 0 a 15V.
A corrente de saída máxima do LM358 é 50mA, então o regulador de tensão ajustável LM317 é usado para controlar a corrente mais alta. Saída do amplificador operacional conectado ao terminal ADJ do LM317. O LM317 manterá 1,2 V entre os terminais ADJ e OUT, de modo que a tensão real da bateria pode ser configurada entre 1,2 e 16,2 V. O LM317 precisa de corrente mínima de 3,5 mA para manter a regulação. Portanto, o resistor R6 de 1kOhm é usado para garantir a regulagem se a bateria não estiver conectada. Capacitor C1 usado para filtrar a tensão de saída e melhorar a estabilidade do LM317.
Tensão medida em dois pontos diferentes.
1. Resistor R5 conectado ao pino A2 do Arduino. Tensão no resistor medida e então a corrente de carga calculada como Icharging =V / R
2. A tensão na bateria pode ser de até 16,2 V, então o divisor resistivo R1, R2 costumava trazer a tensão abaixo de 5 V, permitido pelo Arduino. Saída do divisor conectado ao pino A0 do Arduino. Para R1 =5,1k Ohm e R2 =20kOhm Vout =Vin / (20000 + 5100) * 5100 =0,2 Portanto, a tensão da bateria dividida por 5.
Relé usado para desconectar a bateria do circuito de carga. Você pode ver no foto-relé que usei, mas geralmente qualquer relé com controle de 5V pode ser usado. É mais seguro conectar a bateria aos contatos normalmente abertos do relé.
Usei YwRobot I2C SERIAL LCD MÓDULO 1602 para exibir o status do carregador, mas qualquer outro módulo LCD controlado por I2C pode ser usado. Parece que o módulo YwRobot LCD não é compatível com a biblioteca LiquidCrystal_I2C padrão, então usei a nova biblioteca LiquidCrystal. Se você estiver usando um módulo LCD diferente, será necessário alterar esta linha:
LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVO); // define o endereço LCD para 0x27 para um display de 16 caracteres e 2 linhas
Para alimentar o conversor digital para analógico e o LCD, usei a fonte de alimentação SparkFun Breadboard 5V / 3,3V. Provavelmente não haverá problema em usar 5V da placa Arduino.
Você também precisará fornecer 17 V ao circuito de carregamento. Se você não tem fonte de alimentação, você pode usar um conversor DC / DC ajustável como este
http://www.ebay.com/itm/DC-DC-Adjustable-Step-up-boost-Power-Converter-Module-XL6009-Replace-LM2577-/310717070508
Funcionalidade
Eu não queria muitos fios, então não há botões para configurar o carregamento. Chagrin atual configurado apenas em código. Você precisa definir a corrente de carga desejada no charger.ino
// *************************** Parâmetros de carregamento ************* ***************************** // ******************** *************************************************** ******************* float target_current_mA =30; // Corrente de carregamento mAfloat battery_nominal_capacity_mA =170; // Capacidade nominal da bateria mAfloat max_time_for_trickle_charge =6; // Tempo máximo de carga lenta em minutos // *************************************** *************************************************** / / ************************************************** *****************************************
target_current_mA - corrente de carga constante
max_time_for_trickle_charge - número máximo de minutos para carregamento lento, pode ser configurado até 600 (10h)
battery_nominal_capacity_mA - capacidade da bateria usada para calcular a corrente de gotejamento
Geralmente, a corrente de carga pode atingir a capacidade nominal. Para bateria com capacidade nominal de 170mAh, a corrente máxima de carga é 170mA. Corrente de carga mínima geralmente C / 10 - 17mA para bateria de 170mAh.
Depois de ligar o carregador, verificará se a bateria está conectada. Se a bateria estiver conectada, a bateria será carregada com a corrente constante configurada até que esteja totalmente carregada. O carregamento foi encerrado detectando dV / dt negativo durante 5 minutos. Após o carregamento concluído, o carregador mudará para carregamento lento com C / 40 atual. O carregador se desconectará da bateria depois de decorrido o tempo máximo de carregamento lento.
1 - dV / dt
2 - tempo de carregamento em minutos
1 - Tempo de carregamento
2 - Carga transferida para a bateria
Informações adicionais sobre baterias NiMH:
1. http://data.energizer.com/PDFs/nickelmetalhydride_appman.pdf
2. http://batteryuniversity.com/learn/article/charging_nickel_metal_hydride
Código
- charger.ino
- main.ino
- hw.ino
- lcd.ino
- cálculos.ino
- Nova biblioteca LiquidCrystal usada para este projeto
charger.ino Arduino
Arquivo principal// ISTO para carregar bateria NiMH de 9 V // A bateria pode ter 6,7 ou 8 células de 1,25 V // Isso torna a tensão nominal entre 7,5 e 10 V # include#include #include #include #include LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVO); // definir o endereço LCD para 0x27 para um display de 16 caracteres e 2 linhas // Definições de hardware # definir MCP4725_ADDR 0x60 // endereço DAC # definir DAC_REF_VOLTAGE 5.0 # definir CHARGE_RELAY_PIN 2 # definir DISCONNECT_CHARGE_RELAY HIGH # definir CONNECT_CHARGE_RELAY_VOLTAGE 5.0 # definir CHARGE_RELAY_PIN 2 # definir DISCONNECT_CHARGE_RELAY HIGH # definir CONNECT_CHARGE_RELAY_VOLTAGE 5.0 # definir CURSO_RELAY_PIN 2 # definir DISCONNECT_CHARGE_RELAY HIGH # definir CONNECT_CHARGE_RELAY_RELAY_SORRENT # definir CURSO_REG_RELAY__RELAYW # definir CURSO_IN_RELAY__RELAYW # definir. CURRENT_SENSING_SESISTOR 10.2 // OHm # define BATTERY_VOLTAGE_PIN A0 # define R1 5090 // Resistor do lado inferior do divisor de detecção de tensão # define R2 19910 // Resistor do lado alto do divisor de detecção de tensão # define ADC_REF_VOLTAGE 4.89 // Arduino real tensão de alimentação ou tensão AREF para adequada ADC para conversão de tensão # define R3 3300.0 # define R4 6800.0 # define AMP_GAIN (1 + R4 / R3) // Várias definições // # define MINIMUM_VOLTAGE 8.1 // Tensão mínima após regulador # define BATTERY_GOOD_VOLTAGE_THRESHOLD 7.0 # define MAXIMIM_ALLOWED_CURRENT 200 // Máximo permitido corrente da bateria mA (corte forçado) #define MAXIMUM_BATTERY_VOLTAGE 15.0 // Tensão máxima permitida da bateria V (corte forçado) #define VOLTAGE_STEP 0,001 // Etapa para tensão regulamento # define POINTS_FOR_AVERAGING 100 // Quantos pontos tomados para calcular a média # define MEASURE2MEASURE_US 5000 // Tempo entre medições em microssegundos (precisa ser mais de 200 por causa de duas leituras analógicas) #define VOLTAGE_LOG_TIME_MIN 30,0 // Tempo em minutos para economizar tensão para dV / dT corte # definir MINUTES_TO_LOG 5 # definir TRICKLE_CURRENT_RATIO 40 // Carregador afirma # definir inicialização 0 # definir NO_BATTERY 5 # definir BATTERY_CONNECTED 10 # definir BATTERY_VOLTAGE_LOW 15 # definir CURRENT_RAMP_UP 20 # definem CARREGAMENTO 30 # 32 # definir CURRENT_RAMP_DOWN definir GOTEJAMENTO 35 # definir END_OF_TRICKLE 37 # define UNEXPECTED_CURRENT_FALL 40 # define UNABLE_TO_REACH_CURRENT 60 # define FULLY_CHARGED 70 # define CURRENT_TOO_HIGH 80 # define REGULATION_FAILED 90 # define OVERCURRENT 100 # define OVERVOLTAGE 101 # define FULLY_CHARGED 70 # define CURRENT_TOO_HIGH 80 # define REGULATION_FAILED 90 # define OVERCURRENT 100 # define OVERVOLTAGE 101 # define FINAL_STATE_FONTE_INDES_reading_FORAGENS_Tensão 200_FORAGING_FORTS_readings_interpretado_interno_portagens_tensão_interna_portando_tensão_interna_portagens_portagens_padrão_pontagem // Para averaginglong unsigned int voltage_sum, current_sum; // Soma de averagingf loat regulator_voltage_code, resistor_voltage, csr_voltage_code, regulator_voltage, current_mA, battery_voltage; // Measurmentsfloat tmp_resistor_voltage, tmp_current_mA, tmp_regulator_voltage, tmp_battery_voltage; int i, j, charger_state; unsigned short int last_second, lcd_last_second, log_last_second; Cadeia lcd_last_string1, lcd_last_string2; Cadeia EMPTY_STRING =""; String msg, eoc_line1, eoc_line2; unsigned char sec_index, min_index; // long long int charge_started; float sec_log [60], min_log [MINUTES_TO_LOG], last_blf; float trickle_current_mA; int total_harutes Charutes_averageMillis =0; 0; float last_dac_voltage =0; // Mensagensconst char msg_battery_detected [] PROGMEM ="Bateria detectada"; const char msg_no_battery [] PROGMEM ="Sem bateria"; const char msg_battery_ok [] PROGMEM ="Bateria ok"; const char msg_no_battery [] PROGMEM ="Sem bateria"; const char msg_battery_ok [] PROGMEM ="Bateria ok"; const char msg_voltage_too_ PROGMEM ="Bateria com tensão muito baixa"; const char msg_voltage_too_low_short [] PROGMEM ="V Bateria fraca"; const char msg_ramp_up [] PROGM EM ="Aumentar"; const char msg_charging [] PROGMEM ="Carregando"; const char msg_space [] PROGMEM =""; const char msg_ramp_down [] PROGMEM ="Diminuir"; const char msg_trickle_charge [] PROGMEM ="Carga lenta "; const char msg_no_current [] PROGMEM =" Sem corrente "; const char msg_current_unreachable [] PROGMEM =" I inacessível "; const char msg_current_unreachable_long [] PROGMEM =" Não foi possível atingir a corrente desejada "; const char msg_completed [] "; const char msg_charge [] PROGMEM =" Carga "; const char msg_high_current [] PROGMEM =" Corrente alta "; const char msg_regulation_fault [] PROGMEM =" Falha de regulação "; const char msg_overcurrent [] PROGMEM =" Corrente muito alta "; const char msg_overvoltage [] PROGMEM ="Voltagem muito alta"; const char msg_trickle_completed [] PROGMEM ="Trickle finalizado"; // ************************ **** Parâmetros de carregamento ***************************************** // * *************************************************** *************************************** float target_current_mA =30; // Corrente de carregamento mAfloat battery_nominal_capacity_mA =170; // Capacidade nominal da bateria mAfloat max_time_for_trickle_charge =6; // Tempo máximo de carga lenta em minutos // *************************************** *************************************************** / / ************************************************** ***************************************** struct mytime {unsigned char hours; minutos de char unsigned; unsigned int total_minutes;} tempo decorrido; configuração void () {pinMode (CHARGE_RELAY_PIN, OUTPUT); desconectar_charging_circuit (); // Desconecte o carregador da bateria Wire.begin (); // I2C dac_write_voltage (0); // Certifique-se de menor conjunto de corrente possível Serial.begin (115200); último_segundo =segundo (); lcd_último_segundo =segundo (); log_último_segundo =segundo (); Timer1.initialize (MEASURE2MEASURE_US); // Usará para medir a tensão e a corrente da bateria (microssegundos) Timer1.attachInterrupt (read_hw); // anexa read_hw () como uma interrupção de estouro do temporizador averaging_index =0; sec_index =0; min_index =0; charger_state =0; // Estado inicial da máquina de estado want_dac_voltage =0; // Verifique a saída de tensão mínima 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 ("Ligar ..."), string_vazia); delay (1000);} float log_battery_voltage () {// Registra apenas uma vez por segundo if (log_last_second ==second ()) return last_blf; senão log_último_segundo =segundo (); sec_log [sec_index] =bateria_voltagem; if (sec_index <59) {sec_index ++; } else {// Se um minuto registrado // Calcula a média por minuto if (min_index> =MINUTES_TO_LOG) min_index =0; sec_index =0; float sum_v =0; para (i =0; i <60; i ++) {sum_v + =sec_log [i]; } float min_average =sum_v / 60.0; para (i =1; i main.ino Arduino
void loop () {String msg1; switch (charger_state) {case INITIALIZATION:// Estado inicial disconnect_charging_circuit (); // Faça o relé shure desconectado dac_write_voltage (0); // Certifique-se de menor conjunto de corrente possível Want_dac_voltage =0; // Verifique o retardo de saída de tensão mínima (100); read_status (); if (battery_voltage> 0.1) {charger_state =BATTERY_CONNECTED; // Bateria detectada update_lcd (M2S (msg_battery_detected), empty_string); Serial.println (M2S (msg_battery_detected)); atraso (2000); } else {// Sem bateria Serial.println (M2S (msg_no_battery)); update_lcd (M2S (msg_no_battery), construct_status_string ()); charger_state =NO_BATTERY; // Atraso detectado da bateria (1000); } pausa; case NO_BATTERY:// Sem bateria read_status (); if (battery_voltage> 0.1) {charger_state =BATTERY_CONNECTED; // Bateria detectada Serial.println (M2S (msg_battery_detected)); update_lcd (M2S (msg_battery_detected), construct_status_string ()); atraso (1500); } else {// Se nenhuma bateria permanecer neste estado update_lcd (M2S (msg_no_battery), construct_status_string ()); atraso (1100); } pausa; case BATTERY_CONNECTED:// Bateria conectada dac_write_voltage (0); // Certifique-se de definir a corrente mais baixa possível Want_dac_voltage =0; atraso (100); read_status (); if (battery_voltage> BATTERY_GOOD_VOLTAGE_THRESHOLD) {charger_state =CURRENT_RAMP_UP; // Comece a carregar o aumento atual // snprintf (welcome, sizeof (welcome), "Firmware:V% d.% d% d", ver, ver2, ver3); update_lcd (M2S (msg_battery_ok), construct_status_string ()); Serial.println (M2S (msg_battery_ok)); atraso (2000); Want_dac_voltage =get_approximated_dac_voltage (battery_voltage); // Definir a tensão necessária do regulador //Serial.println(get_approximated_dac_voltage(battery_voltage)); connect_charging_circuit (); atraso (200); } else {charger_state =BATTERY_VOLTAGE_LOW; // Tensão da bateria muito baixa Serial.println (M2S (msg_voltage_too_low)); update_lcd (M2S (msg_voltage_too_low_short), construct_status_string ()); atraso (1000); } pausa; case BATTERY_VOLTAGE_LOW:// Voltagem da bateria muito baixa update_lcd (M2S (msg_voltage_too_low_short), construct_status_string ()); Serial.println (M2S (msg_voltage_too_low)); charger_state =FINAL_STATE; // Interromper pausa; case CURRENT_RAMP_UP:/// Rampup atual // if (current_mA <1.0) charger_state =40; // Atual caiu inesperadamente read_status (); update_lcd (M2S (msg_ramp_up), construct_status_string ()); atraso (50); if (current_mAMAXIMUM_BATTERY_VOLTAGE) charger_state =OVERVOLTAGE; // Sobretensão if (abs (current_mA-target_current_mA) 0,01) want_dac_voltage =wanted_dac_voltage-VOLTAGE_STEP; else charger_state =CURRENT_TOO_HIGH; // Corrente muito alta, incapaz de diminuir}} if (abs (current_mA-target_current_mA)> 5) {// Falha de regulação, diferença muito alta charger_state =REGULATION_FAILED; // Erro de regulação, diferença muito alta} dac_write_voltage (want_dac_voltage); if (total_minutes_average trickle_current_mA) {if (want_dac_voltage> VOLTAGE_STEP) {want_dac_voltage =want_dac_voltage-VOLTAGE_STEP; dac_write_voltage (want_dac_voltage); } else charger_state =CURRENT_TOO_HIGH; // Incapaz de reduzir a corrente para a taxa de gotejamento} else {charger_state =TRICKLE; // Carregamento TrickleChargingTimeMillis =0; Serial.println (M2S (msg_trickle_charge)); } pausa; case TRICKLE:// Atraso de carregamento (200); read_status (); if (current_mA <0.2) charger_state =UNEXPECTED_CURRENT_FALL; // A corrente caiu inesperadamente if (battery_voltage> MAXIMUM_BATTERY_VOLTAGE) charger_state =OVERVOLTAGE; // Sobretensão if (abs (current_mA-trickle_current_mA) 0,01) want_dac_voltage =wanted_dac_voltage-VOLTAGE_STEP; else charger_state =CURRENT_TOO_HIGH; // Corrente muito alta, incapaz de diminuir}} if (abs (current_mA-trickle_current_mA)> 5) {// Falha na regulação, diferença muito alta charger_state =REGULATION_FAILED; // Erro de regulação, diferença muito alta} dac_write_voltage (want_dac_voltage); // if (total_minutes_average max_time_for_trickle_charge) {// Carga residual máxima permitida update_lcd (eoc_line1, eoc_line2); charger_state =END_OF_TRICKLE; // Pare a desconexão_charging_circuit (); // Desconecte o carregador da bateria} break; case END_OF_TRICKLE:if ((second ()% 8) <4) update_lcd (M2S (msg_trickle_completed), construct_status_string ()); senão update_lcd (eoc_line1, eoc_line2); pausa; case UNEXPECTED_CURRENT_FALL:// Atual caiu inesperadamente Serial.println (F ("Atual caiu inesperadamente")); desconectar_charging_circuit (); want_dac_voltage =0; update_lcd (M2S (msg_no_current), construct_status_string ()); charger_state =FINAL_STATE; // Interromper atraso (1000); pausa; case UNABLE_TO_REACH_CURRENT:// Incapaz de alcançar o Serial.println atual desejado (M2S (msg_current_unreachable_long)); desconectar_charging_circuit (); want_dac_voltage =0; dac_write_voltage (want_dac_voltage); atraso (1000); update_lcd (M2S (msg_current_unreachable), construct_status_string ()); charger_state =FINAL_STATE; // Interromper pausa; case FULLY_CHARGED:// Elapsed_time =mills2time (ChargingTimeMillis); int charge_mAh; charge_mAh =calcule_charge (ChargingTimeMillis); msg =String (M2S (msg_completed) + M2S (msg_space) + construct_time_string (elapsed_time)); msg1 =String (M2S (msg_charge) + M2S (msg_space) + String (charge_mAh) + String ("mAh")); eoc_line1 =msg; eoc_line2 =msg1; update_lcd (msg, msg1); Serial.println (msg); // desconectar_charging_circuit (); // want_dac_voltage =0; // dac_write_voltage (wanted_dac_voltage); atraso (3000); charger_state =CURRENT_RAMP_DOWN; // Parar pausa; case CURRENT_TOO_HIGH:// Corrente muito alta Serial.println (F ("Incapaz de diminuir a corrente para o alvo")); desconectar_charging_circuit (); want_dac_voltage =0; dac_write_voltage (0); update_lcd (M2S (msg_high_current), construct_status_string ()); atraso (1000); charger_state =FINAL_STATE; // Interromper pausa; case REGULATION_FAILED:// O regulamento falhou Serial.println (M2S (msg_regulation_fault)); desconectar_charging_circuit (); want_dac_voltage =0; dac_write_voltage (0); update_lcd (M2S (msg_regulation_fault), construct_status_string ()); atraso (1000); charger_state =FINAL_STATE; // Interromper pausa; case OVERCURRENT:// Overcurrent disconnect_charging_circuit (); Serial.println (M2S (msg_overcurrent)); want_dac_voltage =0; dac_write_voltage (want_dac_voltage); update_lcd (M2S (msg_overcurrent), construct_status_string ()); atraso (1000); charger_state =FINAL_STATE; // Interromper pausa; case OVERVOLTAGE:// Overvoltage disconnect_charging_circuit (); Serial.println (M2S (msg_overvoltage)); want_dac_voltage =0; dac_write_voltage (want_dac_voltage); update_lcd (M2S (msg_overvoltage), construct_status_string ()); atraso (1000); charger_state =FINAL_STATE; // Interromper pausa; case FINAL_STATE:// Halt delay (10000); pausa; padrão:want_dac_voltage =0; charger_state =0; } //Serial.println(current_mA); //Serial.print("Current="); //Serial.print(current_mA); //Serial.println("mA "); //Serial.print("DAC voltage "); //Serial.println(dac_voltage); //Serial.print("Wanted DAC voltage "); //Serial.println(wanted_dac_voltage); //Serial.print(current_mA); //Serial.print (""); //Serial.print(dac_voltage); //Serial.print (""); read_status (); if (último_segundo! =segundo ()) {Serial.print (corrente_mA); Serial.print (","); //Serial.print(resistor_voltage); //Serial.print (","); //Serial.print(dac_voltage); //Serial.print (","); //Serial.print(regulator_voltage); //Serial.print (","); Serial.println (bateria_voltagem); último_segundo =segundo (); }} hw.ino Arduino
float get_approximated_dac_voltage (float vbat) {// float offset_voltage =1,2 / R3 * (R3 + R4); float offset_voltage =1,2; float adc_voltage =(vbat-offset_voltage) /AMP_GAIN-0.5; if (adc_voltage <0) adc_voltage =0; retorno adc_voltage;} int voltagem_para_código (voltagem flutuante) {código interno =4095.0 / DAC_REF_VOLTAGE * voltagem; código de retorno;} void dac_write (código interno) {Wire.beginTransmission (MCP4725_ADDR); Wire.write (64); // cmd para atualizar o DAC Wire.write (código>> 4); // os 8 bits mais significativos ... Wire.write ((code &15) <<4); // os 4 bits menos significativos ... Wire.endTransmission ();} void read_status () {voltage_sum =0; current_sum =0; para (i =0; i=POINTS_FOR_AVERAGING) averaging_index =0; if (tmp_battery_voltage> MAXIMUM_BATTERY_VOLTAGE) {disconnect_charging_circuit (); // Desconecte o carregador da bateria charger_state =OVERVOLTAGE; } if (tmp_current_mA> MAXIMIM_ALLOWED_CURRENT) {disconnect_charging_circuit (); // Desconecte o carregador da bateria charger_state =OVERCURRENT; }} void disconnect_charging_circuit () {digitalWrite (CHARGE_RELAY_PIN, DISCONNECT_CHARGE_RELAY); // Desconecte o carregador da bateria} void connect_charging_circuit () {digitalWrite (CHARGE_RELAY_PIN, CONNECT_CHARGE_RELAY); // Conecte o carregador à bateria} // sec_index =0; // min_index =0; lcd.ino Arduino
void update_lcd (String first_line, String 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 (primeira linha); lcd_last_string1 =first_line; lcd.setCursor (0,1); lcd.print (segunda linha); lcd_last_string2 =second_line; } if (lcd_último_egundo! =segundo ()) {if (lcd_último_string2! =segunda_linha) {lcd.setCursor (0,1); lcd.print (segunda linha); lcd_last_string2 =second_line; }} lcd_last_second =second ();} String construct_status_string (void) {String v, i; if (battery_voltage <10) v =String (battery_voltage, 2); else v =String (bateria_voltagem, 1); if (current_mA <10) i =String (current_mA, 2); else i =String (current_mA, 1); //Serial.println(v); meu tempo decorrido; String msg, msg_time; //Serial.print(charging_started); //Serial.print(" "); //Serial.println(String(millis()-charging_started)); switch(charger_state){ case CHARGING:elapsed=mills2time(ChargingTimeMillis); pausa; case TRICKLE:elapsed=mills2time(TrickleChargingTimeMillis); pausa; } if (charger_state==CHARGING || 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){ case CHARGING:msg=v+String(F("V "))+i+String(F("mA"))+" "+msg_time; pausa; case TRICKLE:msg=v+String(F("V "))+i+String(F("mA"))+" "+msg_time; pausa; default:msg=v+String(F("V "))+i+String(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; iNew LiquidCrystal library used for this projectArduino
Sem visualização (somente download).
Esquemas
charger_AgK96zxw2T.zipProcesso de manufatura