Вимірювання ваги руди по струму статора. Практика. Частина 2. Програмна реалізація МК

Остання частина з циклу «Вимірювання ваги корисних копалин». У даній статті буде показана програмна реалізація на МК.

Згадаймо основи даного методу вимірювання ваги корисних копалин по струму статора шахтної підйомної установки (ШПУ), обладнаної високовольтним асинхронним двигуном з фазним ротором.


Замість передмови

Так як реальний пристрій не проектувалося і не виготовлялася, то для симулювання цього процесу використовувався програмний комплекс Proteus. Даний симулятор підтримує безліч різних МК та списку підтримуваних їм вибиралася апаратна платформа для реалізації алгоритму і перевірки всього методу.

Передмова

Для зручності проведення випробувань при симулювання, вихідна схема протеусе, показана в першої частини, зазнала змін. Розглянемо зміни.

Перший лист схеми. Картинка кликабельна.

Зміни торкнулися розмноження сигналу напруги, розриву струмового ланцюга, введення індуктивної складової в ланцюг навантаження.

Другий лист схеми. Картинка кликабельна.

Використовується компонент ComPim, для зв'язку з ком портом системи. МК фірми Microchip. Вхідні сигнали з першого листа. Прилади (вольтметр, амперметр) для візуального контролю параметрів напруги і струму. Перемикачі, що використовуються для проведення автоматичного обчислення середньої точки каналів струму та напруги.

Введення

При написанні програми для МК PIC18F2580 використовувалася безкоштовна MpLab IDE X v 2.26, компілятор XC8 v1.20.
Під час розробки програми, довелося написати власні математичні функції:

  • витяг квадратного кореня з цілого 32-х бітного числа,
  • витяг квадратного кореня з числа з плаваючою точкою одинарної точності,
  • множення цілих беззнакових чисел 16 біт,
  • множення цілих знакових чисел 16 біт.


Стандартні функції, які компілятор використовує, не підходили в плані швидкодії, це стосується множення 16х16. А бібліотечної функції добування квадратного кореня з цілого 32-х бітного числа взагалі не знайшлося.

Також у проекті використовувалися користувальницькі типи змінних. Вони введені для зручності використання.

Користувальницькі типи змінних описані в хидере user_type.h

Ініціалізація МК

Ініціалізація МК винесена в окремий модуль у проекті. Проводиться згідно даташіту на МК. У хидере ініціалізації модуля включені конфігураційні біти (фьюзы). Для даних МК ці фьюзы можна зашити в прошивку, в .hex файл.

Ось хідер.

#include <xc.h>

/*
Установка конфігураційних бітів МК
*/
#pragma config IESO = OFF
#pragma config OSC = HSPLL //HS oscillator, PLL enabled (Clock Frequency = 4 x FOSC1)
#pragma config MCLRE = ON //MCLR pin enabled; RE3 input pin disabled
#pragma config XINST = OFF //Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
#pragma config PBADEN = OFF //PORTB<4:0> pins are configured as digital I/O on Reset

/*
Прототипи функцій ініціалізація периферії МК
*/
void INT_init(void);
void T0_init(void);
void ADC_init(void);
void USART_init(int BAUD);
void T2_init(void);
void PIC_init(void);


Ініціалізуємо необхідну периферію власною функцією.

Переривання в даному МК мають пріоритет. Рівнів всього два: високий і низький. Переривання від таймера 0, за яким відраховуємо тимчасові інтервали (семпли) для вимірювань сигналів напруги та струму, що має найвищий пріоритет, так як він критичний до часу, інші низький.

Обробка сигналів з АЦП

По перериванню від детектора, який заведений на зовнішнє переривання INT1, запускаємо таймер з відліком 200 мкс інтервалу. Переривання таймера, завантажуємо в нього встановлене значення для точного відліку, і виробляємо зчитування значень АЦП з обох каналів і виконуємо попередні обчислення.
if (Count_sample<SAMPLE){ //Якщо не досягли потрібного кількості вимірювань
ADCON0bits.GO_DONE=1; //Запускаємо перетворення АЦП
while(ADCON0bits.GO_DONE); //Чекаємо завершення
ADCON0bits.CHS0=0; //Підключаємо перший канал
I_adc.byte.HB=ADRESH;
I_adc.byte.LB=ADRESL; //Зчитуємо код АЦП
I_int=(INT)I_adc.Val-I_0.Val;
/*
* Так як програмні реалізації множення використовують алгоритм без
* використання апаратного помножувача, користуємося користувача
* функцією множення із залученням апаратного помножувача 8х8
* При симулювання програми вбудованим симулятором, швидкість
* виконання операції множення 16х16=32 біта зросла майже в чотири рази,
* кількість інструкцій зменшилася
* з 854 до 288 для беззнакового і до 302 для знакового твору,
* при чому користувацька функція виконується
* практично в одному і тому ж діапазоні інструкцій, незалежно від значення
* змінних входять у твір
*/
I_sum+=(SLONG)mul_int(I_int,I_int);
ADCON0bits.GO_DONE=1; //Запускаємо перетворення АЦП
while(ADCON0bits.GO_DONE); //Чекаємо завершення
ADCON0bits.CHS0=1; //Підключаємо другий канал до модуля АЦП
U_adc.byte.HB=ADRESH;
U_adc.byte.LB=ADRESL; //Зчитуємо код АЦП
U_int=(INT)U_adc.Val-U_0.Val;
U_sum+=(SLONG)mul_int(U_int,U_int);
P_act+=(SLONG)mul_sint(U_int,I_int);
Count_sample++;
} 
if (Count_sample>=SAMPLE){ //Завершуємо вимірювання, зупиняємо таймер
Count_sample=0;
Flag_izm=1;
T0CONbits.TMR0ON=0;
}


