Sonntag, 20. August 2017

JouleThief XXL V2.1 - noch ein Update

der Betrieb der V2.0 ist schon sehr komfortabel. Die Spannung der Batterien wird zuverlässig angezeigt und es kommt eine Meldung, wenn deren Spannung zu weit absinkt.
Allerdings ist der Kontrast des Displays noch nicht optimal, da dessen Versorgungsspannung abhängig der Leere der Batterien im Bereich von 5V bis unter 3V schwankt. Da muss eine Kontrast-Automatik her! In Anlehnung an diese Webseite, habe ich die Schaltung erweitert: Ich habe noch 2 Analogeingänge frei, mit der ich sowohl Versorgungsspannung des Displays, als auch die Kontrastspannung messen kann. Über einen PWM-Ausgang mit nachgeschaltetem Spannungsteiler, sowie Glättungs-Schaltung kann ich nun den Kontrast immer im optimalen Bereich halten.



















In diesem Zusammenhang habe ich noch ein paar kleine Bugs im Programm beseitigt:




// ---------------------------------------------------------
// Batteriemessger�t
// es wird die Spannung von 6 Batterien gemessen und gleichzeitig
// auf einem LCD-Display dargestellt.
// ---------------------------------------------------------

#include

#define DEBUG
#include "log.h"

struct _Batterie
{
    float spannung;  // die gemessene Spannung
    bool ausgetastet;  // wird die Spannung gerade angezeigt, oder ausgetastet
    float abschaltspannung;  // darunter ist die Batterie leer
};

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // initialize the library with the numbers of the interface pins
int AnalogBatPin1 = A0;
int AnalogBatPin2 = A1;
int AnalogBatPin3 = A2;
int AnalogBatPin4 = A3;
int AnalogBatPin5 = A4;
int AnalogBatPin6 = A5;
int AnalogKontrastPin = A6;  // hier wird die Kontrastspannung gemessen
int AnalogVCCPin = A7; // hier wird die VCC gemessen (für die Kontrastspannungsberechnung)
int KontrastPWM = 6;
int TasterPin = 10;
int SummerPin = 9;
int LEDPin =13;
bool Pieps; // w�hrenddessen wird gepiepst
int Slot; // z�hlt immer durch
struct _Batterie Batterien[6];
bool SekundenBlinkbit; // toggle jede Sekunde
bool HalbsekundenBlinkbit; // toggle jede halbe Sekunde
bool ViertelsekundenBlinkbit; // toggle jede viertel Sekunde

#define NEIN 0  // Taste nicht gedr�ckt
#define KURZ 1  // Taste kurz gedr�ckt
#define LANG 2  // Taste lang gedr�ckt

// -------------------------------
void setup()
{
    SERIAL_BEGIN;
    lcd.begin(16, 2);    // set up the LCD's number of columns and rows:
    analogReference(INTERNAL);
    pinMode(TasterPin, INPUT);
    pinMode(SummerPin, OUTPUT);
    pinMode(LEDPin, OUTPUT);
    InitVariablen();
}

