圣源电子制作

 找回密码
 立即注册
查看: 9802|回复: 1
打印 上一主题 下一主题

AtTiny26简易照度计DIY-LMV772-AtTiny26-S1087-制作DIY

[复制链接]
跳转到指定楼层
楼主
发表于 2011-10-15 22:33:08 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

  照度是受照平面上接受的光通量的面密度。照度计是用于测量被照面上的光照度的仪器。
  跟动辄几千元的商用照度计相比,这个成本不足15元的简易照度计,其超值程度可想而知了。
  这个玩具级的照度计作好以后,我都能想到怎么用,第一件事儿就是拿这个照度计,挨个房间的闯,看看每个房间的照度有什么不同。测过以后呢,不要停,因为关于住宅照明是有标准的。对比一下看看。
  如果将这个照度计加以扩展,做一个照度记录仪,用来测量自己居室、或者植物温室等特定场所一年四季的光照情况,也是很不错的想法,这些科学数据可以用来进行更加深入的研究。
硬件原理图
  闲话少扯,先看看这个简易照度计的原理图。
  其中,以U1 LMV772为核心器件的I-V转换电路将光电管S1087的电流信号转换成电压信号,送入U2 AtTiny26的内置ADC。R5决定了转换系数,为50mV/µA;C5用来增益修正,滤除高频信号。
  原理图顶部的Q1用来防止电池接反,等效于常进的二极管;Q2、Q3、Q4组成电源开关电路,控制电源的通断。

