- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 14

Thema: 1S LiPo Überwachung

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    1S LiPo Überwachung

    Hallo zusammen,
    ich möchte euch hier mal meine Minischaltung für eine 1S LiPo Überwachung vorstellen.

    In meiner Heli-Gruppe haben inzwischen mehrere von uns diesen kleinen 3D Hubschrauber
    Modell: XK Blast K110
    Betrieben wird er mit einemn 1S LiPo Akku.

    Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_01.jpg
Hits:	31
Größe:	46,4 KB
ID:	34985

    Das Problem:
    Irgendwann ist der Akku leer und der Heli fällt wie ein Stein vom Himmel....

    Mal abgesehen davon, dass dies zu Schäden am Heli führen kann, ist das für den LiPo auch nicht gesund.
    Ich habe mal geprüft wann der Heli aussteigt und das passiert bei ca. 2,8 Volt.
    Dann ist der Akku also auch schon unterladen.
    Unter 3 Volt sollte ein LiPo eigentlich nicht entladen werden.

    So kam mir die Idee eine möglichst kleine/leichte Schaltung zu basteln,
    die mittels Blinken den Akkustand anzeigt.

    Da ich ein Microchip PIC Fetischist bin, schaute ich mal nach dem Kleinsten den man bekommen und auch noch selbst löten kann.
    Die Wahl fiel dann auf den PIC10F322 mit 6 Beinchen im SOT23-6 Gehäuse.

    Er hat eine interne Referenzspannung und er hat auch einen ADU Wandler.
    Mehr benötige ich eigentlich auch nicht.

    Den PIC bekommt man für 59 Cent bei Reichelt Elektronik
    https://www.reichelt.de/mcu-picmicro...21699.html?r=1

    Schöne, kleine LEDs hatte ich schon aus Vorversuchen auch bei Reichelt besorgt.
    Sogenannte "Point Leds"

    grün:
    https://www.reichelt.de/point-led-sm...11531.html?r=1

    rot:
    https://www.reichelt.de/point-led-sm...t_sldr::111531

    Absolut geil würde ich die mal nennen.
    Mit 3mA sind die schon derart hell, dass man kaum reingucken kann.
    Kosten der grünen 35 Cent das Stück, die roten sogar nur 24 Cent

    Ausser einem Vorwiderstand für die LED und ein Entkopplungskonensator für den PIC
    benötigt man nichts weiter. Ich habe dennoch 2 LEDs spendiert und 2 Widerstände, einfach der Optik wegen.

    Also hier mal die Schaltung:
    Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_07.jpg
Hits:	24
Größe:	27,7 KB
ID:	34986 Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_09.jpg
Hits:	16
Größe:	30,9 KB
ID:	34992

    Der Keramikkondensator C1 war ursprünglich mit 100nF völlig ausreichend.
    Auf dem Steckbrett brauchte ich auch diesen nicht einmal.
    Versuche später direkt am Hubi ließen aber die gesamte Schaltung ausflippen.
    Ursache sind die Motoren des Hubis. Die ziehen mal locker 4 Ampere und das spiegelt sich
    mit einem Ripple auf der Vorsorgung wieder. Ich hab jetzt einfach mal den Kondi auf 10µF vergrößert und das reicht völlig aus.

    Die gesamte Schaltung, Leiterplatte bestückt mit Zinn und Kabel wiegt weniger als ein halbes Gramm.
    Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_02.jpg
Hits:	20
Größe:	27,7 KB
ID:	34987


    Die Leiterplatte habe ich mit dem Photoverfahren selbst belichtet/entwickelt/geätzt.
    Als Platinenmaterial habe ich 0,5mm Stärke genommen, das kann man sogar noch mit einer Schere zurecht schnippeln.
    Das Platinenmaterial (einseitig mit Fotolack) habe ich bei Segor Electronic gekauft.
    Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_06.jpg
Hits:	18
Größe:	17,2 KB
ID:	34988 bestückt: Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_05.jpg
Hits:	89
Größe:	1,8 KB
ID:	34991

    Die Leiterplatte habe ich so ausgelegt, dass man sie direkt mit doppelseitigem Klebeband hinten auf die beiden Servos
    kleben kann. So kann man die LEDs auch gut erkennen wenn der Heli mit dem Heck vor einem schwebt.
    Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_08.jpg
Hits:	14
Größe:	54,8 KB
ID:	34989


    Die beiden Kabel Plus und Minus werden durch die beiden Servos bis nach vorne verlegt und dort,
    als hätte man mit meiner Schaltung schon gerechnet, gibt es zwei Lötpunkte bezeichnet mit B+ und B-
    wo sie dann einfach aufgelelötet werden. Mehr gibt es nicht zu tun.
    Klicke auf die Grafik für eine größere Ansicht

