Parcourir la source

Print DHT timings to USART.

Vladimir Shilov il y a 5 ans
Parent
commit
fe4f0f6376
3 fichiers modifiés avec 132 ajouts et 1 suppressions
  1. 23 0
      ReadMe.txt
  2. 4 0
      inc/main.h
  3. 105 1
      src/main.c

+ 23 - 0
ReadMe.txt

@@ -63,3 +63,26 @@ My Nixie Clock IN-12 / Мои часы на ГРИ ИН-12
 Вообще планирую в версии для себя выкинуть эту регулировку - мне она кажется 
 лишней. Разве что ночью часы буду стоят возле головы и направлены в лицо.
 Сделал эту фичу отключаемой через дефайн в мейкфайле - 234 байта.
+
+Хочу подключить DHT-22, использую ногу захвата 1-го таймера, на прерываниях.
+Повторим алогритм: запускаем измерения подтяжкой вывода к земле минимум на 800 
+мкс, через 20-200 мкс датчик должен выдать 80 мкс "0" и 80 мкс "1", после чего 
+идут 40 бит данных. Каждый бит - 50 мкс "0", потом 26/70 мкс "1" для лог 0/1.
+Аналазитором заметил, что в начале каждого байта "0" не 50 мкс а почти 70.
+В мануале упоминаний не нашёл. Тайминги, естественно +/- плавают.
+При самых длинных таймингах вся операция должна занятьт 5570 мкс + время 
+запуска. Т.е. таймер можно настроить на счёт до 6 мс, и в прерывании по 
+переполнению признавать факт таймаута.
+Тактовая - 16МГц, предделители есть 8 и 64, так-как я предпочитаю меньшие 
+числа - ставим 64(8), и считаем по 4(0.5) мкс. Итого мы ждём такие интервалы:
+ - ответ на запрос через 5-50 тиков (40-400)
+ - преамбула 18-22 тика (150-170)
+ - 40 штук "0" - 12-14(96-110) + "1" - 5-8(44-60)/17-19(136-150) тиков
+   == 17-22/29-33 (140-170/232-260)
+ - таймаут - 1500(12000) тиков.
+Для тестов думаю поднять USART, делать опрос датчика, полученную инфу 
+складывать в массив, показывать в терминал и переходить на следующий круг.
+Для начала будем считать период (по переходу из "1" в "0"), массив на 42 байта.
+Потом попробую считать только длительность 40-ка "1" данных и сразу записывать их в байты.
+
+Что-то сделал. Скорость ком-порта 19200. +556 байт.

+ 4 - 0
inc/main.h

@@ -24,6 +24,10 @@
  * Дефайны
  */
 /* Port B, puttons, input, pull-up */
+#define DHT_PIN            _BV(PB0)
+#define DHT_PIN_LOW        DDRB |= DHT_PIN
+#define DHT_PIN_INPUT      DDRB &= ~(DHT_PIN)
+
 #define BTN_NUM            3
 #define BUTTON1_PIN        _BV(PB3)
 #define BUTTON2_PIN        _BV(PB4)

+ 105 - 1
src/main.c

@@ -21,6 +21,12 @@
 #include "main.h"
 
 /* Defines */
+/* Timer1, IC negative edge, CTC mode, 64 prescaler */
+#define TIMER1_ON         TCCR1B = ((0<<ICES1) | (1<<WGM12) | (1<<CS11) | (1<<CS10))
+#define TIMER1_OFF        TCCR1B = 0x00
+#define DHT_TIMEOUT       1500
+#define DHT_MAX_COUNT     42
+/* Timer2 settings */
 #define TIMER2_HZ         252
 #define TIMER2_PRESCALER  1024
 #define TIMER2_CS         (1<<CS22 | 1<<CS21 | 1<<CS20)
@@ -36,6 +42,13 @@
 /* Display timeout, sec */
 #define DISP_WDT_TIME   10
 
+/* USART */
+#define BAUD            19200UL
+#define BAUD_PRESCALE   (uint8_t)((F_CPU / BAUD / 16UL) - 1)
+#define CHAR_NEWLINE    '\n'
+#define CHAR_RETURN     '\r'
+#define RETURN_NEWLINE  "\r\n"
+
 
 /* Variables */
 static volatile uint8_t Digit[4] = {1, 2, 3, 4};
@@ -59,6 +72,7 @@ static volatile uint8_t DISP_WDT = 0;
 static EEMEM uint8_t EEP_BrightIdx;
 static uint8_t brightIdx;
 static EEMEM uint8_t EEP_SummerTime;
+static uint8_t dhtBuf[42];
 
 /* Constants */
 #if (USE_BRIGHT_CONTROL == 1)
@@ -75,6 +89,12 @@ static void valIncrease(uint8_t * val, uint8_t max);
 static void valDecrease(uint8_t * val, uint8_t max);
 static void blink(void);
 static void setSummerWinterTime(void);
+static void dhtStart(void);
+static void dhtBegin(void);
+static void dhtEnd(void);
+static void dhtTimeout(void);
+void usart_putc (char send);
+void usart_puts (const char *send);
 
 void main(void) {
   /**
@@ -116,9 +136,11 @@ void main(void) {
   showTime();
 
   RTOS_SetTask(btnProcess, 5, BTN_SCAN_PERIOD);
+  RTOS_SetTask(dhtStart, 7, 60000); //once per minute start DHT22 measure
 
   /** main loop */
   do {
+    /* new second interrupt from RTC */
     if (Flag.RTC_Int != 0) {
       Flag.RTC_Int = 0;
       ES_PlaceEvent(evNewSecond);
@@ -193,15 +215,28 @@ static void Board_Init(void) {
   /* Timer2 - refresh Nixie values */
   TCCR2 = TIMER2_CS;
   TCNT2 = TIMER2_CNT;
-  TIMSK = _BV(TOIE2) | _BV(OCIE2);
+
+  /* Timer interrupts */
+  TIMSK = _BV(TOIE2) | _BV(TICIE1) | _BV(TOIE1);
+
 #if (USE_BRIGHT_CONTROL == 1)
   OCR2 = pgm_read_byte(&brightConv[BRIGHT_IDX_MAX]);
+  TIMSK |= _BV(OCIE2);
 #endif // USE_BRIGHT_CONTROL
 
   /* Interrupt from RTC */
   MCUCR = _BV(ISC11); // falling edge
   GICR = _BV(INT1);
 
+  /* USART */
+  // Turn on USART hardware (no RX, TX)
+  UCSRB |= (0 << RXEN) | (1 << TXEN);
+  // 8 bit char sizes
+  UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
+  // Set baud rate
+  UBRRH = (BAUD_PRESCALE >> 8);
+  UBRRL = BAUD_PRESCALE;
+
   /* Enable Interrupts */
   sei();
 }
@@ -246,6 +281,35 @@ void dotOnPersistent(void) {
   PORTD |= DOT_PIN;
 }
 
+static void dhtStart(void) {
+  RTOS_SetTask(dhtBegin, 2, 0);
+  DHT_PIN_LOW;
+}
+
+static void dhtBegin(void) {
+  DHT_PIN_INPUT;
+  TCNT1 = 0;
+  OCR1A = DHT_TIMEOUT;
+  TIMER1_ON;
+}
+
+static void dhtEnd(void) {
+  uint8_t i;
+  char buffer[8];
+
+  usart_puts("DHT22 timing data:\r\n");
+
+  for (i=0; i<DHT_MAX_COUNT; i++) {
+    itoa(dhtBuf[i], buffer, 10);
+    usart_puts(buffer);
+    usart_puts(RETURN_NEWLINE);
+  }
+}
+
+static void dhtTimeout(void) {
+  usart_puts("DHT22 Timeout reached.\r\n");
+}
+
 /**
   * @brief  Обработка кнопок.
   * @param  : None
@@ -529,6 +593,20 @@ static void valDecrease(uint8_t * val, uint8_t max) {
   *val = ((bin / 10 ) << 4) | (bin % 10);
 }
 
+void usart_putc (char send) {
+    // Do nothing for a bit if there is already
+    // data waiting in the hardware to be sent
+    while ((UCSRA & (1 << UDRE)) == 0) {};
+    UDR = send;
+}
+
+void usart_puts (const char *send) {
+    // Cycle through each character individually
+    while (*send) {
+        usart_putc(*send++);
+    }
+}
+
 
 /**
  *  П р е р ы в а н и я
@@ -622,6 +700,32 @@ ISR(TIMER2_COMP_vect) {
 }
 #endif // USE_BRIGHT_CONTROL
 
+/**
+ * @brief DHT input capture
+ */
+ISR(TIMER1_CAPT_vect) {
+  static uint8_t count = 0;
+  static uint16_t old_tcnt = 0;
+
+  dhtBuf[count] = (uint8_t)(ICR1 - old_tcnt);
+  old_tcnt = ICR1;
+  count ++;
+  if (count == DHT_MAX_COUNT) {
+    TIMER1_OFF;
+    old_tcnt = 0;
+    count = 0;
+    RTOS_SetTask(dhtEnd, 0, 0);
+  }
+}
+
+/**
+ * @brief DHT timeout
+ */
+ISR(TIMER1_OVF_vect) {
+  TIMER1_OFF;
+  RTOS_SetTask(dhtTimeout, 0, 0);
+}
+
 /**
  * @brief заглушка для неиспользуемых прерываний
  */