Facebook RSS Feed
 
Windows IoT: VEML6075 UV Sensör Kullanımı
Tarih: 03.12.2016, Platform: Windows 10 IoT Core, IDE: Visual Studio 2017, Level: 200

Morötesi ışınlar, güneşin ozon tabakasını aşarak bizlere kadar ulaştırdığı sağlığa zararlı ışınlardır. İnsan gözünün göremediği dalga boyunda oldukları için morötesi, ultraviyole ya da kısaltılmışı UV olarak adlandırılırlar. UV Işınları UVA, UVB ve UVC olarak 3 kategoridedir. En zararlı dalga boyu UVC ozon tabakası tarafondan engellenir ancak UVA ve UVB cildimize kadar ulaşabilir.

İşin sağlıkla ilgili boyutunu dilerseniz detaylı araştırabilirsiniz, burada teknik üzerinde duracağız. UV Işınlarının miktarı güneşin açısına ve bir çok duruma göre değişiklik gösterir.  Bir noktaya düşen UV ışınlarını ölçmek için UV sensörleri kullanılır. Yazımızda Vishay'ın ürettiği VEML6075 sensörüyle iletişimi ele alacağız.

Donanım Bağlantısı

VEML6075 Alanındaki en başarılı sensörlerden biridir. Akıllı bileklikler gibi cihazlarda da kullanılabilmesi için 1mm x 2mm gibi küçük bir boyutta üretilmiştir. Bu sensörü Turta IoT HAT gibi bir sensör taşıyıcı bir kart ile kolaylıkla kullanabilirsiniz. Sensörün üzerinde bir çok I2C protokolünü destekleyen sensör gibi 4 bağlantı noktası bulunur: +3.3V, GND, SCL, SDA. Hazır bir kart kullanmıyorsanız, bilgisayarınızdaki pinlerle sensördeki bu pinleri birbirine bağlamanız gerekir.

Başlangıç

- Visual Studio ile Visual C# altından Blank App (Universal Windows) uygulaması oluşturun.
- Üst kısımdaki solution platforms menüsünden ARM'ı seçin.
- Solution Explorer'dan References'a sağ tıklayın, Add Reference seçeneğinden Universal Windows > Extensions sekmesi içinden Windows IoT Extensions for the UWP.dll'i seçin. Aynı isimde birden çok dll görünüyorsa versiyonu yüksek olanı seçin.

Uygulama Kodları

Uygulamanızın I2C protokolü üzerinden VEML6075 sensörüyle bağlantı kurması, sensörün ayarlarını yapması, veri okuması ve UV Index değerini hesaplaması için yardımcı bir sınıf kullanacağız. Projenizde VEML6075Sensor.cs adında bir class oluşturun.

