|
Измерение скорости вращения двигателя
Программные примеры для микроконтроллеров 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);
}
|
Файлы проекта можно скачать здесь:
|
|
|