Вы вошли на сайт, как Гость
Регистрация

Измерение скорости вращения двигателя

Программные примеры для микроконтроллеров AVR - AVRStudio
(Измерение скорости вращения двигателя с отображением результата на ЖК-дисплее)

Для измерения скорости вращения можно воспользоваться оптопрерывате- лем — прибором, в котором между эмитирующим инфракрасное излучение диодом и транзистором-детектором имеется воздушная прослойка (например, прибор Н21А1 производства FAIRCHILD)

Если между диодом и детектором поместить непрозрачный объект, транзистор разомкнет цепь и тем самым "прервет" сигнал. Подключив такое устройство к выводу ICP микроконтроллера, можно в режиме ШИМ регистрировать частоту вращения диска с вырезом, закрепленного на оси двигателя. Всякий раз, когда вырез будет находиться в щели оптопрерывателя, транзистор будет замыкать цепь, а как только вырез будет уходить из щели, транзистор будет ее размыкать. Если выполнять подсчет раз в секунду, то будет получено количество оборотов вала в 1 с, то есть, частоту вращения в герцах. Используем микроконтроллер с тактовой частотой 8 МГц (например, AT90S8535). Используя коэффициент деления 8 получаем частоту тактирования Т/С1 равной 1 МГц (период такта — 1 мкс). Каждый раз, когда на выводе ICP микроконтроллера (для устройства AT90S8535 — вывод PD6) появляется ниспадающий фронт сигнала, возникает прерывание по захвату на входе, и вычисляется количество тактовых импульсов между предыдущим и текущим моментом захвата (хранится в регистре ICR1). Полученный результат будем отображать на ЖК-дисплее.

Модуль DMC2048 работает в четырехразрядном режиме. Это означает, что все поступающие на устройство данные передаются с помощью четырех линий данных (в случае рассматриваемой микросхемы они обозначены как DB4-DB7). Используется три управляющих сигнала:

Е — стробирующий сигнал для подтверждения передачи данных, предназначенных
к отображению на дисплее;
RD (R/W) — определяет текущую операцию: чтение данных из ЖК-модуля
(RD=1) или запись данных в ЖК-модуль (RD=0);
RS —- определяет характер передаваемых данных: команда (RS=0), влияющая
на режим работы дисплея, или данные (RS=1), которые следует отобразить.

В нашем примере линия Е ЖК-модуля будет подсоединена к выводу 0 порта В микроконтроллера, линия RS — к выводу 1, а линия RD — к выводу 2 того же порта. Линии данных будут соединены с выводами 0-3 порта С микроконтроллера.

Примечание: при компиляции проекта требуется добавить в проект следующие библиотеки: "avr/io.h","avr/interrupt.h","avr/signal.h" ,"string.h","avr/delay.h"

#include 
#include 
#include 
#include 
#include 

#define RD_1 PORTB |= 4
#define RS_1 PORTB |= 2
#define E_1  PORTB |= 1
#define RD_0 PORTB &= 3
#define RS_0 PORTB &= 5
#define E_0  PORTB &= 6

const unsigned char addLUT[4] = {0x80, 0xC0, 0x94, 0xD4};
unsigned char LCD_Address, LCD_Line;
unsigned int PreviousTime;
char buffer[15];
  
void WriteNibble(unsigned char data)
{
  RD_0;
  E_1;
  PORTC = (data & 0x0F);
  E_0;
  RD_1;
  _delay_loop_2(3000);
}

void WriteByte(unsigned char data)
{
  RD_0;
  E_1;
  PORTC = (data >> 4);
  E_0;
  E_1;
  PORTC = (data & 0xF);
  E_0;
  RD_1;
  _delay_loop_2(3000);
}

void GoToLine(char LineNum)
{
  RS_0;
  LCD_Address = addLUT[LineNum-1];
  WriteByte(LCD_Address);
  RS_1;
  LCD_Address = 0;
  LCD_Line = LineNum;
}

void ClearLCD(void)
{
  RS_0;
  WriteByte(0x01);
  _delay_loop_2(10000);
  RS_1;
  GoToLine(1);
}

void SetLCDPosition(char row, char col)
{
  RS_0;
  LCD_Address = addLUT[row-1] + col;
  WriteByte(LCD_Address);
  RS_1;
  LCD_Line = row;
}

void ShowChar(unsigned char c)
{
  RS_1;
  WriteByte(c);
  LCD_Address++;
  switch (LCD_Address)
  {
    case 20: GoToLine(2); break;
    case 40: GoToLine(3); break;
	case 60: GoToLine(4); break;
	case 80: GoToLine(1); break;
  }
}

void ShowStr(unsigned char *s)
{
  while (*s != 0) ShowChar(*s++);
}

void InitLCD(void)
{
  RD_1;
  E_0;
  RS_0;
  _delay_loop_2(50000);
  WriteNibble(0x33);
  WriteNibble(0x33);
  WriteNibble(0x33);
  WriteNibble(0x22);
  WriteByte(0x28);
  WriteByte(0x01);
  WriteByte(0x10);
  WriteByte(0x06);
  WriteByte(0x0C);
  for (char i=0x40; i<0x5F; i++)
  {
    _delay_loop_2(10000);
	RS_0;
	WriteByte(i);
	_delay_loop_2(10000);
	ShowChar(0);
  }
  RS_1;
  SetLCDPosition(2, 4);
  buffer[0] = 'V';
  buffer[1] = 'e';
  buffer[2] = 'l';
  buffer[3] = 'o';
  buffer[4] = 's';
  buffer[5] = 'i';
  buffer[6] = 't';
  buffer[7] = 'y';
  buffer[8] = ' ';
  buffer[9] = 'i';
  buffer[10] = 's';
  buffer[11] = '\0';
  ShowStr(buffer);
}

INTERRUPT(SIG_INPUT_CAPTURE1)
{
  unsigned int CurrentTime, T;
  CurrentTime = (256 * ICR1H) + ICR1L;
  if (CurrentTime > PreviousTime) T = CurrentTime - PreviousTime;
  else T = 0xFFFF - CurrentTime + PreviousTime;
  sprintf(buffer, "%06u rpm", (unsigned long)60E6 / (unsigned long)T );
  SetLCDPosition(3, 4);
  ShowStr(buffer);
  PreviousTime = CurrentTime;
}

void main (void)
{
  DDRC = 0x0F;
  DDRB = 0x07;
  DDRD = 0;
  PORTD = _BV(PD6);
  TIMSK = _BV(TICIE1);
  TCCR1A = 0;
  TCCR1B = _BV(CS11);
  TCNT1 = 0;
  InitLCD();
  sei ();
  while(1);
}

Файлы проекта можно скачать здесь: