Gå til innhold

Diverse elektronikkprosjekter på gang


Anbefalte innlegg

Coolbear, kunne du hjulpe meg litt?

 

Jeg skal ha et PWM-signal inn på arduinoen, problemet er bare at signalet er 14V med switchinga på minussiden.

 

jeg vil også at om signalet forsvinner fra inngangen på kresten, så skal arduinoen få lav inngang.

 

Kasta ett kjapt blikk på denne og satt sammen dette:

 

traninv.png

 

 

Kretsen består av R1+D1 som klipper signalet til noe Q1 klarer å jobbe med, Q1 inverterer signalet slik at du får det rett vei. Signal ut tas over RLOAD. Denne kretsen oppfyller ikke punkt to, hvis signalet forsvinner fra inngangen(altså 0v inn), ligger signalet ut på 4.5v.

 

Hvis du ikke trenger signalet invertert(tar det i software eller no) så kan du skippe transistoren og enten lage en rekke dioder for å få rett spenningsfall, eller bruke en zenerdiode. Da vil også spenningnen ut være 0v ved bortfall av V1.

 

-

Kolbjørn

 

EDIT: Lagt ved LTSpice-filen for simulering, ta bort .txt fra filnavnet før bruk.

Draft10.asc.txt

Endret av CoolBeer
Lenke til kommentar
Videoannonse
Annonse

Jepp, stemmer som du sier at dette skal bruker i en bil ja :)

 

 

Men nå viser det jeg at jeg husker feil angående målepungtet. Målepungtet har egen utgang fra enheten som styrer solenoiden. Så signalet jeg skal måle har konstant +12V så lenge bilen er i gang, og så er gnd-signalet switchet, Har hatt oscilliskop på dette signalet, og ved kutting av styresignalet, så så jeg faktisk denne spenningstoppen man får ved frakobling av spoler, jeg husker dog ikke hvor stor denne spenningstoppen var.

 

Hovedsaken er at utstyret jeg kobler på ikke trekker for mye strøm fra systemet, pluss at arduinoen ikke blir svidd av overspenninger. Målepunget er i utgangspunktet beregnet for analogt duty cucle meter/Dwell meter.

 

 

EDIT: Eller så jo ikke en optoissolator så ille ut heller :)

Endret av Puke Nukem
Lenke til kommentar

Ny dag nye prosjekter!

 

Holder på å lese meg opp om forsterkere og prøver da diverse ting på ett breadboard, dette medfører ganske ofte at røyk slipper ut av komponentene. Jeg tenkte da som så, at en transistortester hadde vel ikke vært ett dårlig prosjekt.

 

Som sagt som gjort:

 

img4813yu.jpg

 

 

Nå måler den kun NPN transistorer, forward-drop mellom Base-Emitter og Base-Collector, samt hFE ved 50uA basestrøm.

Planen videre blir å automatisk detektere PNP/NPN og pinout.

 

 

-

Kolbjørn

 

 

EDIT: Av en eller merkelig grunn måles strøm i Ampere og ikke i Volt :blush:

Endret av CoolBeer
Lenke til kommentar

Omformulering : Hvilket spenningsnivå har du Vref på?

Vref ligger foreløpig rett på 5v railen, vurderer å bytte om til den interne 1.1v referansen for økt presisjon.

 

 

For øyeblikket driver jeg å koder pin-detect funksjonaliteten som skal finne rett ben til rett plass.

 

Her er ett skjema over hvordan det ca ser ut:

 

pinfind.png

 

 

Vi bruker tre ADC pinner, en til hvert testben. Vi har 2 utganger for hver ADC, en med 100K motstand og en med 100.

Hver utgang kan ha tre nivåer, høy Impedans(aka ikke tilkoblet), 5v og 0v.

For å finne basen går jeg igjennom de forskjellige mulighetene og registrerer ADC.

 

5v kobles igjennom 100K motstanden og 0v igjennom 100R

 

1  | 2 | 3
----------
5v  0v  hiZ
0v  5v  hiZ
hiZ 5v  0v
hiZ 0v  5v
5v hiZ  0v
0v hiZ  5v

 