Name:	K110_LiPo_Blitzer_03.jpg
Hits:	13
Größe:	58,9 KB
ID:	34990


    Den Programmcode und die genaue Funktionsweise gibt es natürlich auch noch....

    - - - Aktualisiert - - -

    Anbei der momentane Programmcode:

    Code:
    /* 
      File:   main.c
      Date:   07.05.2020  
      Author: Siro
     
      Projekt: 1S LiPo-Blitzer mit PIC10F322 
    */
     
    // PIC10F322 Configuration Bit Settings
    // 'C' source line config statements
    
    // CONFIG
    #pragma config FOSC = INTOSC    // Oscillator Selection bits (INTOSC oscillator: CLKIN function disabled)
    #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
    #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
    #pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
    #pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
    #pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
    #pragma config LPBOR = OFF      // Brown-out Reset Selection bits (BOR disabled)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    
    #include <xc.h>   // die einzige Headerdatei die benötigt wird.
    
    /*----------------------------------------------------------------------*/
    /* hier habe ich meine eigenen Datentypen definiert:  */
    typedef unsigned char BOOL;   /*  0=FALSE,  all others are TRUE */    
    typedef unsigned char   U8;   /*  8 Bit ohne Vorzeichen */
    typedef unsigned short U16;   /* 16 Bit ohne Vorzeichen */
    typedef unsigned long  U32;   /* 32 Bit ohne Vorzeichen */
    
    /* dem Datentyp BOOL sollten nur diese Konstanten zugeordnet werden:    */
    #define FALSE (0)            /* Eine 0  bedeutet FALSE (falsch)            */
    #define TRUE  (!FALSE)       /* alle anderen Werte bedeuten TRUE (wahr) */
    
    // Die HARDWARE : lediglich 2 LEDs
    
    // LED 1 connected to pin RA0
    #define LED1_ON  LATA0=1 
    #define LED1_OFF LATA0=0
    
    // LED 2 connected to pin RA1
    #define LED2_ON  LATA1=1 
    #define LED2_OFF LATA1=0
    
    //------ einige Konstanten
    
    // die LEDs blinken kurz hintereinander 1, 2, 3 oder 4 mal
    // danach folgt eine längere Pause von 1,5 Sekunden
    #define EXTRA_LONG_TIME 1500;  // längere Zeit zwischen den Blinkphasen
    #define LONG_TIME  300         // LED on  time (ms)
    #define SHORT_TIME 200         // LED off time (ms)
    
    // Blinkphase wenn Akku leer < 3,2 Volt
    #define FAST_SHORT_TIME 100   // LED on  time (ms) 
    #define FAST_LONG_TIME  100   // LED off time (ms)
    
    #define ACCU_EMPTY_MV    3200  // empty if voltage is below, fast blink
    #define SLEEP_VOLTAGE_MV 3000  // go in sleepmode below this voltage
    
    #define TIME_BEFORE_STANDBY 2000 // after 2 sec below 3,0 Volt set Standby Mode
    
    // die beiden Zeitwerte werden im 1ms Interrupt verändert, deshalb volatile
    volatile U16 BlinkTimeMS;
    volatile U16 UnderVoltageTime;  // Zeit wie lange wir unter 3 Volt waren
    
    BOOL BlinkPhase;
    U8   BlinkCount;
    U8   VoltageBlinkCount;
    
    U32  value;     // wird zur Berechnung benötigt 32 Bit Wert
    U16  mV_Value;  // calculated Millivolts 
    
    
    //------------------------------------------------------------------------------
    // global interrupt function
    void __interrupt() isr(void)
    {
      if (TMR0IF)             // Timer 0 ueberlauf  1ms  
      {  
        TMR0   = 7;           // restart value for timer 0     
        TMR0IF = 0;           // clear interrupt flag from timer 0
    
        if (BlinkTimeMS) 
            BlinkTimeMS--;
        
        if (UnderVoltageTime)   // der 2 Sekunden Timer
            UnderVoltageTime--;
      }
    }
    
    /*----------------------------------------------------------------------------*/
    // !!! Timer 0 ist nur 8 Bit 
    // wird auf 1 Millisekunde eingestellt
    
    void InitTimer0(void)
    {
      /* Eingangstakt ist Fosc 16Mhz ==> 250ns */
      /* wir benoetigen einen Teiler von 1ms / 250 ns = 4000 */
      /* da wir nur einen 8 Bit Timer haben wird der Vorteiler */
      /* 4000 / 256 = 15,68 also Vorteiler = 16 */
      /* 1 Schritt = 250ns * 16 = 4us  */
      /* 1ms / 4us = 250 */
      /* zaehlen muessen wir als 250 Schritte, denn 250*4us = 1ms */
      /* der Timer 1 zaehlt aber vorwaerts, also muessen wir den */
      /* den Wert 256-250 = 6 ins Counterregister laden */
      /* erreicht der Zaehler den Wert 256 gibt es einen Interrupt */
      /* !!!! SYNC 2 TCY  laut Datenblatt */
    
      /* presacle assigned to timer 0 */
      PSA = 0;
    
      /* !!!!  OPTION_REG steht nach einem Reset komplett auf 0xFF */
      PS2 = 0;
      
      /* clock is internal instruction cycle Fosc/4 */
      T0CS = 0;
    
      TMR0 = 7;    // value for 1 ms mit Simulator ausgetestet 4000 Cycles=1ms 
    
      TMR0IF = 0;  // clear interrupt flag from timer 0
      TMR0IE = 1;  // enable interrupt timer 0
    }
    
    //------------------------------------------------------------------------------
    void StartAdu(void)
    {
      GO_nDONE = 1;       // start ADU conversion 
      
      while (GO_nDONE) ;  // wait until adu ready
      ADIF = 0;           // clear interrupt flag
    }
    
    //------------------------------------------------------------------------------
    // Wenn der Akku leer wird, soll kontinuierlich geblinkt werden.
    // Falls momentan noch eine Blinkzeit länger als die 
    // lange Blinkphase für Akku leer aktiv ist, wird die momentane Zeit gekürzt
    // um schnell die Blinkphase für AKKU leer einzuleiten
    // Die beiden LEDs sollen abwechselnd blinken 
    void FastBlink(void)
    { U16 time;
    
      di();  // DISABLE;
      time=BlinkTimeMS;
      
      if (time > FAST_LONG_TIME)     // maybe
        BlinkTimeMS=FAST_LONG_TIME;  // shorten the time
      
      ei(); // ENABLE;
      
      if (time) return;              // time not ready, exit
    
      BlinkPhase = !BlinkPhase;      // invert the Blinkphase  
        
      if (BlinkPhase)
      {
        LED1_ON;
        LED2_OFF;
        time = FAST_SHORT_TIME;
      } else 
      { 
        LED1_OFF;
        LED2_ON;
        time = FAST_LONG_TIME;
      }
      
      di();  //  DISABLE;
      BlinkTimeMS = time;
      ei();  // ENABLE;  
    }
    //------------------------------------------------------------------------------
    void DoLed(void)
    { U16 time;
    
      di();                     // DISABLE;   
      time=BlinkTimeMS;         // get the current time
      ei();                     // ENABLE;
      if (time) return;         // time not ready, exit
    
      if (BlinkCount==0) BlinkPhase = FALSE;
      
      if (BlinkPhase)  
      {  
        LED1_OFF;                // switch off the Leds
        LED2_OFF;
        time = SHORT_TIME;       // hold leds off for this time
        BlinkPhase = FALSE;
      } else
      {  
        LED1_ON;                 // switch on the Leds
        LED2_ON;
        time = LONG_TIME;        // hold leds on for this time
        BlinkPhase = TRUE;
      
        if (BlinkCount) BlinkCount--;
        else 
        {  
          BlinkCount = VoltageBlinkCount;  // restart the Blink counter
          time = EXTRA_LONG_TIME;          // but first we set a long time
        }  
      }    
    
      di();                     // DISABLE;
      BlinkTimeMS = time;       // set the new time
      ei();                     // ENABLE;
    }
    
    /*----------------------------------------------------------------------------*/
    // Wenn Spannung unter 3 Volt sinkt
    // Aufmerksamkeitsblinker nur ganz kurz blitzen damit man sieht,
    // das der Akku noch dran ist.
    // Die beiden LEDs sollen blitzen
    // !!! Zeiten haben sich verdoppelt weil der Clock runter getaktet wurde..
    void SleepBlink(void)
    { U16 time;
    
      di(); //  DISABLE;
      time=BlinkTimeMS;
      ei();  // ENABLE;
      
      if (time) return;              // time not ready, exit
    
      BlinkPhase = !BlinkPhase;      // invert the Blinkphase  
        
      if (BlinkPhase)
      {
        LED1_ON;
        LED2_ON;
        time = 10;     // 20ms
      } else 
      { 
        LED1_OFF;
        LED2_OFF;
        time = 1500;   // 3 Sekunden
      }
      
      di(); // DISABLE;
      BlinkTimeMS = time;
      ei();  // ENABLE;  
    }
    //------------------------------------------------------------------------------
    void GoSleeping(void)
    {
      IRCF0 = 0;   // switch clock to default 8MHz 500ns Instruction cycle  
      ADON   = 0;  // disable ADU
      
      // Always set the amplifier output selection to off (0) before disabling the FVR module.
      // see errata sheet
      ADFVR0 = 0; // 00 = ADC Fixed Voltage Reference Peripheral output is off.
      ADFVR1 = 0; // 00 = ADC Fixed Voltage Reference Peripheral output is off.  
      
      FVREN  = 0;  // disable Fixed Voltage Reference
    
      while (1)  SleepBlink();  // nur noch blitzen, kein Sleep Modus
     }
    //------------------------------------------------------------------------------
    void main(void) 
    { 
      IRCF0 = 1;        // switch clock from default 8MHz to 16 MHz ==> 250ns Instruction cycle
      
      TRISA = 0x00;     // all pins to output  
      RA2   = 1;        // optional switch, not used at time
      
      // internal fixed voltage reference
      // set first the FREN Bit before changing the gain bits
      // see errata sheet
      FVREN = 1;  // Fixed Voltage Reference is enabled
      
      ADFVR1=1;   // select the 2,048 Volt Reference
      
      // init the ADC
      // ANSELA=1;  // AN0 as analog input, all others as digital output
      // we dont need an ADU input  
      ADCON = (0x07 << 5)    // conversion clock =FOSC/64
           // + (0x00 << 2)  // select channel AN0, we dont need a channel
            + (0x07 << 2)    // select Fixed Voltage Reference  
            + (0x01 << 0);   // ADC enable
      
      nWPUEN = 0;    // enable global pullups 
      WPUA = 8;      // pullup only on RA3/MCLR
      
      InitTimer0();  // set Timer 0 to 1ms Interrupt
      
      UnderVoltageTime = TIME_BEFORE_STANDBY; 
      
      while (1)
      {
        StartAdu(); 
    
        // calculate the LiPo Voltage:
        value  = (U32)(2048) << 8;    // 2041 gemessen     constant 32 Bit = 524.288
        value /= ADRES;               // durch den ADU Wert teilen
        mV_Value = (U16)value;        // 32 to 16 Bit convert
        
        // bei < 3,0 Volt soll nach 2 Sekunden der Sleepmodus aktiviert werden
        if (mV_Value < SLEEP_VOLTAGE_MV)  // wenn Spannung < 3,0 Volt
        {
          if (UnderVoltageTime == 0)      // und wenn 2 Sekunden vorbei
            GoSleeping();                 // do not undercharge the accu
        } else UnderVoltageTime=TIME_BEFORE_STANDBY;   // restart 2 Sekunden Timer, Spannung liegt über 3 Volt 
    
    
        if (mV_Value < ACCU_EMPTY_MV) FastBlink();   // < 3,2 Volt schnell blinken, es sollte gelandet werden 
        else
        {  
          VoltageBlinkCount=1;                       // oberhalb von 3,6 Volt wird nur 1 mal geblinkt
          if (mV_Value < 3600) VoltageBlinkCount=2;  // kleiner 3,6 Volt 2 mal blinken
          if (mV_Value < 3400) VoltageBlinkCount=3;  // kleiner 3,4 Volt 3 mal blinken  
          if (mV_Value < 3300) VoltageBlinkCount=4;  // kleiner 3,3 Volt 4 mal blinken
          
          DoLed();  // sorgt für das Blinken    
        } // else 
    
      } // while 
    
    } // main
    Geändert von Siro (08.05.2020 um 08:05 Uhr)

Ähnliche Themen

  1. Starterkit: Serverraum-Überwachung
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 30.09.2013, 23:30
  2. Elektromagnet Überwachung
    Von nikolausi im Forum Elektronik
    Antworten: 8
    Letzter Beitrag: 28.07.2011, 19:56
  3. Drahtbruch Überwachung.
    Von sellentin im Forum Elektronik
    Antworten: 19
    Letzter Beitrag: 08.02.2008, 12:06
  4. Roboter überwachung
    Von MiniMax im Forum Elektronik
    Antworten: 6
    Letzter Beitrag: 30.07.2007, 16:17
  5. Überwachung von Bleiakkus?
    Von Klingon77 im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 27.09.2006, 17:32

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad