Hörtalaren vart färdigbygd redan i somras, och har inte så jätte mycket att säga om den men väntade med att lägga ut byggloggen innan batteriladdaren också var klar.
Var väldigt inspirerad av maDas högtalare, så byggde en egen genom att kolla på bilder av hans.
Och hur allt gick till:
Det första jag gjorde var att räkna på lådan och skaffade förstärkaren och kraftagget.
Kraftagget är på 350W (overkill) men de va billigare än 150W agget jag först tänkte ta. Sen ritade jag upp allt på papper så jag kunde på en känsla över hur allt kommer ligga i lådan. Efter att jag var nöjd med hur allt skulle ligga så började jag göra alla sidor och ta ut hål och liknande: Sen var det bara att börja skruva ihop allt. Liberala mängder trälim användes

Kan berätta att vägglister fungerar perfekt som batterihållare! Nu skulle en frontpanel byggas, plastade den, tog ut hål och spacklade den: Sen efter målning så var den klar!
Är helt nöjd med resultatet och den spelar riktigt fint! Batteriladdaren - Switchat Nätaggregat med CC och CV funktioner
Lite rapport stil på denna, lite för att ge en insikt i hur jag har tänkt och resonerat.

Det kan vara lite konstigt skrivet ibland då jag har skrivit denna text över lång tid.
Introduktion:
Detta projekt har jag startat för att ge mig en bättre kunskap inom analog elektronik, störningar från switchande nätaggregat och att lära mig kontrollera ett sådant aggregat.
Men anledningen till att detta projekt startade, i grund och botten - innan jag såg vad jag kunde lära mig av det, är på grund av ett sommarprojekt jag byggde på hemma över sommaren. Det är så att vi i klassen gillar att träffas ute och så gillar vi musik, men ingen av oss har en bärbar högtalare, så jag byggde en sådan över sommaren. Men då den både kunde drivas på batteri och ett inbyggt nätaggregat så ville jag inte behöva ha en separat laddare till batterierna. MaDa fixade detta genom att ställa in kraftaggregatet på en lagom nivå och koppla in batterierna rakt därpå, men jag ville ha mer kontroll.
Och här startade min långa vandring in i den stora och underbara världen av switchade nätaggregat och hur man kan kontrollera dessa, både ur spänning- och strömsynpunk.
Tillvägagångssätt:
Det första jag gjorde var att snabbt skissa upp hur jag ville att det skulle fungera (ungefärligt).
Och efter lite funderade kom jag fram till denna bild: Problem:
Det jag försöker åstadkomma är så att min krets F ska ha denna funktion (ändrades lite på vägen, men huvud idén är den samma):
- Finns det spänning i A samt att spänningen över batteriet är > X volt så ska F vara avbrott (där X är gränsen för ett fulladdat batteri).
- Finns det spänning i A samt att spänningen över batteriet är < Y volt så ska F ha kontakt (där Y är gränsen för att påbörja laddning).
- Om den laddar och spänningen kommer upp till gränsen X volt så ska den hålla kontakt i en bestämd tid, Z timmar, och sedan bli avbrott.
- Finns det ingen spänning från kraftagget så ska F ha kontakt (då ska batteriet driva instrumentet).
Samt:
- När F är kopplad för laddning så behöver laddströmmen begränsas och bör ligga som högst omkring 0.9A.
- Men vid urladdning ska det inte finnas någon begränsning.
Lösning:
Jag googlade på mitt problem och ramlade då över switchade nätaggregat. Och efter lite läsning och simuleringar så gjorde jag en illustrerande bild över kretsen Fs funktion när det gäller laddningen: Och det mest förklarar sig självt här, men ska tydliggöra lite:
- När bilden ritades så var jag osäker på om man skulle ha en P-MOS eller en N-MOS, så ritade det som en strömbrytare.
- Gain är en icke inverterande förstärkare, som förstärker 23 gånger, med ett lågpassfiler på. Den mäter spänningsfallet över det försumbart lilla motståndet (dvs. för resten av kretsen) så att jag kan beräkna strömmen i kretsen och styra den.
- Ref2 är spänningsreferens så jag kan styra spänningen.
- PWM Ctrl är en 8-bitars mikrokontroller av märket AVR. Den kör en hårdvaru PWM på 31.2 kHz och läser samtidigt av Ref 1 och Ref 2 och gör nödvändiga ändringar på PWMens Duty (D) för att spänning och ström ska ligga inom gränserna.
- Load representerar batteriet, men det jag ritade var för en generell design, det behöver inte vara just ett batteri man har där.
Efter detta läste jag på om hur man beräknar värdena på komponenterna i dessa såkallade ”Buck converters”. Jag gjorde ett Excelblad för att göra mina beräkningar lätta för ändring, men denna är också för en generell design, behöver inte vara ett batteri, så vissa onödiga saker är inkluderade.
Jag har bifogat ett exempel på olika värden som jag satt och testade med. De vart också dessa värden som vart de slutgiltiga. Jag valde ett ganska stort värden på induktansen därför att jag inte ville att strömmen skulle svänga så mycket pga. slutna blybatteriers natur. De tål inte för höga strömmar.
Design:
Nu var det dags att designa kopplingsschemat och att göra en boardlayout som kan skickas till Kina för produktion. Jag har tyvärr inga bilder på mina gamla versioner. Den första versionen gick sönder pga. P-MOSen var kopplad så den drogs till jord för att öppna sig och det vart då en gatespänning på ca -31V. Den klarade denna spänning i ca 1 timmes användning innan den började bete sig sporadiskt och tillslut att den inte öppnade sig mer. Men till min lycka så innan transistorn gick sönder så fungerade allt perfekt, precis enligt mina beräkningar och simuleringar.
Men efter lite om design så fick jag den nuvarande designen: Och denna design fungerar precis som jag ville!