Vi måler på den pinnen som har 5v signalet(etter 100K motstanden), dersom signalet er relativt lavt, gjerne under ADC 250(av 1024) har vi gjennomslag. Hvis målingen viser nesten full driftspenning(5v) har vi en blokkering. Vi tester rett og slett etter BC/BE (for NPN). Har vi en NPN transistor får vi to lave målinger og kan regne ut hvilken pinne som er basen. En PNP transistor vil gi tre lave målinger, EB, CB og EC.

 

For å skille mellom Collektor og Emitter må vi prøve oss fram. 100K inn på basen gir oss 50uA basestrøm, med 100 ohm på både Collektor og Emitter, +5v på collektor, 0v på emitter. Vi måler på emitter, får vi en veldig lav ADC måling har vi forvekslet C og E, bytt om for hFE måling.

 

 

Føler på meg at denne posten ble omtrent like rotete som koden er for øyeblikket :D Forhåpentligvis var det litt forståelig iallefall \o/

 

-

Kolbjørn

Lenke til kommentar

Da har vi en fungerende prototype!

 

transtest.jpg

 

Koden er ikke veldig mye å skryte av... Veldig raskt rotet sammen. For en god latter se spoiler :D

 

 

 

#define F_CPU 10000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#include "lcd.h"

#define SOURCE_0_100K DDRB |= (1 << PB0); PORTB |= (1 << PB0)
#define SINK_0_100K DDRB |= (1 << PB0); PORTB &= ~(1 << PB0)
#define HIZ_0_100K PORTB &= ~(1 << PB0); DDRB &= ~(1 << PB0)

#define SOURCE_1_100K DDRD |= (1 << PD6); PORTD |= (1 << PD6)
#define SINK_1_100K DDRD |= (1 << PD6); PORTD &= ~(1 << PD6)
#define HIZ_1_100K PORTD &= ~(1 << PD6); DDRD &= ~(1 << PD6)

#define SOURCE_2_100K DDRD |= (1 << PD5); PORTD |= (1 << PD5)
#define SINK_2_100K DDRD |= (1 << PD5); PORTD &= ~(1 << PD5)
#define HIZ_2_100K PORTD &= ~(1 << PD5); DDRD &= ~(1 << PD5)

#define SOURCE_0_100 DDRB |= (1 << PB1); PORTB |= (1 << PB1)
#define SINK_0_100 DDRB |= (1 << PB1); PORTB &= ~(1 << PB1)
#define HIZ_0_100 PORTB &= ~(1 << PB1); DDRB &= ~(1 << PB1)

#define SOURCE_1_100 DDRB |= (1 << PB2); PORTB |= (1 << PB2)
#define SINK_1_100 DDRB |= (1 << PB2); PORTB &= ~(1 << PB2)
#define HIZ_1_100 PORTB &= ~(1 << PB2); DDRB &= ~(1 << PB2)

#define SOURCE_2_100 DDRB |= (1 << PB3); PORTB |= (1 << PB3)
#define SINK_2_100 DDRB |= (1 << PB3); PORTB &= ~(1 << PB3)
#define HIZ_2_100 PORTB &= ~(1 << PB3); DDRB &= ~(1 << PB3)


uint8_t volatile b,c,e;
uint16_t volatile hFE;
bool volatile isNPN;
bool volatile haveTrans;

void init(void)
{
   InitLCD(0);
   LCDClear();

   //Init ADC
   ADCSRA |= (1 << ADEN);
   ADCSRA |= (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2);

}

void baseSource100k(void)
{
   if(b == 0)
       return;
   if(b == 1)
   {
       SOURCE_0_100K;
   }
   else if(b == 2)
   {
       SOURCE_1_100K;
   }
   else if(b == 3)
   {
       SOURCE_2_100K;
   }
}

void emitterSource100(void)
{
   if(e == 0)
       return;
   if(e == 1)
   {
       SOURCE_0_100;
   }
   else if(e == 2)
   {
       SOURCE_1_100;
   }
   else if(e == 3)
   {
       SOURCE_2_100;
   }
}

void baseSink100k(void)
{
   if(b == 0)
       return;
   if(b == 1)
   {
       SINK_0_100K;
   }
   else if(b == 2)
   {
       SINK_1_100K;
   }
   else if(b == 3)
   {
       SINK_2_100K;
   }
}

