Advertisement
alexanderik

AirWick on Attiny13 (update)

Jun 10th, 2013
1,411
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.85 KB | None | 0 0
  1. /*
  2.  * airwick.h
  3.  *
  4.  * Created: 24.05.2013 20:00:11
  5.  * Updated: 25.05.2015 20:00:11
  6.  *  Author: Grigoriev Alexander
  7.  * alexgavs#gmail.com
  8.  */
  9.  
  10.  
  11. #ifndef LED_PHOTO_PSHIK_H_
  12. #define LED_PHOTO_PSHIK_H_
  13.  
  14. #define  u8 unsigned char               //  0 to 255
  15. #define  u16 unsigned int               //  0 to 65535
  16. #define  u32 unsigned long int  //      0 to 4294967295
  17.  
  18. #define USE_LIGHTSENSOR 1
  19.  
  20. #ifdef DEBUG
  21. #define Per_Watch       3
  22. #define Per_Minute      1
  23. #else
  24. #define Per_Watch       705
  25. #define Per_Minute      13
  26. #endif
  27.  
  28. #define BUTTON          PB1
  29. #define LED_A           PB4
  30. #define LED_K           PB0
  31. #define GATE            PB2
  32. #define INFO            PB3
  33.  
  34. #define CALIBRATE_MODE  5
  35.  
  36. #define SRAM __attribute__((section(".noinit")))
  37.  
  38. SRAM            u16             MTimer;
  39. SRAM            u8              counter;
  40. SRAM            u16             countDayTimer;
  41. SRAM            u8              LastLedSensorStatus;
  42.  
  43. EEMEM           u8              eset_hrs=2;
  44. EEMEM           u16             eLight_level=16000;
  45. EEMEM           u8              eNight;
  46.                         u8              sPORTB,sDDRB;
  47.  
  48. void delay_ms(u8 count);
  49. void blinkinfo(u8 bit,u8 col, u8 time);
  50.  
  51. #endif /* airwick.h */
  52.  
  53.  
  54. /*
  55.  * led_photo_pshik.с
  56.  *
  57.  * Created: 12.06.2013 16:00:00
  58.  *  Author: Grigoriev Alexander
  59.         http://pastebin.com/JLT2Gf7a
  60.  */
  61.  
  62. //Изменение состояния светодиода в момент нажатия на кнопку:
  63. //мк ATtiny13
  64. //F_CPU = 9600000/8/2 = 4.8Mhz
  65. // FUSE HIGH = 0xFF, LOW=0x69, (4.8MHz, CKDIV8)
  66.  
  67. #define F_CPU   9600000UL/8UL/2UL
  68.  
  69. // #define DEBUG 0
  70. #include <avr/io.h>
  71. #include <avr/interrupt.h>
  72. #include <compat/deprecated.h>
  73. #include <util/delay.h>
  74. #include <avr/wdt.h>
  75. #include <avr/sleep.h>
  76. #include <avr/eeprom.h>
  77. #include "airwick.h"
  78.        
  79. void init();
  80.  
  81.  
  82. #define BLINK_WARNING   {blinkinfo(LED_K,5,5);}
  83. #define RESET_COUNTER   {countDayTimer=0; MTimer=0; counter=0;}                                     //сброс таймера и единичного пуска}
  84. #define PSHIK           {BLINK_WARNING; sbi(DDRB,GATE); sbi(PORTB,LED_K); sbi(PORTB,GATE); _delay_ms(1000); cbi(DDRB,GATE);cbi(PORTB,GATE); cbi(PORTB,LED_K);}
  85. #define waitms                  50
  86.  
  87.  void keyscan()
  88.  {
  89. wdt_reset();
  90.  
  91. u8 long_key=0;
  92. u8 set_hrs=0;   //eeprom_read_byte(&eset_hrs);
  93.  
  94. delay_ms(waitms);
  95.  
  96. if (bit_is_clear(PINB,BUTTON))
  97. {
  98.         long_key=0;
  99.         delay_ms(waitms);
  100.  
  101.         //Режим длинного нажатия, включаем режим програмирования
  102.         while (bit_is_clear(PINB,BUTTON))
  103.         {
  104.                 long_key=1;                                                     //Устанавливаем флаг длинного нажатия
  105.                 if(++set_hrs >=(CALIBRATE_MODE+1)) set_hrs =1;                  //Пятый режим оставим для калибровки LED, и пускаем по кругу
  106.                 blinkinfo(LED_K,set_hrs,20);                                    //мигаем кол-во выбранных тактов, там же говорим собаке фу.
  107.                 _delay_ms(1000);                                                //пауза перед увеличением такта
  108.                 wdt_reset();                                                    //не забываем про собаку
  109.                 counter=set_hrs;
  110.         }
  111.        
  112.         if (bit_is_set(PINB,BUTTON)){                                           //если кнопочку отпустили- записываем выбранный режим
  113.                 eeprom_update_byte(&eset_hrs,set_hrs);
  114.                 blinkinfo(LED_K, set_hrs, 40);                                  //Подтверждаем выбор более медленной индикацией
  115.         }
  116.        
  117. }
  118. if (!long_key)        {
  119.         cbi(PORTB,LED_A); sbi(PORTB,LED_K);                         //Разовое нажатие вызывает обычный пшик
  120.         counter=1; long_key=0;
  121.         PSHIK;
  122. RESET_COUNTER;}
  123.  
  124.  }
  125.  
  126.  
  127. ISR(INT0_vect)  // Обработчик прерываний
  128. {
  129. keyscan();
  130. }
  131.  
  132.  
  133.  
  134.  
  135. #if USE_LIGHTSENSOR
  136. /**
  137.  * \Измеряем освещенность с помощью внутренней энергии ЦИ светодиода. :)
  138.  * \вовзращаем потраченное на измерение время в тиках пока заряжен диод.
  139.  */
  140. //************************************
  141. u16 LightLumen()
  142. {
  143. u16 j=65534;            //Для определения ночи необходимо увеличить время перебора, но я уменьшил в целях экономии памяти на тиньке 13,
  144.                                         //для ламп люми. при прямом попадании света на диод ,результат функции около 16000. Также, желательно вытащить светодиод максимально наружу.
  145.  
  146.         DDRB|=  (1<<LED_A)|(1<<LED_K);  //ПОРТКИ НА ВЫХОД, НЕ ТЕ ПОРТЫ ЧТО НА МНЕ, А ТЕ ЧТО В  ТИНЬКЕ.
  147.         sbi(PORTB,LED_A);                               //ОБРАТНОЕ НАПРЯЖЕНИЕ НА СВЕТОДИОД, ЗАРЯЖАЕМ ВНУТРЕННЮЮ ЕМКОСТЬ НОГ МИКРОКОНТРОЛЛЕРА, ЭНЕРГИЯ ЦИ НАРАСТАЕТ
  148.         cbi(PORTB,LED_K);                               //БЕЗ ЗЕМЛИ НЕ ЗАРЯДИТСЯ
  149.         cbi(DDRB, LED_A);                               //отключаем подтяжку
  150.         cbi(PORTB,LED_A);
  151.  
  152.         // Считаем сколько времени потребуется, чтобы емкость разрядилась до логич. 0
  153.         do
  154.         {
  155.                 wdt_reset();
  156.                 if (bit_is_clear(PINB,LED_A)) break;
  157.         }while (j--);
  158.  
  159. _delay_ms(10);
  160.  
  161. //blinkinfo(LED_K,1,2);                 //мигаем при каждом измерении.
  162.  
  163. return 65534-j;
  164. }
  165. #endif
  166.  
  167.  
  168. void blinkinfo(u8 bit,u8 col, u8 time){
  169. sPORTB=PORTB;
  170. sbi(DDRB,bit); cbi(PORTB,bit);
  171. sbi(DDRB,LED_A);        cbi(PORTB,LED_A);
  172. //u8 t=0;
  173. //while (t<col)
  174. while (col--)
  175.         {        //t++;
  176.                  sbi(PORTB,bit);        
  177. //               wdt_reset();    
  178.                  delay_ms(time);
  179.                  
  180.                  cbi(PORTB,bit);        
  181.                  wdt_reset();    
  182.                 delay_ms(time);
  183.         }
  184.        
  185. PORTB=sPORTB;
  186.  
  187. }
  188. void delay_ms(u8 count)
  189. {
  190.     while(count--) {_delay_ms(10);}
  191. }
  192.  
  193. void init(){
  194.  
  195.           wdt_enable(WDTO_4S);
  196.                   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  197.  
  198.                   GIMSK |= (1<<INT0);   // 0b01000000;          // Разрешение прерываний INT0 на входе PB1
  199.                   GIFR  |= (1<<INTF0);                
  200.                                  
  201.           //MCUCR = (1<<SE)|(1<<SM1)|(0<<SM0);
  202.           MCUCR |= (0<<ISC01)|(0<<ISC00);                       // при любом перепаде (нужно отслеживать нажатие и отжатие)
  203.          
  204.  
  205.                   DDRB  |= (1<<LED_K)|(1<<LED_A)|(1<<GATE)|(1<<INFO);    //output
  206.           PORTB &=~(1<<LED_K)|(1<<LED_A)|(1<<GATE)|(1<<INFO);    //gnd
  207.           DDRB  &=~(1<<BUTTON);          //input
  208.           PORTB |= (1<<BUTTON);          //pullup
  209.                 sei();
  210. }
  211.  
  212. int __attribute__((naked))
  213. main(void)
  214. {
  215.        
  216.         init();
  217.          
  218. #if USE_LIGHTSENSOR
  219.        
  220.         if (counter==5)    // Режим калибровки светодиода, должен быть включен свет.
  221.         {
  222.         blinkinfo(LED_K,1,100);
  223.          eeprom_update_word(&eLight_level,LightLumen()+2000); RESET_COUNTER;
  224.         blinkinfo(LED_K,1,100);
  225. }
  226. #endif
  227.  
  228.  
  229.  
  230. //***********  Обрабатываем датчик света ********
  231. #if USE_LIGHTSENSOR
  232.  
  233. u8 LedSensorStatus=(LightLumen()>=eeprom_read_word(&eLight_level))?0:1; // Темно -0, Светло -1 : Текущее освещение
  234.  
  235.  
  236. if (!(LastLedSensorStatus==LedSensorStatus)) // Изменилось освещение ?
  237.         {
  238.                 if (LedSensorStatus<LastLedSensorStatus) {
  239.                         if(countDayTimer>3*Per_Minute) //Если выключили свет и прошло 3 минуты- пшик
  240.                                                 {PSHIK;RESET_COUNTER;}
  241.                                                          }
  242.                                                  else //Если включили свет              
  243.                                                          {
  244.                                 blinkinfo(LED_K,10,2);  //Мигнуть длинной очередью
  245.                                                          }
  246.  
  247.                 countDayTimer=0;
  248.                 LastLedSensorStatus=LedSensorStatus; //Запоминаем текущее состояние освещения
  249.                
  250. }
  251.  
  252. if (countDayTimer>3600) countDayTimer=0; //Переполнение счетчика
  253.  
  254.  countDayTimer+=LedSensorStatus;  //Если горит свет - наматывать счетчик
  255.  
  256.  
  257. blinkinfo(LED_K,1+LedSensorStatus,2); // в дневное время моргнуть дважды, ночью одинарной вспышкой
  258. #else
  259. blinkinfo(LED_K,1,2);                   //имитация работы если не используем лед, как датчик света
  260. #endif
  261.  
  262.  
  263. // *********************  Запускаем счетчик ***************
  264. u8 set_hrs=eeprom_read_byte(&eset_hrs); //считываем режим работы
  265. if(set_hrs >=CALIBRATE_MODE+1) set_hrs =1; // бегаем по кругу, в меню. 12345-12345-....
  266. if(++MTimer==((set_hrs)*Per_Watch)){PSHIK;RESET_COUNTER;} //Увеличиваем счетчик и пшикаем если подошло время
  267.      
  268. // if ((MTimer>3500)) RESET_COUNTER;
  269.  
  270. sleep_mode(); //засыпаем и ждем сторожа или кнопку
  271.  
  272. while(1){}    
  273.  
  274. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement