Start Elkretssimulator


Analog utsignal på arduino

Analoga utgångar som inte alls är analoga

Har man labbat lite och börjat begripa hur digitala in och utgångar fungerar så kraschar man eventuellt in i en vägbula när de analoga utgångarna inte följer samma enkelhet. Faktum är att de analoga utgångarna inte alls ger en analog utsignal. De ger istället en pulsbreddsmodulerad utsignal. Vad är det som pågår här?

Om man ansluter en logikanalysator till arduino och kör följande program, så får man nedanstående utdata på logikanalysatorn.

void setup() 
{
  analogWrite(6,250);   // Gul port 6
  analogWrite(5,128);   // Grön port 5
  analogWrite(10,64);   // Blå port 10
  analogWrite(9,10);    // Lila port 9
}

void loop() 
{

}


Det som händer är att de analoga utgångarna är inte "färdigbyggda". Det behövs minst 2 komponenter till här för att skapa den analoga utspänningen.

Blixtintroduktion till PWM

PWM står alltså för Puls-Bredds-Modulering (engelska som vanligt, Pulse-width modulation). Dvs vi skapar en spänning och låter denna vara påslagen en viss tid - en viss pulsbredd, sedan stänger vi av den igen. Detta gör vi väldigt snabbt och upprepar hela tiden.





Konvertera PWM till spänning

För att konvertera en pulsbreddsmodulerad signal till en spänning behövs ett litet RC -filter. Det heter RC -filter därför att det består av en resistor (R) och en kondensator (C). Det ser ut som nedan schema. Ett enkelt sätt att förklara denna RC -krets kan vara att betrakta kondensatorn som ett litet batteri. Vi laddar upp detta batteri när pulsen är hög och laddar ur batteriet när pulsen är låg. Detta sker blixtsnabbt tusentals gånger per sekund, så fort att utsignalen i praktiken blir en hyffsat jämn och fin spänning.

Ett fungerande värde kan vara 1 KΩ för resistorn och 4.7 uF för kondensatorn, fast det beror lite på vilken vilken frekvens du använder på din puls. En käck websida med en kalkylator för att räkna på RC -kretsar går att hitta här. Till vänster klickar vi i R and C values samt exprimenterar med olika värden givet en viss frekvens.

10 KHz med 1KΩ och 1uF ger oss följande stegsvar.


Dvs, vi får en spänning som verkar stabiliserar sig efter ca 0.003 sekunder (3 ms) men signalen ser ut att ha ett rippel på kanske 0.2 volt. Väljer vi istället en kondensator på 4.7 uF allt i övrigt samma får vi en stabilare spänning men det tar 0.020 sekunder innan den stabiliserat sig.


Kan man leva med att det tar 0.020 sekunder innan utspänningen är korrekt? Det beror ju förstås helt på vad man har i den andre änden, som spänningen skall användas till. Det är kanske först när vi pratar musik/audio som det börjar bli rejält kasst med dessa prestanda. I praktiken duger inte arduinos unos D/A till musik med någon högre kvalite. För att få kvalite behöver vi kunna jobba med högre frekvenser och högre upplösning (fler bitar). Men arduinos D/A duger kanske till en liten synt. Det duger utmärkt till att styra yttre grejer, motorer och annat. När allt kommer kring är 0.02 sekunder rätt snabbt. Dvs, om vi inte pratar musik.

Labba i simulatorn


Enkelt RC-filter i simulatorn. Dubbelklicka på pulsgeneratorn och ändra duty cycle (dvs pulsbredd) och notera hur utspänningen förändras. Observera att pulsgeneratorn står på 2.5 volt amplitud och 2.5 volt DC -offset. Detta ger ett pulståg med noll som referens med höjden 5 volt.

En liten testkoppling

Jag har kopplat upp ungefär som nedan. Vad jag gjort är också att använda en potentiometer som spänningsdelare för att få in en variabel spänning, så att jag kan justera nivån på den analoga utgången mellan 0-5 colt.



Kod

Koden läser av värdet på den analoga ingången (potentiometern kopplad som spänningsdelare) och skickar ut motsvarande på den analoga utgången. Observera dock att den analoga ingången ger värde mellan 0-1023 medans den analoga utgången justeras mellan 0-255. Därför dividerar jag värdet från analoga in med 4.

int pwmPin = 3;
int analogInputPin = 3;
int val = 0;

void setup()
{
  pinMode(pwmPin, OUTPUT);
}

void loop()
{
  // vi läser det analoga värdet från potentimetern
  // kopplad som spänningsdelare. Får ett värde mellan
  // 0 och 1023.
  val = analogRead(analogInputPin);  

  // Vi skriver detta värde dividerat med 4 på pwmPin
  // eftersom pwmPin tar ett värde från 0 till 255
  analogWrite(pwmPin, val / 4);
}