软件代码
  软件的主要功能,就是将ADC的读数,经过一定的运算,送入显示器件LED数码管。AD转换器的输入为0 -2.56V,据此推算,可测量的最强光照约30000 lux。开机60秒后,自动关闭电源。
  1. /*--------------------------------------------------*/
  2. /* Lux meter control program (C)ChaN, 2005                        */


  3. #include <avr/io.h>
  4. #include <avr/signal.h>
  5. #include <avr/interrupt.h>
  6. #include <avr/pgmspace.h>
  7. #include <avr/eeprom.h>
  8. #include <string.h>
  9. #include "xitoa.h"

  10. #define        SYSCLK                1000000

  11. /* Bit definition for status flags */
  12. #define        F_800        (_BV(0))                // 800 Hz timer event
  13. #define        F_LVD        (_BV(1))                // Low battery
  14. #define        F_POW        (_BV(2))                // Power event
  15. #define F_PB        (_BV(3))                // Power button




  16. /*------------------------------------------------*/
  17. /* Global variables                               */

  18. uint8_t Leds[5];                                // LED display buffer
  19. volatile uint8_t flags;                        // Status flags
  20. volatile uint16_t OffTimer;                // Auto power off timer

  21. uint32_t Gain[2];
  22. uint16_t Ofs20;



  23. /*------------------------------------------------*/
  24. /* Interval Timer (800Hz)                         */

  25. SIGNAL(SIG_OVERFLOW1)
  26. {
  27.         static uint8_t bltimer;                // LED blink timer
  28.         static uint8_t Col;                        // Dynamic scan pointer


  29.         if(++Col >= sizeof(Leds)) Col = 0;
  30.         PORTA &= 0b00000100;
  31.         PORTB = 0;

  32.         bltimer++;
  33.         if((bltimer & 7) == 0) {        // Check power button every 8 (100/sec)
  34.                 PORTA |= _BV(3);
  35.                 DDRA &= ~_BV(3);
  36.                 DDRA &= ~_BV(3);
  37.                 DDRA &= ~_BV(3);
  38.                 if(PINA & _BV(3)) {
  39.                         flags |= F_PB;
  40.                 } else {
  41.                         if(flags & F_PB)
  42.                                 flags |= F_POW;
  43.                         flags &= ~F_PB;
  44.                 }
  45.                 PORTA &= 0b00000100;
  46.                 DDRA |= _BV(3);
  47.         }
  48.         if((bltimer & 0xC0) || !(flags & F_LVD))        // Blink control
  49.                 PORTB = Leds[Col];
  50.         PORTA |= (0b00001000 << Col);

  51.         if(--OffTimer == 0) flags |= F_POW;                        // Auto power-off timer

  52.         flags |= F_800;
  53. }



  54. /* Character output function for LED display (called by xitoa module) */

  55. void putled(char c)
  56. {
  57.         static uint8_t wp;        // Write index
  58.         static const prog_uint8_t seg7[]        // Segment pattern
  59.                 = {0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0};


  60.         if(c == '\r') {                // Return index to left
  61.                 wp = 0;
  62.                 return;
  63.         }
  64.         c -= '0';                        // Put a segment pattern into display buffer
  65.         if((uint8_t)c > 9) c = 10;
  66.         Leds[wp++] = pgm_read_byte(&seg7[(uint8_t)c]);
  67. }



  68. void delay (uint16_t dly)
  69. {
  70.         do {
  71.                 cli(); flags &= ~F_800; sei();
  72.                 while((flags & F_800) == 0);
  73.         } while(--dly);
  74. }



  75. uint16_t adconv(uint8_t ch)
  76. {
  77.         ADMUX = ch;
  78.         ADCSR = 0b11010011;
  79.         while(bit_is_clear(ADCSR, ADIF));
  80.         return ADC;
  81. }



  82. /*------------------------------------------------*/
  83. /* Main Process                                   */


  84. int main(void)
  85. {
  86.         uint16_t n, d;
  87.         uint32_t v, u;


  88.         /* Initialize ports */
  89.         PORTA = 0b00000100;
  90.         DDRA  = 0b11111110;

  91.         PORTB = 0b00000101;
  92.         DDRB  = 0b01111111;

  93.         /* Start TC1 with 800Hz OC-A */
  94.         OCR1C = SYSCLK/8/800-1;
  95.         TCCR1B = _BV(CTC1) | 0b0100;
  96.         TIMSK = _BV(TOIE1);

  97.         eeprom_read_block(Gain, 0, sizeof(Gain));

  98.         xfunc_out = putled;                // Join xitoa molule and my output function

  99.         OffTimer = 48000;        // Auto power off timer (60sec)

  100.         sei();

  101.         /* Lamp test */
  102.         memset(Leds, 0x7F, sizeof(Leds));
  103.         delay(400);


  104.         delay(10);
  105.         Ofs20 = adconv(0x80 + 13);
  106.         delay(10);


  107.         cli();
  108.         PORTA &= 0b00000100;
  109.         PORTB = 0b00000101;
  110.         DDRB  = 0b01111010;
  111.         DDRB  = 0b01111010;
  112.         DDRB  = 0b01111010;

  113.         /* MOSI is tied to GND. Low range calibration (1250 lux at -100 mV) */
  114.         if((PINB & _BV(0)) == 0) {
  115.                 adconv(0x80 + 11);
  116.                 Gain[0] = 1250 * 65536 / (uint32_t)(adconv(0x80 + 11) - Ofs20);
  117.                 eeprom_write_block(Gain, 0, sizeof(Gain));
  118.                 Leds[0] = 0;
  119.         }

  120.         /* SCK is tied to GND. High range calibration (12500 lux at -1 V) */
  121.         if((PINB & _BV(2)) == 0) {
  122.                 adconv(0x80 + 0);
  123.                 Gain[1] = 12500 * 65536 / (uint32_t)(adconv(0x80 + 0));
  124.                 eeprom_write_block(Gain, 0, sizeof(Gain));
  125.                 Leds[1] = 0;
  126.         }

  127.         DDRB =  0b01111111;
  128.         sei();


  129.         /* Measurement loop continued until any power event occure */

  130.         while(!(flags & F_POW)) {
  131.                 v = 0;
  132.                 for(n = 0; n < 256; n++)        // 256 times averaging to filter-out flicker
  133.                 {
  134.                         d = adconv(0x80 + 11);
  135.                         while(!(flags & F_800));
  136.                         cli(); flags &= ~F_800; sei();
  137.                         d = adconv(0x80 + 11);
  138.                         if(d < 1023) {
  139.                                 d -= Ofs20;
  140.                                 u = Gain[0];
  141.                         } else {
  142.                                 d = adconv(0x80 + 0);
  143.                                 u = Gain[1];
  144.                         }
  145.                         d = (u * (uint32_t)d) >> 16;
  146.                         v += d;
  147.                 }

  148.                 /* Refresh lux value */
  149.                 xputc('\r');
  150.                 xitoa(v / 256, 10, 5);

  151.                 /* Check battrey voltage */
  152.                 DDRA &= ~_BV(1);
  153.                 d = adconv(0x80 + 1);
  154.                 cli();
  155.                 if(d >= 23)
  156.                         flags &= ~F_LVD;
  157.                 else
  158.                         flags |= F_LVD;
  159.                 sei();
  160.                 DDRA |= _BV(1);
  161.         }


  162.         /* Power off */
  163.         memset(Leds, 0, sizeof(Leds));        // Clear display
  164.         PORTA &= ~_BV(2);                                // Release power hold
  165.         for(;;);
  166. }

复制代码
C程序.zip (54.74 KB, 下载次数: 24)


回复

使用道具 举报

推荐
发表于 2013-7-22 22:20:44 | 只看该作者
顶贴  强烈支持一下
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|联系我们|闽公网安备 35012102000020号|闽ICP备11020110号-1|圣源电子

GMT+8, 2024-9-20 15:34 , Processed in 0.045324 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表