В основному циклі, по прапору Flag_izm виробляємо додаткові проміжні обчислення.
if (Flag_izm){ //Виробляємо розрахунки
Flag_izm=0;
if (Count_main_sample<MAIN_SAMPLE){
U_d+=(SLONG)U_sum;
U_sum=0;
I_d+=(SLONG)I_sum;
I_sum=0;
P_m+=(SLONG)P_act;
P_act=0;
Count_main_sample++;
}
}


Протокол ModBus RTU

У даній реалізації зв'язок з «зовнішнім» світом здійснюється з використанням USART МК, поверх даного інтерфейсу застосований промисловий протокол ModBus RTU. Реалізація даного протоколу задоволена проста і не ресурсоємна. Прийом повідомлень здійснюється у перериванні від приймача USART.
/*обробник переривання від приймача уарт*/
if (PIR1bits.RCIF){
if (RCSTAbits.FERR || RCSTAbits.OERR) { /*У разі помилки приймача*/
RCSTAbits.CREN=0; /*Відключаємо приймач для скидання помилки*/
RCSTAbits.CREN=1; /*Включаємо приймач для продовження роботи УАРТ*/
}
MODBUS.rxtimer=0; /*Скидаємо таймер кінця кадру прийому очереднего байт*/
if(MODBUS.rxcnt>(BUF_SZ-2)) MODBUS.rxcnt=0;
MODBUS.buffer[MODBUS.rxcnt++]=RCREG1; /*Записуємо черговий байт в масив даних ModBus*/
PIR1bits.RCIF=0; /*Скидаємо прапор переривання від приймача УАРТ*/
}


Обробка повідомлень від майстра відбувається в основному циклі, коли критичні до часу вимірювання закінчені.
if (Flag_izm){ //Виробляємо розрахунки
...
if (MODBUS.rxgap){ //Якщо прийшло повідомлення
MODBUS_SLAVE(&MODBUS); //обробляємо його
MODBUS.rxgap=0;
} 
}


Передача по USART організована не зовсім оптимальним, блокуючим способом.
/*
* Функція відправлення повідомлення майстру
*/
void TX_FRAME(UART_DATA *MODBUS)
{
RCSTAbits.CREN=0;
TXSTAbits.TXEN=1;
INTCONbits.GIEH=0; /* під час передачі відключимо переривання*/
INTCONbits.GIEL=0;
while(MODBUS->txcnt<MODBUS->txlen){
TXREG=MODBUS->buffer[MODBUS->txcnt++];
while(!PIR1bits.TXIF) NOP();
}
INTCONbits.GIEH=1;
INTCONbits.GIEL=1;
MODBUS->txlen=0;
RCSTAbits.CREN=1;
}


Заповнення таблиці регістрів ModBus

Протокол ModBus дозволяє розробнику обладнання самому визначати, які регістри в карті за який параметр будуть відповідати. Немає якихось жорстких правил у цій справі. Так що ми не будемо вигадувати щось складне і не розумне.

Почнемо з першого регістра (нульового). У нього покладемо значення діючої напруги в форматі Real, тобто значення буде займати два 16-ти бітових регістра Modbus. Далі значення струму, активної потужності, повної потужності, косинуса.
res_table[0].Val=U_real.word.LW; //Заповнюємо таблицю регістрів
res_table[1].Val=U_real.word.HW; //Модбас, для відповіді майстру
res_table[2].Val=I_real.word.LW;
res_table[3].Val=I_real.word.HW;
res_table[4].Val=P_real.word.LW;
res_table[5].Val=P_real.word.HW;
res_table[6].Val=P_pol.word.LW;
res_table[7].Val=P_pol.word.HW;
res_table[8].Val=Cos_p.word.LW;
res_table[9].Val=Cos_p.word.HW;

Тепер при запиті майстра значень даних регістрів, пристрій відповісти цілком адекватними даними.