Samt koden för de som är sugna:
Kod: Markera allt
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define F_CPU 8000000UL
// Pin and Port definitions [PORTA]
#define CONTROL_DDR DDRA
#define CONTROL_PORT PORTA
#define I_ADC_PIN 0
#define V_ADC_PIN 1
#define RELAY_PIN 2
#define LED_PIN 3
// Pin and Port definitions [PORTB]
#define PWM_DDR DDRB
#define PWM_PORT PORTB
#define PWM_PIN 2
// Pointers for different blink-routines
#define BLINK_STOP 0
#define BLINK_SEQ_ERR3 1
#define BLINK_SEQ_ERR2 3
#define BLINK_SEQ_ERR1 5
#define BLINK_SEQ_DONE 8
// Flags that controll various things (their bit position)
#define FLAG_RUN_UPD 0 // bit = 1 -> Run the PWM update
#define FLAG_PWM_CONT 1 // bit = 0 -> Use current controll -||- bit = 1 -> Use voltage controll
#define FLAG_ADC_CHK 2 // bit = 0 -> Summing ADC current -||- bit = 1 -> Summing ADC voltage
#define FLAG_TIMER 3
// Maximum and minimum PWM dutys (safe guards)
#define PWM_MAX 255
#define PWM_MIN 15
//Timing constants
#define TIMER_1H 76200 // = 1h with time error corection
#define TIMER_3H 228600 // = 3h with time error corection
// ADC values that the controller works to achieve
#define ADC_AIM_CURR 414
#define ADC_AIM_VOLT 894
#define ADC_AIM_VOLT_LOW 823
#define ADC_MIN_CURR 3
// Globals
volatile uint8_t flags = 0;
volatile uint8_t blink_seq = 0;
volatile uint16_t adc_value_c = 0;
volatile uint16_t adc_value_v = 0;
volatile uint16_t adc_aim = ADC_AIM_CURR;
volatile uint32_t timer_cnt = 0;
// Functions
void init_ADC();
void init_PWM();
void PWM_off();
void init_DELAY();
int main(void)
{
cli();
CONTROL_DDR |= ((1<<RELAY_PIN)|(1<<LED_PIN)); // LED & Relay Outputs
CONTROL_DDR &= ~((1<<I_ADC_PIN)|(1<<V_ADC_PIN)); // ADC Inputs
CONTROL_PORT = 0;
PWM_DDR |= (1<<PWM_PIN); // PWM output
PWM_PORT = 0;
init_DELAY();
init_ADC();
CONTROL_PORT |= (1<<RELAY_PIN);
sei();
no_battery: // Restart point if the battery was disconnected
/*--- Checking for battery ---*/
blink_seq = BLINK_SEQ_ERR1; // Start "waiting for battery"-blink
PWM_off();
flags = 0; // Reset variables
adc_aim = ADC_AIM_CURR;
timer_cnt = 0;
for (uint8_t i = 0; i < 133; i++) // 8s delay for the capacitors to discharge and not give a faulty voltage reading
{
_delay_ms(30);
_delay_ms(30);
}
while (adc_value_v < 700); // Check if battery is connected, if the voltage is over 23V = battery connected
blink_seq = BLINK_STOP;
CONTROL_PORT |= (1<<LED_PIN); // Start "battery charging"-light
/*--- Starting first charging cycle with CC = 0.9A and CV = 29.3V ---*/
init_PWM();
while (timer_cnt < TIMER_3H) // timer_cnt is 0 until CV kicks in
{
if (adc_value_c < ADC_MIN_CURR) // If the battery is disconnected restart the program.
goto no_battery;
if (adc_value_c > ADC_AIM_CURR) // If the current has risen over the allowed limit, switch to CC
{
flags &= ~(1<<FLAG_PWM_CONT);
adc_aim = ADC_AIM_CURR;
}
else if (adc_value_v > ADC_AIM_VOLT) // If the voltage has risen over the allowed limit, switch to CV
{
flags |= ((1<<FLAG_PWM_CONT)|(1<<FLAG_TIMER)); // Start counting timer_cnt when CV kicks in
adc_aim = ADC_AIM_VOLT;
}
}
/*--- Starting second charging cycle with CC = 0.9A and CV = 27V ---*/
timer_cnt = 0; // Reset timer_cnt, timer_cnt is still counting
while (timer_cnt < TIMER_1H)
{
if (adc_value_c < ADC_MIN_CURR) // If the battery is disconnected restart the program.
goto no_battery;
if (adc_value_c > ADC_AIM_CURR) // If the current has risen over the allowed limit, switch to CC
{
flags &= ~(1<<FLAG_PWM_CONT);
adc_aim = ADC_AIM_CURR;
}
else if (adc_value_v > ADC_AIM_VOLT_LOW) // If the voltage has risen over the allowed limit, switch to CV
{
flags |= (1<<FLAG_PWM_CONT);
adc_aim = ADC_AIM_VOLT_LOW;
}
}
/*--- Charge completed! Continue with tickle charge CV = 27V ---*/
blink_seq = BLINK_SEQ_DONE;
while (1)
{
if (adc_value_c < ADC_MIN_CURR) // If the battery is disconnected restart the program.
goto no_battery;
if (adc_value_c > ADC_AIM_CURR) // If the current has risen over the allowed limit, switch to CC
{
flags &= ~(1<<FLAG_PWM_CONT);
adc_aim = ADC_AIM_CURR;
}
else if (adc_value_v > ADC_AIM_VOLT_LOW) // If the voltage has risen over the allowed limit, switch to CV
{
flags |= (1<<FLAG_PWM_CONT);
adc_aim = ADC_AIM_VOLT_LOW;
}
}
}
void init_ADC()
{
ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADATE)); // ADC prescaler 128 - Autotrigger
ADMUX &= ~((1<<REFS0)|(1<<REFS1)); // Vcc as voltage reference
ADCSRB &= ~((1<<ADTS0)|(1<<ADTS1)|(1<<ADTS2)); // Free running mode
ADCSRA |= ((1<<ADIE)|(1<<ADEN)|(1<<ADSC)); // Interupt enable - Enable ADC - Start conversion
ADMUX &= ~0b00111111; // Start with a current reading
}
void init_DELAY()
{
TCCR1B |= ((1<<WGM12)|(1<<CS10)|(1<<CS12)); // Start Timer1, CTC mode, 1024 prescaler
TIMSK1 |= (1<<OCIE1A); // Compare interupt
OCR1AH = 1;
OCR1AL = 105; // 8000000Hz / 1024 / 390 = ~20Hz
}
void init_PWM()
{
TCCR0A |= ((1<<WGM00)|(1<<WGM01)|(1<<COM0A1)); // Start Timer0, Fast PWM mode, output pin OC0A (PB2)
TCCR0B |= (1<<CS00); // No prescaler, 8000000Hz / 256 = ~31 250Hz PWM
OCR0A = PWM_MIN;
}
void PWM_off()
{
OCR0A = 0;
TCCR0B &= ~(1<<CS00);
TCCR0A &= ~((1<<WGM00)|(1<<WGM01)|(1<<COM0A1));
}
ISR(TIM1_COMPA_vect)
{
const static uint8_t blinklist[] = {0,3,3,3,3,3,20,0,20,20,0};
static uint8_t cnt = 0;
static uint8_t count = 0;
static uint8_t ptr = 0;
static uint16_t adc_value = 0;
if (flags & (1<<FLAG_PWM_CONT)) // Check if Current or Voltage controll
adc_value = adc_value_v; // and adjust adc_value
else
adc_value = adc_value_c;
if (cnt & 1)
{
if ((adc_value > adc_aim) && (OCR0A > PWM_MIN)) // Adjust PWM Duty, if needed
OCR0A--;
else if ((adc_value < adc_aim) && (OCR0A < PWM_MAX))
OCR0A++;
else if (OCR0A < PWM_MIN)
OCR0A++;
}
if ((cnt >= count) && (blink_seq != 0))
{
cnt = 0;
count = blinklist[ptr++];
if (count == 0)
{
CONTROL_PORT &= ~(1<<LED_PIN);
ptr = blink_seq;
}
else
CONTROL_PORT ^= (1<<LED_PIN);
}
if (flags & FLAG_TIMER)
timer_cnt++;
cnt++;
}
ISR(ADC_vect) // Sum 64 readings and then divide by 64 for average
{ // Every second is voltage average and the other is current average
static uint8_t cnt = 0;
static uint16_t sum = 0;
if (cnt >= 63)
{
if (flags & (1<<FLAG_ADC_CHK))
{
adc_value_v = (sum>>6);
ADMUX &= ~0b00111111; // Clear all MUX0..5 - ADC on ADC0 pin (PA0) (current reading)
flags &= ~(1<<FLAG_ADC_CHK); // Set flags for current reading
}
else
{
adc_value_c = (sum>>6);
ADMUX |= (1<<MUX0); // ADC on ADC1 pin (PA1) (voltage reading)
flags |= (1<<FLAG_ADC_CHK); // Set flags for voltage reading
}
cnt = 0;
sum = 0;
}
else
{
sum += ADCL;
sum += (ADCH<<8);
cnt++;
}
}
Färdigbyggd version 1: Slaktad version 1 och version 2s kretskort: Testbänken under testerna: Och testet i högtalaren då jag laddade batteriena för första gången.
Film: Det här var mitt första stora projekt och jag är väldigt nöjd!
Kom gärna med kommentarer, men en förbättring som kan göras är att ha en differentialförstärkare över motståndet för bättre strömmätning och mindre störningar, men det blir kanske i en senare design.

Och det var allt för mig! Och beklagar över dålig svenska samt felskrivningar!