void emitterSink100(void)
{
   if(e == 0)
       return;
   if(e == 1)
   {
       SINK_0_100;
   }
   else if(e == 2)
   {
       SINK_1_100;
   }
   else if(e == 3)
   {
       SINK_2_100;
   }
}

void collectorSink100(void)
{
   if(c == 0)
       return;
   if(c == 1)
   {
       SINK_0_100;
   }
   else if(c == 2)
   {
       SINK_1_100;
   }
   else if(c == 3)
   {
       SINK_2_100;
   }
}

void collectorSource100(void)
{
   if(c == 0)
       return;
   if(c == 1)
   {
       SOURCE_0_100;
   }
   else if(c == 2)
   {
       SOURCE_1_100;
   }
   else if(c == 3)
   {
       SOURCE_2_100;
   }
}

void allHIZ(void)
{
   HIZ_0_100K;
   HIZ_0_100;
   HIZ_1_100K;
   HIZ_1_100;
   HIZ_2_100K;
   HIZ_2_100;
}

uint16_t runADC(void)
{
   ADCSRA |= (1 << ADSC);
   _delay_ms(10);
   while(!ADCSRA & (1 << ADIF))
       asm volatile ( "nop" );
   return ADC;
}

void checkhFE(void)
{
   allHIZ();

   if(isNPN)
   {
       baseSource100k();
       collectorSource100();
       emitterSink100();
       ADMUX = e-1;
   }
   else
   {
       baseSink100k();
       collectorSink100();
       emitterSource100();
       ADMUX = c-1;
   }
   _delay_ms(1);
   runADC();
   hFE = (uint32_t)5000000 / (uint32_t)(1024000/ADC);
   hFE /= 5;
   allHIZ();
}

void findPins(void)
{
   haveTrans = true;
   uint8_t sightings = 0;
   uint8_t data[6] = {0,0,0,0,0,0};

   allHIZ();

   ADMUX = 0;
   SOURCE_0_100K;
   SINK_1_100;
   _delay_ms(1);

   runADC();
   if(ADC < 175)
   {
       ++sightings;
       data[0] = 1;
       data[1] = 2;
   }
//	LCDWriteIntXY(0,0, ADC, 4);

   allHIZ();
   ADMUX = 1;
   SOURCE_1_100K;
   SINK_0_100;
   _delay_ms(1);

   runADC();

   if(ADC < 175)
   {
       data[sightings*2] = 2;
       data[sightings*2+1] = 1;
       ++sightings;
   }
//	LCDWriteIntXY(5,0, ADC, 4);

   allHIZ();
   ADMUX = 1;
   SOURCE_1_100K;
   SINK_2_100;
   _delay_ms(1);

   runADC();

   if(ADC < 175)
   {
       data[sightings*2] = 2;
       data[sightings*2+1] = 3;
       ++sightings;
   }
//	LCDWriteIntXY(10,0, ADC, 4);

   allHIZ();	
   ADMUX = 2;
   SOURCE_2_100K;
   SINK_1_100;
   _delay_ms(1);

   runADC();

   if(ADC < 175)
   {
       data[sightings*2] = 3;
       data[sightings*2+1] = 2;
       ++sightings;
   }
//	LCDWriteIntXY(0,1, ADC, 4);

   allHIZ();	
   ADMUX = 0;
   SOURCE_0_100K;
   SINK_2_100;
   _delay_ms(1);

   runADC();

   if(ADC < 175)
   {
       data[sightings*2] = 1;
       data[sightings*2+1] = 3;
       ++sightings;
   }
//	LCDWriteIntXY(5,1, ADC, 4);

   allHIZ();	
   ADMUX = 2;
   SOURCE_2_100K;
   SINK_0_100;
   _delay_ms(1);

   runADC();

   if(ADC < 175)
   {
       data[sightings*2] = 3;
       data[sightings*2+1] = 1;
       ++sightings;
   }
//	LCDWriteIntXY(10,1, ADC, 4);

   allHIZ();	

   if(sightings != 0)
   {
       if((data[1] == data[3]) || (data[1] == data[5]))
       {
           isNPN = false;
           b = data[1];
       }
       else if(data[3] == data[5])
       {
           isNPN = false;
           b = data[3];
       }
       else if(data[0] == data[2])
       {
           isNPN = true;
           b = data[0];
       }

       if(b == 1)
       {
           c = 2;
           e = 3;
       }
       else if(b == 2)
       {
           c = 1;
           e = 3;
       }
       else if(b == 3)
       {
           c = 1;
           e = 2;
       }

       checkhFE();
       uint16_t firsthFE = hFE;



       uint8_t thmp = c;
       c = e;
       e = thmp;

       checkhFE();
       if(firsthFE > hFE)
       {
           thmp = c;
           c = e;
           e = thmp;
           hFE = firsthFE;
       }
   }
   else
       haveTrans = false;
}

