IPB

Здравствуйте, гость ( Вход | Регистрация )

 Правила форума Правила форума
Роторный компрессометр своими руками
Рейтинг 5 V
 
vl-alexander
сообщение 26.7.2013, 3:44
Сообщение #1


GOLD
************

Группа: Пользователи
Сообщений: 1604
Регистрация: 9.1.2011
Из: vl
Пользователь №: 4086



Для изготовления нам потребуется купить:
  • Ноутбук
  • Датчик давления
  • Ардуина (arduino)

На первом пункте останавливаться не буду - нужен тот, у которого есть usb порт, а значит любой smile.gif


Датчик давления нужен с пределом измерения не ниже 10 кг^см2, но и не сильно большим, чтобы обеспечить приемлимую точность. Исполнение - трёх контактное, с питанием = 5вольт.
  • +5V
  • минус
  • сигнальный (выход)

Как правило такие датчики выдают линейный сигнал от 0.5 до 4.5 вольт, 0.5 при нулевом давлении, 4.5 - при максимальном.
Например такой: http://www.ebay.com/itm/Pressure-transduce...56c&vxp=mtr


Ардуина. Это плата для разработчиков на основе микроконтроллера atmega. Купить можно в ближайшем радио-магазине. Выбор моделей довольно огромен (http://arduino.cc/en/Main/Products) - подойдет любая 5-вольтовая. (есть 3.3 вольтовые исполнения - они нам не подходят)


Железная часть: вкручиваем датчик давления в свечное отверстие (понадобится выточить переходник у любого токаря). Подключаем датчик давления к ардуине: питание датчика на контакт 5V, землю на GND, сигнальный выход на A0.

Программная часть:
Скачиваем три программы:
Arduino IDE
Processing
Megalog Viewer

Все три программы платформо-независимые, можно работать из под винды, мака, линукса. Если немножно исхитриться, то даже под андроидом замер компрессии не сложно организовать.

Arduino IDE
Этой программой прошиваем нашу плату. процедура делается всего один раз. и в последующие замеры не понадобится. Открываем редактор, и в поле ввода кода вставляем это:
Код
char incByte;
boolean converting;
unsigned int samplesFrequency, adcValue;
unsigned long samplesInterval, previousMicros;

void setup() {
  // initialize the serial communication:
  Serial.begin(115200);
  converting = false;
  samplesFrequency = 500;
  samplesInterval = 1000000 / samplesFrequency;
}

void loop() {

  if (Serial.available() > 0){
    incByte = Serial.read();
    switch (incByte){
     case 's':
      converting = true;
      previousMicros = micros();
      break;
     case 'p':
      converting = false;
      break;
    }
  }

  if (converting && (micros() >= previousMicros + samplesInterval))
  {
    previousMicros += samplesInterval;
    adcValue = analogRead(A0);
    Serial.println (adcValue);
  }
}

Получается примерно так:
Прикрепленный файл  arduino.png ( 26.27 килобайт ) Кол-во скачиваний: 126

Подключаем плату к компу, в меню tools->board выбираем модель своей ардуины, в меню tools->serial port выбираем порт через который подключена ардуина, и нажимаем кнопку Upload. процесс занимает около 10 секунд. после этого наш компрессометр готов к работе, закрываем arduino ide и не открываем больше никогда smile.gif


Процесс замера следующим сообщением...
Перейти в начало страницы
 
+Цитировать сообщение
 
Начать новую тему
Ответов
pcdeath
сообщение 19.6.2014, 16:09
Сообщение #2


Новичок (<30 постов)
*

Группа: Пользователи
Сообщений: 12
Регистрация: 27.1.2014
Пользователь №: 5724



Отловлено несколько багов, связанных с крайне низком объёмом памяти у АТМеги и большим разбросом параметров кнопок на LCD Keypad.

Версия 0.14.
Главные изменения:
- Между пином 3 и землёй повешена кнопка калибровки.
- С пина 2 убрана кнопка выбора типа датчика - теперь тип переключается по нажатию "вверх-вниз" до замера
- При первом включении после заливки скетча обязательна калибровка кнопок LCD keypad, также калибровку можно выполнить, зажав кнопку калибровки при подаче питания на компрессометр.
- Мерить можно только одну секцию за один раз. датчик на аналоговом входе 1, можно менять.
- Замер останавливается через заданный таймаут (по умолчанию 30 секунд), а не по нажатию кнопки.

Просьба оттестировать и сообщить, если будут баги.
Модеров прошу потереть старый пост, чтоб не было проблем с использованием старого скетча..

Код
// Компрессометр by PCDeath  

char ver[6] = "v0.14";

/* Версия 0.14
Для Arduino Uno R3 с LCD keypad shield. На других платформах не проверялось.
Мерит обычные поршневые двигатели 4Т/2Т или РПД.

В связи с большим разбросом значений кнопок у разных производителей LCD keypad Shield добавлена
возможность калибровки кнопок.
Для калибровки необходимо прицепить тактовую кнопку между цифр.пином 3 и массой.
Датчик давления 5В, при атм.давлении возвращают 0,5В (102), при макс.давлении - 4,5В (922), погрешность не более +/-10%
Верхний предел давления регулируемый, можно использовать 2 различных типа датчиков,
в моём варианте 10,5 кгс/см2 и 14 кгс/см2.

Установлены 2 порога давления - 20% и 30% от показаний датчика, для чёткого разделения по секциям
Датчик подключается  к аналоговому входу Arduino, по умолчанию 1, можно менять.
Рекомендуется питать компрессометр от отдельного батарейного источника питания +8...+12В, во избежание помех и
ошибок из-за просадки напряжения при прокрутке двигателя стартером.


Управление:

Калибровка кнопок:
Если при включении нажата кнопка на цифр.пине 3, или ПО только что залито в контроллер, компрессометр переходит в режим калибровки.
При калибровке требуется нажать кнопку, которая запрошена на экране, затем  нажать кнопку калибровки.
После записи значений на экране появится приглашение отпустить кнопку калибровки.
Отпускаем сначала кнопку калибровки, затем - кнопку на keypad shield, которую откалибровали, и переходим к калибровке следующей кнопки.
По окончании калибровки требуется перезагрузить компрессометр

До замера:
"ВВЕРХ"  переходит к типу датчика 2
"ВНИЗ"   переходит к типу датчика 1
"ВПРАВО" переводит к следующему типу измерения
"ВЛЕВО"  переводит к предыдущему типу измерения


По нажатию кнопки "SELECT" стартует процесс измерения, останавливается через заданное время.
При старте происходит десятикратный опрос датчиков с интервалом в 50 мс.
Если показания на входе имеют погрешность более 10% от заявленного значения,
(датчик отсутствует или замкнут), на экран выводится предупреждение с указанием, в какую сторону погрешность

Во время роторного замера на экране сырые значения на аналоговом входе для всех камер.

Во время поршневого замера на экране сырые значения.

После роторного замера:
"ВВЕРХ"  показывает скорректированные значения
"ВНИЗ"   возвращается к истинным значениям

Если  хотя бы у одной из камер давление ниже порога или обороты двигателя слишком низкие
- выдаётся предупреждение о низких оборотах или вылете секции.

После поршневого замера на кнопки не реагирует.

Если во время замера было достигнуто предельное давление, на которое рассчитан датчик, то при отображении
результатов поршневого или роторного замера без коррекции информация об этом выводится на экран.
При отображении результатов роторного замера с коррекцией полученные значения приводятся к эталонным оборотам

Приятного использования.
PCDeath

P.S.
Если захотите поблагодарить создателя, это можно сделать:
1. Добрым словом где-нибудь на форумах
2. Запчастями от РПД ВАЗа и RX-7
3. Деньгами на QIWI-кошелёк +79053834132

Коммерческое распространение кода без согласования с автором запрещено
*/

/**********************************************************************
Четыре параметра ниже требуется поправить под используемые Вами датчики
***********************************************************************/

int MAX_SENS1   = 105;               // Макс.показания датчика 1 типа в кгс/см2 * 10
int MAX_SENS2   = 140;               // Макс.показания датчика 2 типа в кгс/см2 * 10
byte TRESHOLD1  = 20;                // Порог 1 в процентах от диапазона датчика. Рекомендуется не менее 2 атм.
// При падении давления ниже порога 1 компрессометр считает замер камеры завершённым.
byte TRESHOLD2  = 30;                // Порог 2 в процентах от диапазона датчика. Рекомендуется не менее 1,5 от порога 1.
// При возрастании давления выше порога 2 компрессометр начнёт замер следующей камеры.

/*********************************************************************
Всё, что дальше, менять не стоит, если Вы не знаете точно, что делаете
**********************************************************************/
int MINS        = 102;               // Показания датчика на аналоговом входе при атмосферном (нулевом) давлении
int MAXS        = 922;               // Показания датчика на аналоговом входе при макс.давлении
byte MODE       = 0;                 // Режим работы. 0 - роторный, 1 - поршневой 4Т, 2 - поршневой 2Т
int CORRPM      = 250;               // Обороты, к которым приводится компрессия при коррекции
int MINRPM      = 170;               // Мин.допустимые для измерения обороты, не менее 2/3 от CORRPM
byte Z_FIRST    = 6;                 // Оборот, с которого начинается подсчёт RPM
byte Z_LAST     = 9;                 // Оборот, на котором заканчивается подсчёт RPM, не менее Z_FIRST + 3, не более Z_FIRST + 15
byte TIMER      = 2;                 // Периодичность замера в миллисекундах, не более 30.
byte TIMEOUT    = 30;                // Время, отведённое на замер после нажатия SELECT
#define SENSPIN   1                  // Аналоговый пин, на котором висит датчик
#define btnCAL    3                  // Цифровой пин, на котором висит кнопка калибровки

/********************************
БОЛЬШЕ НАСТРАИВАТЬ НИЧЕГО НЕ НАДО
********************************/


/*******************************
      ОБЪЯВЛЯЕМ ПЕРЕМЕННЫЕ
*******************************/


int  CALIBRE,                        // Для калибровки "нуля" датчика и установки порогов измерения
     TRESHLOW, TRESHHIGH,            // Для вычисления пороговых значений
     KGSCOMPR[3],                    // Итоговые значения компрессии, приведённые к кгс/см2 * 10
     RPM,                            // Частота вращения вала.
     CORRVAL,                        // Значение множителя коррекции
     bUP, bDN, bLT, bRT, bSL;        // Переменные для значений кнопок

byte i,                              // Счётчики для калибровки датчиков
     ERRORCODE,                      // Коды ошибок    
     BTN[6];                         // Массив для калибровки кнопок

boolean START, CORR, RPMCOUNT,       // Флаги старта, коррекции, подсчёта оборотов
        ERR, OUT,                    // Флаг ошибки датчика, флаг вывода на экран
        MAX[3];                      // Массив флагов информирования о достижении предельного давления

volatile int DIGCOMPR[3],            // Максимальные значения компрессии, сырые
             CURRCNT, Z_TMP, CNT[16];// Счётчик "тиков" таймера и массив для расчёта оборотов

volatile byte CH, Z;                 // Номер камеры для расчётов, номер оборота
                                

volatile boolean STOP, UP;           // Флаги остановки и движения к ВМТ
                

int MAX_SENS        = MAX_SENS1;                          // Устанавливаем начальное значение в тип 1
unsigned int T_OUT  = TIMEOUT / TIMER * 1000;             // Счётчик "тиков" для таймаута замера
unsigned int FREQ   = 2000 * TIMER;                       // Предельное значение для таймера. 1 мсек = 2000 тактов при делителе /8
unsigned int MAXCNT = 60000 / TIMER / MINRPM;             // Максимальное зачение счётчика для мин.оборотов
long DIVRPM         = 60000 / TIMER * (Z_LAST - Z_FIRST); // Делитель для подсчёта RPM.


/********************************************
ЦКПЛЯЕМ БИБЛИОТЕКИ И УЧИМ РАБОТАТЬ С КНОПКАМИ
********************************************/


#include <EEPROM.h>                                      // Прицепляем EEPROM для калибровки кнопок

#include <LiquidCrystal.h>                               // Прицепляем LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
byte lcd_key    = 0;
int adc_key_in  = 0;
#define btnNONE   0
#define btnSELECT 1
#define btnLEFT   2
#define btnUP     3
#define btnDOWN   4
#define btnRIGHT  5

// Обработка кнопок
int read_LCD_buttons()
{
adc_key_in = analogRead(0);         // Читаем значение нопок.
if (adc_key_in > bSL +10 )  return btnNONE;
if (adc_key_in < bRT)  return btnRIGHT;
if (adc_key_in < bUP)  return btnUP;
if (adc_key_in < bDN)  return btnDOWN;
if (adc_key_in < bLT)  return btnLEFT;
if (adc_key_in < bSL)  return btnSELECT;  
return btnNONE;                    // Если "всё не так" - считаем. что никакая кнопка не нажата.
}




void setup() {
  lcd.begin(16, 2);                          // Запускаем библиотеку LCD
  ERR = 1;                                   // Ставим датчику признак высокого уровня на входе
  
/******************************************
     РИСУЕМ СПЛЕШ-СКРИН С ВЫВОДОМ ВЕРСИИ
******************************************/

  lcd.setCursor(0,0);                        
  lcd.print(" ROTARY C-METER ");            
  lcd.setCursor(0,1);                        
  lcd.print("      BY PCDeath");            
  lcd.setCursor(0,1);                        
  lcd.print(ver);            
  delay (3000);

/*****************************************
НАСТРАИВАЕМ ТАЙМЕР НА НАЧАЛЬНЫЕ ЗНАЧЕНИЯ
*****************************************/

  TCCR1A  = 0; TIMSK1 = 0;                    // Сбрасываем на всякий эти регистры
  TCCR1B  = 0;                                // Мало ли что arduino IDE туда записало
  TCNT1   = 0;                                // Сбрасываем счетный регистр таймера 1
  OCR1A   = 0;                                // Отключаем таймер
  TCCR1B  |= ((1 << CS11) | (1 << WGM12));    // Настраиваем таймер на делитель /8, режим CTC

/*****************************************
     ОБРАБАТЫВАЕМ КАЛИБРОВОЧНУЮ КНОПКУ
*****************************************/

pinMode(btnCAL, INPUT);                      // Назначаем цифр.пину 3 режим входа
digitalWrite(btnCAL, HIGH);                  // Устанавливаем высокий уровень сигнала по умолчанию

if (digitalRead(btnCAL) == 0)                // Если нажата кнопка калибровок
  EEPROM.write(0, 0);                        // Снимаем флаг выполнения калибровки
  
BTN[0] = EEPROM.read(0);                     // Читаем значение флага калибровки
if (BTN[0] != 1) {                           // Если необходима калибровка,
  ERRORCODE = 5;                             // Выносим в обработку ошибки
  OUT = 1;                                   // Настраиваем флаг записи
  CURRCNT = analogRead(0);                   // Калибруем отсутствие нажатия
}
else {
  bSL = int(EEPROM.read(1) * 4);             // Читаем значение для кнопки "SELECT"  
  bLT = int(EEPROM.read(2) * 4);             // Читаем значение для кнопки "ВЛЕВО"
  bUP = int(EEPROM.read(3) * 4);             // Читаем значение для кнопки "ВВЕРХ"  
  bDN = int(EEPROM.read(4) * 4);             // Читаем значение для кнопки "ВНИЗ"
  bRT = int(EEPROM.read(5) * 4);             // Читаем значение для кнопки "ВПРАВО"
  
}
}


void loop() {
/***************************************
           ОБРАБОТКА ОШИБОК
***************************************/

if (ERRORCODE > 0){                      
  TIMSK1  &= (0 << OCIE1A);              // Запрещаем генерацию прерывания таймера 1
  OCR1A = 0;                             // И останавливаем таймер
  
  if (ERRORCODE == 5) CALIBER();         // Если требуется калибровка, входим в режим калибровки кнопок
  
  /************************************
    ОШИБКА НИЗКИХ ОБОРОТОВ ИЛИ ВЫЛЕТА
  ************************************/
  
  if (ERRORCODE == 3) {
  lcd.setCursor(0,0);      
  lcd.print("LOW RPM!");               // Выводим на экран ошибку
  lcd.setCursor(0,1);    
  lcd.print("OR CHAMBER  DOWN");  
  ERRORCODE ++;
  }
  
  /********************************************
    ОШИБКА ОТСУТСТВИЯ ИЛИ НЕИСПРАВНОСТИ ДАТЧИКА
  ********************************************/
  
  if (ERRORCODE == 1){                
  lcd.setCursor(0,0);      
  lcd.print(" SENSOR  ERROR! ");       // Выводим на экран ошибку
  lcd.setCursor(0,1);    
  if (ERR == 0)                        // Если собранные значения ниже заявленных более чем на 10%
        lcd.print(" VALUE TOO LOW  "); // Информируем о слишком низком значении
  else  lcd.print(" VALUE TOO HIGH "); // Иначе информируем о слишком высоком значении
  ERRORCODE ++;
  }
  return;
}


/***************************************************************
    ЕСЛИ НЕ ПРОИЗВОДИТСЯ ЗАМЕР КОМПРЕССИИ, ОБРАБАТЫВАЕМ КНОПКИ
***************************************************************/

if (START - STOP == 0 ) {                      
lcd_key = read_LCD_buttons();                   // Обрабатываем нажатие кнопки на LCD Shield
if (lcd_key > 0) BUTTON();                      // Если что-то нажато, идём в функцию обработки кнопок

}

/***************************************************
             ВЫВОД НА ЭКРАН ДО ЗАМЕРА
***************************************************/            

if (START == 0 && OUT == 0) {                  // Если замер не выполнялся и сброшен флаг вывода
  lcd.setCursor(0,0);      
  lcd.print("MAX =       ATMs");               // Отображаем верхний предел выбранного типа датчиков
  lcd.setCursor(6,0);      
  lcd.print((float)MAX_SENS / 10.0);
  if (MODE == 0) {
    lcd.setCursor(0,1);      
    lcd.print("ROTARY          ");             // Отображаем тип замера: роторный
  }
  else {
    lcd.setCursor(0,1);                        // Или поршневой
    lcd.print("PISTON         T");
    lcd.setCursor(14,1);
    if (MODE == 1) lcd.print("4");             // Четырёхтактный
    else           lcd.print("2");             // Или двухтактный
  }
  OUT  = 1;                                    // Ставим флаг вывода, чтоб не мерцал экран
  return;      
}

/*************************
    ВО ВРЕМЯ ЗАМЕРА
*************************/

if (START == 1 && STOP == 0) {                // Если выполняется замер

  lcd.begin(16,2);      
  lcd.print("WAIT     SECONDS");              // Выводим на экран обратный отсчёт
  lcd.setCursor(5,0);        
  lcd.print((T_OUT - CURRCNT) / (1000 / TIMER));
  lcd.setCursor(0,1);                         // и текущие сырые значения компрессии
  lcd.print(DIGCOMPR[0]);
  if (MODE == 0) {                            // Если режим роторный
    lcd.setCursor(6,1);                       // Выводим текущие сырые значения по камерам 2 и 3
    lcd.print(DIGCOMPR[1]);
    lcd.setCursor(12,1);      
    lcd.print(DIGCOMPR[2]);
   }
  delay(1000);
  return;
}

/****************************************************
                   ПОСЛЕ  ЗАМЕРА
****************************************************/



if (STOP == 1 && OUT == 0) {                                  // Если сброшен флаг вывода

  lcd.begin(16,2);                                            // Очищаем экран. begin поставлен, т.к.иногда во время замера вывод на экран из-за прерывания ломается
  
/****************************************************
            ОРГАНИЗУЕМ ПОДСЧЁТ ОБОРОТОВ
****************************************************/
  if (RPMCOUNT == 0) {                                        // Если подсчёт не выполнялся
     for (Z_TMP = 0; Z_TMP <= Z_LAST - Z_FIRST; Z_TMP ++) {   // Проверяем на низкие обороты и вылет секции
     if (CNT[Z_TMP+1] - CNT[Z_TMP] > MAXCNT && MODE == 0)     // Если частота обновления ниже минимального порога и режим замера - роторный
     ERRORCODE = 3;                                           // Ставим флаг низких оборотов
     }
     RPM = DIVRPM / (CNT[Z_LAST - Z_FIRST] - CNT[0]);         // Считаем обороты в минуту
     if (MODE == 1) RPM *= 2;                                 // Если тип замера поршневой 4-тактный, умножаем обороты на 2
     RPMCOUNT = 1;                                            // Ставим флаг выполнения подсчёта
  }

/************************************************
     ПОКАЗЫВАЕМ ОБОРОТЫ ИЛИ ИНФО О КОРРЕКЦИИ
************************************************/

  if (MODE == 0 && CORR == 1) {                               // Если мерился роторный двигатель и установлен флаг коррекции
    CORRVAL = 1000 + (CORRPM - RPM) * 3;                      // рассчитываем значение для множителя х 1000
    lcd.setCursor(9,0);                                       // Информируем о коррекции
    lcd.print("CORR");
    lcd.setCursor(13,0);        
    lcd.print(CORRPM);
  }
  else {
    CORRVAL = 1000;                                           // Иначе ставим множитель в единицу х 1000
    lcd.setCursor(9,0);                                       // И выводим обороты, при которых производился замер
    lcd.print("RPM=   ");
    lcd.setCursor(13,0);        
    lcd.print(RPM);
  }

/******************************************************
       ПЕРЕВОДИМ КОМПРЕССИЮ ИЗ ПОПУГАЕВ В КГС/СМ2
******************************************************/

  for (CH = 0; CH <= 2; CH ++) {                              // Для каждой камеры
    if (DIGCOMPR[CH] > MAXS + 3)                              // Если превышены макс.показания + погрешность
      MAX[CH] = 1;                                            // Ставим флаг достижения максимального порога давления
      KGSCOMPR[CH] =                                          // Мапим показания датчика из сырых в кгс/см2 х 10
    //    map((long)DIGCOMPR[CH] * CORRVAL / 1000, MINS, MAXS, 0, MAX_SENS);             // без учёта начальной калибровки
      map((long)DIGCOMPR[CH] * CORRVAL / 1000, CALIBRE, MAXS, 0, MAX_SENS);              // с учётом начальной калибровки
    }

/*****************************************************
        ПОКАЗЫВАЕМ НА ЭКРАН, ЧЕГО ТАМ НАМЕРИЛИ
*****************************************************/

  if (MODE == 0){                                              // Если режим роторный
    lcd.setCursor(0,0);      
    lcd.print("ROTARY");                                       // Выводим на экран тип замера
    for (CH = 0; CH <= 2; CH ++){                              // И итоговые значения компрессии по камерам
      lcd.setCursor(CH * 6,1);                                          
      if (MAX[CH] == 1 && CORR == 0)                           // Если нет флага коррекции и достигнут макс.порог измерения - информируем об этом
        lcd.print("MAX!");
      else lcd.print((float)KGSCOMPR[CH] / 10.0);
    }
  }
  else {                                                       // Если режим поршневой
    lcd.setCursor(0,0);      
    lcd.print("PISTON");                                       // Выводим на экран инфо о поршневом замере
    lcd.setCursor(0,1);                                        // И итоговые значения компрессии
    if (MAX[0] == 1) {                                         // Если достигнут макс.порог измерения - информируем об этом
      lcd.print("MAX! >");
      lcd.print((float)KGSCOMPR[0] / 10.0);
    }
    else lcd.print((float)KGSCOMPR[0] / 10.0);
  }
  OUT = 1;
}

}

/******************************************************
            ФУНКЦИЯ ОБРАОТКИ НАЖАТИЯ
******************************************************/
void BUTTON(){
  switch (lcd_key)                              // Производим действие, в зависимости от нажатой кнопки
  {
   case btnRIGHT:                               // Кнопка "ВПРАВО"
     {
      OUT  = 0;                                 // Сбрасываем флаг вывода для обновления экрана
      if (START == 0) {MODE ++;                 // Если замер не выполнялся, переключаем режим
        MODE = min(MODE, 2);                    // Ограничиваем номер режима
      }
     break;
     }
   case btnLEFT:                                // Кнопка "ВЛЕВО"
     {
      OUT  = 0;                                 // Сбрасываем флаг вывода для обновления экрана
      if (START == 0) {MODE --;                 // Если замер не выполнялся, переключаем режим
        if (MODE != 1) MODE = 0;                // Ограничиваем номер режима
      }
     break;
     }
   case btnUP:                                  // Кнопка "ВВЕРХ"
     {
      OUT  = 0;                                 // Сбрасываем флаг вывода для обновления экрана
      if (START == 0) MAX_SENS = MAX_SENS2;     // Переключаем на тип датчика 2
      if (STOP == 1 && MODE == 0) CORR = 1;     // Если роторный замер завершён, ставим флаг коррекции      
     break;
     }
   case btnDOWN:                                // Кнопка "ВНИЗ"
     {
      OUT  = 0;                                 // Сбрасываем флаг вывода для обновления экрана
      if (START == 0) MAX_SENS = MAX_SENS1;     // Переключаем на тип датчика 1
      if (STOP == 1 && MODE == 0) CORR = 0;     // Если роторный замер завершён, убираем флаг коррекции
     break;
     }
   case btnSELECT:                              // Кнопка "SELECT"
     {          
      if (START == 0){                          // Если замер остановлен
          START = 1;                            // Ставим флаг запуска
          OUT  = 0;                             // Сбрасываем флаг вывода для обновления экрана
          lcd.clear();                          // Очищаем экран
          for (i=0; i < 10; i++) {              // Проверяем датчики на отсутствие/замыкание/большую погрешность
              CALIBRE += analogRead(SENSPIN);   // С интервалом 50 мс 10 раз читаем показания
            delay(50);
          }
          if (CALIBRE > 11 * MINS ||
              CALIBRE < 9 * MINS) {             // Если отсутствует/неисправен датчик (погрешность более 10% от заявленной)
              ERRORCODE = 1;                    // Ставим флаги ошибок
              if (CALIBRE < 9 * MINS)           // Если показания ниже заявленных
              ERR = 0;                          // Ставим указатель на низкое значение
             }
          }
      if (ERRORCODE == 0) {                     // Если датчики опрошены успешно
         CALIBRE = analogRead(SENSPIN);         // Калибруем датчики - выставляем "0"
         TRESHLOW =  (long)CALIBRE * (100 + TRESHOLD1) / 100;    // Ставим порог падения давления
         TRESHHIGH = (long)CALIBRE * (100 + TRESHOLD2) / 100;    // Ставим порог роста давления
         delay(500);                           // Ждём 0,5 сек, чтоб точно отпустить кнопку
         OCR1A = FREQ;                         // И настраиваем таймер:
         TIMSK1  |= (1 << OCIE1A);             // Разрешаем генерацию прерывания таймера 1 по совпадению с регистром OCR1A
      }
     break;
     }
  }
  delay(500);
}

/******************************************************
            ФУНКЦИЯ КАЛИБРОВКИ КНОПОК
******************************************************/

void CALIBER(){
while (1 == 1){                              // Входим в бесконечный цикл
    if (digitalRead(btnCAL) == 0) {          // Если нажата кнопка калибровки
       lcd.setCursor(0,0);      
       lcd.print("RELEASE  CALIBER");        // Выводим на экран приглашение отпустить кнопку калибровки
       lcd.setCursor(0,1);
       lcd.print("     BUTTON     ");
       if (i <= 4 && OUT == 0) {             // Если значение калибровки ещё не снято
         i++;                                // Увеличиваем счётчик кнопки на единицу
         BTN[i] = analogRead(0) / 4 + 5;     // Пишем в переменную значение кнопки / 4, чтоб влезло в тип byte
         OUT = 1;                            // Ставим флаг записи значения кнопки
       }
       if (i > 4 && BTN[0] != 1) {           // Если все кнопки откалиброваны и значения ещё не записаны в EEPROM
          BTN[0] = 1;                        // Ставим флаг завершения калибровки
          for (CH = 0; CH <= 5; CH ++)       // Повторяем 6 раз
            EEPROM.write(CH, BTN[CH]);       // Пишем в EEPROM значения из массива
       }
    }
    else {                                   // Если кнопка калибровки не нажата
    delay(100);                              // Задержка для исключения дребезга кнопки
      if (i > 4) {                           // Если калибровка завершена
         lcd.setCursor(0,0);      
         lcd.print("   REBOOT THE   ");      // Выводим на экран приглашение к перезагрузке
         lcd.setCursor(0,1);
         lcd.print("     DEVICE     ");  
      }
      else {                                 // Если калибровка ещё не завершена
           lcd.setCursor(0,0);      
           lcd.print(" PRESS          ");    // Выводим на экран приглашение к нажатию кнопки на KEYPAD
           lcd.setCursor(0,1);      
           lcd.print("                    ");// Выводим на экран приглашение к нажатию кнопки на KEYPAD
           lcd.setCursor(8,0);
           if (i == 0) lcd.print("SELECT");  // Для каждой кнопки своя строка
           if (i == 1) lcd.print("LEFT");
           if (i == 2) lcd.print("UP");
           if (i == 3) lcd.print("DOWN");
           if (i == 4) lcd.print("RIGHT");
           if (analogRead(0) < CURRCNT - 10 ||
             analogRead(0) > CURRCNT + 10) {    // Если нажата кнопка на Keypad
             lcd.setCursor(0,1);
             lcd.print(" PRESS  CALIBER ");     // Выводим приглашение к нажатию кнопки калибровки
           }
           OUT = 0;
      }

    }
    delay(500);
  }
}





/*************************************************
    А ВОТ ЗДЕСЬ ТВОРИТСЯ ВСЁ САМОЕ ИНТЕРЕСНОЕ
*************************************************/

ISR(TIMER1_COMPA_vect) {                                // Обрабатываем прерывание по таймеру
CURRCNT ++;                                             // Увеличиваем значение текущего счётчика "тиков"

/************************
   ДЛЯ РАСЧЁТА ОБОРОТОВ
************************/
if (Z >= Z_FIRST && Z <= Z_LAST + 1){
    if(CNT[Z - Z_FIRST] == 0) {                         // Если счётчик оборотов в пределах измерений и измерение ещё не записано
     CNT[Z - Z_FIRST] = CURRCNT;                        // Присваиваем значение счётчика элементу массива
    }
}

/***************************
   ДЛЯ РАСЧЁТА КОМПРЕССИИ
***************************/
int TMP = analogRead(SENSPIN);                          // Читаем показания датчика
                                                        // и пишем во временную переменную
if (UP == 1) {                                          // Если установлен флаг движения к ВМТ
   if (TMP >= TRESHLOW) {                               //   Если временное значение больше нижнего порога (окончания замера)
      if (TMP > DIGCOMPR[CH])                           //     Если временное значение больше итогового
          DIGCOMPR[CH] = TMP;                           //       Пишем временное значение в итоговое
   }
   else UP = 0;                                         //   Иначе снимаем флаг движения к ВМТ
}

else {                                                  // Если флаг движения к ВМТ не установлен
     if (TMP >= TRESHHIGH) {                            //   Если текущее значение больше верхнего порога (начала замера следующей камеры)
        UP = 1;                                         //     Ставим флаг движения к ВМТ
        Z ++;                                           //     Прибавляем счётчик оборотов
        if (MODE == 0) CH ++;                           //     Если режим роторный, переходим к следующей камере
        if (CH > 2) CH = 0;                             //     Ходим по кругу камер
     }
}

/*****************************************
    ДЕЛАЕМ ВЫХОД ИЗ ЗАМЕРА ПО ТАЙМАУТУ
*****************************************/
if (CURRCNT > T_OUT) {                                  // Если вышло время замера
   TIMSK1  &= (0 << OCIE1A);                            // Запрещаем генерацию прерывания таймера 1
   OCR1A = 0;                                           // Останавливаем таймер
   STOP  = 1;                                           // Ставим флаг остановки
   }

}


Сообщение отредактировал pcdeath - 24.6.2014, 17:14
Перейти в начало страницы
 
+Цитировать сообщение

Сообщений в этой теме
- vl-alexander   Роторный компрессометр своими руками   26.7.2013, 3:44
- - vl-alexander   Для того чтобы фиксировать замер, и удобно его ана...   26.7.2013, 5:01
- - dennis_ex   Отличное решение. А я когда писал прогу для Ардуин...   26.7.2013, 6:07
|- - vl-alexander   Цитата(dennis_ex @ 26.7.2013, 14:07) Отли...   26.7.2013, 7:12
- - Unnamed   Супер статья! Датчик давления заказал, на днях...   26.7.2013, 9:42
- - dennis_ex   Да подойдет   26.7.2013, 9:51
- - VZuRa   Огонь! Сам не смог догадаться дальше покупки д...   26.7.2013, 10:48
|- - vl-alexander   Цитата(VZuRa @ 26.7.2013, 18:48) Вопрос-н...   26.7.2013, 10:59
|- - vl-alexander   Цитата(VZuRa @ 26.7.2013, 18:48) Чем може...   26.7.2013, 11:52
|- - vl-alexander   Цитата(vl-alexander @ 26.7.2013, 19...   5.12.2013, 7:57
- - Unnamed   Ну я заказал датчик с ebay по твоей ссылке, посмот...   26.7.2013, 12:10
|- - D-Man   В Москве можно штучно купить хороший промышленный,...   26.7.2013, 12:59
|- - dennis_ex   Цитата(Unnamed @ 26.7.2013, 13:10) Ну я з...   26.7.2013, 17:17
|- - Rotorlav   Цитата(dennis_ex @ 26.7.2013, 17:17) 3. С...   26.7.2013, 23:12
|- - dennis_ex   Цитата(Rotorlav @ 27.7.2013, 0:12) Только...   27.7.2013, 5:10
- - dennis_ex   У кого под виндой прога написанная в процессинге н...   4.8.2013, 7:13
- - dll   Дешевле арудины готовое решение (то что поставляет...   20.8.2013, 20:41
|- - vl-alexander   Цитата(dll @ 21.8.2013, 4:41) Дешевле ару...   21.8.2013, 3:41
|- - dll   Цитата(vl-alexander @ 21.8.2013, 4:4...   21.8.2013, 15:38
- - Unnamed   Хз где ты смотрел, в инэте они по 800-1200 рэ   21.8.2013, 16:21
- - Nooxyd   А есть нормальные заводские компрессометры? Со шта...   3.9.2013, 10:20
|- - dennis_ex   Цитата(Nooxyd @ 3.9.2013, 11:20) А есть н...   3.9.2013, 12:25
|- - Rotorlav   Цитата(Nooxyd @ 3.9.2013, 10:20) А есть н...   4.9.2013, 6:02
|- - Nooxyd   Цитата(Rotorlav @ 4.9.2013, 11:02) Если н...   4.9.2013, 11:27
|- - Rotorlav   Цитата(Nooxyd @ 4.9.2013, 11:27) Спасибо)...   6.9.2013, 7:21
- - VZuRa   Остался неосвещенным один вопрос- как сделать пере...   14.10.2013, 23:32
- - vl-alexander   Прикольная идея только вкручивать доработанную ...   15.10.2013, 5:03
- - VZuRa   У меня тока новые лежат, за 3 года так и не выката...   15.10.2013, 8:22
- - VZuRa   Взорвался мозг. Собрали, запустили - датчик видит ...   16.10.2013, 3:14
|- - Rotorlav   Хэ зэ, у меня всегда надо сначала оттарировать т.е...   16.10.2013, 6:13
- - VZuRa   Интересный нюанс. Если мерить компрессию на лидинг...   17.10.2013, 18:37
|- - vl-alexander   Цитата(VZuRa @ 18.10.2013, 2:37) Интересн...   18.10.2013, 3:24
- - VZuRa   По градациям пока не смотрел, занимался практическ...   18.10.2013, 9:38
- - vl-alexander   По-моему не стоит искать зависимость там где её не...   18.10.2013, 16:26
- - sashamd   настройка это главное что бы ротор жил))) поменял ...   18.10.2013, 17:13
- - pcdeath   Всем доброго дня. Специально для этого компрессом...   15.4.2014, 14:35
|- - dennis_ex   Прикольно и правда носиться с буком в гараже не вс...   15.4.2014, 16:31
- - vl-alexander   pcdeath, отличная работа! Тоже посещали подобн...   16.4.2014, 8:20
|- - John   Цитата(vl-alexander @ 16.4.2014, 9:2...   16.4.2014, 9:19
- - dennis_ex   Предложение - предлагаю добавить при включении, по...   16.4.2014, 8:50
|- - vl-alexander   Цитата(dennis_ex @ 16.4.2014, 16:50) Так ...   16.4.2014, 10:26
- - pcdeath   Цитата(vl-alexander @ 16.4.2014, 9:2...   16.4.2014, 10:45
|- - vl-alexander   Цитата(pcdeath @ 16.4.2014, 18:45) Статор...   18.4.2014, 4:57
|- - John   Цитата(vl-alexander @ 18.4.2014, 5:5...   18.4.2014, 6:21
- - pcdeath   ОК, благодарю. Буду знать, что искать. Если у ког...   18.4.2014, 20:07
- - pcdeath   Версия 0.11. Изменения: 1. Поправил баг с плавающ...   30.4.2014, 13:11
- - dennis_ex   Попробуем. Первая версия рисовала погоду на марсе:...   30.4.2014, 17:44
|- - pcdeath   Цитата(dennis_ex @ 30.4.2014, 18:44) Попр...   2.5.2014, 12:14
- - dennis_ex   Да надо отладить. Правда сейчас ротор замерить нет...   2.5.2014, 18:03
- - pcdeath   Отловлено несколько багов, связанных с крайне низк...   19.6.2014, 16:09
- - Alarmistt   Приветствую! Собрал все как описано в первом п...   1.7.2014, 20:26
- - VxD   добрый день. сижу, читаю про копрессометр на ардуи...   12.7.2014, 11:39
- - Alarmistt   Приветствую! Собрал схему из первого поста это...   5.8.2014, 19:23
|- - vl-alexander   Цитата(Alarmistt @ 6.8.2014, 3:23) Привет...   6.8.2014, 2:17
- - Alarmistt   Приветствую! Пробный замер выполнен. Результа...   13.8.2014, 21:55
- - Alarmistt   Приветствую! Провел на днях замер на авто, и в...   8.9.2014, 9:30
|- - FIL   Цитата(Alarmistt @ 8.9.2014, 14:30) Приве...   8.9.2014, 11:15
- - Alarmistt   Надеюсь за флуд не сочтут. Подключение к OBDII кит...   8.9.2014, 12:49
- - vl-alexander   Цитата(Alarmistt @ 8.9.2014, 17:30) время...   9.9.2014, 4:25
|- - dennis_ex   Цитата(vl-alexander @ 9.9.2014, 5:25...   9.9.2014, 6:27
- - Alarmistt   Всем спасибо за разъяснения! По ссылке результ...   9.9.2014, 12:40
|- - vl-alexander   Цитата(Alarmistt @ 9.9.2014, 20:40) P.s. ...   10.9.2014, 2:47
|- - FIL   Цитата(Alarmistt @ 9.9.2014, 17:40) Всем ...   10.9.2014, 4:47
- - Rotor   Я конечно не "самый умный")) может есть ...   17.9.2014, 1:57
- - Piga   да мне тоже интересно, может есть тут кто смог бы ...   26.11.2014, 20:13
- - vl-alexander   Они украли мою идею Собственно, в скором времени...   8.12.2014, 7:03
|- - dennis_ex   Цитата(vl-alexander @ 8.12.2014, 8:0...   8.12.2014, 7:50
||- - vl-alexander   Цитата(dennis_ex @ 8.12.2014, 15:50) А кт...   8.12.2014, 9:29
||- - FIL   Цитата(vl-alexander @ 8.12.2014, 14...   8.12.2014, 11:30
|- - cherepnev   Цитата(vl-alexander @ 8.12.2014, 14...   8.12.2014, 8:14
- - dennis_ex   2000-3000 руб. Фантастика если у них старая модель...   8.12.2014, 11:51
- - vl-alexander   Цитата(FIL @ 8.12.2014, 19:30) а как быть...   8.12.2014, 12:22
- - vl-alexander   Первые шпионские фотки Прототип почти готов. З...   23.12.2014, 15:18
|- - fastmak   Цитата(vl-alexander @ 23.12.2014, 15...   25.12.2014, 23:30
|- - Rotor   Цитата(fastmak @ 26.12.2014, 0:30) Когда ...   27.12.2014, 12:54
|- - vl-alexander   Цитата(Rotor @ 27.12.2014, 20:54) А уже в...   28.12.2014, 16:35
|- - cherepnev   Цитата(vl-alexander @ 28.12.2014, 23...   29.12.2014, 2:22
- - Unnamed   Даешь версию софта под Windowsphone ))))   23.12.2014, 15:56
|- - vl-alexander   Цитата(Unnamed @ 23.12.2014, 23:56) Даешь...   23.12.2014, 16:07
- - Piga   что в телефон нужно для андройда?? для такого дева...   23.12.2014, 17:04
|- - vl-alexander   Цитата(Piga @ 24.12.2014, 1:04) что в тел...   24.12.2014, 1:13
- - Unnamed   Цитатаага, а ещё под symbian и j2me Не, под них не...   23.12.2014, 17:31
- - vl-alexander   http://www.youtube.com/watch?v=6jbe30eB2-c   24.12.2014, 16:16
|- - John   Цитата(vl-alexander @ 24.12.2014, 17...   24.12.2014, 16:43
|- - cherepnev   Цитата(vl-alexander @ 24.12.2014, 23...   25.12.2014, 7:01
- - dll   Дорогие мои, а есть у кого в москве компрессометр?...   12.1.2015, 8:55
|- - John   Цитата(dll @ 12.1.2015, 9:55) Дорогие мои...   12.1.2015, 14:53
|- - dll   Цитата(John @ 12.1.2015, 15:53) Есть в По...   12.1.2015, 14:56
|- - John   Цитата(dll @ 12.1.2015, 15:56) Ммм, дашь ...   12.1.2015, 15:10
|- - dll   Цитата(John @ 12.1.2015, 16:10) Можно. Со...   12.1.2015, 15:20
- - Rotor   Как обстоят дела?)   5.2.2015, 1:59
- - Piga   Как успехи с компрессометром ? Никто больше не соб...   5.2.2015, 13:09
- - vl-alexander   Скоро-скоро всё будет. Просто желание сделать вещь...   5.2.2015, 19:36
|- - Rotor   Цитата(vl-alexander @ 5.2.2015, 20:3...   6.2.2015, 0:18
- - Piga   Доооо, ждём   6.2.2015, 14:45
- - Baron4eg   Приветствую, тоже хочу данный девайс. Запишите м...   14.2.2015, 1:59
- - Alarmistt   Приветствую! Сделал несколько замеров по схем...   6.4.2015, 13:42
|- - vl-alexander   Цитата(Alarmistt @ 6.4.2015, 21:42) Приве...   6.4.2015, 16:33
- - dennis_ex   Скорее всего при повороте ключа в камере создается...   6.4.2015, 15:44
- - Alarmistt   Картинка в предыдущем сообщении для примера. Вот ф...   6.4.2015, 18:04
2 страниц V   1 2 >


Ответить в данную темуНачать новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



RSS Текстовая версия Сейчас: 8.6.2024, 9:21