Поиск по этому блогу

суббота, 3 апреля 2010 г.

Влажометр... То есть гигрометр на датчике влажности HIH-4000-001 и AVR atmega2560

В этом году нашей кафедре выделили деньги на закупку оборудования для обучения и научных исследований. Я заказал стартовый набор от Atmel STK 600. Цена на набор, на мой взгляд, безобразно высока (около 12000 руб).
Вот сам отладочный набор:

stk600 с мезониной платой для 2560

Как видите, на плате разведены все порты, есть диоды и кнопочки. Но в целом, это продвинутый программатор, не поддерживающий отладку по JTAG, что разочаровывает.
К нему я купил россыпь датчиков и LCD дисплей WH1602b. Для этого дисплея есть отличная библиотека WH1602b. Спасибо anterior! Моргать на плате диодами быстро надоело :) Захотелось создать прибор - гигрометр. Для отображения информации использовался WH1602b.
Для подключения дисплея к плате был сооружен вот такой шлейф:

шлейф для дисплея

Переменный резистор используется для регулировки контрастности. Питание подсветки индикатора (снизу) организованно по шине USB, так как питания с GND и VCC не хватает. При стандартном напряжении +5В индикатор дико грелся, поэтому пришлось поставить регулируемый резистор для уменьшения напряжения.
Распиновка понятна из кода настроек библиотеки дисплея wh1602b/conf.h:

#define F_CPU 1600000 /* частота мк, Гц */
#define USE_PUTN /* включить поддержку wh1602b_putn() */
#define USE_PUTH /* включить поддержку wh1602b_puth() */
#define USE_GENC /* включить поддержку wh1602b_genc() */

/* ножки к которым подключены выводы RS, RW, EN */
#define NPIN_RS PE0
#define NPIN_RW PE1
#define NPIN_EN PE2

/* порты к которым подключены выводы RS, RW, EN */
#define PORT_RS _SFR_IO_ADDR(PORTE)
#define PORT_RW _SFR_IO_ADDR(PORTE)
#define PORT_EN _SFR_IO_ADDR(PORTE)
#define DDR_RS _SFR_IO_ADDR(DDRE)
#define DDR_RW _SFR_IO_ADDR(DDRE)
#define DDR_EN _SFR_IO_ADDR(DDRE)

/* ножки к которым подключены выводы DB4-DB7 */
#define NPIN_DB7 PE7
#define NPIN_DB6 PE6
#define NPIN_DB5 PE5
#define NPIN_DB4 PE4

/* порты к которым подключены выводы DB4-DB7 */
#define PORT_DB7 _SFR_IO_ADDR(PORTE)
#define PORT_DB6 _SFR_IO_ADDR(PORTE)
#define PORT_DB5 _SFR_IO_ADDR(PORTE)
#define PORT_DB4 _SFR_IO_ADDR(PORTE)
#define DDR_DB7 _SFR_IO_ADDR(DDRE)
#define DDR_DB6 _SFR_IO_ADDR(DDRE)
#define DDR_DB5 _SFR_IO_ADDR(DDRE)
#define DDR_DB4 _SFR_IO_ADDR(DDRE)

В качестве датчика влажности используется HIH-4000-02. У него 3 ноги - питание, земля и выходной сигнал, пропорциональный влажности.


Вот код основной программы:


  #include <avr/io.h>
  #include <stdio.h>
  #include <util/delay.h>
  #include "wh1602b/wh1602b.h"
  #include <avr/pgmspace.h>
  #include <avr/interrupt.h>


  double humidity = 0;
  const double  n2 = 1024;
  const double  Vcc = 5;
  const double v_ofset = 0.826;






  void init_ADC(void)
  {
  ADMUX |= (1 << MUX2) | (1 << MUX1) | (1 << MUX0); // порт PF7
  ADCSRA |=(1 << ADEN); // ВКЛЮЧИЛИ АЦП
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // ЧАСТОТА ПРЕОБРАЗОВАНИЯ
  ADMUX |= (1 << REFS0); // ИСПОЛЬЗУЕТСЯ ОПОРНОЕ НАПРЯЖЕНИЕ AVCC
  }


  unsigned int read_ADC(void)
  {
  ADCSRA |= (1 << ADSC); // НАЧАЛО ПРЕОБРАЗОВАНИЯ
  _delay_ms(100);
  if (ADIF)
  {
  return ADCW; // виртуальный регистр результатов
  }
  else
  return 0;
  }




  int main(void)
  {


  wh1602b_init(); // инициализировать модуль, порты
   // настроить параметры управления дисплеем
  wh1602b_displayctl(DC_DISPLAY_ON); // дисплей включён
   // задать число строк
  wh1602b_funcset(FS_LINES_2); // 2 строки
   // очистить область
  wh1602b_clear();
  // вернуться в начало (команда аналогичная move).
  //   этот вызов является обязательным после вызова genc()
  wh1602b_home();
  init_ADC();
  wh1602b_puts("Please press SW0");


  DDRB = 0xff;            // все на вывод
  DDRD = 0x00;   // все на ввод




  while ((PIND & (1<<PIND0))); // пока не нажата кнопка 0 ничего не делаем
  wh1602b_clear();
  wh1602b_puts("Ждите...");


while (1)
{


unsigned int h = 0;
h = read_ADC();
wh1602b_clear();
double u = h*Vcc/n2; // вычисляем напряжение из показаний АЦП, с разрядностью n = 2^10
humidity = (u - 0.826)/0.0315; // из даташита на датчик влажности
wh1602b_puts("Влажность ");
wh1602b_putn(humidity);
wh1602b_puts("%");


wh1602b_move(1,0);
wh1602b_puts("Uвых ");
wh1602b_putn(u*1000);
wh1602b_puts(" мВ");
_delay_ms(50);
}
return 0;
   }