Lux Metre Devresi

DeMSaL

Özel Üye
#1
Sponsorlu Bağlantılar
Lux Metre Devresi Nedir - Lux Metre Devresi Şeması - Lux Metre Devresi Hakkında - Lux Metre Devresi Işık Ölçümü - Işık Ölçümü - Attiny26-16





Lux metre devresi atmel attiny26-16 mikrodenetleyici üzerine kurulu led display üzerinde lux değerini görüntülüyor ledler 2sk1061 mosfetler ile sürülmüş. İlginç bir uygulama tüm kaynak dosyalar (pcb, şema, kod) paylaşılmış ayrıca devrenin kalibrasyon bilgileride verilmiş

Lux metre devre şeması;



Dosya ve detaylar (ingilizce): Lux Meter

The Lux Meter is usually used to measure illumination. The illumination is how level of luminous flux is falling on a surface area. The luminous flux is visible component that is defined in radiant flux (light power) divided by relative sensitivity of human eyes over the visible spectrum. This means the Lux is well fit to light level from sense of human eyes.
lux.c yazılımı;


Kod:
/*--------------------------------------------------*/
/* Lux meter control program (C)ChaN, 2005            */
 
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <string.h>
#include "xitoa.h"
 
#define    SYSCLK        1000000
 
/* Bit definition for status flags */
#define    F_800    (_BV(0))        // 800 Hz timer event
#define    F_LVD    (_BV(1))        // Low battery
#define    F_POW    (_BV(2))        // Power event
#define F_PB    (_BV(3))        // Power button
 
/*------------------------------------------------*/
/* Global variables                               */
 
uint8_t Leds[5];                // LED display buffer
volatile uint8_t flags;            // Status flags
volatile uint16_t OffTimer;        // Auto power off timer
 
uint32_t Gain[2];
uint16_t Ofs20;
 
/*------------------------------------------------*/
/* Interval Timer (800Hz)                         */
 
SIGNAL(SIG_OVERFLOW1)
{
    static uint8_t bltimer;        // LED blink timer
    static uint8_t Col;            // Dynamic scan pointer
 
    if(++Col >= sizeof(Leds)) Col = 0;
    PORTA &= 0b00000100;
    PORTB = 0;
 
    bltimer++;
    if((bltimer & 7) == 0) {    // Check power button every 8 (100/sec)
        PORTA |= _BV(3);
        DDRA &= ~_BV(3);
        DDRA &= ~_BV(3);
        DDRA &= ~_BV(3);
        if(PINA & _BV(3)) {
            flags |= F_PB;
        } else {
            if(flags & F_PB)
                flags |= F_POW;
            flags &= ~F_PB;
        }
        PORTA &= 0b00000100;
        DDRA |= _BV(3);
    }
    if((bltimer & 0xC0) || !(flags & F_LVD))    // Blink control
        PORTB = Leds[Col];
    PORTA |= (0b00001000 << Col);
 
    if(--OffTimer == 0) flags |= F_POW;            // Auto power-off timer
 
    flags |= F_800;
}
 
/* Character output function for LED display (called by xitoa module) */
 
void putled(char c)
{
    static uint8_t wp;    // Write index
    static const prog_uint8_t seg7[]    // Segment pattern
        = {0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0};
 
    if(c == '\r') {        // Return index to left
        wp = 0;
        return;
    }
    c -= '0';            // Put a segment pattern into display buffer
    if((uint8_t)c > 9) c = 10;
    Leds[wp++] = pgm_read_byte(&seg7[(uint8_t)c]);
}
 
void delay (uint16_t dly)
{
    do {
        cli(); flags &= ~F_800; sei();
        while((flags & F_800) == 0);
    } while(--dly);
}
 
uint16_t adconv(uint8_t ch)
{
    ADMUX = ch;
    ADCSR = 0b11010011;
    while(bit_is_clear(ADCSR, ADIF));
    return ADC;
}
 
/*------------------------------------------------*/
/* Main Process                                   */
 
int main(void)
{
    uint16_t n, d;
    uint32_t v, u;
 
    /* Initialize ports */
    PORTA = 0b00000100;
    DDRA  = 0b11111110;
 
    PORTB = 0b00000101;
    DDRB  = 0b01111111;
 
    /* Start TC1 with 800Hz OC-A */
    OCR1C = SYSCLK/8/800-1;
    TCCR1B = _BV(CTC1) | 0b0100;
    TIMSK = _BV(TOIE1);
 
    eeprom_read_block(Gain, 0, sizeof(Gain));
 
    xfunc_out = putled;        // Join xitoa molule and my output function
 
    OffTimer = 48000;    // Auto power off timer (60sec)
 
    sei();
 
    /* Lamp test */
    memset(Leds, 0x7F, sizeof(Leds));
    delay(400);
 
    delay(10);
    Ofs20 = adconv(0x80 + 13);
    delay(10);
 
    cli();
    PORTA &= 0b00000100;
    PORTB = 0b00000101;
    DDRB  = 0b01111010;
    DDRB  = 0b01111010;
    DDRB  = 0b01111010;
 
    /* MOSI is tied to GND. Low range calibration (1250 lux at -100 mV) */
    if((PINB & _BV(0)) == 0) {
        adconv(0x80 + 11);
        Gain[0] = 1250 * 65536 / (uint32_t)(adconv(0x80 + 11) - Ofs20);
        eeprom_write_block(Gain, 0, sizeof(Gain));
        Leds[0] = 0;
    }
 
    /* SCK is tied to GND. High range calibration (12500 lux at -1 V) */
    if((PINB & _BV(2)) == 0) {
        adconv(0x80 + 0);
        Gain[1] = 12500 * 65536 / (uint32_t)(adconv(0x80 + 0));
        eeprom_write_block(Gain, 0, sizeof(Gain));
        Leds[1] = 0;
    }
 
    DDRB =  0b01111111;
    sei();
 
    /* Measurement loop continued until any power event occure */
 
    while(!(flags & F_POW)) {
        v = 0;
        for(n = 0; n < 256; n++)    // 256 times averaging to filter-out flicker
        {
            d = adconv(0x80 + 11);
            while(!(flags & F_800));
            cli(); flags &= ~F_800; sei();
            d = adconv(0x80 + 11);
            if(d < 1023) {
                d -= Ofs20;
                u = Gain[0];
            } else {
                d = adconv(0x80 + 0);
                u = Gain[1];
            }
            d = (u * (uint32_t)d) >> 16;
            v += d;
        }
 
        /* Refresh lux value */
        xputc('\r');
        xitoa(v / 256, 10, 5);
 
        /* Check battrey voltage */
        DDRA &= ~_BV(1);
        d = adconv(0x80 + 1);
        cli();
        if(d >= 23)
            flags &= ~F_LVD;
        else
            flags |= F_LVD;
        sei();
        DDRA |= _BV(1);
    }
 
    /* Power off */
    memset(Leds, 0, sizeof(Leds));    // Clear display
    PORTA &= ~_BV(2);                // Release power hold
    for(;;);