[C#] VEML6075Sensor.cs

// VEML6075 Sensor Driver
// Rev. 1.01, Initial Release
// Copyright (c) 2016 Turta
// www.turta.io

using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;

namespace WinIoTVEML6075
{
    public class VEML6075Sensor : IDisposable
    {
        #region Enums
        public enum IntegrationTime : byte
        {
            IT_050ms = 0b00000000,
            IT_100ms = 0b00010000,
            IT_200ms = 0b00100000,
            IT_400ms = 0b00110000,
            IT_800ms = 0b01000000
        }

        public enum DynamicSetting : byte
        {
            Normal = 0b00000000,
            High = 0b00001000
        }

        public enum Trigger : byte
        {
            NoActiveForceTrigger = 0b00000000,
            TriggerOneMeasurement = 0b00000100
        }

        public enum ActiveForceMode : byte
        {
            NormalMode = 0b00000000,
            ActiveForceMode = 0b00000010
        }

        public enum PowerMode : byte
        {
            PowerOn = 0b00000000,
            ShutDown = 0b00000001
        }
        #endregion

        #region Globals
        // Correction Factors
        double k1 = 0;
        double k2 = 0;

        // Default Values
        double uva_a_coef = 2.22; // Default value for the UVA VIS coefficient
        double uva_b_coef = 1.33; // Default value for the UVA IR coefficient
        double uvb_c_coef = 2.95; // Default value for the UVB VIS coefficient
        double uvb_d_coef = 1.74; // Default value for the UVB IR coefficient
        double uva_resp = 0.001461;
        double uvb_resp = 0.002591;

        // VEML6075 Address
        internal const byte VEML6075_I2C_ADDRESS = 0x10;

        // Read Out Commands
        private const byte VEML6075_UVA_DATA = 0x07;
        private const byte VEML6075_DUMMY = 0x08;
        private const byte VEML6075_UVB_DATA = 0x09;
        private const byte VEML6075_UVCOMP1_DATA = 0x0A;
        private const byte VEML6075_UVCOMP2_DATA = 0x0B;
        private const byte VEML6075_ID = 0x0C;

        // Register Addresses
        private const byte VEML6075_UV_CONF = 0x00;

        // Device
        private I2cDevice veml6075 = null;

        // System
        private bool isInitialized = false;
        #endregion

        ///
        /// Initiates the VEML6075 Sensor.
        ///
        public VEML6075Sensor()
        {
            Initialize();
        }

        private async void Initialize()
        {
            try
            {
                I2cConnectionSettings settings = new I2cConnectionSettings(VEML6075_I2C_ADDRESS);

                settings.BusSpeed = I2cBusSpeed.FastMode;
                settings.SharingMode = I2cSharingMode.Shared;

                DeviceInformationCollection dis =
                    await DeviceInformation.FindAllAsync(I2cDevice.GetDeviceSelector("I2C1"));

                veml6075 = await I2cDevice.FromIdAsync(dis[0].Id, settings);

                isInitialized = true;
            }
            catch (Exception e)
            {
                throw;
            }
        }

        ///
        /// Configures the VEML6075 Sensor. Verifies if the settings are stored.
        ///
        ///
        ///
        ///
        ///
        ///
        /// True if settings are stored. False if not.
        public async Task Config(IntegrationTime UV_IT, DynamicSetting HD,
        Trigger UV_TRIG, ActiveForceMode UV_AF, PowerMode SD)
        {
            int tryCounter = 0;

            while (!isInitialized)
            {
                await Task.Delay(1);
                if (tryCounter++ > 1000)
                    return false;
            }

            try
            {
                byte configCommand = 0x00;

                configCommand += (byte)UV_IT;
                configCommand += (byte)HD;
                configCommand += (byte)UV_TRIG;
                configCommand += (byte)UV_AF;
                configCommand += (byte)SD;

                WriteRegister(new byte[] { VEML6075_UV_CONF, Convert.ToByte(configCommand), 0x00 });

                if ((configCommand & 0b11111011) == ReadRegister(VEML6075_UV_CONF))
                    return true;
                else
                    return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// 
        /// Triggers one time measurement for Active Force Mode enabled scenarios.
        /// 
        public void TriggerOneMeasurement()
        {
            byte[] tempConfig = ReadRegisterAsByte(VEML6075_UV_CONF);

            tempConfig[0] += 0b00000100;

            WriteRegister(new byte[] { VEML6075_UV_CONF, tempConfig[0], tempConfig[1] });
        }

        /// 
        /// Reads RAW UVA.
        /// 
        /// RAW UVA Value.
        public UInt16 Read_RAW_UVA()
        {
            return ReadRegister(VEML6075_UVA_DATA);
        }

        /// 
        /// Reads RAW UVB.
        /// 
        /// RAW UVB Value.
        public UInt16 Read_RAW_UVB()
        {
            return ReadRegister(VEML6075_UVB_DATA);
        }

        /// 
        /// Reads RAW UVD.
        /// 
        /// RAW UVD Value.
        public UInt16 Read_RAW_UVD()
        {
            return ReadRegister(VEML6075_DUMMY);
        }

        /// 
        /// Reads Noise Compensation Channel 1 data which allows only visible noise to pass through.
        /// 
        /// UV Comp 1 Value.
        public UInt16 Read_RAW_UVCOMP1()
        {
            return ReadRegister(VEML6075_UVCOMP1_DATA);
        }

        /// 
        /// Reads Noise Compensation Channel 2 data which allows only infrared noise to pass through.
        /// 
        /// UV Comp 2 Value.
        public UInt16 Read_RAW_UVCOMP2()
        {
            return ReadRegister(VEML6075_UVCOMP2_DATA);
        }

        /// 
        /// Calculates Compensated UVA.
        /// 
        /// UVA Comp Value.
        public double Calculate_Compensated_UVA()
        {
            // UVAcalc = UVA - a x UVcomp1 - b x UVcomp2

            UInt16 uva = ReadRegister(VEML6075_UVA_DATA);
            UInt16 uvcomp1 = ReadRegister(VEML6075_UVCOMP1_DATA);
            UInt16 uvcomp2 = ReadRegister(VEML6075_UVCOMP2_DATA);

            Double UVAcalc = uva - uva_a_coef * uvcomp1 - uva_b_coef * uvcomp2;

            return UVAcalc;
        }

        /// 
        /// Calculates Compensated UVB.
        /// 
        /// UVB Comp Value.
        public double Calculate_Compensated_UVB()
        {
            // UVBcalc = UVB - c x UVcomp1 - d x UVcomp2

            UInt16 uvb = ReadRegister(VEML6075_UVB_DATA);
            UInt16 uvcomp1 = ReadRegister(VEML6075_UVCOMP1_DATA);
            UInt16 uvcomp2 = ReadRegister(VEML6075_UVCOMP2_DATA);

            Double UVBcalc = uvb - uvb_c_coef * uvcomp1 - uvb_d_coef * uvcomp2;

            return UVBcalc;
        }

        /// 
        /// Calculates the UV Index A.
        /// 
        /// UV Index A Value.
        public double Calculate_UV_Index_A()
        {
            // UVIA = UVAcalc x k1 x UVAresponsivity

            UInt16 uva = ReadRegister(VEML6075_UVA_DATA);
            UInt16 uvcomp1 = ReadRegister(VEML6075_UVCOMP1_DATA);
            UInt16 uvcomp2 = ReadRegister(VEML6075_UVCOMP2_DATA);

            Double UVAcalc = uva - uva_a_coef * uvcomp1 - uva_b_coef * uvcomp2;

            Double UVIA = UVAcalc * k1 * uva_resp;

            return UVIA;
        }

        /// 
        /// Calculates the UV Index B.
        /// 
        /// UV Index B Value.
        public double Calculate_UV_Index_B()
        {
            // UVIB = UVBcalc x k2 x UVBresponsivity

            UInt16 uvb = ReadRegister(VEML6075_UVB_DATA);
            UInt16 uvcomp1 = ReadRegister(VEML6075_UVCOMP1_DATA);
            UInt16 uvcomp2 = ReadRegister(VEML6075_UVCOMP2_DATA);

            Double UVBcalc = uvb - uvb_c_coef * uvcomp1 - uvb_d_coef * uvcomp2;

            Double UVIB = UVBcalc * k2 * uvb_resp;

            return UVIB;
        }

        /// 
        /// Calculates the Average UV Index.
        /// 
        /// Average UV Index Value.
        public double Calculate_Average_UV_Index_Alt()
        {
            // Average UVI = (UVIA + UVIB) / 2

            UInt16 uva = ReadRegister(VEML6075_UVA_DATA);
            UInt16 uvb = ReadRegister(VEML6075_UVB_DATA);
            UInt16 uvcomp1 = ReadRegister(VEML6075_UVCOMP1_DATA);
            UInt16 uvcomp2 = ReadRegister(VEML6075_UVCOMP2_DATA);

            Double UVAcalc = uva - uva_a_coef * uvcomp1 - uva_b_coef * uvcomp2;
            Double UVBcalc = uvb - uvb_c_coef * uvcomp1 - uvb_d_coef * uvcomp2;

            Double UVIA = UVAcalc * k1 * uva_resp;
            Double UVIB = UVBcalc * k2 * uvb_resp;

            Double AverageUVI = (UVIA + UVIB) / 2;

            if (AverageUVI < 0) AverageUVI = 0;

            return AverageUVI;
        }

        /// 
        /// Calculates the Average UV Index.
        /// 
        /// Average UV Index Value.
        public double Calculate_Average_UV_Index()
        {
            //UVAcomp = (UVA - UVD) - a * (UVcomp1 - UVD) - b * (UVcomp2 - UVD);
            //UVBcomp = (UVB - UVD) - c * (UVcomp1 - UVD) - d * (UVcomp2 - UVD);

            //UVI = ((UVBcomp * UVBresp) + (UVAcomp * UVAresp)) / 2;

            UInt16 uva = ReadRegister(VEML6075_UVA_DATA);
            UInt16 uvb = ReadRegister(VEML6075_UVB_DATA);
            UInt16 uvd = ReadRegister(VEML6075_DUMMY);
            UInt16 uvcomp1 = ReadRegister(VEML6075_UVCOMP1_DATA);
            UInt16 uvcomp2 = ReadRegister(VEML6075_UVCOMP2_DATA);

            double UVAcomp = (uva - uvd) - uva_a_coef * (uvcomp1 - uvd) - uva_b_coef * (uvcomp2 - uvd);
            double UVBcomp = (uvb - uvd) - uvb_c_coef * (uvcomp1 - uvd) - uvb_d_coef * (uvcomp2 - uvd);

            double UVI = ((UVBcomp * uvb_resp) + (UVAcomp * uva_resp)) / 2;

            if (UVI < 0) UVI = 0;

            return UVI;
        }

        private async void WriteRegister(byte[] data)
        {
            veml6075.Write(data);
            await Task.Delay(1);
            return;
        }

        private UInt16 ReadRegister(byte reg)
        {
            UInt16 value = 0;
            byte[] writeBuffer = new byte[] { reg };
            byte[] readBuffer = new byte[] { 0x00, 0x00 };

            veml6075.WriteRead(writeBuffer, readBuffer);
            int h = readBuffer[1] << 8;
            int l = readBuffer[0];
            value = (UInt16)(h + l);
            return value;
        }

        private byte[] ReadRegisterAsByte(byte reg)
        {
            byte[] writeBuffer = new byte[] { reg };
            byte[] readBuffer = new byte[] { 0x00, 0x00 };

            veml6075.WriteRead(writeBuffer, readBuffer);

            return readBuffer;
        }

        /// 
        /// Cleans up the resources.
        /// 
        public void Dispose()
        {
            isInitialized = false;
            veml6075.Dispose();
        }
    }
}

 Şimdi uygulamanızın mantığını yazmak için MainPage.xaml.cs dosyasını açın ve aşağıdaki kodları ekleyin.

[C#] MainWindow.xaml.cs

using Windows.UI.Xaml.Controls;
using System.Threading;
using System.Diagnostics;

namespace WinIoTVEML6075
{
    public sealed partial class MainPage : Page
    {
        // VEML6075 Sensörü tanımla
        static VEML6075Sensor veml = new VEML6075Sensor();

        // UV Değerinin tutulacağı değişkeni oluştur
        static double uvIndex = 0;

        // Timer tanımla
        Timer sensorTimer;

        public MainPage()
        {
            this.InitializeComponent();

            // Sensörü yapılandır
            Init();

            // Uygulama başladıktan 2 saniye sonra,
            // 2 saniyede bir tickleyecek timer'ı başlat
            sensorTimer = new Timer(
                new TimerCallback(SensorTimerTick), null, 2000, 2000);
        }

        private async void Init()
        {
            // VEML6075 Sensörü başlat
            veml = new VEML6075Sensor();

            // Sensörü yapılandır
            await veml.Config(
                VEML6075Sensor.IntegrationTime.IT_800ms,
                VEML6075Sensor.DynamicSetting.High,
                VEML6075Sensor.Trigger.NoActiveForceTrigger,
                VEML6075Sensor.ActiveForceMode.NormalMode,
                VEML6075Sensor.PowerMode.PowerOn
                );
        }

        private static void SensorTimerTick(object state)
        {
            // Sensör verisini oku
            uvIndex = veml.Calculate_Average_UV_Index();

            // Sensör verisini yaz
            Debug.WriteLine(uvIndex.ToString("00.00"));
        }
    }
}

Uygulamanızı çalıştırdığınızda, sensör yapılandırılacak ve 2 saniyede bir sensörden UV Index değeri alınacaktır. Elde edilen değeri Visual Studio Output ya da Immediate Window penceresinden görebilirsiniz.

Sensörü yapılandırırken ölçümleme süresini 50ms ile 800ms arasında değiştirebiliyorsunuz. VEML6075Sensor sınıfında tüm ölçüm fonksiyonlarının içinde ölçüm metodu not edilmiştir. Bu ölçümlerin hangisinin işinize yarayacağını araştırmanız gerekir.

Bu yazıyı ve anlatılan yöntemleri tıbbi amaçla kullanacaksanız tüm hesaplamaları gözden geçirin. Bu yazıları referans olarak kullanmayın.


Ek Dosya: Belirtilmemiş.
Okunma Sayısı: 912

comments powered by Disqus
 
Hoşgeldiniz!
Son güncelleme: 25.12.2016
-
Yeni Teknik Yazılar
Latte Panda İncelemesi
Turta IoT HAT İncelemesi
USB Gamepad Kullanımı
GPIO Kullanımı
VEML6075 UV Sensör Kullan...
-
İlgili Gruplar
.NET MF ve Gadgeteer FB Grubu
İst. IoT & Wearables Meet-up
-
 

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.Copyright © 1999 - 2017, Umut Erkal. Bu materyal, "Creative Commons Public Licence" ile sunulmuştur.
Kaynak göstererek ve ücretsiz olarak, aynı şartlar altında paylaşabilir ve kullanabilirsiniz. | Kullanım Sözleşmesi