Для відображення даних від пристрою, на даному етапі, скористаємося OPC сервером. Його внутрішніх інструментів достатньо для відображення даних, запису значень в регістри і т. д.

Автоматичне визначення середньої точки каналів і розрахунок коефіцієнтів

Для проведення вимірювань, нам необхідно обчислювати середню точку синусоїди сигналів напруги та струму. В даному випадку, ми будемо використовувати алгоритм, розписаний вминулій статті.

Для автоматичного обчислення АЦП0 каналів, необхідно зняти з них корисний сигнал, тобто розірвати струмовий петлю, в яку включений датчик струму ACS712 і підключити на вхід напруги середню точку з ОУ. Далі алгоритм, зробить обчислення середньоквадратичного значення сигналу, і по команді від майстра, ми обчислені значення занесемо в АЦП0 для кожного каналу і запишемо ці значення в EEPROM. Після цього, підключимо досліджувані сигнали напруги та струму.
if (MODBUS.write){
if (res_table[10].Val==1){ //Команда на автоматичне
U_0.Val=(WORD)U_real.Val; //обчислення АЦП0
I_0.Val=(WORD)I_real.Val;
eeprom_write(0,U_0.byte.HB); //Записуємо в еепром значення
eeprom_write(1,U_0.byte.LB); //АЦП0 по каналах
eeprom_write(2,I_0.byte.HB);
eeprom_write(3,I_0.byte.LB);
}
}

Для обчислення коефіцієнтів скористаємося наступним порядком дій. Після обчислення середньої точки каналів, підключення реальних сигналів на аналогові входи, алгоритм обчислює середньоквадратичне значення напруги і струму в одиницях АЦП. Для переведення їх у фізичні величини необхідно виміряти дані сигнали приладами, вольтметром і амперметром. Виміряні приладами значення записуємо в потрібні регістри Модбас, і по команді від майстра виробляємо обчислення коефіцієнтів. Для зменшення довжини посилки Модбас, в даній реалізації, значення з приладів переводиться до целочисленному значенням шляхом множення значення напруги на 10, а значення струму на 100. Отримані дані записуються в регістри і по команді від майстра проводиться розрахунок коефіцієнтів. Розраховані коефіцієнти записуються в EEPROM.
if (MODBUS.write){
if (res_table[10].Val==2){ //Команда на обчислення коефіцієнтів
K_u.Val=U_real.Val/res_table[11].Val; //струму і напруги
K_u.Val*=10.0;
K_i.Val=I_real.Val/res_table[12].Val;
K_i.Val*=100.0;
eeprom_write(4,K_u.byte.MB); //Записуємо коефіцієнти
eeprom_write(5,K_u.byte.UB);
eeprom_write(6,K_u.byte.HB);
eeprom_write(7,K_u.byte.LB);
eeprom_write(8,K_i.byte.MB);
eeprom_write(9,K_i.byte.UB);
eeprom_write(10,K_i.byte.HB);
eeprom_write(11,K_i.byte.LB);
}
res_table[10].Val=0;
MODBUS.write=0;
}


Розрахунок ваги

Вага руди можна вираховувати безпосередньо з формули, наведеної в першої частини оповіді.



Де:
  • F0 – сила, що розвивається двигуном при підйомі порожнього судини,
  • F – сила, виміряна при підйомі завантаженого судини,
  • g – прискорення вільного падіння точки зважування.


У даній реалізації вимірювання маси не проводиться, так як симулирование в Протеусе не передбачає таку можливість.
Симуляція в протеусе дозволяє зрозуміти життєздатність основної ідеї: «Вимірювання ваги руди під час транспортування в підйомному посудині по струму статора».

Архів з проектом в MpLab X і файлом проекту протеуса перебуває тут.

Відео, наочно показує обробку сигналів напруги та струму, обчислення активної потужності, косинуса фі і повної потужності показано нижче.



Висновок

Вимірювання ваги видобутих корисних копалин у промисловості має велике значення в технологічному обліку, оцінки ефективності виконуваних робіт і т. д.

Для вимірювання маси руди використовується багато різних видів і типів вагових пристроїв.

В даному циклі статей була розглянута можливість вимірювання ваги руди, по вимірюванню розвиваючого моменту приводного двигуна ШПУ під час транспортування вантажу в підйомному посудині. Даний спосіб використовується в ШПУ оснащеними двигунами постійного струму, де обчислення маси проводиться за струмом якоря при постійному збудженні.

p.s.

Так як видобуток корисних копалин у світі виробляється у великих обсягах, і передумов на зниження немає, то цей спосіб виміру ваги руди для технологічного обліку має право на життя. І може в недалекому майбутньому ми побачимо промислові пристрої для вимірювання маси вантажу в підйомному посудині, засновані на цьому принципі.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.