Operácie

Luxmeter: Rozdiel medzi revíziami

Z SensorWiki

(Algoritmus a program)
 
(16 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 20: Riadok 20:
 
[http://www.pobot.org/IMG/pdf/tcs230_datasheet.pdf Datasheet]
 
[http://www.pobot.org/IMG/pdf/tcs230_datasheet.pdf Datasheet]
 
[http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/ Tutorial pre kniznicu FreqCounter pre arduino]
 
[http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/ Tutorial pre kniznicu FreqCounter pre arduino]
 +
[http://www.teachastronomy.com/astropedia/article/Wiens-Law Wienov zákon]
  
 
__TOC__
 
__TOC__
Riadok 25: Riadok 26:
 
== Analýza ==
 
== Analýza ==
  
TCS 230je programovate2n7 prevodník zo svetla na frekveniciu(light-to-frequency converter), kombinuje fotodiódy s prevodníkom prúdu na  
+
TCS 230je programovateľný prevodník zo svetla na frekvenciu(light-to-frequency converter), kombinuje fotodiódy s prevodníkom prúdu na  
 
frekvenciu v jednom integrovanom obvode.Výstup je obdĺžnikový signál so striedou 50% a frekvenciou priamo úmernou intenzite svetla. Výstupná  
 
frekvenciu v jednom integrovanom obvode.Výstup je obdĺžnikový signál so striedou 50% a frekvenciou priamo úmernou intenzite svetla. Výstupná  
 
frekvencia môže byť škálovaná jednou z troch prednastavených hodnôt. Digitálne vstupy a výstupy umožňujú priame pripojenie k mikrokontroléru.
 
frekvencia môže byť škálovaná jednou z troch prednastavených hodnôt. Digitálne vstupy a výstupy umožňujú priame pripojenie k mikrokontroléru.
Riadok 31: Riadok 32:
 
Technické parametre senzora:
 
Technické parametre senzora:
  
- napájacie napätie 2,7 V - 5,5 V
+
#- napájacie napätie 2,7 V - 5,5 V
- úsporný mód
+
#- úsporný mód
- nelinerita 0,2% pri 50kHz
+
#- nelinerita 0,2% pri 50kHz
- stabilný teplotný koeficient 200ppm/°C
+
#- stabilný teplotný koeficient 200ppm/°C
- spotreba 2 mA
+
#- spotreba 2 mA
  
[[Súbor:tcs230 package.png]]
+
[[Súbor:tcs230Package.png]]
V tejto časti popíšete ako idete daný problém riešiť. Uvediete sem aj všetky potrebné technické údaje,
 
ktoré sú potrebné na úspešné vyriešenie projektu. Napríklad:
 
  
* popis komunikačnej zbernice (i2c, 1-wire, RS-232 a pod.)
+
#GND 4 Zem
* obrázok zapojenia vývodov použitej súčiastky
+
#OE 3 Vstup - povolovací vstup
* odkaz na katalógový list
+
#OUT 6 Výstup - výstupná frekvencia
* priebehy dôležitých signálov
+
#S0, S1 1, 2 Vstup - výber škálovanie výstupnej frekvencie
* este jedna polozka
+
#S2, S3 7, 8 Vstup - výber typu fotodiód
 +
#VDD 5 Napájacie napätie
 +
 
 +
[[Súbor:tcs230Table.png]]
 +
 
 +
Maximálne rozlíšenie a presnosť je možné dosiahnuť meraním frekvencie. Meranie frekvencie oproti meraniu periódu má výhodu v tom, že sa obmedzení vplyv náhodných a vysokých frekvencií. Rozlíšenie je hlavne obmedzené veľkosťou čítača a prípustného meracieho času. Maximálna výstupná frekvencia senzoru je 600kHz a mikrokontrolér so zvolenou knižnicou na meranie frekvencie dokáže zmerať merať frekvencie do 8MHz. Meranie frekvencii je vhodné pre pomaly sa meniace alebo konštantú hodnoty osvetlenia.
  
 
== Popis riešenia ==
 
== Popis riešenia ==
  
Sem opíšete ako konkrétne ste problém vyriešili. Začnite popisom pripojenia k procesoru
+
Vzhľadom na to, že senzor obsahuje aj fotodiódy s farebnými filtrami, medzi ktorými sa vyberá pomocou vstupov, budú sa používať len diódy bez filtra.
(nezabudnite na schému zapojenia!) a zdôraznite ktoré jeho periférie ste pritom využili.  
+
Na meranie výstupnej frekvencie som požil Timer1, ten má na starosti počítanie vonkajších impulzov a Timer2, ten má na starosti časovanie. O ich ovládanie sa stara kničnica FreqCounter.h
  
 
'''Schéma zapojenia snímača'''
 
'''Schéma zapojenia snímača'''
[[Súbor:Zapojenie.png]]
+
[[Súbor:Tcs230Schema.png]]
  
[[Súbor:Example.jpg]]
 
  
Pozn.: Názov obrázku musí byť jedinečný, uvedomte si, že Obr1.jpg už pred vami skúsilo
+
=== Algoritmus a program ===
nahrať už aspoň 10 študentov.
 
  
[[Súbor:MojObrazok.jpg|center|250px]]
+
Kód pre mikrokntrolér bol napísaný vo vývojovom prostredí Arduino. Program je jednoduchý najprv sa nastavia potrebné výstupy(fotodiódy bez filtra, škálovanie), potom sa periodicky meria frekvencia a po prepočte sa odosiela do PC. Dominantná vlnová dĺžka slnečného svetla je podľa Wienovho zákonu na základe vzťahu λ = 0.0029 / T => 508nm. Vzhľadom na to, že datasheet neobsahuje hodnotu Hz/lux pre túto vlnovú dĺžku, ale len pre 470 nm a 524 nm, prepokladal som  lineárnu závislosť medzi frekvenciou a vlnovou dĺžkou. Po vypočítaní rovnice priamky a dosadení vlnovej dĺžky 508 nm som dostal hodnotu
 +
478 Hz/lux, ktorú som nakoniec použil na prepočet v mikrokontroléry.
  
=== Algoritmus a program ===
+
Kód pre mikrokontrolér:
 +
 
 +
<source lang="c">
 +
#include <FreqCounter.h>
  
Uveďte stručný popis algoritmu, v akom jazyku a verzii vývojového prostredia ste ho vytvorili.
+
#define S2 0
Je vhodné nakresliť aspoň hrubú štruktúru programu napríklad vo forme vývojového diagramu.
+
#define S3 1
Rozsiahly program pre lepšiu prehľadnosť rozdeľte do viacerých súborov.
+
#define S1 2
 +
#define S0 3
 +
#define enable 4
  
Vyberte podstatné časti zdrojového kódu, použite na to prostredie ''source'':
+
void setup() {
 +
  pinMode(S2,OUTPUT);          //nastavenie vystupných pinov
 +
  pinMode(S3,OUTPUT);
 +
  pinMode(S1,OUTPUT);
 +
  pinMode(S0,OUTPUT);
 +
  pinMode(enable,OUTPUT);
 +
  digitalWrite(enable,LOW);    // povelenie vystupu
 +
 
 +
  digitalWrite(S1,HIGH);
 +
  digitalWrite(S0,HIGH);        // nastavenie skalovania na 100%
 +
 +
  digitalWrite(S2,HIGH);
 +
  digitalWrite(S3,LOW);        // zapnutie diod bez filtra
 +
 
 +
  Serial.begin(9600);          // pripojenie sa k seriovemu portu
 +
}
  
<source lang="c">
+
unsigned long int frq;
/* A nezabudnite zdroják hojne komentovať  */
+
unsigned long int ill;
 +
void loop() {
  
int main(void) {
+
      FreqCounter::f_comp= 8;            // nastavenie kompenzacie
   
+
      FreqCounter::start(100);            // Start merací čas 100ms
    printf("Hello, World!\n");   
+
      while (FreqCounter::f_ready == 0)   //cakaj kym nie je citac pripraveny
    return(0);
+
      frq=FreqCounter::f_freq;   
 +
     
 +
      ill =  frq/478;                //prevod z frekvencie
 +
      if(ill<= 2500 && ill>=0)            // obmedzenie vystupu
 +
      { 
 +
        Serial.println(ill);               // odoslanie namerenej hodnoty
 +
      }
 +
      delay(250);                          //oneskorenie
 
}
 
}
 +
 
</source>
 
</source>
  
Nezabudnite však nahrať aj kompletné zdrojové kódy vášho programu!
+
GUI bolo vytvorené vo Visula Studiu 2015 v jazyku C#. Po spustení sa automaticky načíta zoznam COM portov, z ktorých sa vyberie z rozbalovacieho menu(comboBox). Po vybratí sa začnú dáta automaticky zobrazovať na grafe.Vzhľad GUI sa robil už z predpripravených prvkov dostupných vo Visual Studiu, ale bolo potrebne doplniť EventListenery. Na obrázku je znázornené GUI s testovacími dátami.
  
Zdrojový kód: [[Médiá:Serial.h|serial.h]] a [[Médiá:Pip.c|main.c]]
+
[[Súbor:LuxGUI.png]]
  
[[Médiá:MojProgram.c|program.c]]
+
Inicializažný kód:
 +
<source lang="c">
 +
        Series dataVsetky;  //predstavuje mnozinu vsetkzch nameranych dat
 +
        ulong vzCount = 0;  // pocet prijatych vzoriek
 +
        public Form1()
 +
        {
 +
            InitializeComponent();
 +
        }
 +
 
 +
        private void Form1_Load(object sender, EventArgs e)  //spusta sa pri nacitani
 +
        {
 +
            foreach (string s in SerialPort.GetPortNames())  //nacitanie vsetkzch dostupnzch COM portov
 +
            {
 +
                comboBox1.Items.Add(s);                      //priradenie portov do comboBox, na vyber portu
 +
            }
 +
            serialPort1.DataBits = 8;                        //nastavenie seriovej komunikacie
 +
            serialPort1.Parity = Parity.None;
 +
            serialPort1.StopBits = StopBits.One;
 +
            serialPort1.BaudRate = 9600;
 +
            dataVsetky = chart1.Series.Add("Luxy");          //priradenie mnoziny dat grafu
 +
        }
 +
</source>
  
 +
Kód výberu portu:
 +
<source lang="c">
 +
        private void comboBox1_DropDownClosed(object sender, EventArgs e)  //spusta po zatvoreni comboBoxu
 +
        {
 +
            try
 +
            {
 +
                serialPort1.Close();                                      //zatvori sa otvoreny port
 +
                serialPort1.PortName = comboBox1.SelectedItem.ToString();  //priradi sa pozadovaný nazov portu
 +
                serialPort1.Open();                                        //Otvorenie portu
 +
            }
 +
            catch (System.NullReferenceException)
 +
            { }
 +
            catch (System.ArgumentException)                              //ostrenie pripadu, ked sa vybere ziadny port
 +
            { }
 +
        }
 +
</source>
  
 +
Kód spracovania dát:
 +
<source lang="c">
 +
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)  //spusta sa pri prijati dat zo serioveho portu
 +
        {
 +
           
 +
            String lastLine;        //obsahuje poslednu prijatu hodnotu ako string
 +
            double lastValue;      //obsahuje poslednu prijatu hodnotu ako cislo
 +
            bool valueOK;          //urcuje ci je prijata hodnota v poriadku
 +
            try
 +
            {
 +
                lastLine = serialPort1.ReadLine();  //precita
 +
                valueOK = true;
 +
            }
 +
            catch (System.ArgumentOutOfRangeException)
 +
            {
 +
                valueOK = false;
 +
                lastLine = "0";
 +
            }
 +
            catch (System.OverflowException)
 +
            {
 +
                valueOK = false;
 +
                lastLine = "0";
 +
            }
 +
            catch (System.IndexOutOfRangeException)
 +
            {
 +
                valueOK = false;
 +
                lastLine = "0";
 +
            }
 +
            if (this.InvokeRequired)      //umoznuje pristupovat k prvkom z inych treadov
 +
            {
 +
                this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(serialPort1_DataReceived), new object[] { sender, e });
 +
                return;
 +
            }
 +
            if (dataVsetky.Points.Count >= 50)  //obmedzenie poctu zobrazench dat na 50
 +
            {
 +
                dataVsetky.Points.Remove(dataVsetky.Points.First());  //odobera sa vzdy prva vzorka
 +
            }
 +
            try
 +
            {
 +
                lastValue = Convert.ToDouble(lastLine);  //converzia na cislo
 +
                if (valueOK == true)      //zapisat len ak je sa nevyskytol problem
 +
                {
 +
                    if (lastValue <= 2500 && lastValue >= 0)
 +
                    {
 +
                        dataVsetky.Points.Add(lastValue);              // pridanie hondty
 +
                        vzCount++;                                      //pocet vzoriek
 +
                        if (vzCount % 10 == 0)
 +
                        {
 +
                            dataVsetky.AxisLabel = DateTime.Now.ToString("HH:mm:ss"); //cas na x-osi sa pridava kazdu desiatu vzorku kvoli miestu
 +
                        }
 +
                    }
 +
                   
 +
                }
 +
            }
 +
            catch(FormatException)
 +
            {
 +
            }
 +
        }
 +
</source>
 +
Zvyšný kód bol generovaný vývojovým prostredím.
  
 +
Zdrojový kód:
 +
[[Médiá:LuxARdu.c|LuxARdu.c]] 
 +
[[Médiá:LuxForm1.cs|LuxForm1.cs]]
 +
[[Médiá:LuxForm1.Designer.cs|LuxForm1.Designer.cs]]
 +
[[Médiá:LuxProgram.cs|LuxProgram.cs]]
 +
[[Médiá:LuxProjekt.zip|LuxProjekt.zip]]
  
 
=== Overenie ===
 
=== Overenie ===
  
Nezabudnite napísať čosi ako užívateľský návod. Z neho by malo byť jasné čo program robí,  
+
Po spustení stačí rozbaliť menu, a vybrať port na ktorom  je pripojený luxmeter. O zvyšok sa stará program. Ak by v menu neboli k dispozícii žiadne porty pravdepodobne je problém s nimi.
ako sa prejavuje a aké má užívateľské rozhranie (čo treba stlačiť, čo sa kde zobrazuje).
+
 
Ak ste namerali nejaké signály, sem s nimi. Ak je výsledkom nejaký údaj na displeji,
 
odfotografujte ho.
 
  
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.
 
  
  
 
[[Category:AVR]] [[Category:DVPS]]
 
[[Category:AVR]] [[Category:DVPS]]

Aktuálna revízia z 13:13, 24. máj 2016

Autori: Marek Petráš
Študijný odbor: Aplikovaná mechatronika 2. Ing. (2013)

Zadanie

  1. Vytvorte luxmeter za pomoci senzoru TCS230
  1. Preštudujte dokumentáciu k senzoru.
  2. Senzor pripojte k mikrokontroléru
  3. Napíšte program pre mikrokontrolár, ktorý načíta dáta zo senzoru, spracuje ich a odošle do PC
  4. Vytvorte GUI aplikáciu pre meranie


Literatúra:

  • Zoznam použitej literatúry, vrátane katalógových údajov (datasheet), internetových odkazov a pod.

Datasheet Tutorial pre kniznicu FreqCounter pre arduino Wienov zákon

Analýza

TCS 230je programovateľný prevodník zo svetla na frekvenciu(light-to-frequency converter), kombinuje fotodiódy s prevodníkom prúdu na frekvenciu v jednom integrovanom obvode.Výstup je obdĺžnikový signál so striedou 50% a frekvenciou priamo úmernou intenzite svetla. Výstupná frekvencia môže byť škálovaná jednou z troch prednastavených hodnôt. Digitálne vstupy a výstupy umožňujú priame pripojenie k mikrokontroléru.

Technické parametre senzora:

  1. - napájacie napätie 2,7 V - 5,5 V
  2. - úsporný mód
  3. - nelinerita 0,2% pri 50kHz
  4. - stabilný teplotný koeficient 200ppm/°C
  5. - spotreba 2 mA

Tcs230Package.png

  1. GND 4 Zem
  2. OE 3 Vstup - povolovací vstup
  3. OUT 6 Výstup - výstupná frekvencia
  4. S0, S1 1, 2 Vstup - výber škálovanie výstupnej frekvencie
  5. S2, S3 7, 8 Vstup - výber typu fotodiód
  6. VDD 5 Napájacie napätie

Tcs230Table.png

Maximálne rozlíšenie a presnosť je možné dosiahnuť meraním frekvencie. Meranie frekvencie oproti meraniu periódu má výhodu v tom, že sa obmedzení vplyv náhodných a vysokých frekvencií. Rozlíšenie je hlavne obmedzené veľkosťou čítača a prípustného meracieho času. Maximálna výstupná frekvencia senzoru je 600kHz a mikrokontrolér so zvolenou knižnicou na meranie frekvencie dokáže zmerať merať frekvencie do 8MHz. Meranie frekvencii je vhodné pre pomaly sa meniace alebo konštantú hodnoty osvetlenia.

Popis riešenia

Vzhľadom na to, že senzor obsahuje aj fotodiódy s farebnými filtrami, medzi ktorými sa vyberá pomocou vstupov, budú sa používať len diódy bez filtra. Na meranie výstupnej frekvencie som požil Timer1, ten má na starosti počítanie vonkajších impulzov a Timer2, ten má na starosti časovanie. O ich ovládanie sa stara kničnica FreqCounter.h

Schéma zapojenia snímača Tcs230Schema.png


Algoritmus a program

Kód pre mikrokntrolér bol napísaný vo vývojovom prostredí Arduino. Program je jednoduchý najprv sa nastavia potrebné výstupy(fotodiódy bez filtra, škálovanie), potom sa periodicky meria frekvencia a po prepočte sa odosiela do PC. Dominantná vlnová dĺžka slnečného svetla je podľa Wienovho zákonu na základe vzťahu λ = 0.0029 / T => 508nm. Vzhľadom na to, že datasheet neobsahuje hodnotu Hz/lux pre túto vlnovú dĺžku, ale len pre 470 nm a 524 nm, prepokladal som lineárnu závislosť medzi frekvenciou a vlnovou dĺžkou. Po vypočítaní rovnice priamky a dosadení vlnovej dĺžky 508 nm som dostal hodnotu 478 Hz/lux, ktorú som nakoniec použil na prepočet v mikrokontroléry.

Kód pre mikrokontrolér:

#include <FreqCounter.h>

#define S2 0
#define S3 1
#define S1 2
#define S0 3
#define enable 4

void setup() {
  pinMode(S2,OUTPUT);           //nastavenie vystupných pinov
  pinMode(S3,OUTPUT);
  pinMode(S1,OUTPUT);
  pinMode(S0,OUTPUT);
  pinMode(enable,OUTPUT);
  digitalWrite(enable,LOW);     // povelenie vystupu
  
  digitalWrite(S1,HIGH); 
  digitalWrite(S0,HIGH);        // nastavenie skalovania na 100%
 
  digitalWrite(S2,HIGH);
  digitalWrite(S3,LOW);         // zapnutie diod bez filtra
  
  Serial.begin(9600);           // pripojenie sa k seriovemu portu
}

unsigned long int frq;
unsigned long int ill;
void loop() {

       FreqCounter::f_comp= 8;             // nastavenie kompenzacie
       FreqCounter::start(100);            // Start merací čas 100ms
       while (FreqCounter::f_ready == 0)   //cakaj kym nie je citac pripraveny
       frq=FreqCounter::f_freq;  
       
       ill =  frq/478;                 //prevod z frekvencie
       if(ill<= 2500 && ill>=0)             // obmedzenie vystupu
       {  
        Serial.println(ill);                // odoslanie namerenej hodnoty
       }
       delay(250);                          //oneskorenie
}

GUI bolo vytvorené vo Visula Studiu 2015 v jazyku C#. Po spustení sa automaticky načíta zoznam COM portov, z ktorých sa vyberie z rozbalovacieho menu(comboBox). Po vybratí sa začnú dáta automaticky zobrazovať na grafe.Vzhľad GUI sa robil už z predpripravených prvkov dostupných vo Visual Studiu, ale bolo potrebne doplniť EventListenery. Na obrázku je znázornené GUI s testovacími dátami.

LuxGUI.png

Inicializažný kód:

        Series dataVsetky;   //predstavuje mnozinu vsetkzch nameranych dat 
        ulong vzCount = 0;   // pocet prijatych vzoriek
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)  //spusta sa pri nacitani
        {
            foreach (string s in SerialPort.GetPortNames())  //nacitanie vsetkzch dostupnzch COM portov
            {
                comboBox1.Items.Add(s);                      //priradenie portov do comboBox, na vyber portu
             }
            serialPort1.DataBits = 8;                        //nastavenie seriovej komunikacie
            serialPort1.Parity = Parity.None;
            serialPort1.StopBits = StopBits.One;
            serialPort1.BaudRate = 9600;
            dataVsetky = chart1.Series.Add("Luxy");          //priradenie mnoziny dat grafu
        }

Kód výberu portu:

        private void comboBox1_DropDownClosed(object sender, EventArgs e)  //spusta po zatvoreni comboBoxu
        {
            try
            {
                serialPort1.Close();                                       //zatvori sa otvoreny port
                serialPort1.PortName = comboBox1.SelectedItem.ToString();  //priradi sa pozadovaný nazov portu
                serialPort1.Open();                                        //Otvorenie portu
            }
            catch (System.NullReferenceException)
            { }
            catch (System.ArgumentException)                               //ostrenie pripadu, ked sa vybere ziadny port
            { }
        }

Kód spracovania dát:

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)  //spusta sa pri prijati dat zo serioveho portu
        {
            
            String lastLine;        //obsahuje poslednu prijatu hodnotu ako string
            double lastValue;       //obsahuje poslednu prijatu hodnotu ako cislo
            bool valueOK;           //urcuje ci je prijata hodnota v poriadku
            try
            {
                lastLine = serialPort1.ReadLine();  //precita 
                valueOK = true;
            }
            catch (System.ArgumentOutOfRangeException)
            {
                valueOK = false;
                lastLine = "0";
            }
            catch (System.OverflowException)
            {
                valueOK = false;
                lastLine = "0";
            }
             catch (System.IndexOutOfRangeException)
            {
                valueOK = false;
                lastLine = "0";
            }
            if (this.InvokeRequired)      //umoznuje pristupovat k prvkom z inych treadov
            {
                this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(serialPort1_DataReceived), new object[] { sender, e });
                return;
            }
            if (dataVsetky.Points.Count >= 50)  //obmedzenie poctu zobrazench dat na 50
            {
                dataVsetky.Points.Remove(dataVsetky.Points.First());   //odobera sa vzdy prva vzorka
            }
            try
            {
                lastValue = Convert.ToDouble(lastLine);   //converzia na cislo
                if (valueOK == true)       //zapisat len ak je sa nevyskytol problem
                {
                    if (lastValue <= 2500 && lastValue >= 0)
                    {
                        dataVsetky.Points.Add(lastValue);               // pridanie hondty
                        vzCount++;                                      //pocet vzoriek
                        if (vzCount % 10 == 0)
                        {
                            dataVsetky.AxisLabel = DateTime.Now.ToString("HH:mm:ss"); //cas na x-osi sa pridava kazdu desiatu vzorku kvoli miestu
                        }
                    }
                    
                }
            }
            catch(FormatException)
            {
            }
        }

Zvyšný kód bol generovaný vývojovým prostredím.

Zdrojový kód: LuxARdu.c LuxForm1.cs LuxForm1.Designer.cs LuxProgram.cs LuxProjekt.zip

Overenie

Po spustení stačí rozbaliť menu, a vybrať port na ktorom je pripojený luxmeter. O zvyšok sa stará program. Ak by v menu neboli k dispozícii žiadne porty pravdepodobne je problém s nimi.