|
- #include <stdbool.h>
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #define F_CPU 20000000UL //20 MHz
- #include <util/delay.h>
-
- /* 7-Segment display: */
- #define NUM_DIGITS 3U //3 Digits
- #define DIGIT_TENS 2U //left
- #define DIGIT_ONES 1U //middle
- #define DIGIT_UNIT 0U //right
- #define SELECT_DIGIT(digit) (1U << digit)
-
- /* DHT22 peripherals: */
- #define DDR_SENSOR DDRC
- #define PORT_SENSOR PORTC
- #define PIN_SENSOR PINC
- #define SENSOR PINC3
-
- /* DHT22 commands: */
- #define SENSOR_sda_out DDR_SENSOR |= (1 << SENSOR)
- #define SENSOR_sda_in DDR_SENSOR &= ~(1 << SENSOR) // release sda => hi in consequence of pullup
- #define SENSOR_sda_low PORT_SENSOR &= ~(1 << SENSOR)
- #define SENSOR_is_hi PIN_SENSOR & (1 << SENSOR)
- #define SENSOR_is_low !(PIN_SENSOR & (1 << SENSOR))
-
- #define MODE_MEASURE 0U
- #define MODE_ANIMATION_1 1U
- #define MODE_ANIMATION_2 2U
-
- #define ANIMATION_DELAY_MS 70U
-
- #define ANIMATION_START_DELAY_MS 70U
-
- #define BUTTON_THRESHOLD 50 //software debounce
-
- /* Symbol indexes: */
- #define SYM_n 10U
- #define SYM_o 11U
- #define SYM_E 12U
- #define SYM_R 13U
- #define SYM_DEG_CELCIUS 14U
- #define SYM_P_P 15U
- #define SYM_OFF 16U
- #define SYM_DASH 17U
- #define SYM_I 18U
- #define SYM_SEG_A 19U
- #define SYM_SEG_B 20U
- #define SYM_SEG_C 21U
- #define SYM_SEG_D 22U
- #define SYM_SEG_E 23U
- #define SYM_SEG_F 24U
- #define SYM_SEG_AB 25U
- #define SYM_SEG_BCD 26U
- #define SYM_SEG_CD 27U
- #define SYM_SEG_DE 28U
- #define SYM_SEG_DEF 29U
- #define SYM_SEG_AEF 30U
- #define SYM_SEG_AF 31U
-
- /*
- 7-Segment Layout:
-
- A
- F B
- G
- E C
- D P
-
- Pin 7 6 5 4 3 2 1 0
- Segment A F B E D C G P
- */
- static uint8_t g_au8Symbols[32U] =
- {
- /* 00 */ 0b11111100U, //0 (ABCDEF)
- /* 01 */ 0b00100100U, //1 (BC)
- /* 02 */ 0b10111010U, //2 (ABDEG)
- /* 03 */ 0b10101110U, //3 (ABCDG)
- /* 04 */ 0b01100110U, //4 (BCFG)
- /* 05 */ 0b11001110U, //5 (ACDFG)
- /* 06 */ 0b11011110U, //6 (ACDEFG)
- /* 07 */ 0b10100100U, //7 (ABC)
- /* 08 */ 0b11111110U, //8 (ABCDEFG)
- /* 09 */ 0b11101110U, //9 (ABCDFG)
- /* 10 */ 0b00010110U, //n (CEG) SYM_n
- /* 11 */ 0b00011110U, //o (CDEG) SYM_o
- /* 12 */ 0b11011010U, //E (ADEFG) SYM_E
- /* 13 */ 0b00010010U, //r (EG) SYM_r
- /* 14 */ 0b10101101U, //degC (ABCDP) SYM_DEG_CELCIUS
- /* 15 */ 0b11110011U, //P. (ABEFGP) SYM_P_P
- /* 16 */ 0b00000000U, //OFF SYM_OFF
- /* 17 */ 0b00000010U, //- (G) SYM_DASH
- /* 18 */ 0b01010000U, //I (EF) SYM_I
- /* 19 */ 0b10000000U, //SegA SYM_SEG_A
- /* 20 */ 0b00100000U, //SegB SYM_SEG_B
- /* 21 */ 0b00000100U, //SegC SYM_SEG_C
- /* 22 */ 0b00001000U, //SegD SYM_SEG_D
- /* 23 */ 0b00010000U, //SegE SYM_SEG_E
- /* 24 */ 0b01000000U, //SegF SYM_SEG_F
- /* 25 */ 0b10100000U, //SegAB SYM_SEG_AB
- /* 26 */ 0b00101100U, //SegBCD SYM_SEG_BCD
- /* 27 */ 0b00001100U, //SegCD SYM_SEG_CD
- /* 28 */ 0b00011000U, //SegDE SYM_SEG_DE
- /* 29 */ 0b01011000U, //SegDEF SYM_SEG_DEF
- /* 30 */ 0b11010000U, //SegAEF SYM_SEG_AEF
- /* 31 */ 0b11000000U //SegAF SYM_SEG_AF
- };
-
- static uint8_t g_u8ButtonCountTop = 0U; //upper button counter
- static uint8_t g_u8ButtonCountBot = 0U; //lower button counter
- static uint8_t g_u8Mode = MODE_MEASURE; //Current display mode
-
-
- uint16_t g_u16Humidity = 0U;
- uint16_t g_u16Temperature = 0U;
-
- uint8_t g_u8ISRDigitSelect = 0U;
- uint8_t g_au8Digits[3U] =
- {
- SYM_OFF, //unit
- SYM_OFF, //ones
- SYM_OFF //tens
- };
-
- void s_vInit( void );
- void s_vSetValue( uint8_t u8Value, uint8_t u8Unit );
- void s_vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit );
-
- void s_vReadButtons( void );
- void s_vShowAnim( uint8_t u8Select );
-
- uint8_t s_u8ReadSensor( void );
-
- /************************************************************************/
- /* Timer1 ISR - show values on display */
- /************************************************************************/
- ISR ( TIMER1_COMPA_vect )
- {
- PORTB = 0;
- PORTD = 0;
- _delay_us(2);
- PORTB = SELECT_DIGIT(g_u8ISRDigitSelect);
- PORTD = g_au8Symbols[g_au8Digits[g_u8ISRDigitSelect]];
- g_u8ISRDigitSelect++;
- if (g_u8ISRDigitSelect > 2U)
- {
- g_u8ISRDigitSelect = 0U;
- }
-
- /* Read and evaluate button status */
- s_vReadButtons();
- }
-
- /************************************************************************/
- /* main() */
- /************************************************************************/
- int main(void)
- {
- uint8_t u8ErrorCode = 0U;
- uint8_t u8Loop = 0U;
-
- s_vInit();
-
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
- _delay_ms(10);
-
- s_vSetDisplayDigits( SYM_SEG_A, SYM_OFF, SYM_OFF );
- _delay_ms(300);
- s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_OFF );
- _delay_ms(300);
- s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_SEG_A );
- _delay_ms(300);
-
- while ( u8Loop < 5U )
- {
- s_vSetDisplayDigits( SYM_OFF, SYM_SEG_A, SYM_SEG_AB );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, 7U );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_SEG_BCD );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, SYM_SEG_D, SYM_SEG_CD );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_SEG_D, SYM_SEG_D, SYM_SEG_D );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_SEG_DE, SYM_SEG_D, SYM_OFF );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_SEG_DEF, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_SEG_AEF, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_SEG_AF, SYM_SEG_A, SYM_OFF );
- _delay_ms(ANIMATION_START_DELAY_MS);
- s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_SEG_A );
- _delay_ms(ANIMATION_START_DELAY_MS);
- u8Loop++;
- }
-
- /* Set default value: */
- //s_vSetDisplayDigits( SYM_DASH, SYM_DASH, SYM_DASH );
-
- /* wait 3 seconds for humity sensor */
- //_delay_ms(3000);
-
- /* Set default value: */
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
- _delay_ms(600);
-
- while ( 1 )
- {
- switch ( g_u8Mode )
- {
- case MODE_MEASURE:
- if ( SENSOR_is_hi )
- {
- SENSOR_sda_out;
- SENSOR_sda_low;
- _delay_ms(20);
- u8ErrorCode = s_u8ReadSensor();
- if ( 0U == u8ErrorCode )
- {
- s_vSetValue( g_u16Humidity / 10, SYM_P_P );
- //vSetDisplayValues( g_u16Temperature / 10, SYM_DEG_CELCIUS );
- }
- else
- {
- s_vSetDisplayDigits( SYM_E, u8ErrorCode, SYM_OFF );
- }
- }
- if ( g_u8Mode == MODE_MEASURE )
- {
- _delay_ms(500);
- }
- break;
- case MODE_ANIMATION_1:
- s_vShowAnim(g_u8Mode);
- g_u8Mode = MODE_MEASURE;
- _delay_ms(200);
- break;
- case MODE_ANIMATION_2:
- s_vShowAnim(g_u8Mode);
- g_u8Mode = MODE_MEASURE;
- _delay_ms(200);
- break;
- default:
- break;
- } //end switch
-
- // _delay_ms(3000); //wait 3 seconds for new measurement
- } //end while(1)
-
- return 0;
- }
-
- /************************************************************************/
- /* Initialize inputs and outputs */
- /************************************************************************/
- void s_vInit( void )
- {
- /* Port D - Pins 0-7: Outputs */
- DDRD = 0b11111111U;
-
- /* Port B - Pins 0-2: Outputs */
- DDRB = 0b00000111U;
-
- /* Port C - Pins 4-5: Inputs with internal Pull-up */
- PORTC = 0b00110000U;
-
- /* Sensor init: */
- DDR_SENSOR &= ~(1 << SENSOR); // define as input
- PORT_SENSOR &= ~(1 << SENSOR); // disable pullup
-
- /* 16-bit TIMER1 in CTC mode
- * prescaler = 8
- * 20 MHz / 8 = 2.5 MHz
- * Compare value = 2500 => 1 ms IRQ
- */
- TCCR1A = 0U;
- TCCR1B = (1<<WGM12) | (1<<CS11);
- OCR1A = 2500U;
- TIMSK1 |= (1<<OCIE1A);
- sei();
-
- return; //void
- }
-
- /************************************************************************/
- /* Set new values to be shown on display */
- /************************************************************************/
- void s_vSetValue( uint8_t u8Value, uint8_t u8Unit )
- {
- uint8_t u8Tmp = u8Value / 10U;
- s_vSetDisplayDigits(u8Tmp, u8Value - (u8Tmp * 10U), u8Unit);
-
- return; //void
- }
-
- /************************************************************************/
- /* Set display digits individually */
- /************************************************************************/
- void s_vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit )
- {
- g_au8Digits[DIGIT_TENS] = u8Tens;
- g_au8Digits[DIGIT_ONES] = u8Ones;
- g_au8Digits[DIGIT_UNIT] = u8Unit;
-
- return; //void
- }
-
- /************************************************************************/
- /* Read button status */
- /************************************************************************/
- void s_vReadButtons( void )
- {
- if ( !(PINC & (1<<PINC4)) ) //if button '+' pressed
- {
- g_u8ButtonCountTop++;
- }
- else
- {
- g_u8ButtonCountTop = 0U; //reset button counter
- }
-
- if ( !(PINC & (1<<PINC5)) ) //if button '-' pressed
- {
- g_u8ButtonCountBot++;
- }
- else
- {
- g_u8ButtonCountBot = 0U; //reset button counter
- }
-
- if ( g_u8ButtonCountTop > BUTTON_THRESHOLD )
- {
- g_u8ButtonCountTop = 0U; //reset top counter
- g_u8Mode = MODE_ANIMATION_1;
- }
- else if ( g_u8ButtonCountBot > BUTTON_THRESHOLD )
- {
- g_u8ButtonCountBot = 0U; //reset bottom counter
- g_u8Mode = MODE_ANIMATION_2;
- }
-
- return; //void
- }
- /************************************************************************/
- /* */
- /************************************************************************/
- void s_vShowAnim( uint8_t u8Select )
- {
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- switch ( u8Select )
- {
- case MODE_ANIMATION_1: //fade from left to right and from right to left
- s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, 8U, 1U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, 3U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, 8U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, 3U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, 1U );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, 8U, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- break;
- case MODE_ANIMATION_2: //fade from left to right and clear
- s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 8U, 8U, 1U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, 3U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 8U, 8U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( 3U, 8U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( 1U, 8U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, 8U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( SYM_OFF, 3U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, 1U, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, 8U );
- _delay_ms(ANIMATION_DELAY_MS);
-
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_E );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_I );
- _delay_ms(ANIMATION_DELAY_MS);
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
- break;
- default:
- break;
- } //end switch
- s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF );
- _delay_ms(ANIMATION_DELAY_MS);
-
- return; //void
- }
-
- /************************************************************************/
- /* Read humidity and temperature from DHT22 */
- /************************************************************************/
- uint8_t s_u8ReadSensor( void )
- {
- uint8_t timeout = 200;
-
- SENSOR_sda_in;
-
- // Bus master has released time min: 20us, typ: 30us, max: 200us
- while ( SENSOR_is_hi )
- {
- _delay_us(1);
- if ( !timeout-- )
- {
- return 2;
- }
- }
-
- // AM2302 response signal min: 75us typ:80us max:85us
- timeout = 85;
- while(SENSOR_is_low)
- {
- _delay_us(1);
- if (!timeout--)
- {
- return 3;
- }
- } // response to low time
-
- timeout = 85;
- while(SENSOR_is_hi)
- {
- _delay_us(1);
- if (!timeout--)
- {
- return 4;
- }
- } // response to high time
-
-
- /*
- * time in us: min typ max
- * signal 0 high time: 22 26 30 (bit=0)
- * signal 1 high time: 68 70 75 (bit=1)
- * signal 0,1 down time: 48 50 55
- */
-
- uint8_t sensor_data[5]={0};
-
- for(uint8_t i = 0; i < 5; i++)
- {
- uint8_t sensor_byte = 0;
-
- // get 8 bits from sensor
- for(uint8_t j = 1; j <= 8; j++)
- {
- // wait for sensor response
- timeout = 55;
- while(SENSOR_is_low)
- {
- _delay_us(1);
-
- // if timeout == 0 => sensor do not response
- if (!timeout--)
- {
- return 5;
- }
- }
-
- // wait 30 us to check if bit is logical "1" or "0"
- _delay_us(30);
- sensor_byte <<= 1; // add new lower bit
-
- // If sda ist high after 30 us then bit is logical "1" else it was a logical "0"
- // For a logical "1" sda have to be low after 75 us.
- if (SENSOR_is_hi)
- {
- sensor_byte |= 1; // add logical "1"
- timeout = 45; // 30us - 75us = 45us
-
- while(SENSOR_is_hi)
- {
- _delay_us(1);
-
- if (!timeout--)
- {
- return 6;
- }
- }
- }
- }
-
- sensor_data[i] = sensor_byte;
- }
-
- // checksum
- if ( ((sensor_data[0] + sensor_data[1] + sensor_data[2] + sensor_data[3]) & 0xff ) != sensor_data[4])
- {
- // debug output
- //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 ));
- return 7;
- }
-
- g_u16Humidity = (sensor_data[0] << 8) + sensor_data[1];
- g_u16Temperature = (sensor_data[2] << 8) + sensor_data[3];
-
- return 0;
- }
|