// -------------------------------
void InitVariablen(void)
{
    int i;

    for(i=0; i<6 br="" i="">        Batterien[i].abschaltspannung = 0.02F;
}

// -------------------------------
void MesseBatterien(void)
{
    int aval;
    float offset[6] = { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F };
    float zaehl[6] = { 1.24F, 1.24F, 1.24F, 1.24F, 1.24F, 1.24F };
    float nenner[6] = { 0.83F, 0.83F, 0.83F, 0.83F, 0.83F, 0.83F };

    aval = analogRead(AnalogBatPin1);
    Batterien[0].spannung = (float)aval *zaehl[0] / nenner[0] / 1000.0F + offset[0];
    aval = analogRead(AnalogBatPin2);
    Batterien[1].spannung =
        (float)aval *2.0F * zaehl[1] / nenner[1] / 1000.0F + offset[1];
    Batterien[1].spannung -= Batterien[0].spannung;
    aval = analogRead(AnalogBatPin3);
    Batterien[2].spannung =
        (float)aval *3.0F * zaehl[2] / nenner[2] / 1000.0F + offset[2];
    Batterien[2].spannung -= Batterien[0].spannung;
    Batterien[2].spannung -= Batterien[1].spannung;
    aval = analogRead(AnalogBatPin4);
    Batterien[3].spannung =
        (float)aval *4.0F * zaehl[3] / nenner[3] / 1000.0F + offset[3];
    Batterien[3].spannung -= Batterien[0].spannung;
    Batterien[3].spannung -= Batterien[1].spannung;
    Batterien[3].spannung -= Batterien[2].spannung;
    aval = analogRead(AnalogBatPin5);
    Batterien[4].spannung =
        (float)aval *5.0F * zaehl[4] / nenner[4] / 1000.0F + offset[4];
    Batterien[4].spannung -= Batterien[0].spannung;
    Batterien[4].spannung -= Batterien[1].spannung;
    Batterien[4].spannung -= Batterien[2].spannung;
    Batterien[4].spannung -= Batterien[3].spannung;
    aval = analogRead(AnalogBatPin6);
    Batterien[5].spannung =
        (float)aval *6.0F * zaehl[5] / nenner[5] / 1000.0F + offset[5];
    Batterien[5].spannung -= Batterien[0].spannung;
    Batterien[5].spannung -= Batterien[1].spannung;
    Batterien[5].spannung -= Batterien[2].spannung;
    Batterien[5].spannung -= Batterien[3].spannung;
    Batterien[5].spannung -= Batterien[4].spannung;
}

// -------------------------------
void AusgabeLCD(void)
{
    char buffer1[40], buffer2[40];
    char t1[10], t2[10], t3[10], t4[10], t5[10], t6[10];

    if(Batterien[0].ausgetastet)
        strcpy(t1, "    ");
    else
        dtostrf(Batterien[0].spannung, 4, 2, t1);
    if(Batterien[1].ausgetastet)
        strcpy(t2, "    ");
    else
        dtostrf(Batterien[1].spannung, 4, 2, t2);
    if(Batterien[2].ausgetastet)
        strcpy(t3, "    ");
    else
        dtostrf(Batterien[2].spannung, 4, 2, t3);
    sprintf(buffer1, "%s %s %s  ", t1, t2, t3);

    if(Batterien[3].ausgetastet)
        strcpy(t4, "    ");
    else
        dtostrf(Batterien[3].spannung, 4, 2, t4);
    if(Batterien[4].ausgetastet)
        strcpy(t5, "    ");
    else
        dtostrf(Batterien[4].spannung, 4, 2, t5);
    if(Batterien[5].ausgetastet)
        strcpy(t6, "    ");
    else
    dtostrf(Batterien[5].spannung, 4, 2, t6);
    sprintf(buffer2, "%s %s %s  ", t4, t5, t6);

    lcd.setCursor(0, 0);
    lcd.print(buffer1);
    lcd.setCursor(0, 1);
    lcd.print(buffer2);
}

// -------------------------------
int LeseTaster(void)
{
    int tasterGedrueckt; // und hier ist die Taste
    static long int anfang; // hier merken wir uns, seit wann der Taster gedr�ckt ist
    long int jetzt=millis(); // Millisekunden
    long int drueckdauer; // so lange ist der Taster bereits gedr�ckt
    bool gedrueckt;
    static bool letztes_gedrueckt=0;

    gedrueckt = digitalRead(TasterPin);
    digitalWrite(LEDPin, gedrueckt); // visuelle R�ckmeldung

    if (gedrueckt)
    {
        drueckdauer = jetzt-anfang;
        if (drueckdauer > 1000)
            tasterGedrueckt = LANG;
        else
        {
            if (drueckdauer > 500)
                tasterGedrueckt = KURZ;
            else
                tasterGedrueckt = NEIN;
        }
        if (letztes_gedrueckt == 0)
            anfang = jetzt;
    }
    else
        anfang = jetzt; // damit die Tasten-Dr�ck-Dauer kurz ist

    letztes_gedrueckt = gedrueckt;

//    SERIAL_PRINT(anfang);
//    SERIAL_PRINT(" ");
//    SERIAL_PRINT(jetzt);
//    SERIAL_PRINT(" ");
//    SERIAL_PRINTLN(tasterGedrueckt);

    return tasterGedrueckt;
}

// -------------------------------
void PruefeBatterien(void)
{
    int i;
    int leereBatterie = -1;

    for(i=0; i<6 br="" i="">    {
        if (Batterien[i].spannung < Batterien[i].abschaltspannung)
            leereBatterie = i+1;           
    }
    // SERIAL_PRINTLN(leereBatterie);
   
    if (leereBatterie > Slot)
    {
        Pieps = true;
        //SERIAL_PRINT("Slot ");
        //SERIAL_PRINTLN(Slot);
    }
    else
        Pieps = false;
   
}

// -------------------------------
void StelleKontrast(void)
{
    int kont, vcc;
    static int kontrastwert=0;  // der PWM-Stellwert für den Kontrast
   
    kont = analogRead(AnalogKontrastPin);
    SERIAL_PRINT("Kin=");
    SERIAL_PRINT(kont);

    vcc = analogRead(AnalogVCCPin);
    SERIAL_PRINT("VCC=");
    SERIAL_PRINTLN(vcc);  // 1000bit = 5V

    kontrastwert += ((800*(vcc/1000))-kont)/7;
    if (kontrastwert<0 br="">        kontrastwert = 0;
    if (kontrastwert>255)
        kontrastwert = 255;

    SERIAL_PRINT(" Kout=");
    SERIAL_PRINTLN(kontrastwert);

    analogWrite(KontrastPWM, kontrastwert);
}

// -------------------------------
void loop()
{
    long int jetzt;
    int taste;
    static long int jedeSekunde=0; // f�r den Timer jeder Sekunde
    static long int jedeHalbeSekunde=0; // f�r den Timer jeder halben Sekunde
    static long int jedeViertelSekunde=0; // f�r den Timer jeder viertel Sekunde

    jetzt = millis();
    taste = LeseTaster();
    PruefeBatterien();

    if ((jetzt-jedeSekunde) > 1000)
    {   // was hier steht, wird zyklisch jede Sekunde ausgef�hrt
        MesseBatterien();
        StelleKontrast();

        SekundenBlinkbit = ~SekundenBlinkbit;
        jedeSekunde = jetzt;
    }

    if ((jetzt-jedeHalbeSekunde) > 500)
    {   // was hier steht, wird zyklisch jede halbe Sekunde ausgef�hrt
        AusgabeLCD();

        Slot++;
        if (Slot>5)
            Slot=0;

        SERIAL_PRINTLN(Slot);

        HalbsekundenBlinkbit = ~HalbsekundenBlinkbit;
        jedeHalbeSekunde = jetzt;
    }

    if ((jetzt-jedeViertelSekunde) > 250)
    {   // was hier steht, wird zyklisch jede viertel Sekunde ausgef�hrt
        static bool letzte; // nur maximal 1/4 Sek. piepsen
        if (Pieps & !letzte)
        {
            letzte = true;
            digitalWrite(SummerPin, HIGH);
        }
        else
        {
            letzte = false;
            digitalWrite(SummerPin, LOW);
        }
        ViertelsekundenBlinkbit = ~ViertelsekundenBlinkbit;
        jedeViertelSekunde = jetzt;
    }
}

Keine Kommentare:

Kommentar veröffentlichen