Frekvensmodul

Fra Holstebro HTX Wiki
Skift til: navigering, søgning

Frekvensmodulet kan måle maksimum spænding, minimum spænding og periodetiden for en vekselspænding, som derefter kan kommunikeres til en anden enhed via I2C.

Teori

En vekselspænding kan beskrives som en sinussvingning med funktionen: Sinussvingning formel.png.

Symboler og begreber.

Spændingen U: Spænding ved tiden t. Enhed: [V]

Amplituden A: Maksimal udsving i spændingen. Enhed: [V]

Periodetiden T: Tiden en periode tager. Enhed: [s]

Frekvensen f: Antallet af perioder pr. tid. Enhed: [1/s = Hz]

Fasen ϕ: Startpositionen af svingning ved tiden t=0. Enhed: [radianer el. grader]


Nedenstående illustrerer en svingning med størrelserne: A = 5 V, T = 1/3 s, f = 3 Hz, ϕ = 0.

Sinussvingning plot.png


Generelt om modulet

Modulet består overordnet set af to dele. En konverter, der forskyder svingingen så den ligger omkring 2.5 V, som derefter måles af mikroprocessoren ATTiny45, som vist i blokdiagrammet herunder.

Blokdiagram

Blokdiagram frekvensmaaler.png

Udviklingsmiljø

Modulet er udviklet med et Atmel_udviklingsmiljø. Print og beskrivelse af programmering af mikroprocessoren kan findes under siderne AVR-programmer_Shield og ATTiny45.

Specifikationer

Forsyning: +5V

Strømforbrug: 15.3 mA - 19.5 mA

Effekt: 76.5 mW - 97.5 mW

Inputspænding: -2.5 V - +2.5 V

Måleområde: 50 Hz - 800 Hz

Typisk tolerance: ±15%

Hardware

Da inputspændingen til tider er negativ kan denne spænding ikke måles direkte med ATTiny45'en. Derfor må man forskyde spændingen op i et positivt område mellem 0V og +5V, som er det område ATTiny45'en kan måle. Hvordan man kan gøre dette er beskrevet i følgende afsnit.

Konverter

Spændingen forskydes fra intervallet [-2.5V; +2.5V] til intervallet [0V; +5V], ved hjælp af følgende kredsløb.

Konverter schem2.png

Kredsløbet fungerer således at der øverst er en spændingsdeler, der laver en +2,5V spænding. Denne spænding bliver nu udgangspunktet for den nye svingning. Ud fra spændingen fra inputsvingningen bliver kondensatoren C1 skiftetvis op- og afladet, hvilket gør at spændingen til ATTiny'en svinger op og ned omkring de +2,5V. På den måde kan svingningen nu måles med ATTiny'en.

ATtiny45

ATTiny45 er produceret af Atmel, og er en del af en række af mikroprocessorer, som kører med AVR-arkitektur. For disse gælder der, at de ved hjælp af deres opbygning kan programmeres med kompileret C-kode[1].

Software

Nedenstående er en beskrivelse af den software, der ligger bag modulet. Software'en er skrevet i programmeringssproget C. Hvordan udviklingsmiljøet kan opsættes kan læses under siden Atmel_udviklingsmiljø.

Hvis man er vandt til at programmerer en Arduino, er en udgave Arduino IDE's BareMinimum følgende til ATTiny.

int main( void ) 
{
  //Setup
  
  while(1) //Loop
  {

  }

  return 0;
}

I2C

For at modulet skal kunne kommunikerer ved hjælp af I2C, er der anvendt et software bibliotek kaldet usiTwiSlave[2].

Biblioteket benyttes ved at placerer filerne i samme mappe, som sin programkode, hvorefter den indlæses ved at skrive følgende i toppen af koden.

extern "C" 
{
	#include "usiTwiSlave.h"
}

Herefter kan man benytte følgende kommandoer til at modtage og sende data via I2C.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
extern "C" 
{
	#include "usiTwiSlave.h"
}

