diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f3a6b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Debug +Release diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..e59e812 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,14 @@ +Created on: 13.03.2013 +Author: Pascal Gollor +web: http://www.pgollor.de + +Dieses Werk ist unter einer Creative Commons Lizenz vom Typ +Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. +Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie +http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich +brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + + +----- WICHTIG!!! ----- +Ich uebernehme keinerlei Haftung fuer Schaeden die durch die Nutzung dieser Software enstehen. +----- WICHTIG!!! ----- diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..2b39aa7 --- /dev/null +++ b/README.txt @@ -0,0 +1,26 @@ +Created on: 13.03.2013 +Author: Pascal Gollor +web: http://www.pgollor.de + +Dieses Werk ist unter einer Creative Commons Lizenz vom Typ +Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. +Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie +http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich +brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + + +----- WICHTIG!!! ----- +Ich uebernehme keinerlei Haftung fuer Schaeden die durch die Nutzung dieser Software enstehen. +----- WICHTIG!!! ----- + + + +-- Installation + +Die Makefile ist von Eclipse unter Debian generiert worden. +Zum flashen einfach in den Ordner Release wechseln und folgendes ausfuehren: +- make +- make flash + +Vorsicht! Die Frequenz ist auf 8 MHz eingestellt und auch nur damit getestet worden. +Die Fusebits werden allerdings nicht durch das Makefile gesetzt. diff --git a/am2302.c b/am2302.c new file mode 100644 index 0000000..57b248d --- /dev/null +++ b/am2302.c @@ -0,0 +1,124 @@ +/* + * am2302.h + * + * Created on: 13.03.2013 + * Author: Pascal Gollor + * web: http://www.pgollor.de + * + * Dieses Werk ist unter einer Creative Commons Lizenz vom Typ + * Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. + * Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie + * http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich + * brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + * + * + * AM2302/DHT22 (Temperatur und Luftfeuchtigkeitssensor) + * _________ + * | -+-+- | + * | +-+-+-+ | + * | +-+-+-+ | + * | -+-+- | + * | +-+-+-+ | + * |_________| + * | | | | + * 1 2 3 4 + * + * 1. VCC (3 to 5V power) + * 2. Data out (Pullup 4,7k) + * 3. Not connected + * 4. Ground + * + * + * Error codes + * 1: sensor sda bus not free + * 2: timeout: bus master release time + * 3: timeout: response to low time + * 4: timeout: response to high time + * 5: timeout: signal low timeout + * 6: timeout: signal high timeout + * + * Read the datasheet for more information about the times. + */ + + +#include "am2302.h" + +#include +#include + +#include "main.h" +#include "uart.h" + + +#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)) + + +uint8_t am2302(uint16_t *humidity, uint16_t *temp) +{ + if (SENSOR_is_low) + { + // bus not free + return 1; + } + + SENSOR_sda_out; + SENSOR_sda_low; // MCU start signal + _delay_ms(20); // start signal (pull sda down for min 0.8ms and maximum 20ms) + SENSOR_sda_in; + + // Bus master has released time min: 20us, typ: 30us, max: 200us + uint8_t timeout = 200; + 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; + for(uint8_t j = 1; j <= 8; j++) // get 8 bits from sensor + { + timeout = 55; + while(SENSOR_is_low) {_delay_us(1); if (!timeout--) {return 5;}} // signal "0", "1" low time + _delay_us(30); + sensor_byte <<= 1; // add new lower byte + if (SENSOR_is_hi) // if sda high after 30us => bit=1 else bit=0 + { + sensor_byte |= 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; + } + + *humidity = (sensor_data[0]<<8) + sensor_data[1]; + *temp = (sensor_data[2]<<8) + sensor_data[3]; + + return 0; +} diff --git a/am2302.h b/am2302.h new file mode 100644 index 0000000..59c731b --- /dev/null +++ b/am2302.h @@ -0,0 +1,32 @@ +/* + * am2302.h + * + * Created on: 13.03.2013 + * Author: Pascal Gollor + * web: http://www.pgollor.de + * + * Dieses Werk ist unter einer Creative Commons Lizenz vom Typ + * Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. + * Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie + * http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich + * brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + */ + +#ifndef AM2302_H_ +#define AM2302_H_ + + +#include + +#define DDR_SENSOR DDRC +#define PORT_SENSOR PORTC +#define PIN_SENSOR PINC +#define SENSOR PC0 + + +uint8_t am2302(uint16_t *humidity, uint16_t *temp); + + + +#endif /* AM2302_H_ */ diff --git a/fifo.c b/fifo.c new file mode 100644 index 0000000..f128892 --- /dev/null +++ b/fifo.c @@ -0,0 +1,37 @@ +/* + * fifo.c + * + * Created on: 01.12.2012 + * Author: mikrocontroller.net + * web: http://www.mikrocontroller.net + * sub Author: Pascal Gollor (www.pgollor.de) + */ + + +#include "fifo.h" + +void fifo_init (fifo_t *f, uint8_t *buffer, const uint8_t size) +{ + f->count = 0; + f->pread = f->pwrite = buffer; + f->read2end = f->write2end = f->size = size; +} + +uint8_t fifo_put (fifo_t *f, const uint8_t data) +{ + return _inline_fifo_put (f, data); +} + +uint8_t fifo_get_wait (fifo_t *f) +{ + while (!f->count); + + return _inline_fifo_get (f); +} + +int fifo_get_nowait (fifo_t *f) +{ + if (!f->count) return -1; + + return (int) _inline_fifo_get (f); +} diff --git a/fifo.h b/fifo.h new file mode 100644 index 0000000..11fcb30 --- /dev/null +++ b/fifo.h @@ -0,0 +1,84 @@ +/* + * fifo.h + * + * Created on: 01.12.2012 + * Author: mikrocontroller.net + * web: http://www.mikrocontroller.net + * sub Author: Pascal Gollor (www.pgollor.de) + */ + + +#ifndef FIFO_H +#define FIFO_H + +#include +#include + +typedef struct +{ + uint8_t volatile count; // # Zeichen im Puffer + uint8_t size; // Puffer-Größe + uint8_t *pread; // Lesezeiger + uint8_t *pwrite; // Schreibzeiger + uint8_t read2end, write2end; // # Zeichen bis zum Überlauf Lese-/Schreibzeiger +} fifo_t; + +extern void fifo_init (fifo_t*, uint8_t* buf, const uint8_t size); +extern uint8_t fifo_put (fifo_t*, const uint8_t data); +extern uint8_t fifo_get_wait (fifo_t*); +extern int fifo_get_nowait (fifo_t*); + +static inline uint8_t +_inline_fifo_put (fifo_t *f, const uint8_t data) +{ + if (f->count >= f->size) + return 0; + + uint8_t * pwrite = f->pwrite; + + *(pwrite++) = data; + + uint8_t write2end = f->write2end; + + if (--write2end == 0) + { + write2end = f->size; + pwrite -= write2end; + } + + f->write2end = write2end; + f->pwrite = pwrite; + + uint8_t sreg = SREG; + cli(); + f->count++; + SREG = sreg; + + return 1; +} + +static inline uint8_t +_inline_fifo_get (fifo_t *f) +{ + uint8_t *pread = f->pread; + uint8_t data = *(pread++); + uint8_t read2end = f->read2end; + + if (--read2end == 0) + { + read2end = f->size; + pread -= read2end; + } + + f->pread = pread; + f->read2end = read2end; + + uint8_t sreg = SREG; + cli(); + f->count--; + SREG = sreg; + + return data; +} + +#endif /* FIFO_H */ diff --git a/main.c b/main.c new file mode 100644 index 0000000..84ead68 --- /dev/null +++ b/main.c @@ -0,0 +1,72 @@ +/* + * main.c + * + * Created on: 13.03.2013 + * Author: Pascal Gollor + * web: http://www.pgollor.de + * + * Dieses Werk ist unter einer Creative Commons Lizenz vom Typ + * Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. + * Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie + * http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich + * brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + * + * testet with: + * - avr-gcc 4.3.4 + * - Atmega8 @ 8 MHz + */ + + +#include "main.h" + +#include +#include +#include + +#include "uart.h" +#include "am2302.h" + + +#define led_on PORT_LED |= (1 << LED); +#define led_off PORT_LED &= ~(1 << LED); + + +int main(void) +{ + DDR_SENSOR &= ~(1 << SENSOR); // define as input + DDR_LED |= (1 << LED); // define as output + + PORT_SENSOR &= ~(1 << SENSOR); // disable pullup + + led_off; + + uart_init(BAUDRATE); + sei(); + + usart_write_str(CR "--- AM2302 ---" CR); + + while(1) + { + uint16_t humidity = 0; + uint16_t temp = 0; + + led_on; + + uint8_t error = am2302(&humidity, &temp); + if (!error) + { + printf("%i,%i%% %i,%iC" CR, humidity/10, humidity%10, temp/10, temp%10); + } + else + { + printf("Error %i" CR, error); + } + + led_off; + + _delay_ms(1000); + } + + return 0; +} diff --git a/main.h b/main.h new file mode 100644 index 0000000..2e71592 --- /dev/null +++ b/main.h @@ -0,0 +1,30 @@ +/* + * main.h + * + * Created on: 13.03.2013 + * Author: Pascal Gollor + * web: http://www.pgollor.de + * + * Dieses Werk ist unter einer Creative Commons Lizenz vom Typ + * Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich. + * Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie + * http://creativecommons.org/licenses/by-nc-sa/3.0/de/ oder wenden Sie sich + * brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. + * + */ + +#ifndef MAIN_H_ +#define MAIN_H_ + + +#define DDR_LED DDRC +#define PORT_LED PORTC +#define LED PC1 + + +#define CR "\r\n" + +#define BAUDRATE 9600 + + +#endif /* MAIN_H_ */ diff --git a/uart.c b/uart.c new file mode 100644 index 0000000..42f68a2 --- /dev/null +++ b/uart.c @@ -0,0 +1,207 @@ +/* + * uart.c + * + * Created on: 01.12.2012 + * Author: mikrocontroller.net + * web: http://www.mikrocontroller.net + * sub Author: Pascal Gollor (www.pgollor.de) + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "uart.h" +#include "fifo.h" // erklärt im Artikel "FIFO mit avr-gcc" + + +// FIFO-Objekte und Puffer für die Ein- und Ausgabe + +#define BUFSIZE_IN 0x0F +uint8_t inbuf[BUFSIZE_IN]; +fifo_t infifo; + +#define BUFSIZE_OUT 0xFF +uint8_t outbuf[BUFSIZE_OUT]; +fifo_t outfifo; + + +void uart_init (unsigned long baudrate) +{ + uint8_t sreg = SREG; + uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16UL*baudrate) - 1); + + UBRRH = (uint8_t) (ubrr>>8); + UBRRL = (uint8_t) (ubrr); + + // Interrupts kurz deaktivieren + cli(); + + // UART Receiver und Transmitter anschalten, Receive-Interrupt aktivieren + // Data mode 8N1, asynchron + UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE); + UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); + + // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) + do + { + // UDR auslesen (Wert wird nicht verwendet) + UDR; + } + while (UCSRA & (1 << RXC)); + + // Rücksetzen von Receive und Transmit Complete-Flags + UCSRA = (1 << RXC) | (1 << TXC); + + // Global Interrupt-Flag wieder herstellen + SREG = sreg; + + // FIFOs für Ein- und Ausgabe initialisieren + fifo_init (&infifo, inbuf, BUFSIZE_IN); + fifo_init (&outfifo, outbuf, BUFSIZE_OUT); +} + +// Empfangene Zeichen werden in die Eingangs-FIFO gespeichert und warten dort +ISR (USART_RXC_vect) +{ + _inline_fifo_put (&infifo, UDR); +} + +// Ein Zeichen aus der Ausgabe-FIFO lesen und ausgeben +// Ist das Zeichen fertig ausgegeben, wird ein neuer SIG_UART_DATA-IRQ getriggert +// Ist die FIFO leer, deaktiviert die ISR ihren eigenen IRQ. +ISR (USART_UDRE_vect) +{ + if (outfifo.count > 0) + UDR = _inline_fifo_get (&outfifo); + else + UCSRB &= ~(1 << UDRIE); +} + +int uart_putc (const uint8_t c) +{ + int ret = fifo_put (&outfifo, c); + + UCSRB |= (1 << UDRIE); + + return ret; +} + +void uart_puts (const char *s) +{ + do + { + uart_putc (*s); + } + while (*s++); +} + +int uart_getc_nowait (void) +{ + return fifo_get_nowait (&infifo); +} + +uint8_t uart_getc_wait (void) +{ + return fifo_get_wait (&infifo); +} + + + + +//------------------------------------------------------------------------------ +void usart_write_P (const char *Buffer,...) +{ + va_list ap; + va_start (ap, Buffer); + + int format_flag; + char str_buffer[10]; + char str_null_buffer[10]; + char move = 0; + char Base = 0; + int tmp = 0; + //char by; + uint8_t by; + char *ptr; + + //Ausgabe der Zeichen + for(;;) + { + by = pgm_read_byte(Buffer++); + if(by==0) break; // end of format string + + if (by == '%') + { + by = pgm_read_byte(Buffer++); + if (isdigit(by)>0) + { + str_null_buffer[0] = by; + str_null_buffer[1] = '\0'; + move = atoi(str_null_buffer); + by = pgm_read_byte(Buffer++); + } + + switch (by) + { + case '%': + usart_write_char('%'); + break; + case 's': + ptr = va_arg(ap,char *); + while(*ptr) { usart_write_char(*ptr++); } + break; + case 'b': + Base = 2; + goto ConversionLoop; + case 'c': + //Int to char + format_flag = va_arg(ap,int); + usart_write_char (format_flag++); + break; + case 'i': + Base = 10; + goto ConversionLoop; + case 'o': + Base = 8; + goto ConversionLoop; + case 'x': + Base = 16; + //**************************** + ConversionLoop: + //**************************** + itoa(va_arg(ap,int),str_buffer,Base); + int b=0; + while (str_buffer[b++] != 0){}; + b--; + if (b +#include +#include + +extern void uart_init (unsigned long); +extern int uart_putc (const uint8_t); +void uart_puts (const char *s); +extern uint8_t uart_getc_wait (void); +extern int uart_getc_nowait (void); + +void usart_write_P (const char *Buffer,...); + +#define usart_init(baudrate) uart_init(baudrate); +#define usart_write_char(c) uart_putc(c); +#define usart_write_str(c) uart_puts(c); +#define usart_write(format, args...) usart_write_P(PSTR(format) , ## args); +#define printf(format, args...) usart_write_P(PSTR(format), ## args); + +static inline void uart_flush (void) +{ + while (UCSRB & (1 << UDRIE)); +} + + +#endif /* UART_H_ */