All-in-One Zonne-energie Hub: Laadregelaar, Omvormer, Power Bank & LED-lamp
Onderdelen en Benodigdheden
| Microchip Technology Atmega8 | × | 1 |
| Buck Converter | × | 1 |
| SparkFun LED - 3W Aluminium PCB (5-pack, Warm White) | × | 1 |
| Nokia 5110 Display | × | 1 |
| SparkFun Heatsink | × | 1 |
| SparkFun N-kanaal MOSFET | × | 4 |
| SparkFun P-kanaal MOSFET | × | 1 |
| Zonnepaneel 40 Watt of minder voor 12V systeem | × | 1 |
| SparkFun Lithium-Ion Batterij - 18650 Cel | × | 1 |
| DC-DC 0.9V-5V naar USB Module 5V DC Boost Step-up Voeding | × | 1 |
| Algemene Doel Transistor NPN | × | 1 |
| 12-0-12/220 Center Tapped Transformer | × | 1 |
| 1N4007 – Hoogspanning, Hoge Stroom Diode | × | 1 |
| Male-Header 36 Positie 1 Rij - Lang (0.1") | × | 1 |
| Schuifschakelaar | × | 1 |
| SparkFun Drukknop 12mm | × | 1 |
| Arduino Proto Shield | × | 1 |
| Strip/Vero/Proto Board 8x11 cm | × | 1 |
| Arduino UNO | × | 1 |
| Arduino Nano R3 | × | 1 |
| Arduino Mega 2560 | × | 1 |
| Lage FW Spannings Schottky Diode 5822 | × | 1 |
| Condensator 10 µF | × | 1 |
| Condensator 100 nF | × | 1 |
Benodigde Tools en Machines
| Solderbout (generiek) |
| Boormachine |
| Lijmpistool (generiek) |
Apps en Online Diensten
| Arduino IDE |
| AutoDesk 123D |
Over Dit Project
Over Dit Project
Ik had een paar zonnepanelen, 12 Volt batterijen, transformatoren en nog wat spullen die al een tijdje herumlagen en om goed gebruikt te worden roepen. Zo ontstond dit apparaat – een complete kleine PV-oplossing op een enkel bord. Laten we eens kijken wat wat doet:
- Een laadregelaar is een apparaat dat de lading van een DC-opslag/batterij vanuit een fotovoltaisch zonnepaneel en de ontlading van de batterij door de belasting regelt om de batterijlevensduur te verlengen.
- Een omvormer is een apparaat dat DC-eletriciteit omzet in AC-eletriciteit voor het bedienen van AC-belasting.
- Een Power Bank levert 5V DC-voeding via USB-poort aan gadgets/mobiele apparaten voor draagbare of off-grid lading.
- Een noodlamp is een superheldere LED-lichtbron die gebruikt kan worden tijdens stroomuitval, kampen, outdoor-activiteiten na zonsondergang.
Dit apparaat dat ik gemaakt heb heeft al deze functies; de laatste twee worden onafhankelijk ondersteund door de onboard Li-ion batterij. Met een zonnepaneel (tot 100 Watt), een 12 Volt zuurloodbatterij en een transformator kunnen alle opties benut worden.
Protoversie op Uno
De eerste versie werd ontwikkeld op een Uno-board met minimaal hardware en minimale opties. Het Nokia-display was direct gemonteerd en een MOSFET-shield werd ontwikkeld om laden/ontladen van de batterij te ondersteunen. Er is geen menucontrole, geen omvormer, geen PWM-laden en geen coole features! Alleen aan/uit laden en batterij- en paneelspanningsniveaus tonen. Het doet zijn werk maar heeft geen sfeer!

Volledige Versie op Protoboard
Vervolgens heb ik deze nieuwe versie ontwikkeld met de volgende features:
- PWM Zonnepaneel Laadregelaar tot 100 Watt Paneel
- Golfvorm mini 60 Watt Omvormer
- Tot drie 12 Volt DC-belastingbesturing
- Primaire DC-belasting ondersteunt auto aan/uit functies
- Onafhankelijke USB Power Bank
- Buck-regelaar module
- Nood-bord LED-lamp met Knipper- en Helderheidsregeling
Twee knop/schakelaar-gecontroleerde scroll- en selectie-gebaseerde menu voor gebruikersbesturing, opties en statusinformatie tonen op het Nokia 5110 display. Heel cool! De achterkant is geïsoleerd met lijm tegen kortsluiting door metalen voorwerpen!
Er zijn nog een paar handige features zoals aan/uit schakelaar voor display-verlichting, loskoppelen van de buck voor onafhankelijke werking door af te schakelen van de interne batterij.




Toegang tot het menu op het Nokia 5110 display met gebruikersknop wordt hier getoond:
Laten We Wat Technische Details Leren!
Laadregelaars kunnen On/Off, PWM of MPPT types zijn. On/Off is de simpelste vorm (mijn versie 1 - foto hierboven) van regelaar die de laadstroom niet drosselt naarmate de batterijspanning de volle laadspanning benadert.
Waarbij PWM de laadstroom geleidelijk vermindert naarmate de batterij vol wordt. PWM-regelaar heeft de voordelen:
- Helpt verloren batterijcapaciteit te herstellen en een batterij te desulferen
- Verhoogt de capaciteit van de batterij om meer lading te accepteren
- Houdt hoge gemiddelde batterijcapaciteiten tot 95%
- Equaliseert afwijkende batterijcellen, zodat interne cellen hetzelfde potentieel bereiken
- Vermindert batterijverhitting en gasvorming, dus elektrolytverlies wordt voorkomen
- Vertraagt veroudering en verlengt systeemlevensduur
Maar PWM kan niet het meeste elektrische vermogen uit PV-zonnepanelen halen, omdat het het paneel dwingt om nabij de batterijspanning te werken. MPPT is de oplossing voor dit probleem, wat eigenlijk een DC-naar-DC instelbare buck-boost converter is; het kan het meeste zonne-energie omzetten vergeleken met een PWM-regelaar.
Omvormers kunnen blokgolf, gemodificeerde sinusgolf en pure sinusgolf types zijn. Blokgolf omvormer is ontwerptechnisch heel simpel en goed genoeg voor kleine DC-belasting zoals AC-lampen, CFL-lampen, tafelventilatoren, soldeerbouten, maar niet aanbevolen voor inductieve motoren, gevoelige apparaten/voedingen vanwege harmonische vervorming.
Gemodificeerde sinusgolf is een soort achterlijke sinusgolf gevormd uit blokgolven, beter dan gewone blokgolf omvormers. Pure sinusgolf omvormers zijn het beste voor alle belastingstypes, maar complex in hardware-ontwerp, moeilijke software-algoritme om te bedienen en duur om te maken.
Een buck-regelaar is een stap-naar-beneden DC-DC converter; hier heb ik een buck-module gebruikt om de 4.2V Li-ion batterij op te laden die de controller (Arduino + display), onafhankelijke USB power bank, onboard LED-lamp voedt.

Nu is een USB power bank eigenlijk een DC-DC boost die een bereik van spanningen onder 5V (zoals 3.3 tot 4.2 volt bereik) van een Li-ion of LiPo batterij kan omzetten naar 5 volt, wat de USB-busspanning is die mobiele apparaten kan laden.
Het heeft ook een buck-converter om die batterij op te laden. In mijn project haalt de buck-module iets van stroom van het paneel om de interne (onboard) batterij op te laden.
Werking van de Hardware
Voordat we in detail gaan, bekijk deze afbeelding van alles wat rondom het apparaat is aangesloten:

Het systeem heeft diverse hardware voor verschillende doeleinden. Natuurlijk is de hersenen de AVR Atmega8A microcontroller (kan ook Atmega328P met kleine aanpassingen, besproken hieronder) die in Arduino is geprogrammeerd.

Een verse Atmega8A wordt gebrand met de Arduino Optiboot8 bootloader; je kunt ook een gebootloadede Arduino Mini/Atmega328 kopen om de rommel te vermijden.
De controller, display, LED-lamp en power bank worden gevoed door de onboard Li-ion batterij. Twee momentane drukknoppen zijn voor toegang tot het menu op het display, wat de gebruiker toestaat om verschillende functies van het apparaat te bedienen. De schakelaars zijn hardware gedebounced door smoothing condensators die parallel geschakeld zijn.
Een schuifschakelaar stelt de gebruiker in staat het apparaat in- en uit te schakelen zoals vereist.

De zonne-oopladerfunctie wordt uitgevoerd door een P-MOSFET aangedreven door een 2N2222 transistor-gebaseerd aansturingscircuit dat via PWM vanuit de microcontroller wordt bestuurd. De PWM wordt geregeld op basis van de externe batterijspanning. Stroom van zonnepanelen vloeit via de P-MOSFET naar de zuurloodbatterij. Wanneer de batterij volledig opgeladen is, wordt de MOSFET door de microcontroller uitgeschakeld. Na het uitschakelen van de lading begint de batterijspanning geleidelijk te dalen; wanneer hij 13.6 volt bereikt, wordt de lading weer hervat met lage duty cycle om float-lading te handhaven.
De 12 Volt DC-belasting wordt bestuurd door een N-MOSFET door de Gate-pin vanuit de microcontroller te besturen.

De onboard LED-lamp wordt ook aangedreven door een NMOS. De Gate van deze MOSFET is PWM-gestuurd voor helderheidsinstelling van de LED.

Het omvormerblok bestaat uit 2 N-MOSFETs die abwisselend aan/uit geschakeld worden om AC te simuleren. Door een extern center-getapte transformator toe te voegen, kan blokgolf AC-voeding gerealiseerd worden.

De volgende figuur verduidelijkt de omvormerwerking:

Door stroom te laten vloeien door de center-tap van een optransen spoel in tegengestelde richting abwisselend met MOSFETs, kan AC-spanning in de secundaire spoel gecreëerd worden. Dit gebeurt omdat wanneer de bovenste MOSFET aan is en de onderste uit, de stroom omhoog vloeit. Maar wanneer de bovenste MOSFET uit is en de onderste aan, vloeit de stroom omlaag.
Beide MOSFETs moeten getoggled worden met tweemaal de frequentie van AC. Bekijk de volgende afbeelding om het te begrijpen:

Om 50 Hz AC te creëren, wordt een afwisselende blokgolf toegepast op de lage kant van een 12-0-12V/220V center-getapte transformator. 50 Hz betekent 20 ms per golf.
Daarom 20ms/2 = 10 ms of 100 keer de Gate-signalen toggelen die aan de transformator-aansturende MOSFETs (omvormer MOSFETs) worden toegepast.



Waarschuwing !!! : AC-spanning is dodelijk voor mens, kan dood/letsel veroorzaken! Raak de HV-kant van de transformator nooit met blote handen aan!
Als de omvormerfunctie niet gebruikt wordt, stelt de 2XDC Belasting-optie je in staat om nog twee extra 12 volt DC-belastingen aan de omvormerterminals aan te sluiten.
Magie van de Software
Twee sets code worden geleverd: één is de volledige code in een enkele Arduino-tab, de andere is getabde code volgens gescheiden functies.
Ik heb groepen taken gegeneraliseerd tot één functie.
Bijvoorbeeld:
Get_ADCVal()meet paneel-, interne batterij- en externe batterijspanningen, neemt 20 monsters, gemiddelde die waarden en update de variabelen met spanningsinformatie.Context_Control()doet de gebruikersinteractie, actiecontrole, infoupdate op display gerelateerde activiteiten.Charging_Control(),Discharging_Control(),Load_Control()zijn achtergrondfuncties die fungeren als gesloten lus voor het systeem, monitoren batterijspanningsniveau, controleren Auto Load functie, Overlaad/Diepe Ontlading bescherming, etc.
Gebruikersinvoer wordt verzameld via interrupt-gestuurde momentane drukknoppen. Wanneer deze knoppen ingedrukt worden, worden INT0/INT1 gerelateerde ISR's uitgevoerd. Twee volatile variabelen dp en ds veranderen. Een derde variabele level samen met dp (display pointer →) en ds (display content selector) stelt de gebruiker in staat door menu/submenu te navigeren en acties uit te voeren.
16-bit Timer1 van AVR is geconfigureerd om een Timer Overflow Interrupt te genereren elke 10 ms en PIN_INVP en PIN_INVN om te keren wanneer de omvormerfunctie aanstaat.
Alle Lcd_....() functies hebben te maken met displaybesturing.
Atmega8A vs Atmega328P (Uno)
Het systeem kan gemakkelijk geüpgraded worden om met Atmega328P/Uno te werken door de volgende codewijzigingen aan te brengen. Vind en vervang:
TIMSK met TIMSK1
#define ADC_VREF 2.69 met #define ADC_VREF 1.11
#define ADCVDIV_R1 22 met #define ADCVDIV_R1 8.2
In het hardwaregedeelte moet je een 8.2K weerstand in plaats van 22K gebruiken om de paneel- en batterijspanningen te schalen naar het ADC-meetbereik.
Actie Video's
Ik lees meestal niet alleen woorden over een project, ik ga eerst naar de video. Als jij dat ook doet, geniet van de video's:
Verbetermogelijkheden
Ik liep uit de Flash-ruimte in de Atmega8A. Kon geen kritieke features toevoegen zoals:
- Software-gestuurde Overload/Kortsluiting-beveiliging
- Enkele grafische iconen en een logo
- Energie meting en logging
- Schatting en alarm voor back-up tijd
- Laptop laadoptie
- Ondersteuning voor 6 Volt systemen
- Bluetooth belastingbesturing
- Timer-gebaseerde belastingbesturing
- Een RTC-klok voor meer coole features
- IoT-verbonden oplossing
Als je plannen hebt om zoiets te maken, vergeet dan niet om een aantal van deze features toe te voegen!
Atmega328P (Uno) of Arduino Mega zou een betere kandidaat zijn om al deze opties te includeren.
Toch doet het zijn werk, ik ben er blij mee.
Aanvullende Bronnen
- Download Arduino 1.0.6 met Atmega8 board ondersteuning
- Open Arduino.exe, ga naar Tools > Board > Optiboot8
- Brand bootloader met deze methode
- Compileer en upload code
Code
- Single Tab Code
- Full Code
- Bootloaders
Single Tab Code Arduino
#define PIN_SCE 12
#define PIN_RESET 13
#define PIN_DC 8
#define PIN_SDIN 7
#define PIN_SCLK 6
#define PIN_INVP 4
#define PIN_INVN 5
#define PIN_LOAD 9 // 12 v dc load
#define PIN_LAMP 10 // WHITE LED LIGHT
#define PIN_BATTPWM 11 // Drives PMOS for Ext BAtt Charging
#define PIN_BATTint_Sense A2
#define PIN_SOLAR_Sense A0
#define PIN_BATText_Sense A3
#define ADC_VREF 2.695 // internal ref voltage, around 1.11V for Arduino Uno aka Atmega328P, here my Atmega8A gives this!
#define ADCVDIV_R1 22 // 22 K voltage divider lower Resistor
#define ADCVDIV_R2 175 // 175 K voltage divider upper Resistor
//const uint8_t skulljoke[] PROGMEM ={2,} ; // PIN 2 & 3 USED AS INTERRUPT SWITCH
// PIN 0 & 1 AS PROGRAMMING
// PIN RESET AS
#define LCD_C LOW
#define LCD_D HIGH
#define LCD_X 84
#define LCD_Y 48
uint8_t x=0;
uint8_t level=0;
uint8_t blinker=0;
boolean Load_Auto_Enable=0;
float maxADC_Voltage=0.0;
float BattInt_Voltage=0.0;
float BattExt_Voltage=0.0;
float PV_Voltage=0.0;
volatile int y=0;
volatile uint8_t dp =0;
volatile uint8_t ds =0;
volatile boolean cycle=0;
volatile uint8_t cdc_level =0;
void setup(void) {
LcdInitialise();
LcdClear();
LcdString("*ARDUBOY PV*");
LcdString(" CONTROLLER,");
LcdString("AC INVERTER,");
LcdString("POWER BANK, ");
LcdString("LAMP THING!!");
delay(3000);
analogReference(INTERNAL);
maxADC_Voltage=(ADC_VREF/ADCVDIV_R1)*(ADCVDIV_R1+ADCVDIV_R2);
pinMode(PIN_LOAD,OUTPUT);
digitalWrite(PIN_LOAD,LOW);
pinMode(2, INPUT_PULLUP);
attachInterrupt(0, SW1, FALLING);// Interrupt for Switch 1
pinMode(3, INPUT_PULLUP);
attachInterrupt(1, SW2, FALLING);// Interrupt for Switch 2
}
void loop(void) {
Get_ADCVal();
Context_Control();
Charging_Control();
Discharging_Control();
Load_Control();
LcdClear();;
}
///////////// ADC ///////////////
void Get_ADCVal(void) {
int I=0; int J=0; int K=0;
for(x=0;x<20;x++) {
I=I+analogRead(PIN_BATTint_Sense);
J=J+analogRead(PIN_BATText_Sense);
K=K+analogRead(PIN_SOLAR_Sense);
}
// average voltage
BattInt_Voltage=I/20.0;
BattExt_Voltage=J/20.0;
PV_Voltage=K/20.0;
BattInt_Voltage=maxADC_Voltage*BattInt_Voltage/1023.0;
BattExt_Voltage=maxADC_Voltage*BattExt_Voltage/1023.0;
PV_Voltage=maxADC_Voltage*PV_Voltage/1023.0;
}
//////////// Display and Control //////////////
void Context_Control(void) {
if(ds==0) {show_menu();}
if(ds==1 && dp == 0) {show_info(); delay(100);} //LcdClear();Get_ADCVal();}
///////////////////////Enters 1st Sub Menu////////////////////////////
if(ds==1 && dp == 1) {
level=1; dp=0;
while(level==1) {
int temp=ds;
LcdClear(); show_load_ctrl();delay(250);
if (dp==0){ if(ds!=temp){Load_Auto_Enable=0;digitalWrite(PIN_LOAD,LOW);}}
if (dp==1){if(ds!=temp){Load_Auto_Enable=0; digitalWrite(PIN_LOAD,HIGH);}}
if (dp==2){ if(ds!=temp){Load_Auto_Enable=1;}}
if (dp==3){show_load_ctrl();delay(250);level=0;dp=0;ds=0;}
}
}
//////////////////////Enters 2nd Sub Menu//////////////////////////////
if(ds==1 && dp == 2) {
level=2; dp=0;
while(level==2) {
int temp=ds;
show_inv_ctrl();delay(250);
LcdClear();
if (dp==0){ if(ds!=temp){Timer1_Init();}}
if (dp==1){ if(ds!=temp){Timer1_DeInit();}}
if (dp==2){ if(ds!=temp){Timer1_DeInit();digitalWrite(PIN_INVP,1);digitalWrite(PIN_INVN,1);}}
if (dp==3){show_inv_ctrl();delay(250);level=0;dp=0;ds=0;}
}
}
/////////////////////////////////////////////////////////
////////////////Enters 3rd Sub Menu/////////////////////////////
if(ds==1 && dp == 3) {
level=3; dp=0;
while(level==3) {
int temp=ds;
LcdClear(); show_led_ctrl();delay(250);
if (dp==0){blinker=0;if(ds!=temp) {if(y<=255){y=y+15;analogWrite(PIN_LAMP,y);}}}
if (dp==1){blinker=0;if(ds!=temp) {if(y>=0){y=y-15;analogWrite(PIN_LAMP,y);}}}
if (dp==2){if(ds!=temp) {blinker^=1;analogWrite(PIN_LAMP,127);delay(250);analogWrite(PIN_LAMP,0);}}
if (dp==3){show_led_ctrl();delay(250);level=0;dp=0;ds=0;}
}
}
if(blinker==1) {analogWrite(PIN_LAMP,0);}
delay(250);
if(blinker==1) {analogWrite(PIN_LAMP,127);}
}
/////////////////////////// Menu Text to be shown on Nokia 5110 display ///////////////////
void show_menu(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("Sys Info");
LcdXY(15,1); LcdString("DC Load+");
LcdXY(15,2); LcdString("AC Load~");
LcdXY(15,3); LcdString("LED Lamp");
}
void show_info(void) {
LcdXY(0,0); LcdString("Bat_I="); LcdNumtoString(BattInt_Voltage); LcdString("v");
LcdXY(0,1); LcdString("Bat_E="); LcdNumtoString(BattExt_Voltage); LcdString("v");
LcdXY(0,2); LcdString("Sol_P="); LcdNumtoString(PV_Voltage); LcdString("v");
LcdXY(0,3);
if(BattExt_Voltage >8.0) {LcdString("Batt Conn OK");} else {LcdString("Connect Batt");}
if (PV_Voltage > 10.5 && cdc_level!=3 && cdc_level!=0) {LcdString("Charging:ON ");} else {LcdString("Charging:OFF");}
if (TCNT1 >=45535 ) {LcdString("Inverter:ON");} else {LcdString("Inverter:OFF");}
}
void show_load_ctrl(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("Load Off");
LcdXY(15,1); LcdString("Load On");
LcdXY(15,2); LcdString("Load Auto");
LcdXY(15,3); LcdString("Return");
LcdXY(0,4); LcdString("Must Connect");
LcdString("12V DC Load");
}
void show_inv_ctrl(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("AC Inv On");
LcdXY(15,1); LcdString("AC Inv Off");
LcdXY(15,2); LcdString("2XDC Load");
LcdXY(15,3); LcdString("Return");
LcdXY(0,4); LcdString("2XDC Load,NO");
LcdXY(0,5); LcdString("TRANSFORMER!");
}
void show_led_ctrl(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("LED ++");
LcdXY(15,1); LcdString("LED --");
LcdXY(15,2); LcdString("LED Blk");
LcdXY(15,3); LcdString("Return");
LcdXY(0,4); LcdString("LED DISABLEs");
LcdXY(0,5); LcdString("When INVR On");
}
////////////// Interrupt ISRs //////////////
void SW1() {
dp++;
if(dp>3){dp=0;}
}
void SW2() {
ds^=1;
}
ISR(TIMER1_OVF_vect) {
noInterrupts();
TCNT1 = 45535; // TCNT1 = 25535;
cycle^=1;
if(cycle==0) {
digitalWrite(PIN_INVP,HIGH);
delayMicroseconds(1); // dead band
digitalWrite(PIN_INVN,LOW);
delayMicroseconds(1);
}
if(cycle==1) {
digitalWrite(PIN_INVP,LOW);
delayMicroseconds(1); // dead band
digitalWrite(PIN_INVN,HIGH);
delayMicroseconds(1);
}
interrupts();
}
/////////////Nokia 5110 Functions //////////
static const byte ASCII[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // 20
{0x00, 0x00, 0x5f, 0x00, 0x00}, // 21 !
{0x00, 0x07, 0x00, 0x07, 0x00}, // 22 "
{0x14, 0x7f, 0x14, 0x7f, 0x14}, // 23 #
{0x24, 0x2a, 0x7f, 0x2a, 0x12}, // 24 $
{0x23, 0x13, 0x08, 0x64, 0x62}, // 25 %
{0x36, 0x49, 0x55, 0x22, 0x50}, // 26 &
{0x00, 0x05, 0x03, 0x00, 0x00}, // 27 '
{0x00, 0x1c, 0x22, 0x41, 0x00}, // 28 (
{0x00, 0x41, 0x22, 0x1c, 0x00}, // 29 )
{0x14, 0x08, 0x3e, 0x08, 0x14}, // 2a *
{0x08, 0x08, 0x3e, 0x08, 0x08}, // 2b +
{0x00, 0x50, 0x30, 0x00, 0x00}, // 2c ,
{0x08, 0x08, 0x08, 0x08, 0x08}, // 2d -
{0x00, 0x60, 0x60, 0x00, 0x00}, // 2e .
{0x20, 0x10, 0x08, 0x04, 0x02}, // 2f /
{0x3e, 0x51, 0x49, 0x45, 0x3e}, // 30 0
{0x00, 0x42, 0x7f, 0x40, 0x00}, // 31 1
{0x42, 0x61, 0x51, 0x49, 0x46}, // 32 2
{0x21, 0x41, 0x45, 0x4b, 0x31}, // 33 3
{0x18, 0x14, 0x12, 0x7f, 0x10}, // 34 4
{0x27, 0x45, 0x45, 0x45, 0x39}, // 35 5
{0x3c, 0x4a, 0x49, 0x49, 0x30}, // 36 6
{0x01, 0x71, 0x09, 0x05, 0x03}, // 37 7
{0x36, 0x49, 0x49, 0x49, 0x36}, // 38 8
{0x06, 0x49, 0x49, 0x29, 0x1e}, // 39 9
{0x00, 0x36, 0x36, 0x00, 0x00}, // 3a :
{0x00, 0x56, 0x36, 0x00, 0x00}, // 3b ;
{0x08, 0x14, 0x22, 0x41, 0x00}, // 3c <
{0x14, 0x14, 0x14, 0x14, 0x14}, // 3d =
{0x00, 0x41, 0x22, 0x14, 0x08}, // 3e >
{0x02, 0x01, 0x51, 0x09, 0x06}, // 3f ?
{0x32, 0x49, 0x79, 0x41, 0x3e}, // 40 @
{0x7e, 0x11, 0x11, 0x11, 0x7e}, // 41 A
{0x7f, 0x49, 0x49, 0x49, 0x36}, // 42 B
{0x3e, 0x41, 0x41, 0x41, 0x22}, // 43 C
{0x7f, 0x41, 0x41, 0x22, 0x1c}, // 44 D
{0x7f, 0x49, 0x49, 0x49, 0x41}, // 45 E
{0x7f, 0x09, 0x09, 0x09, 0x01}, // 46 F
{0x3e, 0x41, 0x49, 0x49, 0x7a}, // 47 G
{0x7f, 0x08, 0x08, 0x08, 0x7f}, // 48 H
{0x00, 0x41, 0x7f, 0x41, 0x00}, // 49 I
{0x20, 0x40, 0x41, 0x3f, 0x01}, // 4a J
{0x7f, 0x08, 0x14, 0x22, 0x41}, // 4b K
{0x7f, 0x40, 0x40, 0x40, 0x40}, // 4c L
{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // 4d M
{0x7f, 0x04, 0x08, 0x10, 0x7f}, // 4e N
{0x3e, 0x41, 0x41, 0x41, 0x3e}, // 4f O
{0x7f, 0x09, 0x09, 0x09, 0x06}, // 50 P
{0x3e, 0x41, 0x51, 0x21, 0x5e}, // 51 Q
{0x7f, 0x09, 0x19, 0x29, 0x46}, // 52 R
{0x46, 0x49, 0x49, 0x49, 0x31}, // 53 S
{0x01, 0x01, 0x7f, 0x01, 0x01}, // 54 T
{0x3f, 0x40, 0x40, 0x40, 0x3f}, // 55 U
{0x1f, 0x20, 0x40, 0x20, 0x1f}, // 56 V
{0x3f, 0x40, 0x38, 0x40, 0x3f}, // 57 W
{0x63, 0x14, 0x08, 0x14, 0x63}, // 58 X
{0x07, 0x08, 0x70, 0x08, 0x07}, // 59 Y
{0x61, 0x51, 0x49, 0x45, 0x43}, // 5a Z
{0x00, 0x7f, 0x41, 0x41, 0x00}, // 5b [
{0x02, 0x04, 0x08, 0x10, 0x20}, // 5c \
{0x00, 0x41, 0x41, 0x7f, 0x00}, // 5d ]
{0x04, 0x02, 0x01, 0x02, 0x04}, // 5e ^
{0x40, 0x40, 0x40, 0x40, 0x40}, // 5f _
{0x00, 0x01, 0x02, 0x04, 0x00}, // 60 `
{0x20, 0x54, 0x54, 0x54, 0x78}, // 61 a
{0x7f, 0x48, 0x44, 0x44, 0x38}, // 62 b
{0x38, 0x44, 0x44, 0x44, 0x20}, // 63 c
{0x38, 0x44, 0x44, 0x48, 0x7f}, // 64 d
{0x38, 0x54, 0x54, 0x54, 0x18}, // 65 e
{0x08, 0x7e, 0x09, 0x01, 0x02}, // 66 f
{0x0c, 0x52, 0x52, 0x52, 0x3e}, // 67 g
{0x7f, 0x08, 0x04, 0x04, 0x78}, // 68 h
{0x00, 0x44, 0x7d, 0x40, 0x00}, // 69 i
{0x20, 0x40, 0x44, 0x3d, 0x00}, // 6a j
{0x7f, 0x10, 0x28, 0x44, 0x00}, // 6b k
{0x00, 0x41, 0x7f, 0x40, 0x00}, // 6c l
{0x7c, 0x04, 0x18, 0x04, 0x78}, // 6d m
{0x7c, 0x08, 0x04, 0x04, 0x78}, // 6e n
{0x38, 0x44, 0x44, 0x44, 0x38}, // 6f o
{0x7c, 0x14, 0x14, 0x14, 0x08}, // 70 p
{0x08, 0x14, 0x14, 0x18, 0x7c}, // 71 q
{0x7c, 0x08, 0x04, 0x04, 0x08}, // 72 r
{0x48, 0x54, 0x54, 0x54, 0x20}, // 73 s
{0x04, 0x3f, 0x44, 0x40, 0x20}, // 74 t
{0x3c, 0x40, 0x40, 0x20, 0x7c}, // 75 u
{0x1c, 0x20, 0x40, 0x20, 0x1c}, // 76 v
{0x3c, 0x40, 0x30, 0x40, 0x3c}, // 77 w
{0x44, 0x28, 0x10, 0x28, 0x44}, // 78 x
{0x0c, 0x50, 0x50, 0x50, 0x3c}, // 79 y
{0x44, 0x64, 0x54, 0x4c, 0x44}, // 7a z
{0x00, 0x08, 0x36, 0x41, 0x00}, // 7b {
{0x00, 0x00, 0x7f, 0x00, 0x00}, // 7c |
{0x00, 0x41, 0x36, 0x08, 0x00}, // 7d }
{0x10, 0x08, 0x08, 0x10, 0x08}, // 7e ~
{0x78, 0x46, 0x41, 0x46, 0x78} // 7f
};
void LcdCharacter(char character) {
LcdWrite(LCD_D, 0x00);
for (int index = 0; index < 5; index++) {
LcdWrite(LCD_D, ASCII[character - 0x20][index]);
}
LcdWrite(LCD_D, 0x00);
}
void LcdClear(void) {
for (int index = 0; index < LCD_X * LCD_Y / 8; index++) {
LcdWrite(LCD_D, 0x00);
}
}
void LcdInitialise(void) {
pinMode(PIN_SCE, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_DC, OUTPUT);
pinMode(PIN_SDIN, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);
digitalWrite(PIN_RESET, LOW);
digitalWrite(PIN_RESET, HIGH);
LcdWrite(LCD_C, 0x21); // LCD Extended Commands.
LcdWrite(LCD_C, 0xA0); // Set LCD Vop (Contrast). //0xB1
LcdWrite(LCD_C, 0x04); // Set Temp coefficient. //0x04
LcdWrite(LCD_C, 0x14); // LCD bias mode 1:48. //0x13
LcdWrite(LCD_C, 0x20); // LCD Basic Commands
LcdWrite(LCD_C, 0x0C); // LCD in normal mode.
}
void LcdString(char *characters) {
while (*characters) {
LcdCharacter(*characters++);
}
}
void LcdWrite(byte dc, byte data) {
digitalWrite(PIN_DC, dc);
digitalWrite(PIN_SCE, LOW);
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
digitalWrite(PIN_SCE, HIGH);
}
void LcdXY(int x,int y) {
LcdWrite(LCD_C,0x80|x);
LcdWrite(LCD_C,0x40|y);
}
void LcdNumtoString(float number) {
char string[8];
LcdString(dtostrf(number,5,2, string));
}
////////////// Background Loop Control Functions //////////
// This codelet will automatically enable external load when Sun is Down using PV as Light Sensor
void Load_Control(void) {
if (Load_Auto_Enable == 1 && PV_Voltage < 4.5 && cdc_level > 0) {digitalWrite(PIN_LOAD,HIGH);}
if (Load_Auto_Enable == 1 && PV_Voltage >10.5 || cdc_level==0) {digitalWrite(PIN_LOAD,LOW);}
}
void Charging_Control (void) {
// BattExt_Voltage Level 14.3 Charging off, 13.5 or below Charging on, 10.8 Load off, 12.5 Load on
// this next condition prevents the attempts of charging during night when PV is 0 volt!
if (PV_Voltage > 10.5 && BattExt_Voltage >8.0) {
if (BattExt_Voltage <= 12.5) { analogWrite(PIN_BATTPWM,255); cdc_level = 0; }
if (BattExt_Voltage > 12.5 && BattExt_Voltage <=12.9) { analogWrite(PIN_BATTPWM,200); cdc_level = 1; }
if (BattExt_Voltage > 12.9 && BattExt_Voltage <=13.3) { analogWrite(PIN_BATTPWM,160); cdc_level = 1; }
if (BattExt_Voltage > 13.3 && BattExt_Voltage <=13.6) { analogWrite(PIN_BATTPWM,120); cdc_level = 2; }
if (BattExt_Voltage > 13.6 && BattExt_Voltage <=13.9 && cdc_level == 2) { analogWrite(PIN_BATTPWM,80); cdc_level = 2; }
if (BattExt_Voltage > 13.9 && BattExt_Voltage <=14.3 && cdc_level == 2) { analogWrite(PIN_BATTPWM,40); cdc_level = 2; }
// Over Voltage Lockout, while cdc_level is 3, NO Charging! Charging Resumes when cdc is 2 which is below 13.5 v
if (BattExt_Voltage > 14.3) { analogWrite(PIN_BATTPWM,0); cdc_level = 3; }
} else {analogWrite(PIN_BATTPWM,0);cdc_level = 3;}
}
/// Under voltage Lockout
void Discharging_Control (void) {
if (BattExt_Voltage <= 10.8) {
cdc_level = 0;
{digitalWrite(PIN_LOAD,LOW);}
Timer1_DeInit();
}
}
/////////////// Timer 2 Functions //////////////
// This portion of the code is written in AVR style
void Timer1_Init(void) {
noInterrupts(); // disable all interrupts
pinMode(PIN_INVP,OUTPUT);
pinMode(PIN_INVN,OUTPUT);
TCCR1A = 0;
TCCR1B = 0;
/* ========================================
50 Hz AC means 20 ms Wave which is formed by 2, 10 ms Pulses from PIN_INVP and PIN_INVN pins
so both this pin should toggle at 100 Hz!
Now 100 Hz = .01 sec Arduino System Clock 16 MHz = 16000000 cycle in 0,01 sec we have 160000 cycles
using prescaler of 8 (CS11) makes timer count 160000/8 = 20000 timer ticks
Since the timer 2 is 16 bit Up Counter and it Overflows at 65635 value
we need to start counting from 65535-20000 = from 45535 value upto 65535
thus TCNT1 starts at 45535 ..then tick tick tick ... 46000 .... 50000 .............. 65536 !!!
Boom Timer Over Flow Interrupt and toggle the Inverter driving pins in ISR and start counting from 45535 Again !!!
(This happens in the Background)
======================================== */
TCNT1 = 45535; //TCNT1 = 25535;
TCCR1B |= (1 << CS11); // 8 prescaler
TIMSK |= (1 << TOIE1); // enable timer compare interrupt
interrupts();
}
void Timer1_DeInit(void) {
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
// TIMSK &= (0 << TOIE1); // disable timer compare interrupt
digitalWrite(PIN_INVP,LOW);
digitalWrite(PIN_INVN,LOW);
interrupts();
}
Full Code C/C++
Code georganiseerd & leesbaar
Geen preview (alleen download).
Bootloaders C/C++
Geen preview (alleen download).
Schema's
Productieproces
- Halogeenlampen: Technologie, Geschiedenis en Toekomst – Experts Inzicht
- Lava Lamp: Geschiedenis, Ontwerp en Productiegeheimen
- Zonneverwarmingssystemen: Van Passief tot Actieve Oplossingen voor Duurzame Huisverwarming
- Geïntegreerde Schakelingen (IC's): Compacte, Krachtige Chips die Moderne Elektronica Aandrijven
- Zonnecellen: van vroege experimenten tot moderne fotovoltaïsche technieken – Technologie, productie en toekomstperspectieven
- Slimme Verkeerslicht: Adaptieve Straatverlichting Aangedreven door IoT
- DIY Arduino USB Gaming Controller – Bouw Je Eigen High-Performance Gamepad
- DIY Wolk Kostuum: LED-strip, Arduino Nano & SparkFun Onderdelen
- Zonnetracker V2.0 – Geavanceerd DIY Zonnepaneel Volgsysteem
- Zonenergie Benutten: Complete Gids voor Schone, Betrouwbare Energie
- Wat is een zonnepanelen omvormer? Hoe het zonne-omzet in bruikbare elektriciteit zet