Dateien hochladen nach „ino“

This commit is contained in:
2021-01-05 18:09:54 +01:00
parent b87376516c
commit 0e510b43d1

841
ino/charger_2_1.ino Normal file
View File

@@ -0,0 +1,841 @@
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_ADS1015.h>
//I2C device found at address 0x3C ! -> SSD1306
//I2C device found at address 0x48 ! -> ADS1115
//I2C device found at address 0x60 ! -> MCP4725
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define MCP4725 96 // Adresse 96 oder 97, wie Brücke
#define OLED_RESET 10 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_ADS1115 ads1115(0x48);
//IO pins
byte const io_enter = 2;
byte const io_right = 3;
byte const io_discharge = 4;
byte const io_akku_on = 5;
byte const io_left = 6;
byte const io_U_akku = A7;
byte const io_U_own = A0;
byte const io_U_temp = A1;
//control parameters
int dev_dawert = 3500;
int dawert = 3500;
int const step_up = 1;
int const step_down = 1;
int const search_step_up = 5;
int const search_step_down = 5;
int16_t time;
float T;
float T_start;
byte const T_count = 20;
//limit values
int U_akku_max = 0;
int U_akku_dis_min;
int U_akku_dis_max;
int U_akku_dis_tmp;
int U_akku_dis_tmp_step;
byte const dawert_min = 119;
byte const dawert_max = 131;
//sensor valueas
byte const U_rep = 50;
float dU[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
float dU_xy = 0;
float dU_xx = 0;
float dU_X;
float dU_Y;
float dU_mid = 0;
float dU_mid_max = 0;
int U_akku;
int U_out;
int I_akku;
int32_t U_sum;
int16_t U;
int16_t coulomb_u;
float coulomb_v;
int16_t coulomb;
float U_temp;
float U_own;
float R_T;
float dT[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
const byte dT_count = 20;
byte dT_n;
float dT_mid;
const byte dT_t = 30; // t = dT_t(s) * 1024
int dT_sum = 0;
byte dT_position = 0;
int16_t dT_t_tmp = 0;
float dT_mid_max = 0;
float dT_xy = 0;
float dT_xx = 0;
float dT_X;
float dT_Y;
//temp sensor parameters
float const B = 3435.0;
float const R_R = 10000.0;
float const R_ST = 1000.0;
//menue
bool menu = true;
int sub_menu = 0;
byte position = 0;
byte menu_step;
byte old_position = 0;
byte new_position = 0;
bool press;
bool pressed;
bool select_type = true;
byte type;
String types[] = {"NiMh", "NiCd", "Alkali"};
byte const types_count = 3;
bool select_I_charge = true;
int I_charge;
int charges[] = {10, 20, 30, 40, 50, 80, 100, 150, 200, 250, 300, 350, 400, 450, 500};
byte const charges_count = 15;
bool select_discharge = true;
bool discharge = false;
bool direction = true;
bool max_discharge = true;
String discharges[] = {"true", "false"};
byte const discharge_count = 2;
//global bools
bool full = false;
bool search_mode = true;
void setup() {
analogReference(INTERNAL4V096);
pinMode(io_enter, INPUT);
pinMode(io_right, INPUT);
pinMode(io_discharge, ANALOG);
pinMode(io_left, INPUT);
pinMode(io_akku_on, OUTPUT);
pinMode(io_U_akku, INPUT);
digitalWrite(io_akku_on, LOW);
analogWrite(io_discharge, 0);
Wire.begin();
writemcp4725(dev_dawert);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
ads1115.begin();
}
void loop() {
if (menu == true) {
sub_menu = 0;
position = (types_count * 5);
while (select_type) {
position = position + arrow();
write_display_menu(sub_menu, position);
select_type = enter();
}
type = position % types_count;
sub_menu += 1;
position = (charges_count * 5) + 6;
while (select_I_charge) {
write_display_menu(sub_menu, position);
position = position + arrow();
select_I_charge = enter();
}
I_charge = charges[position % charges_count];
sub_menu += 1;
position = (discharge_count * 5);
while (select_discharge && type != 2) {
write_display_menu(sub_menu, position);
position = position + arrow();
select_discharge = enter();
}
discharge = (position + 1) % discharge_count;
menu = false;
U_akku = map(U_measure(0, 2, 5), 0, 32768, 0, 2048);
if (U_akku < 100) {
menu = true;
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 5);
display.print("no battery");
//print
display.display();
delay(2000);
}
}
display.clearDisplay();
display.display();
if (discharge == true && type != 2) {
dawert = 150;
fnc_discharge();
}
for (int i = 0; i < dT_count; i++) {
T = temp();
U_akku = map(U_measure(0, 2, 20), 0, 32768, 0, 2048);
dT[i] = T;
dU[i] = U_akku;
}
switch (type) {
case 0: //NiMh
dawert = 4096;
while (true) {
charge_nimh();
}
break;
case 1: //NiCd
dawert = 4096;
while (true) {
charge_nicd();
}
break;
case 2: //Alkali
dawert = 4096;
while (true) {
charge_alkali();
}
break;
}
}
bool enter() {
press = false;
pressed = true;
if (digitalRead(io_enter) == HIGH) {
delay(10);
if (digitalRead(io_enter) == HIGH) {
press = true;
}
}
while (press) {
if (digitalRead(io_enter) == LOW) {
pressed = false;
press = false;
}
}
return pressed;
}
byte arrow() {
press = false;
menu_step = 0;
if (digitalRead(io_right) == HIGH) {
delay(10);
if (digitalRead(io_right) == HIGH) {
press = true;
}
}
if (digitalRead(io_left) == HIGH) {
delay(10);
if (digitalRead(io_left) == HIGH) {
press = true;
}
}
while (press) {
if (digitalRead(io_left) == LOW) {
press = false;
menu_step = 1;
}
if (digitalRead(io_right) == LOW) {
press = false;
menu_step = -1;
}
}
delay(250);
return menu_step;
}
void write_display_menu(int sub_menu, int position) {
switch (sub_menu) {
case 0: //select_type
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("select batterie type");
display.setTextSize(2);
display.setCursor(0, 16);
display.print(">");
display.setCursor(20, 16);
display.print(types[position % types_count]);
//print
display.display();
break;
case 1: //select_I_charge
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("select I charge");
display.setTextSize(2);
display.setCursor(0, 16);
display.print(">");
display.setCursor(20, 16);
display.print(charges[position % charges_count]);
display.setCursor(10, 35);
display.print("mA");
//print
display.display();
break;
case 2: //select_discharge
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("discharge before load");
display.setTextSize(2);
display.setCursor(0, 16);
display.print(">");
display.setCursor(20, 16);
display.print(discharges[position % discharge_count]);
//print
display.display();
break;
}
}
int16_t U_measure(byte channel, int gain, int rep) {
switch (gain) {
case 0:
ads1115.setGain(GAIN_TWOTHIRDS);
break;
case 1:
ads1115.setGain(GAIN_ONE);
break;
case 2:
ads1115.setGain(GAIN_TWO);
break;
case 4:
ads1115.setGain(GAIN_FOUR);
break;
case 8:
ads1115.setGain(GAIN_EIGHT);
break;
case 16:
ads1115.setGain(GAIN_SIXTEEN);
break;
case 101:
//
break;
default:
ads1115.setGain(GAIN_TWOTHIRDS);
break;
}
U_sum = 0;
for (int i = 0; i < rep; i++) {
switch (channel) {
case 0:
U = ads1115.readADC_Differential_0_1();;
break;
case 1:
U = ads1115.readADC_Differential_2_3();
break;
case 2:
U = analogRead(io_U_akku);
break;
}
U_sum += U;
}
U = U_sum / rep;
return U;
}
void search_I(int I_charge, bool direction) {
analogWrite(io_discharge, 0);
digitalWrite(io_akku_on, LOW);
I_akku = map(U_measure(1, 16, 10), 0, 32768, 0, 2560) * -1;
writemcp4725(dawert);
direction = true;
while (direction) {
U_out = U_measure(2, 101, 50);
U_akku = map(U_measure(0, 2, 10), 0, 32768, 0, 2048);
if (U_out > (U_akku + 10)) {
direction = false;
digitalWrite(io_akku_on, HIGH);
} else {
dawert -= search_step_down;
writemcp4725(dawert);
digitalWrite(io_akku_on, LOW);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
//line 1 M
display.setCursor(10, 0);
display.print("<search voltage>");
//line 2 L
display.setCursor(0, 12);
display.print("U_a: ");
display.print(U_akku);
//line 2 L
display.setCursor(75, 12);
display.print("I_a: ");
display.print(I_akku);
//line 3 L
display.setCursor(0, 22);
display.print("U_o: ");
display.print(U_out);
//print
display.display();
}
while (I_akku != I_charge && !direction) {
U_akku = map(U_measure(0, 2, 10), 0, 32768, 0, 2048);
I_akku = map(U_measure(1, 16, 10), 0, 32768, 0, 2560) * -1;
if (I_akku < I_charge) {
dawert -= search_step_down;
writemcp4725(dawert);
} else {
dawert += search_step_up;
writemcp4725(dawert);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
//line 1 M
display.setCursor(10, 0);
display.print("<search current>");
//line 2 L
display.setCursor(0, 12);
display.print("U_a: ");
display.print(U_akku);
//line 2 R
display.setCursor(75, 12);
display.print("I_a: ");
display.print(I_akku);
//print
display.display();
}
}
void write_display_data() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
temp_dT();
if (coulomb < I_charge && discharge) {
dT_mid_max = 0;
dU_mid_max = 0;
}
//line 1 L
display.setCursor(0, 0);
display.print("dUmU: ");
if (dU_mid >= 0) {
display.print(" ");
}
display.print(dU_mid, 0);
display.setCursor(70, 0);
if (dU_mid_max == 0) {
display.print("--");
} else {
display.print(dU_mid_max, 0);
}
display.setCursor(100, 0);
display.print(U_akku);
//line 2 L
display.setCursor(0, 12);
display.print("I-Uh: ");
display.print(I_akku);
display.setCursor(70, 12);
if (U_akku_max - U_akku == 0) {
display.print("--");
} else {
display.print(U_akku_max - U_akku);
}
display.setCursor(100, 12);
display.print(fnc_coulomb());
//line 3 L
display.setCursor(0, 22);
display.print("dTmT: ");
if (dT_mid >= 0) {
display.print(" ");
}
display.print(dT_mid, 1);
display.setCursor(70, 22);
if (dT_mid_max == 0) {
display.print("--");
} else {
display.print(dT_mid_max, 1);
}
display.setCursor(100, 22);
display.print(T, 1);
display.display();
}
void writemcp4725(int wert) {
// Analog Wert 0 bis 4095
if (wert < 0) {
wert = 0;
}
if (wert > 4095) {
wert = 4095;
}
Wire.beginTransmission(MCP4725);
Wire.write(64); // Kommando Update DAC
Wire.write(wert >> 4); // die 8 höherwertigen Bits
Wire.write((wert & 15) << 4); // die 4 niederwertigen Bits
Wire.endTransmission();
}
float temp() {
analogReference(INTERNAL1V024);
T = 0;
for (int i = 0; i < T_count; i++) {
U_own = 14000;// analogRead(io_U_own) * 5; //voltage divider 5:1 => 5V == 1V (alternativ ~14000)
U_temp = analogRead(io_U_temp);
R_T = ((U_own / U_temp) * R_ST) - R_ST;
T += pow(((log(R_T / R_R) / B) + (1 / 293.15)), -1);
}
analogReference(INTERNAL4V096);
T = T / T_count;
T = T - 273.15;
T = T * 1.05;
return T;
}
void temp_dT() {
dT_sum += (millis() - dT_t_tmp);
dT_t_tmp = millis();
if (dT_sum > (dT_t * 1024)) {
dT_sum = 0;
dT[dT_position] = temp();
dT_position += 1;
if (dT_position == dT_count) {
dT_position = 0;
}
//dT
dT_xx = 0;
dT_xy = 0;
dT_n = 1;
//avarage x
dT_X = dT_count / 2;
//avarage y
dT_Y = 0;
for (int i = 0; i < dT_count; i++) {
dT_Y += dT[i];
}
dT_Y = dT_Y / dT_count;
for (int i = dT_position; i < dT_count; i++) {
dT_xy += (dT_n - dT_X) * (dT[i] - dT_Y);
dT_xx += pow((dT_n - dT_X), 2);
dT_n++;
}
for (int i = 0; i < dT_position; i++) {
dT_xy += (dT_n - dT_X) * (dT[i] - dT_Y);
dT_xx += pow((dT_n - dT_X), 2);
dT_n++;
}
dT_mid = dT_xy / dT_xx;
dT_mid = dT_mid * (3600 / dT_t);
if (dT_mid_max < dT_mid) {
dT_mid_max = dT_mid;
}
//dU
dU[dT_position] = U_akku;
dU_xx = 0;
dU_xy = 0;
dT_n = 1;
//avarage x
dU_X = dT_count / 2;
//avarage y
dU_Y = 0;
for (int i = 0; i < dT_count; i++) {
dU_Y += dU[i];
}
dU_Y = dU_Y / dT_count;
for (int i = dT_position; i < dT_count; i++) {
dU_xy += (dT_n - dU_X) * (dU[i] - dU_Y);
dU_xx += pow((dT_n - dU_X), 2);
dT_n++;
}
for (int i = 0; i < dT_position; i++) {
dU_xy += (dT_n - dU_X) * (dU[i] - dU_Y);
dU_xx += pow((dT_n - dU_X), 2);
dT_n++;
}
dU_mid = dU_xy / dU_xx;
dU_mid = dU_mid * (3600 / dT_t);
if (dU_mid_max < dU_mid) {
dU_mid_max = dU_mid;
}
}
}
void fnc_discharge () {
switch (type) {
case 0: //NiMh
U_akku_dis_min = 1000;
U_akku_dis_max = 1100;
break;
case 1: //NiCd
U_akku_dis_min = 950;
U_akku_dis_max = 1050;
break;
case 2: //Alkali
break;
}
writemcp4725(200);
dawert = dawert_min;
U_akku_dis_tmp = U_akku_dis_max - ((U_akku_dis_max - U_akku_dis_min) / (dawert_max - dawert_min) * (dawert - dawert_min));
U_akku_dis_tmp_step = ((U_akku_dis_max - U_akku_dis_min) / (dawert_max - dawert_min));
analogWrite(io_discharge, dawert);
discharge = true;
max_discharge = true;
while (max_discharge) {
U_akku = map(U_measure(0, 2, 20), 0, 32768, 0, 2048);
if (dawert == dawert_max || U_akku <= U_akku_dis_tmp) {
max_discharge = false;
} else {
dawert += step_up;
if (dawert > dawert_max) {
dawert = dawert_max;
}
analogWrite(io_discharge, dawert);
delay(1000);
}
U_akku_dis_tmp = U_akku_dis_max - ((U_akku_dis_max - U_akku_dis_min) / (dawert_max - dawert_min) * (dawert - dawert_min));
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
//line 1 M
display.setCursor(30, 0);
display.print("<discharge>");
//line 2 L
display.setCursor(0, 12);
display.print("U_a: ");
display.print(U_akku);
//line 2 R
display.setCursor(70, 12);
display.print("d_w: ");
display.print(dawert - dawert_min);
//line 3 L
display.setCursor(0, 22);
display.print("T_a: ");
display.print(temp(), 1);
//line 3 R
display.setCursor(70, 22);
display.print("U_m: ");
display.print(U_akku_dis_tmp);
//print
display.display();
}
while (discharge) {
U_akku = map(U_measure(0, 2, 20), 0, 32768, 0, 2048);
if (dawert <= dawert_min) {
discharge = false;
}
if (U_akku <= U_akku_dis_tmp) {
U_akku_dis_tmp += U_akku_dis_tmp_step;
dawert -= step_down;
if (dawert < 0) {
dawert = 0;
}
analogWrite(io_discharge, dawert);
delay(1000);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
//line 1 M
display.setCursor(30, 0);
display.print("<discharge>");
//line 2 L
display.setCursor(0, 12);
display.print("U_a: ");
display.print(U_akku);
//line 2 R
display.setCursor(70, 12);
display.print("d_w: ");
display.print(dawert - dawert_min);
//line 3 L
display.setCursor(0, 22);
display.print("T_a: ");
display.print(temp(), 1);
//line 3 R
display.setCursor(70, 22);
display.print("U_m: ");
display.print(U_akku_dis_tmp);
//print
display.display();
}
analogWrite(io_discharge, 0);
discharge = true;
}
int fnc_coulomb() {
coulomb_u = (millis() - time);
coulomb_v += (float)coulomb_u * I_akku / 1024.0;
coulomb = coulomb_v / 3600.0;
time = millis();
return coulomb;
}
void charge_nimh() {
if (search_mode) {
search_I(I_charge, true);
delay(100);
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
U_akku_max = U_akku;
time = millis();
search_mode = false;
T_start = temp();
}
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
I_akku = -1 * map(U_measure(1, 16, U_rep), 0, 32768, 0, 2560);
if (U_akku_max < U_akku || (coulomb < I_charge && discharge)) {
U_akku_max = U_akku;
}
if (U_akku_max - U_akku > 5 || temp() > 35) {// || dT_mid < dT_mid_max - 2) {
I_charge = 10;
search_I(I_charge, false);
delay(100);
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
U_akku_max = U_akku;
time = millis();
}
if (I_akku < I_charge) {
dawert -= step_down;
writemcp4725(dawert);
} else {
if (I_akku > I_charge) {
dawert += step_up;
writemcp4725(dawert);
}
}
write_display_data();
}
void charge_nicd() {
if (search_mode) {
search_I(I_charge, true);
delay(100);
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
U_akku_max = U_akku;
time = millis();
search_mode = false;
T_start = temp();
}
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
I_akku = -1 * map(U_measure(1, 16, U_rep), 0, 32768, 0, 2560);
if (U_akku_max < U_akku || (coulomb < I_charge)) {// && discharge)) {
U_akku_max = U_akku;
}
if (U_akku_max - U_akku > 15 || temp() > 35) {
I_charge = 10;
search_I(I_charge, false);
delay(100);
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
U_akku_max = U_akku;
time = millis();
}
if (I_akku < I_charge) {
dawert -= step_down;
writemcp4725(dawert);
} else {
if (I_akku > I_charge) {
dawert += step_up;
writemcp4725(dawert);
}
}
write_display_data();
}
void charge_alkali() {
if (search_mode) {
search_I(I_charge, true);
delay(100);
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
U_akku_max = U_akku;
time = millis();
search_mode = false;
}
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
I_akku = -1 * map(U_measure(1, 16, U_rep), 0, 32768, 0, 2560);
if (U_akku_max < U_akku) {
U_akku_max = U_akku;
}
if (I_akku < I_charge) {
dawert -= step_down;
writemcp4725(dawert);
} else {
if (I_akku > I_charge) {
dawert += step_up;
writemcp4725(dawert);
}
}
if (U_akku > 1690) {
while (true) {
U_akku = map(U_measure(0, 2, U_rep), 0, 32768, 0, 2048);
I_akku = -1 * map(U_measure(1, 16, U_rep), 0, 32768, 0, 2560);
if (U_akku < 1690) {
dawert -= step_down;
writemcp4725(dawert);
} else {
if (U_akku > 1690) {
dawert += step_up;
writemcp4725(dawert);
}
}
write_display_data();
}
}
write_display_data();
}