Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

558 рядки
17 KiB

  1. #include <stdbool.h>
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4. #define F_CPU 20000000UL //20 MHz
  5. #include <util/delay.h>
  6. /* 7-Segment display: */
  7. #define NUM_DIGITS 3U //3 Digits
  8. #define DIGIT_TENS 2U //left
  9. #define DIGIT_ONES 1U //middle
  10. #define DIGIT_UNIT 0U //right
  11. #define SELECT_DIGIT(digit) (1U << digit)
  12. /* DHT22 peripherals: */
  13. #define DDR_SENSOR DDRC
  14. #define PORT_SENSOR PORTC
  15. #define PIN_SENSOR PINC
  16. #define SENSOR PINC3
  17. /* DHT22 commands: */
  18. #define SENSOR_sda_out DDR_SENSOR |= (1 << SENSOR)
  19. #define SENSOR_sda_in DDR_SENSOR &= ~(1 << SENSOR) // release sda => hi in consequence of pullup
  20. #define SENSOR_sda_low PORT_SENSOR &= ~(1 << SENSOR)
  21. #define SENSOR_is_hi PIN_SENSOR & (1 << SENSOR)
  22. #define SENSOR_is_low !(PIN_SENSOR & (1 << SENSOR))
  23. #define MODE_MEASURE 0U
  24. #define MODE_ANIMATION_1 1U
  25. #define MODE_ANIMATION_2 2U
  26. #define ANIMATION_DELAY_MS 70U
  27. #define ANIMATION_START_DELAY_MS 70U
  28. #define BUTTON_THRESHOLD 50 //software debounce
  29. /* Symbol indexes: */
  30. #define SYM_n 10U
  31. #define SYM_o 11U
  32. #define SYM_E 12U
  33. #define SYM_R 13U
  34. #define SYM_DEG_CELCIUS 14U
  35. #define SYM_P_P 15U
  36. #define SYM_OFF 16U
  37. #define SYM_DASH 17U
  38. #define SYM_I 18U
  39. #define SYM_SEG_A 19U
  40. #define SYM_SEG_B 20U
  41. #define SYM_SEG_C 21U
  42. #define SYM_SEG_D 22U
  43. #define SYM_SEG_E 23U
  44. #define SYM_SEG_F 24U
  45. #define SYM_SEG_AB 25U
  46. #define SYM_SEG_BCD 26U
  47. #define SYM_SEG_CD 27U
  48. #define SYM_SEG_DE 28U
  49. #define SYM_SEG_DEF 29U
  50. #define SYM_SEG_AEF 30U
  51. #define SYM_SEG_AF 31U
  52. /*
  53. 7-Segment Layout:
  54. A
  55. F B
  56. G
  57. E C
  58. D P
  59. Pin 7 6 5 4 3 2 1 0
  60. Segment A F B E D C G P
  61. */
  62. static uint8_t g_au8Symbols[32U] =
  63. {
  64. /* 00 */ 0b11111100U, //0 (ABCDEF)
  65. /* 01 */ 0b00100100U, //1 (BC)
  66. /* 02 */ 0b10111010U, //2 (ABDEG)
  67. /* 03 */ 0b10101110U, //3 (ABCDG)
  68. /* 04 */ 0b01100110U, //4 (BCFG)
  69. /* 05 */ 0b11001110U, //5 (ACDFG)
  70. /* 06 */ 0b11011110U, //6 (ACDEFG)
  71. /* 07 */ 0b10100100U, //7 (ABC)
  72. /* 08 */ 0b11111110U, //8 (ABCDEFG)
  73. /* 09 */ 0b11101110U, //9 (ABCDFG)
  74. /* 10 */ 0b00010110U, //n (CEG) SYM_n
  75. /* 11 */ 0b00011110U, //o (CDEG) SYM_o
  76. /* 12 */ 0b11011010U, //E (ADEFG) SYM_E
  77. /* 13 */ 0b00010010U, //r (EG) SYM_r
  78. /* 14 */ 0b10101101U, //degC (ABCDP) SYM_DEG_CELCIUS
  79. /* 15 */ 0b11110011U, //P. (ABEFGP) SYM_P_P
  80. /* 16 */ 0b00000000U, //OFF SYM_OFF
  81. /* 17 */ 0b00000010U, //- (G) SYM_DASH
  82. /* 18 */ 0b01010000U, //I (EF) SYM_I
  83. /* 19 */ 0b10000000U, //SegA SYM_SEG_A
  84. /* 20 */ 0b00100000U, //SegB SYM_SEG_B
  85. /* 21 */ 0b00000100U, //SegC SYM_SEG_C
  86. /* 22 */ 0b00001000U, //SegD SYM_SEG_D
  87. /* 23 */ 0b00010000U, //SegE SYM_SEG_E
  88. /* 24 */ 0b01000000U, //SegF SYM_SEG_F
  89. /* 25 */ 0b10100000U, //SegAB SYM_SEG_AB
  90. /* 26 */ 0b00101100U, //SegBCD SYM_SEG_BCD
  91. /* 27 */ 0b00001100U, //SegCD SYM_SEG_CD
  92. /* 28 */ 0b00011000U, //SegDE SYM_SEG_DE
  93. /* 29 */ 0b01011000U, //SegDEF SYM_SEG_DEF
  94. /* 30 */ 0b11010000U, //SegAEF SYM_SEG_AEF
  95. /* 31 */ 0b11000000U //SegAF SYM_SEG_AF
  96. };
  97. static uint8_t g_u8ButtonCountTop = 0U; //upper button counter
  98. static uint8_t g_u8ButtonCountBot = 0U; //lower button counter
  99. static uint8_t g_u8Mode = MODE_MEASURE; //Current display mode
  100. uint16_t g_u16Humidity = 0U;
  101. uint16_t g_u16Temperature = 0U;
  102. uint8_t g_u8ISRDigitSelect = 0U;
  103. uint8_t g_au8Digits[3U] =
  104. {
  105. SYM_OFF, //unit
  106. SYM_OFF, //ones
  107. SYM_OFF //tens
  108. };
  109. void s_vInit( void );
  110. void s_vSetValue( uint8_t u8Value, uint8_t u8Unit );
  111. void s_vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit );
  112. void s_vReadButtons( void );
  113. void s_vShowAnim( uint8_t u8Select );
  114. uint8_t s_u8ReadSensor( void );
  115. /************************************************************************/
  116. /* Timer1 ISR - show values on display */
  117. /************************************************************************/
  118. ISR ( TIMER1_COMPA_vect )
  119. {
  120. PORTB = 0;
  121. PORTD = 0;
  122. _delay_us(2);
  123. PORTB = SELECT_DIGIT(g_u8ISRDigitSelect);
  124. PORTD = g_au8Symbols[g_au8Digits[g_u8ISRDigitSelect]];
  125. g_u8ISRDigitSelect++;
  126. if (g_u8ISRDigitSelect > 2U)
  127. {
  128. g_u8ISRDigitSelect = 0U;
  129. }
  130. /* Read and evaluate button status */
  131. s_vReadButtons();
  132. }
  133. /************************************************************************/
  134. /* main() */
  135. /************************************************************************/
  136. int main(void)
  137. {
  138. uint8_t u8ErrorCode = 0U;
  139. uint8_t u8Loop = 0U;
  140. s_vInit();
  141. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
  142. _delay_ms(10);
  143. s_vSetDisplayDigits( SYM_SEG_A, SYM_OFF, SYM_OFF );
  144. _delay_ms(300);
  145. s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_OFF );
  146. _delay_ms(300);
  147. s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_SEG_A );
  148. _delay_ms(300);
  149. while ( u8Loop < 5U )
  150. {
  151. s_vSetDisplayDigits( SYM_OFF, SYM_SEG_A, SYM_SEG_AB );
  152. _delay_ms(ANIMATION_START_DELAY_MS);
  153. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, 7U );
  154. _delay_ms(ANIMATION_START_DELAY_MS);
  155. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_SEG_BCD );
  156. _delay_ms(ANIMATION_START_DELAY_MS);
  157. s_vSetDisplayDigits( SYM_OFF, SYM_SEG_D, SYM_SEG_CD );
  158. _delay_ms(ANIMATION_START_DELAY_MS);
  159. s_vSetDisplayDigits( SYM_SEG_D, SYM_SEG_D, SYM_SEG_D );
  160. _delay_ms(ANIMATION_START_DELAY_MS);
  161. s_vSetDisplayDigits( SYM_SEG_DE, SYM_SEG_D, SYM_OFF );
  162. _delay_ms(ANIMATION_START_DELAY_MS);
  163. s_vSetDisplayDigits( SYM_SEG_DEF, SYM_OFF, SYM_OFF );
  164. _delay_ms(ANIMATION_START_DELAY_MS);
  165. s_vSetDisplayDigits( SYM_SEG_AEF, SYM_OFF, SYM_OFF );
  166. _delay_ms(ANIMATION_START_DELAY_MS);
  167. s_vSetDisplayDigits( SYM_SEG_AF, SYM_SEG_A, SYM_OFF );
  168. _delay_ms(ANIMATION_START_DELAY_MS);
  169. s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_SEG_A );
  170. _delay_ms(ANIMATION_START_DELAY_MS);
  171. u8Loop++;
  172. }
  173. /* Set default value: */
  174. //s_vSetDisplayDigits( SYM_DASH, SYM_DASH, SYM_DASH );
  175. /* wait 3 seconds for humity sensor */
  176. //_delay_ms(3000);
  177. /* Set default value: */
  178. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
  179. _delay_ms(600);
  180. while ( 1 )
  181. {
  182. switch ( g_u8Mode )
  183. {
  184. case MODE_MEASURE:
  185. if ( SENSOR_is_hi )
  186. {
  187. SENSOR_sda_out;
  188. SENSOR_sda_low;
  189. _delay_ms(20);
  190. u8ErrorCode = s_u8ReadSensor();
  191. if ( 0U == u8ErrorCode )
  192. {
  193. s_vSetValue( g_u16Humidity / 10, SYM_P_P );
  194. //vSetDisplayValues( g_u16Temperature / 10, SYM_DEG_CELCIUS );
  195. }
  196. else
  197. {
  198. s_vSetDisplayDigits( SYM_E, u8ErrorCode, SYM_OFF );
  199. }
  200. }
  201. if ( g_u8Mode == MODE_MEASURE )
  202. {
  203. _delay_ms(500);
  204. }
  205. break;
  206. case MODE_ANIMATION_1:
  207. s_vShowAnim(g_u8Mode);
  208. g_u8Mode = MODE_MEASURE;
  209. _delay_ms(200);
  210. break;
  211. case MODE_ANIMATION_2:
  212. s_vShowAnim(g_u8Mode);
  213. g_u8Mode = MODE_MEASURE;
  214. _delay_ms(200);
  215. break;
  216. default:
  217. break;
  218. } //end switch
  219. // _delay_ms(3000); //wait 3 seconds for new measurement
  220. } //end while(1)
  221. return 0;
  222. }
  223. /************************************************************************/
  224. /* Initialize inputs and outputs */
  225. /************************************************************************/
  226. void s_vInit( void )
  227. {
  228. /* Port D - Pins 0-7: Outputs */
  229. DDRD = 0b11111111U;
  230. /* Port B - Pins 0-2: Outputs */
  231. DDRB = 0b00000111U;
  232. /* Port C - Pins 4-5: Inputs with internal Pull-up */
  233. PORTC = 0b00110000U;
  234. /* Sensor init: */
  235. DDR_SENSOR &= ~(1 << SENSOR); // define as input
  236. PORT_SENSOR &= ~(1 << SENSOR); // disable pullup
  237. /* 16-bit TIMER1 in CTC mode
  238. * prescaler = 8
  239. * 20 MHz / 8 = 2.5 MHz
  240. * Compare value = 2500 => 1 ms IRQ
  241. */
  242. TCCR1A = 0U;
  243. TCCR1B = (1<<WGM12) | (1<<CS11);
  244. OCR1A = 2500U;
  245. TIMSK1 |= (1<<OCIE1A);
  246. sei();
  247. return; //void
  248. }
  249. /************************************************************************/
  250. /* Set new values to be shown on display */
  251. /************************************************************************/
  252. void s_vSetValue( uint8_t u8Value, uint8_t u8Unit )
  253. {
  254. uint8_t u8Tmp = u8Value / 10U;
  255. s_vSetDisplayDigits(u8Tmp, u8Value - (u8Tmp * 10U), u8Unit);
  256. return; //void
  257. }
  258. /************************************************************************/
  259. /* Set display digits individually */
  260. /************************************************************************/
  261. void s_vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit )
  262. {
  263. g_au8Digits[DIGIT_TENS] = u8Tens;
  264. g_au8Digits[DIGIT_ONES] = u8Ones;
  265. g_au8Digits[DIGIT_UNIT] = u8Unit;
  266. return; //void
  267. }
  268. /************************************************************************/
  269. /* Read button status */
  270. /************************************************************************/
  271. void s_vReadButtons( void )
  272. {
  273. if ( !(PINC & (1<<PINC4)) ) //if button '+' pressed
  274. {
  275. g_u8ButtonCountTop++;
  276. }
  277. else
  278. {
  279. g_u8ButtonCountTop = 0U; //reset button counter
  280. }
  281. if ( !(PINC & (1<<PINC5)) ) //if button '-' pressed
  282. {
  283. g_u8ButtonCountBot++;
  284. }
  285. else
  286. {
  287. g_u8ButtonCountBot = 0U; //reset button counter
  288. }
  289. if ( g_u8ButtonCountTop > BUTTON_THRESHOLD )
  290. {
  291. g_u8ButtonCountTop = 0U; //reset top counter
  292. g_u8Mode = MODE_ANIMATION_1;
  293. }
  294. else if ( g_u8ButtonCountBot > BUTTON_THRESHOLD )
  295. {
  296. g_u8ButtonCountBot = 0U; //reset bottom counter
  297. g_u8Mode = MODE_ANIMATION_2;
  298. }
  299. return; //void
  300. }
  301. /************************************************************************/
  302. /* */
  303. /************************************************************************/
  304. void s_vShowAnim( uint8_t u8Select )
  305. {
  306. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
  307. _delay_ms(ANIMATION_DELAY_MS);
  308. switch ( u8Select )
  309. {
  310. case MODE_ANIMATION_1: //fade from left to right and from right to left
  311. s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF );
  312. _delay_ms(ANIMATION_DELAY_MS);
  313. s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF );
  314. _delay_ms(ANIMATION_DELAY_MS);
  315. s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF );
  316. _delay_ms(ANIMATION_DELAY_MS);
  317. s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF );
  318. _delay_ms(ANIMATION_DELAY_MS);
  319. s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF );
  320. _delay_ms(ANIMATION_DELAY_MS);
  321. s_vSetDisplayDigits( 8U, 8U, SYM_OFF );
  322. _delay_ms(ANIMATION_DELAY_MS);
  323. s_vSetDisplayDigits( 8U, 8U, 1U );
  324. _delay_ms(ANIMATION_DELAY_MS);
  325. s_vSetDisplayDigits( 8U, 8U, 3U );
  326. _delay_ms(ANIMATION_DELAY_MS);
  327. s_vSetDisplayDigits( 8U, 8U, 8U );
  328. _delay_ms(ANIMATION_DELAY_MS);
  329. s_vSetDisplayDigits( 8U, 8U, 8U );
  330. _delay_ms(ANIMATION_DELAY_MS);
  331. s_vSetDisplayDigits( 8U, 8U, 3U );
  332. _delay_ms(ANIMATION_DELAY_MS);
  333. s_vSetDisplayDigits( 8U, 8U, 1U );
  334. _delay_ms(ANIMATION_DELAY_MS);
  335. s_vSetDisplayDigits( 8U, 8U, SYM_OFF );
  336. _delay_ms(ANIMATION_DELAY_MS);
  337. s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF );
  338. _delay_ms(ANIMATION_DELAY_MS);
  339. s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF );
  340. _delay_ms(ANIMATION_DELAY_MS);
  341. s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF );
  342. _delay_ms(ANIMATION_DELAY_MS);
  343. s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF );
  344. _delay_ms(ANIMATION_DELAY_MS);
  345. s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF );
  346. _delay_ms(ANIMATION_DELAY_MS);
  347. break;
  348. case MODE_ANIMATION_2: //fade from left to right and clear
  349. s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF );
  350. _delay_ms(ANIMATION_DELAY_MS);
  351. s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF );
  352. _delay_ms(ANIMATION_DELAY_MS);
  353. s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF );
  354. _delay_ms(ANIMATION_DELAY_MS);
  355. s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF );
  356. _delay_ms(ANIMATION_DELAY_MS);
  357. s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF );
  358. _delay_ms(ANIMATION_DELAY_MS);
  359. s_vSetDisplayDigits( 8U, 8U, SYM_OFF );
  360. _delay_ms(ANIMATION_DELAY_MS);
  361. s_vSetDisplayDigits( 8U, 8U, 1U );
  362. _delay_ms(ANIMATION_DELAY_MS);
  363. s_vSetDisplayDigits( 8U, 8U, 3U );
  364. _delay_ms(ANIMATION_DELAY_MS);
  365. s_vSetDisplayDigits( 8U, 8U, 8U );
  366. _delay_ms(ANIMATION_DELAY_MS);
  367. s_vSetDisplayDigits( 3U, 8U, 8U );
  368. _delay_ms(ANIMATION_DELAY_MS);
  369. s_vSetDisplayDigits( 1U, 8U, 8U );
  370. _delay_ms(ANIMATION_DELAY_MS);
  371. s_vSetDisplayDigits( SYM_OFF, 8U, 8U );
  372. _delay_ms(ANIMATION_DELAY_MS);
  373. s_vSetDisplayDigits( SYM_OFF, 3U, 8U );
  374. _delay_ms(ANIMATION_DELAY_MS);
  375. s_vSetDisplayDigits( SYM_OFF, 1U, 8U );
  376. _delay_ms(ANIMATION_DELAY_MS);
  377. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, 8U );
  378. _delay_ms(ANIMATION_DELAY_MS);
  379. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_E );
  380. _delay_ms(ANIMATION_DELAY_MS);
  381. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_I );
  382. _delay_ms(ANIMATION_DELAY_MS);
  383. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
  384. _delay_ms(ANIMATION_DELAY_MS);
  385. break;
  386. default:
  387. break;
  388. } //end switch
  389. s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
  390. _delay_ms(ANIMATION_DELAY_MS);
  391. return; //void
  392. }
  393. /************************************************************************/
  394. /* Read humidity and temperature from DHT22 */
  395. /************************************************************************/
  396. uint8_t s_u8ReadSensor( void )
  397. {
  398. uint8_t timeout = 200;
  399. SENSOR_sda_in;
  400. // Bus master has released time min: 20us, typ: 30us, max: 200us
  401. while ( SENSOR_is_hi )
  402. {
  403. _delay_us(1);
  404. if ( !timeout-- )
  405. {
  406. return 2;
  407. }
  408. }
  409. // AM2302 response signal min: 75us typ:80us max:85us
  410. timeout = 85;
  411. while(SENSOR_is_low)
  412. {
  413. _delay_us(1);
  414. if (!timeout--)
  415. {
  416. return 3;
  417. }
  418. } // response to low time
  419. timeout = 85;
  420. while(SENSOR_is_hi)
  421. {
  422. _delay_us(1);
  423. if (!timeout--)
  424. {
  425. return 4;
  426. }
  427. } // response to high time
  428. /*
  429. * time in us: min typ max
  430. * signal 0 high time: 22 26 30 (bit=0)
  431. * signal 1 high time: 68 70 75 (bit=1)
  432. * signal 0,1 down time: 48 50 55
  433. */
  434. uint8_t sensor_data[5]={0};
  435. for(uint8_t i = 0; i < 5; i++)
  436. {
  437. uint8_t sensor_byte = 0;
  438. // get 8 bits from sensor
  439. for(uint8_t j = 1; j <= 8; j++)
  440. {
  441. // wait for sensor response
  442. timeout = 55;
  443. while(SENSOR_is_low)
  444. {
  445. _delay_us(1);
  446. // if timeout == 0 => sensor do not response
  447. if (!timeout--)
  448. {
  449. return 5;
  450. }
  451. }
  452. // wait 30 us to check if bit is logical "1" or "0"
  453. _delay_us(30);
  454. sensor_byte <<= 1; // add new lower bit
  455. // If sda ist high after 30 us then bit is logical "1" else it was a logical "0"
  456. // For a logical "1" sda have to be low after 75 us.
  457. if (SENSOR_is_hi)
  458. {
  459. sensor_byte |= 1; // add logical "1"
  460. timeout = 45; // 30us - 75us = 45us
  461. while(SENSOR_is_hi)
  462. {
  463. _delay_us(1);
  464. if (!timeout--)
  465. {
  466. return 6;
  467. }
  468. }
  469. }
  470. }
  471. sensor_data[i] = sensor_byte;
  472. }
  473. // checksum
  474. if ( ((sensor_data[0] + sensor_data[1] + sensor_data[2] + sensor_data[3]) & 0xff ) != sensor_data[4])
  475. {
  476. // debug output
  477. //printf("%b %b %b %b %b %b" CR, sensor_data[0], sensor_data[1], sensor_data[2], sensor_data[3], sensor_data[4], ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ));
  478. return 7;
  479. }
  480. g_u16Humidity = (sensor_data[0] << 8) + sensor_data[1];
  481. g_u16Temperature = (sensor_data[2] << 8) + sensor_data[3];
  482. return 0;
  483. }