int main( void ) 
{
  sei();
  usiTwiSlaveInit(slaveAddress); //Her sætter man den adresse som slaven skal have.

  while(1)
  {
	
	if(usiTwiDataInReceiveBuffer()) // Her tjekker man om der er modtaget data.
		{

		        uint8_t inp = usiTwiReceiveByte(); // Gemmer modtaget data i en variable inp.
			usiTwiTransmitByte(inp); // Sender det modtaget tilbage.
		
		}
  }

  return 0;
}

Ovenstående virker blot, som en echo, der sender det der modtages fra masteren tilbage til masteren.

Timer

For at benytte sig af en timer, til at holde styr på tiden, kan man benytte følgende kode inden loop'et.

TCCR0B |= ((1 << CS02) | (1 << CS00));

Herefter kan tiden aflæses som en 8-bit værdi med følgende kode.

uint8_t ctime = TCNT0;

Ønsker man at udvide tælleren, kan man skrive følgende.

t1 = t2;
t2 = TCNT0;
if(t1<=t2){
	ctime += t2-t1;
}else{
	ctime += t2-t1 + 256;
}

Hvor tiden nu kan aflæses i en som 16-bit, hvis ctime er defineret således, og den kan endda være 32bit, hvis man ønsker dette.

Den egentlige tid kan nu beregnes med nedenstående formel.

T = (0.125/1000) * ctime * s

Analog input

For at måle en analog spænding skal man ændre en del værdier i ATTiny'ens registre. Denne funktion gør denne process lettere funktion[3] der gør dette for en.

void initADC()
{
  ADMUX =
            (1 << ADLAR) |     // left shift result
            (0 << REFS1) |     // Sets ref. voltage to VCC, bit 1
            (0 << REFS0) |     // Sets ref. voltage to VCC, bit 0
            (0 << MUX3)  |     // use ADC2 for input (PB4), MUX bit 3
            (0 << MUX2)  |     // use ADC2 for input (PB4), MUX bit 2
            (1 << MUX1)  |     // use ADC2 for input (PB4), MUX bit 1
            (0 << MUX0);       // use ADC2 for input (PB4), MUX bit 0

  ADCSRA = 
            (1 << ADEN)  |     // Enable ADC 
            (1 << ADPS2) |     // set prescaler to 64, bit 2 
            (1 << ADPS1) |     // set prescaler to 64, bit 1 
            (0 << ADPS0);      // set prescaler to 64, bit 0  
}

Funktionen skal blot kaldes en gang i koden, hvorefter man kan måle analog spænding ved følgende kode.

ADCSRA |= (1 << ADSC);         // Starter analog måling.
while (ADCSRA & (1 << ADSC) ); // Venter til målingen er færdig.
uint8_t val = ADCH;            //gemmer målingen i en variable val.

Herefter kan man omregne den 8-bit værdi man får fra målingen med følgende formel.

U = val/255 * 5V

Analyse af input

For at måle den maksimale og minimale spænding, kan man skrive følgende kode.

if(val>ma){
	ma = val;
}
if(P<mi){
	mi = val;
}

Hvor val er den målte spænding. mi og ma er globale variabler af type uint8_t, der gemmer den maksimale og minimale spænding, der er målt.

Måling af periodetiden

Man kan registrerer periodetiden, ved at se på hvornår spændingen passerer middelspændingen på +2,5V svarende til en decimal værdi på 127, når spændingen måles med en 8-bit værdi. Dette kan gøres på følgende måde.

oldval = val; // Den gamle analoge værdi gammes.
val = ADCH; // der foretages en ny måling.
if(oldval > (mid - (ma-mi)/20) && val <= (mid - (ma-mi)/20)){ // 
	time = ctime;
	ctime = 0;
}

Koden virker således at, hvis den gamle måling er større en midterspændingen + en sikkerhedsmargin, samt at den nye spænding er under eller lig med midterspændingen - et margin, så skal den gemme den tid der gået siden sidste periodeskift, og derefter nulstille tiden.

Opkobling m. Arduino

Den komplette kode samt kode til at benytte en Arduino som master kan downloades her

Fil:I2C frekvensmaaler.zip