MezData-Logo

Zylonenauge Solar

Zylonenauge Solar betreiben

Prototyp

Zur Weihnachtszeit 2019 probierte ich kurzerhand mit den übrig gebliebenen Zylonenaugen-Prototypen aus, ob diese mit zwei NiHM-Akkus hell genug leuchten um als Weihnachtsbeleuchtung am Fenster zu funktionieren. Zu meiner Überraschung leuchtete auch die Version mit blauen LED noch ausreichend hell. Im weiteren Verlauf experimentierte ich mit einem Solar-Ladegerät für NiMH-Accus von Würth Solar, das ursprünglich Walkman usw. betreiben sollte.

Schaltplan

Tagsüber ist der µC im Schlafmodus, abends wacht er auf. Gesteuert wird dies über die Spannung der Solarzelle, die an PD2 (INT0) angeschlossen ist.

Stromverbrauch

Warmweisse und blaue LED harmonieren sehr gut mit der Spannung zweier Akkus. Auch bei wenig Licht im Winter leuchten die LED bis zur Abschaltung am Morgen ausreichend hell. Allerdings werden die Akkus dabei nur wenig entladen, es besteht die Gefahr der Überladung am Tag in sonnenreichen Zeiten. Vergleiche Entladungsspannung NiHM-Akku mit Spannungs-Stromkennlinie blaue (weisse) LED siehe LEDKennlinie.

Bei einem Zylonenauge mit roten LED besteht die Chance den Akku mehr zu entladen.

Software

Schneefall Solar [ZylonenSchneeSolar.ino]
// ZylonenaugeSchneeanimationSolar V1.1 (c) Oliver Mezger 5.01.2020
 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
 
unsigned char muster[]={0x78,0x74,0x72,0x71,0xb8,0xb4,0xb2,
0xb1,0xd8,0xd4,0xd2,0xd1,0xe8,0xe4,0xe2,0xe1};
 
ISR(INT0_vect){ // wenn es dunkel ist wird ISR ausgelöst
  GIMSK &= ~(1 << INT0); // Interrupt wieder abschalten
  PORTD |= 1<<PD0; // Beleuchtung einschalten
} 
void enter_sleep(void){
  PORTD &= ~(1<<PD0);
  GIMSK |= (1 << INT0); // Interrupt0 ermoeglichen
  MCUCR = (1<<SM0) | (1<<SE); // Schlafmodus auf PWR_Down
  sleep_mode(); // Schalfen schicken
  /* Aufgewacht! */
  MCUCR = 0;
}
 
int main(){
  DDRB=0xff;      // PORTB auf Ausgang
  signed char musterz=0; // Position 0
  char z=0,i;
  PORTD = 0b01111011; // Pullups an PD2 hat pullDown, PD0 an
  DDRD = 1; // PD0 als Ausgang
  sei();
  while(1){
    if(PIND&4) enter_sleep(); // wenn es hell ist schlafen
    else{ 
      musterz=8+rand()%8;
      z=2+(rand()%32);
      for(i=0;i<=z;i++){
        _delay_ms(30);
      }
      z=2+(rand()%16);
      while (musterz>=0){
        PORTB=muster[musterz--];
        for(i=0;i<=z;i++){
          _delay_ms(20);
        } 
      }
      PORTB=0;
    }
  }
}

Bauteile

Die Eingänge des µC sind als Schmitt-Trigger ausgeführt und haben versorgungsspannungsabhängige Schaltschwellen.

Im Wachzustand läuft die Animation und der Zustand von PD2 wird überwacht. Bei Helligkeit wird dieser zu 1 und der Schlafmodus wird aktiviert. Zum Aufwachen wird Interrupt INT0 mit low-Pegel verwendet. Wird es dunkel, bekommt PD2 (INT0) low, dies löst den INT0-Interrupt aus. Beim Erwachen wird der dem sleep_mode() folgende Befehl ausgeführt.

Leuchtstern am Fenster mit "Booster"

Leuchtstern Schaltplan
Schneefall Solar [ZylonenSchneeSolar2.ino]
// ZylonenaugeSchneeanimationSolar V1.2 (c) Oliver Mezger 6.01.2020
// 4MHz externer Schwinger B.O.D. bei 1,8V
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
 
#define KEYREADER (~PIND&0x70)>>4 // Einlesen, invertieren, maskieren zurecht schieben
unsigned char keyOld = 0;       // alter Tasten-Zustand 
unsigned char keyEnter,keyExit; // gedrueckte und losgelassene Tasten 
 
volatile unsigned int zeit=0; // zaehlt 0,1ms runter in my_delay
 
void my_delay(unsigned int z){ // 0,1 ms 
  zeit=z;
  while(zeit); 
}
 
void keyCheck(){                // Tastaturabfrage mit Flankendedektion  
  unsigned char keyTest,tmp; 
  keyEnter = 0, keyExit = 0; 
  keyTest = KEYREADER;          // Einlesen
  if (keyOld != keyTest){       // hat sich was getan 
    my_delay(100);              // Prellen abwarten 
    tmp = KEYREADER;            // noch mal Einlesen
    if (tmp == keyTest){        // ist es stabil? 
      keyEnter = (~keyOld) & keyTest; // steigende Flanke !alt und neu 
      keyExit = keyOld & (~keyTest);  // fallende Flanke alt und !neu 
      keyOld = keyTest; 
    } 
  } 
} 
unsigned char muster[]={0x78,0x74,0x72,0x71,0xb8,0xb4,0xb2,0xb1,0xd8,
0xd4,0xd2,0xd1,0xe8,0xe4,0xe2,0xe1};
unsigned char booster = 0; // Pulsbreite = 2µs*booster 
 
