
- •1 Техническое задание
- •2.2 Описание объекта автоматизации
- •Принцип работы
- •2.4 Выбор элементной базы
- •Шаговый двигатель
- •Расходомер
- •Корректирующий датчик температуры
- •Корректирующий датчик давления
- •Индикация
- •Блок питания
- •Блок питания
- •Стабилизатор
- •Электрический насос
- •Принципиальная схема устройства
- •Алгоритм работы устройства
Шаговый двигатель
Расходомер
Корректирующий датчик температуры
Микроконтроллер
Корректирующий датчик давления
Индикация
Блок питания
220 В -24 В
Блок питания
220 В -5 В
Стабилизатор
12 В
Ъ
Электрический насос
Рисунок 2. Структурная схема устройства
Насос подключается к микропроцессору через реле.
К расходомеру подключены датчики давления и температуры, которые позволяют более точно в зависимости от состояния среды вести подсчет. С выхода расходомера данные идут на порт микроконтроллера.
Модуль индикации содержит два одинаковых табло: «Реал» - значение, полученное с расходомера и «Уставка» - цифры, введенные оператором с клавиатуры. Как только реальное значение начинает приближаться к установленному, насос отключается и заслонка начинает плавно закрываться.
Микроконтроллер запитывается от 5 В, расходомер и электрический насос от 24 В, шаговый двигатель и датчики - от 12 В. Для этого в схеме присутствуют готовые блоки питания, выдающие 24 В и 5 В, а также стабилизатор, преобразующий напряжение с 24 В до 12 В.
Принципиальная схема устройства
Разработка принципиальной схемы системы управления ведется согласно общей модульной структуре микроконтроллерной системы, представленной на рис.6 и с учетом разделения функций между аппаратными и программными средствами микропроцессорной системы.
Микроконтроллер
Микроконтроллер PIC16F777 в корпусе TQFP содержит 44 вывода. К выводам OSС1 и OSС2 подключен кварцевый резонатор и конденсаторы фильтрации. Изображение микроконтроллера на принципиальной схеме приведено на рисунке 3.
Рисунок 3. Микроконтроллер на принципиальной схеме
Подключение насоса
Электрический насос AG-600 имеет мощность 180 Вт и силу тока 25 А. Поэтому осуществим подключение с помощью реле РЭК77/3. Для управления реле выберем транзистор КТ829А. Резистор сопротивлением в 1000 Ом ограничивает ток транзистора.
Управление электрическим насосом показано на рисунке 4.
Рисунок 4. Микроконтроллер на принципиальной схеме
Подключение
шагового двигателя
Двигатель 28 BJY-48 подключается с помощью резисторов, транзисторов. Транзисторы работают в ключевом режиме, что порождает импульсы самоиндукии. Для их погашения используем полупроводниковые диоды 1N4007. Резисторы в свою очередь ограничивают ток базы. Для индикации фазы поставим светоизлучающие диоды. Схема изображена на рисунке 5.
Рисунок 5. Шаговый двигатель на принципиальной схеме
Подключение
клавиатуры
Матричная шестнадцатикнопочная клавиатура подключается напрямую к микроконтроллеру. Во избежание случайного нажатия двух клавиш одновременно по столбцам подключены диоды 1N4148. Подключение клавиатуры показано на рисунке 6.
Рисунок 6. Матричная клавиатура на принципиальной схеме
Подключение расходомера
На входы А1 и А2 расходомера UFM3030 приходят сигналы с первичных измерительных преобразователей – датчиков температуры и давления – для более точного подсчета в зависимости от состояния среды. С выхода P расходомера сигнал идет на порт микроконтроллера.
Подключение индикаторов
Семисегментные индикаторы подключаются по схеме «с общим анодом» с помощью транзисторов КТ829А. Чтобы ограничить ток через светодиоды, поставим семь резисторов. Учитывая падение напряжения на индикаторах и транзисторах, выберем сопротивление резисторов 240 Ом. Подключение модуля индикации показано на рисунке 7.
Рисунок 7. Индикация на принципиальной схеме
Подключение модуля питания
Так как устройства в схеме запитываются от 5 В, 12 В, 24 В, выберем готовые блоки питания БП60Б на 5 и 24 В, а также используем стабилизатор напряжения LM7812. Модуль питания изображен на рисунке 8.
Рисунок 8. Блоки питания на принципиальной схеме
32.2
Проектирование программной части
Одна из важных частей системы – индикация. Введенные с клавиатуры значения отображаются на табло «УСТАВКА», а показания с расходомера можно увидеть на табло «РЕАЛ». Пример программы для организации динамической индикации приведен ниже.
3.2.1 Листинг программы
include 16f777
-- This program assumes a 20 MHz resonator or crystal
-- is connected to pins OSC1 and OSC2.
pragma target clock 4_000_000 -- oscillator frequency
-- configuration memory settings (fuses)
--pragma target OSC HS -- HS crystal or resonator
pragma target OSC INTOSC_NOCLKOUT -- внутренний генератор
pragma target WDT disabled -- no watchdog
pragma target LVP disabled -- no Low Voltage Programming
pragma target MCLR external -- reset externally
--
enable_digital_io() -- disable analog I/O (if any)
alias tr1 is pin_A2
alias tr2 is pin_A3
portb_direction = all_output
porta_direction = all_output
const byte seven_segment_clear = 0b_0000_0000
const byte seven_segment_a_ra = 0b_0001_0000
const byte seven_segment_b_rb = 0b_0001_0000
const byte seven_segment_c_rb = 0b_0010_0000
const byte seven_segment_d_rb = 0b_1000_1000
const byte seven_segment_e_rb = 0b_0100_0000
const byte seven_segment_f_rb = 0b_0000_0001
const byte seven_segment_g_ra = 0b_0000_0001
var byte i = 0
var byte j = 0
include delay
include print
include format
-- setup pin definitions for dallas one-wire bus
alias d1w_bus is pin_a1
alias d1w_bus_direction is pin_a1_direction
include one_wire -- include one-wire library
d1w_init()
-- init one-wire bus
const ds18b20_value_raw = 0
const ds18b20_value_celcius = 1
const ds18b20_value_farenheit = 0
const ds18b20_ignore_crc = 0 -- 1 tell lib to ignore crc (code becomes smaller and faster, but reliability of data is less)
const ds18b20_max_retries = 2 -- 1 means the library re-reads once when crc fails, 4 means up to 4 retries (so max 5 reads)
include 18b20
const byte str1[] = "Temp="
const byte str_err1[] = "ds18b20 read failed."
var sword temperature
var bit r
const _seven_common_mask_ra = 0x00
const _seven_common_mask_rb = 0x00
const byte seven_value_space_ra[] = {
-- value 0 is character 0
_seven_common_mask_ra ^ (seven_segment_a_ra),
-- value 1 is character 1
_seven_common_mask_ra ^ (seven_segment_clear),
-- value 2 is character 2
_seven_common_mask_ra ^ (seven_segment_a_ra
+ seven_segment_g_ra),
-- value 3 is character 3
_seven_common_mask_ra ^ (seven_segment_a_ra
+ seven_segment_g_ra),
-- value 4 is character 4
_seven_common_mask_ra ^ (seven_segment_g_ra),
-- value 5 is character 5
_seven_common_mask_ra ^ (seven_segment_a_ra
+ seven_segment_g_ra),
-- value 6 is character 6
_seven_common_mask_ra ^ (seven_segment_a_ra
+ seven_segment_g_ra),
-- value 7 is character 7
_seven_common_mask_ra ^ (seven_segment_a_ra),
-- value 8 is character 8
_seven_common_mask_ra ^ (seven_segment_a_ra
+ seven_segment_g_ra),
-- value 9 is character 9
_seven_common_mask_ra ^ (seven_segment_a_ra
+ seven_segment_g_ra)
}
const byte seven_value_space_rb[] = {
-- value 0 is character 0
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
+ seven_segment_d_rb
+ seven_segment_e_rb
+ seven_segment_f_rb
),
-- value 1 is character 1
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
),
-- value 2 is character 2
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_d_rb
+ seven_segment_e_rb
),
-- value 3 is character 3
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
+ seven_segment_d_rb
),
-- value 4 is character 4
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
+ seven_segment_f_rb
),
-- value 5 is character 5
_seven_common_mask_rb ^ (
seven_segment_c_rb
+ seven_segment_d_rb
+ seven_segment_f_rb
),
-- value 6 is character 6
_seven_common_mask_rb ^ (
seven_segment_c_rb
+ seven_segment_d_rb
+ seven_segment_e_rb
+ seven_segment_f_rb
),
-- value 7 is character 7
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
),
-- value 8 is character 8
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
+ seven_segment_d_rb
+ seven_segment_e_rb
+ seven_segment_f_rb
),
-- value 9 is character 9
_seven_common_mask_rb ^ (
seven_segment_b_rb
+ seven_segment_c_rb
+ seven_segment_d_rb
+ seven_segment_f_rb
)
}
function seven_from_digit_ra( byte in x ) return byte is
return seven_value_space_ra[x]
end function
function seven_from_digit_rb( byte in x ) return byte is
return seven_value_space_rb[x]
end function
T1CON_T1CKPS = 0b_10 -- предделитель, 2 бита 1:4
T1CON_TMR1CS = 0 -- тактирование от системной частоты
PIE1_TMR1IE = on-- разрешаем прерывание от TMR1
PIR1_TMR1IF = off-- сбрасываем флаг прерывания от TMR1
INTCON_PEIE = on-- разрешаем прерывания от периферии
T1CON_TMR1ON = on-- включаем таймер
INTCON_GIE = on-- включаем обработку прерываний
;10
;таймер тактируется от Fosc/4 : 4MHz/4 = 1 Mhz
;предделитель установлен на 1:4 : 1Mhz/4 = 250 kHz
;таймер - 16 бит : 250000/65536 = 3,81 Hz
;увеличение сч¸тчика за 1 прерывания : итоговая частота моргания 3,81 Hz
;увеличение сч¸тчика за 0,26 с.
;11
;таймер тактируется от Fosc/4 : 4MHz/4 = 1 Mhz
;предделитель установлен на 1:8 : 1Mhz/8 = 125 kHz
;таймер - 16 бит : 125000/65536 = 1.9 Hz
;увеличение сч¸тчика за 1 прерывания : итоговая частота моргания 1.9 Hz
;увеличение сч¸тчика за 0,53 с.
procedure TMR1_ISR is pragma interrupt
if
PIR1_TMR1IF then-- проверяем флаг нужного нам
прерывания
PIR1_TMR1IF = off-- сбрасываем флаг прерывания
i=i+1
if i==10 then
i=0
j=j+1
end if
if j==10 then
i=0
j=0
end if
end if
end procedure
forever loop
porta=seven_from_digit_ra(j)
portb=seven_from_digit_rb(j)
tr1 = on
tr2 = off
--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; ds18b20_convert() -- tell all ds18b20 devices to start conversion
-- note: the statement above starts the conversion and it can take
-- up to 750ms to complete.
-- If the sensor is in parasite mode, it is mandatory to leave the bus
-- during conversion. You could include a delay like:
; delay_1ms(750)
-- If you have other stuff to do, feel free to do so and create proper
-- timing in an other way.
--
-
- If the sensor is conventional powered, you don't have to keep the
-- bus idle and could read the sensor before conversion is complete.
-- The sensor will return the previous value.
; r = ds18b20_s_temp(temperature) -- read conversion result
; if (r) then
-- success, so print temperature
--print_string(device, str1) -- print string
;format_sword_dec(device, temperature, 4, 1) -- print temperature in xx.x format
--device = "C"
--device = " "
; round
; else
-- print fail message
-- print_string(device, str_err1)
;end if
; r = ds18b20_s_read_rom()
; if (r) then
-- read_rom successful, so print ID which is now stored in scratchpad
; for 8 using i loop
-- print_byte_hex(device, scratchpad[i])
; end loop
; else
-- print fail message
--print_string(device, str_err1)
; end if
--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
_usec_delay(5000)
porta=seven_from_digit_ra(i)
portb=seven_from_digit_rb(i)
tr1 = off
tr2 = on
_usec_delay(5000)
end loop