void runTest(void)
{
   uint16_t volatile be, bc;
   ADMUX = 0;

   //test BE drop
   if(isNPN)
   {
       baseSource100k();
       emitterSink100();
       ADMUX = b - 1;
   }
   else
   {
       baseSink100k();
       emitterSource100();
       ADMUX = b - 1;
   }
   runADC();
   be = ADC;

   allHIZ();

   //test BC drop
   if(isNPN)
   {
       baseSource100k();
       collectorSink100();
       ADMUX = b - 1;
   }
   else
   {	
       baseSink100k();
       collectorSource100();
       ADMUX = b - 1;
   }
   runADC();
   bc = ADC;

   allHIZ();


   if(isNPN)
   {
       LCDWriteStringXY(0,0, "BE=");
       LCDWriteStringXY(8,1, " NPN/");
   }
   else
   {
       LCDWriteStringXY(0,0, "EB=");
       LCDWriteStringXY(8,1, " PNP/");
   }

   LCDWriteIntXY(3, 0, (uint32_t)5000000 / (uint32_t)(1024000/be), 3);
   LCDWriteString("mV");

   if(isNPN)
   {
       LCDWriteStringXY(0,1, "BC=");
   }
   else
   {
       LCDWriteStringXY(0,1, "CB=");
   }
   LCDWriteIntXY(3, 1, (uint32_t)5000000 / (uint32_t)(1024000/bc), 3);
   LCDWriteString("mV");

   LCDWriteStringXY(8,0, " hFE=");
   LCDWriteIntXY(13, 0, hFE, 3);

   LCDGotoXY(13,1);
   if(b == 1)
   {
       LCDWriteString("B");
   }
   else if(c == 1)
   {
       LCDWriteString("C");
   }
   else if(e == 1)
   {
       LCDWriteString("E");
   }

   if(b == 2)
   {
       LCDWriteString("B");
   }
   else if(c == 2)
   {
       LCDWriteString("C");
   }
   else if(e == 2)
   {
       LCDWriteString("E");
   }

   if(b == 3)
   {
       LCDWriteString("B");
   }
   else if(c == 3)
   {
       LCDWriteString("C");
   }
   else if(e == 3)
   {
       LCDWriteString("E");
   }

}


void printMes()
{
   LCDWriteStringXY(0,0, "Please          ");
   LCDWriteStringXY(0,1, "Insert BJT      ");
}

int main(void)
{
   init();


   allHIZ();

   while(1)
   {
       findPins();
       if(haveTrans)
           runTest();
       else
           printMes();

       asm volatile ( "nop" );
   }
   return 0;
}

 

 

 

 

-

Kolbjørn

 

 

EDIT: Rettet kodetabbe.

Endret av CoolBeer
Lenke til kommentar

Som noen sikkert har fått med seg har jeg holdt på med forsterkerteori i det siste. Jeg har pløyd meg igjennom diverse bøker(Audio Power Amplifier Design Handbook(Douglas Self), Designing Audio Power Amplifiers(Bob Cordell) og High-Power Audio Amplifier Construction Manual(G. Randy Sloan).

 

En ting jeg har funnet ut er at jeg må begynne rolig, ikke med en vanvittig komplisert konstruksjon(som jeg har en tendens til å gjøre). I det siste har jeg koblet opp en C-Moy hodetelefon-forsterker, denne har en lei tendens til å gå varm etter en stund, jeg tipper at enten er det hodetelefonene mine den ikke liker eller så har jeg laget meg en oscillator.

Uansett hvorfor og hvordan den ikke fungerer så gir dette meg ett påskudd for å prøve ut forsterker-teori i praksis uten å begynne med en komplisert design på flere hundre watt som trenger ett eget kraftverk.

 

 

 

Dette er så kretsen jeg har kokt ihop:

(Merk at for hodetelefoner må man ha to av denne, en til hvert øre)

 

 

headphonetry1.png

 

 

En forsterker er hovedsakelig bygd opp av tre deler, LTP(Q14/15/7/5/8 og 11), VAS(Q6 + Q13/10) og OPS(Q4/1/9/2). (LTP = Long Tailed Pail, VAS = Voltage Amplification Stage, OPS = OutPut Stage). Dette går igjen i 99% av alle forsterkere. Jeg skal ikke gå inn på hvordan det hele henger sammen(bøkene jeg nevnte kan anbefales for det), og jeg skal på ingen måte erklære at jeg forstår kretsen 100% enda.

 

Simulering av kretsen er gjort i LTSpice, der det framkommer at vi har ca 3.5W ut før klipping(THD 0.006928%), 3.8W ved 1% THD og rundt 4.7W ved 10% THD(i det tilfelle man absolutt har lyst på 10% forvrengning), for normale verdier inn(+-0.7v) har vi ut rundt 900mW, som i selv seg er vanvittig mye for hodetelefoner(iallefall normale typer).

 

 

Det skal bli interessant å se hvordan kretsen oppfører seg utenfor LTSpice, tingen med LTSpice er at simuleringen er akkurat det, en simulering, gjerne med ideelle komponenter. Jeg skulle gjerne hatt ideelle komponenter i virkeligheten, men så heldige er vi ikke. Derfor må man ta simuleringer med en klype salt og være forberedt på at uforutsette ting dukker opp.

 

-

Kolbjørn

Lenke til kommentar

Godt observert toreae.

 

Det blir ikke noe strøm der. Se på Q10 og Q13. Disse er riktig plasserte.

 

En liten ting til: merkinga av tilbakekoblinga tror jeg for noen kan være lett å missforstå. Jeg ble lært opp til alltid å ha en synlig tilkobling. Men det er kansje noe nytt lærebøkene er begynt med for å forenkle tegninga.

Lenke til kommentar

Du må gjerne utdype hvordan Q14 og Q15 virker (PNP-transistorer med collektor og emitter "feil vei" i forhold til pluss og minus). Og Q11 med base collektor sammenkoblet.

 

For all del, dette er ikke ironisk ment.

 

Jepp, ble en bommert der, pent observert :)

 

 

En liten ting til: merkinga av tilbakekoblinga tror jeg for noen kan være lett å missforstå. Jeg ble lært opp til alltid å ha en synlig tilkobling. Men det er kansje noe nytt lærebøkene er begynt med for å forenkle tegninga.

 

Er nok jeg som har tatt mine friheter ;)

 

 

Nytt oppdatert skjema:

 

headphonetry2.png

 

 

 

Og en testkrets med strømforsyning:

 

img4819h.jpg

 

 

 

Etter noen timer feilsøking ble det oppdaget at emittermotstandene i utgangstrinnet ikke var 2x0.2 Ohm, men rundt 0.6M (Tatt ifra ett annet forsterkerprosjekt, tror jeg vet hvorfor det prosjektet ikke fungerte...). Etter bytting av disse ble det liv i forsterkeren!

 

Siden denne er bygd på ett breadboard må man regne med at kretsen ikke vil fungere optimalt(mye kapasitans, dårlige koblinger, ikke egnet for høye strømmer), så resultater her må tas med en kilo salt...

Hvis jeg klarer å legge kablene på en slik måte at de fungerer minst mulig som antenner, er det mulig å nesten bli kvitt bakgrunnsstøyen. kvalitetsmessig er lyden helt ok, nå har jeg bare koblet opp en kanal, så får ikke ett totalt bilde av lydkvaliteten, det får vente til ett printkort er etset.

 

-

Kolbjørn

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...