ISR(INT0_vect){ // wenn es dunkel ist wird ISR ausgelöst
  GIMSK &= ~(1 << INT0); // Interrupt wieder abschalten
  PORTD &= ~(1<<PD0); // Beleuchtung einschalten
}
ISR(TIMER0_COMPA_vect){ // Interrupt Service Routine
  unsigned char level;
  zeit--;
  if(booster){
  asm volatile ("sbi 0x12,1"); // sbi PORTD,1
  for(level=0;level<booster;level++) asm volatile ("nop");
  asm volatile ("cbi 0x12,1"); // cbi PORTD,1
  }
}
void enter_sleep(void){
  PORTD |= 1<<PD0; // Beleuchtung ausschalten
  GIMSK |= (1 << INT0); // Interrupt0 ermoeglichen
  MCUCR = (1<<SM0) | (1<<SE); // Schlafmodus auf PWR_Down
  sleep_mode(); // Schalfen schicken
  /* Aufgewacht! */
  MCUCR = 0;
}
 
int main(){
  DDRB=0xff;      // PORTB auf Ausgang
  signed char musterz=0; // Position 0
  char z=0,i,up=0;
  PORTD = 0b01111000; // Pullups an PD2 hat pullDown, PD0 an
  DDRD = 3; // PD0 und PD1 als Ausgang
  TCCR0A |= 1<<WGM01; // Timer im CTC-Mode
  TCCR0B |= 2; // Vorteiler 1: Phi/1; 2: Phi/8; 3: Phi/64; 4: Phi/256; 5: Phi/1024
  TIMSK |= 1<<OCIE0A; // Timer/Counter0 Output Compare Match A Interrupt Enable
  OCR0A = 49; // Wert bei dem der Timer wieder auf 0 gesetzt wird
  sei();
  while(1){
    if(PIND&4) enter_sleep(); // wenn es hell ist schlafen
    else{
      keyCheck(); // Maske,NLogik
      if(keyEnter&1){ // Taste0 gedrueckt?
        if(booster>0)booster--;
      }
      if(keyEnter&2){ // Taste1 gedrueckt?
        if(booster<15)booster++;
      }
      musterz=8+rand()%8;
      z=2+(rand()%32);
      for(i=0;i<=z;i++){
        my_delay(300);
      }
      z=2+(rand()%16);
      while (musterz>=0){
        PORTB=muster[musterz--];
        for(i=0;i<=z;i++){
          my_delay(200);
        } 
      }
      PORTB=0;
      if(up){ // Helligkeit veraendern
        booster++;
        if (booster>=10){
          up=0;
        }
      }
      else{
        if (booster>0) booster--;
        else up=1;
      }
    }
  }
}

Der Booster

Die Akkus werden nicht gut entladen, daher soll ein "Booster" für den notwendigen Verbrauch sorgen. Ein Step-Up Wandler erhöht die Spannung, die Pulsweitenmodulation (PWM) wird per Software realisiert. Damit können nicht so hohe Frequenzen > 50 kHz wie mit der Timer-Hardware erzeugt werden, gewählt wurden: 4MHz Systemtakt mit externem Keramikschwinger, 10 kHz ISR-Aufruf. In der ISR wurde zwecks Zeitoptimierung Inlineassembler verwendet. Jede 100µs wird die Induktion für eine Zeit von 0..30µs (einstellbar in der Variablen booster) mit PD1 gegen GND geschaltet und dabei aufgeladen. Die gespeicherte Energie wird dann an die Lichterkette abgegeben, dabei die Spannung erhöht. Längere Ladezeiten ton würden die Spule in die Sättigung führen, dabei steigt der Strom an, ohne mehr Energie zu speichern, oder den maximalen Strom des Transistors überschreiten. Experimentel wurde eine Induktion von 4,7mH als geeignet ermittelt.

Hier sollten Formeln stehen! Denkfaul empirisch ermittelte Werte statt dessen...

Schaltregler-Grundlagen

Dimensionierung von Schaltnetzteilen

Cool, die Berechnung bei Dr. Heinz Schmidt-Walter passen gut zu meinen ermittelten Werten!

Ein paar Ströme

Bei Helligkeit im Schlafmodus: 0,04 mA

Volle Pulle Booster bei vollem Akku: 30 mA

Stromverbrauch: 2,5V: 4..22mA; 2,7V: 8..26mA

Unter 1,8V im B.O.D-Zustand: 0,2 mA

Gesammelte Informationen

Verschiedene Solarzellen (z.T aus Gartenlampen)

Gemessen mit 100 W Glühlampe und 1000 Lux Beleuchtungsstärke wurden die Lehrlaufspannung und der Kurzschlusstrom.

Bezeichnung Spannung in V Strom in mA
Würth Solar 4,5 49
Gartenleuchte 2 19,3
Gartenleuchte 4,3 25
Gartenleuchte 4,4 18

LED Spannungs-Strom-Kennlinie

Preiswerte LED-Lichterketten mit 24 LED.

LED-Kennlinie

Schaltschwellen der Eingänge

Interrupteingang soll als Spannungswächter für die Helligkeit der Solarzelle dienen. Die Eingänge sind mit Schmitt-Triggern versehen aus den Diagrammen des Datenblatts können die Schaltschwellen entnommen werden. Bei 2,6V Batteriespannung low: 1,05V high: 1,3V

 

Schaltschwellen-Kennlinien I/O Pins

Schaltschwelle 0

Schaltschwelle 1Hysterese