Drain batteries through an LM324 controlled CEB6030L from a defunct graphics card

Dependencies:   mbed FastAnalogIn PID mbed-rtos

main.cpp

Committer:
eisd
Date:
2020-05-16
Revision:
7:3061a3da1c97
Parent:
5:7112e564d33a

File content as of revision 7:3061a3da1c97:

#include "mbed.h"
#include "rtos.h"
#include "FastAnalogIn.h"
#include "PID.h"

PID I(10.0, 0.01, 0.0, 0.01);

AnalogOut Iset(PTE30);
FastAnalogIn Iget(PTE20);
AnalogIn Vbat(PTB0);
bool active = true;

class Lag {
    float k, v;
public:
    Lag(float seed, float factor = 0.005) { v = seed; k = factor; }
    float operator()(float in) { return v = k * in + (1 - k) * v; }
    operator float() { return v; }
};
inline float Iin(float x) { return x < 0.0008? 0 : x * 33.07273 + 0.016; }
inline float Vin(float x) { return x * 34.08516 + 0.06567447; }

Lag iget(Iin(Iget.read())), vbat(Vin(Vbat.read())), vbat_rest(Vin(Vbat.read()));
void filter() {
    if (active) {
        iget(Iin(Iget.read()));
        vbat(Vin(Vbat.read()));
    }
    if (Iset.read() == 0)
        vbat_rest(Vin(Vbat.read()));
}
void rest(const void *) {
    while (true) {
        Thread::wait(5000);
        if (Iset.read() > 0) {
            active = false;
            Iset.write_u16(16);
            Thread::wait(400);
            Iset.write_u16(0);
            Thread::wait(100);
            active = true;
        }
    }
}
int flop = 0;
void adjust() {
    //flop = (flop + 1) % 4;
    //Iset.write(flop == 0? 0.2/4.61 : 0);
    if (active) {
        I.setProcessValue(iget);
        Iset = I.compute();
    }
}

Serial pc(USBTX, USBRX);
void ui(const void*) {
    while (true) {
        Thread::wait(100);
        while (pc.readable()) {
            int d = pc.getc();
            pc.printf("Increasing current: %d\r\n", d);
            I = I + 0.1;
        }
    }
}

bool header = false;
Timer T;
float charge = 0;
void discharge(const void*) {
    Thread::wait(3000);
    I = 2;
    T.start();
    header = true;
    int lastT = 0;
    while(vbat_rest > 0.9 && (lastT < 5000000 || iget > I/2)) {
        int t = T.read_us();
        charge += iget * (t - lastT)/3600000.0;
        lastT = t;
        Thread::wait(30);
    }
    I = 0;
    PwmOut led(LED1);
    led.period_ms(2000);
    led = 0.2;
}

int main()
{
    pc.baud(115200);

    I.setInputLimits(0, 100);
    I.setOutputLimits(0, 1);
    I = 0;
    I.setMode(AUTO_MODE);

    Ticker t2;
    t2.attach_us(&filter, 1000);
    Ticker t;
    t.attach(&adjust, I.getInterval());
    Thread t3(&rest);
    Thread t4(&ui);

    Thread t5(&discharge);

    while (true) {
        if (header) {
            header = false;
            pc.printf("Discharging\r\n");
            pc.printf("Duration (s)\tVbat (V)\tVbat_rest (V)\tTarget (I)\tDischarge (I)\tCapacity (mAh)\r\n");
        }
        //pc.printf("Iset %f    Iget %6d %f    Vbat %6d %f    \r", Iset.read(), Iget.read_u16(), Iget.read(), Vbat.read_u16(), Vbat.read());
        //pc.printf("Iset %f      Iget %8d %f %f", Iset.read(), Iget.read_u16(), Iin(Iget.read()), (float)iget);
        //pc.printf("      Vbat %8d %f %f %f    charge %f\r", Vbat.read_u16(), Vin(Vbat.read()), (float)vbat, (float)vbat_rest, charge);
        if (active)
            pc.printf("%-8.2f  \t%f  \t%f  \t%f  \t%f  \t%f\r\n", (T.read_us()/10000)/100.0, (float)vbat, (float)vbat_rest, (float)Iset.read(), (float)iget, charge);
        Thread::wait(1000);
    }
}