Срабатывание пищалки при загорании одного из нескольких светодиодов

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот продолжение проектирование программы.Но там еще куча нюансов полезло. Так например надо сбрасывать кнопкой не только звук зуммера, но и взод датчиков сеялки

/*зерносеялка*/
unsigned long mill; // переменная под millis()
typedef (*pDo)();// тип - обработчик
//--------------------------------
// класс зуммер
class Cl_Zoomer {
  protected:
    byte pin; /*пин зуммера*/
  public:
    /*конструктор*/
    Cl_Zoomer(byte p): pin(p) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
    /*вкл*/
    void ON() {}
    /*выкл*/
    void OFF() {}
};
//------------------------------
// класс сопло сеялки
class Cl_DrillNozzle {
  protected:
    pDo Do;
    byte pin1, pin2, pin3; /*пины красный,желтой,датчика*/
  public:
    /*конструктор*/
    Cl_DrillNozzle(byte p1, byte p2, byte p3, pDo D)
      : pin1(p1), pin2(p2), pin3(p3), Do(D) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//-----------------------------------
// класс кнопкa
class Cl_Btn {
  protected:
    byte pin; /*кнопки*/
    pDo Do;
  public:
    /*конструктор*/
    Cl_Btn(byte p, pDo D)
      : pin(p), Do(D) {}
    /*инициализация*/
    void init() {}
    /*работа*/
    void run() {}
};
//---Компоновка-----------------------------
Cl_Zoomer Zoomer(/*пин зуммера*/10);
void DoDR() {
  Zoomer.ON();
}
Cl_DrillNozzle DR1(/*пин красный*/6,/*пин желтый*/A0,/*датчик*/2,/*обработчик аварии*/& DoDR);
Cl_DrillNozzle DR2(/*пин красный*/7,/*пин желтый*/A1,/*датчик*/3,/*обработчик аварии*/& DoDR);
Cl_DrillNozzle DR3(/*пин красный*/8,/*пин желтый*/A2,/*датчик*/4,/*обработчик аварии*/& DoDR);
Cl_DrillNozzle DR4(/*пин красный*/9,/*пин желтый*/A3,/*датчик*/5,/*обработчик аварии*/& DoDR);
void DoBtn1() {
  Zoomer.OFF();
}
Cl_Btn Btn1(/*пин кнопки*/11,/**/&DoBtn1);
//---main-----------------------------
void setup() {
  Zoomer.init();
  DR1.init();
  DR2.init();
  DR3.init();
  DR4.init();
  Btn1.init();
}
void loop() {
  mill = millis();
  Zoomer.run();
  DR1.run();
  DR2.run();
  DR3.run();
  DR4.run();
  Btn1.run();
}
/*Скетч использует 630 байт (2%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 37 байт (1%) динамической памяти, оставляя 2011 байт для локальных переменных. Максимум: 2048 байт.
*/

И это я еще не начал писать код и просто вырабатываю структуру программы и уточняю ТЗ

ПС: А еще для решения задачи банально не хватает пинов. И надо переходить на Мегу или аппаратно расширять количество ног. В последнем случае придется писать класс посредник.

Sbalakirev
Offline
Зарегистрирован: 23.12.2017

Доброго вечера! 

Про экран, табло и прочее думал. Если бы лично я сеял, то без раздумий бы сделал выход на LSD экран, или табо. Но трактором я уже не кправляю, а нанимаю тракториста. В большинстве своем они уже пожилого возраста, плохо видят близко, да и тяжеловато им электроника дается. Поэтому решил сделать все просто и сердито. Тракторист сеет, у него все внимаение вперед на гон, запищал зуммер!!!!!!, он глянул на светодиод и порядковый номер - остановился для устранения причин.

Откулючать зуммер я не намерен, он будет пищать - пока проблема не будет устранена или не выключена система. Единственное подумываю о регуляторе громкости. 

Зная психологию трактористов - это сделано специально, так как если он попищит да перестанет, тракторист будет устранять проблему только на конце гона или на заправке семенами - проходили через это.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Оффтоп

Sbalakirev пишет:

LSD экран

Такой можно программировать? Я думал это случайный неконтролируемый процесс

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Sbalakirev пишет:
Откулючать зуммер я не намерен, он будет пищать - пока проблема не будет устранена или не выключена система. Единственное подумываю о регуляторе громкости.
 

Вот попробуем представить . Вы тракторист. Запищало. Тракторист глянул.Остановил трактор. Влез, прочистил. Но как система узнает что там чисто. И как тракторист узнает, система узнала, что там чисто.  Где находится система. Ведь  место тракториста и сопло на чистке это разные места. Вы думаете что пожилой тракторист будет бегать в кабину и на место чистки . Опять же если трактор стоит, он не сеит. Но система работает. А зерна нет. Значит система думает, что все сопла забиты. А раз все сопла забиты, то звенеть и чистить сопла. 

 А так человек почистил, зумер звенит,сел завел трактор , поехал, сделал сброс системы . И дальше сеит.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

qwone пишет:

 А так человек почистил, зумер звенит,сел завел трактор , поехал, сделал сброс системы . И дальше сеит.

В предложеном мной коде сброс происходит автоматически - поехал - семена покатились и все потухло, система вошла в рабочее состояние!

Sbalakirev
Offline
Зарегистрирован: 23.12.2017

Вот мой комплекс - один в один.

Модуль будет находится по правую руку механизатора. Расстояние от модуля до датчиков примерно 3 метра. Модуль прекрасно виден через заднее стекло от датчиков. Да и в любом месте его можо воткнуть, вся кабина прекрасно наблюдается снаружи. В механичеких сеялках привод высева идет от колеса сеялки. Зерно будет сыпаться только во время движения. Для визуального контроля сыпи семян, сеялка приподымается гидравликой в транспортное положение, при полном поднятии на 30 см от земли приводные колеса оторваны от земли, тракторист рукой делает оборот колеса и все прекрасно видно где сыпится где нет.

И так я тракторист .

1 вариант забился семяпровод, загорелся красный светодиод. Запищало. Остановился. Сеялка перестала работать, зерно не сыпется. Загорелось дополнительно 16 желтых светодиодов красный горит один. Я подымаю гидравликой сеялку, так как засор 90%% в лапе. Я устранил причину затора, зерно высыпалось из семяпровода на землю - датчик не получает сигнал, красный погас.Зуммер пищит, так как горят желтые.Моем руки, Садимся в кабину -  тронулся, пошел поток зерна, желтые светодиоды сразу гаснут после первого зернышка. Зуммер затух. В моей криворуко чайниковской версии алгоритма на эмуляторе все так и происходит. При желании можно крутануть приводное колесо блок сразу весь затухнет.

2 вариант затор в бункере перед высевающим аппаратом. Зерно перестало сыпаться через датчик, загорелся желтый имнно того высевающего аппарата где нет потока семян, запищал зуммер. Запомнил номер высевающего. СТоп машина! Устраняем причину засора в нужном высевающем. Прокручиваем приводное колесо, смотрим на блок, можно и слушать, если открыть боковое окно. ВИзуально наблюдаем сыпь семян в нужном отсеке, отсутствие сигнала на блоке. Моем руки, садимя в кабину и сеем дальше. 

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну где то так. Скетч не проверял. Может где-то что надо подправить.

/*зерносеялка*/
unsigned long mill; // переменная под millis()
//--------------------------------
// класс зуммер
class Cl_Zoomer {
  protected:
    byte pin; /*пин зуммера*/
  public:
    /*конструктор*/
    Cl_Zoomer(byte p): pin(p) {}
    /*инициализация*/
    void init() {}
    /*вкл*/
    void ON() {
      tone(pin, 262);
    }
    /*выкл*/
    void OFF() {
      noTone(pin);
    }
    /*работа*/
    void run() {}
};
//------------------------------
// класс сопло сеялки
const unsigned long MINTIMEHIGH = 1000;// время сработки
class Cl_DrillNozzle {
  protected:
    Cl_Zoomer Zoomer;
    byte redPin, yellowPin, sensPin; /*пины красный,желтой,датчика*/
    unsigned long past;
    byte state ; // 0 - идет поток / 1 временно пропал / 2 совсем пропал
    /*установить в состояние*/
    void stand(byte s) {
      state = s;
      past = mill;
      switch (state) {
        case 0:/* идут семена*/
          digitalWrite(yellowPin, 0);
          digitalWrite(redPin, 0);
          Zoomer.OFF();
          break;
        case 1:/*пропали семена*/
          digitalWrite(yellowPin, 1);
          Zoomer.ON();
          break;
        case 2:/*долго нет семян*/
          digitalWrite(redPin, 1);
          break;
      }
    }
  public:
    /*конструктор*/
    Cl_DrillNozzle(byte p1, byte p2, byte p3, Cl_Zoomer &Z)
      : redPin(p1), yellowPin(p2), sensPin(p3), Zoomer(Z) {}
    /*инициализация*/
    void init() {
      pinMode(redPin, OUTPUT);
      pinMode(yellowPin, OUTPUT);
      pinMode(sensPin, INPUT);
      stand(0);
    }
    /*работа*/
    void run() {
      bool value = digitalRead(sensPin);/*0 - нет семян /1 есть*/
      if (state != 0 && value == 1) {// если посыпались семена
        stand(0);
      }
      if (state == 0 && value == 0) {// если пропали семена
        stand(1);
      }
      if (state == 1 && value == 0 && mill - past > MINTIMEHIGH) { // если пропали семена надолго
        stand(2);
      }
    }
};
//---Компоновка-----------------------------
Cl_Zoomer Zoomer(/*пин зуммера*/10);
Cl_DrillNozzle DR1(/*пин красный*/6,/*пин желтый*/A0,/*датчик*/2,/*зуммер*/Zoomer);
Cl_DrillNozzle DR2(/*пин красный*/7,/*пин желтый*/A1,/*датчик*/3,/*зуммер*/Zoomer);
Cl_DrillNozzle DR3(/*пин красный*/8,/*пин желтый*/A2,/*датчик*/4,/*зуммер*/Zoomer);
Cl_DrillNozzle DR4(/*пин красный*/9,/*пин желтый*/A3,/*датчик*/5,/*зуммер*/Zoomer);
//---main-----------------------------
void setup() {
  Zoomer.init();
  DR1.init();
  DR2.init();
  DR3.init();
  DR4.init();
}
void loop() {
  mill = millis();
  Zoomer.run();
  DR1.run();
  DR2.run();
  DR3.run();
  DR4.run();
}
/*Скетч использует 2206 байт (7%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 73 байт (3%) динамической памяти, оставляя 1975 байт для локальных переменных. Максимум: 2048 байт.
*/

 

arduinec
Offline
Зарегистрирован: 01.09.2015

"Хлеб - Родине!" (из лозунгов СССР)

В алгоритм проверки датчика не стал углубляться, так как не понял как один датчик отслеживает два засора.
Набросал скетч с двумя наборами датчиков (RED и YELLOW), пины и прочее объединил в массивы:

#define NUM_D 4  // количество датчиков

#define PIN_ZUM 9  // пин зуммера

byte pin_datchik_red[NUM_D] = {11, 12, 13, 14};  // пины датчиков RED
byte pin_datchik_yel[NUM_D] = {15, 16, 17, 18};  // пины датчиков YEL
byte pin_led_red[NUM_D] = {21, 22, 23, 24};      // пины светодиодов RED
byte pin_led_yel[NUM_D] = {25, 26, 27, 28};      // пины светодиодов YEL
byte zator_red[NUM_D], zator_yel[NUM_D];         // запоминание заторов
byte sum_red, sum_yel;                           // для запуска зуммера
int i;

void setup()
{
  for(i=0; i<NUM_D; i++) pinMode(pin_datchik_red[i], INPUT);
  for(i=0; i<NUM_D; i++) pinMode(pin_datchik_yel[i], INPUT);
  for(i=0; i<NUM_D; i++) pinMode(pin_led_red[i], OUTPUT);
  for(i=0; i<NUM_D; i++) pinMode(pin_led_yel[i], OUTPUT);
  pinMode(PIN_ZUM, OUTPUT);
}

void loop()
{
  for(i=0; i<NUM_D; i++) {  // проверка датчиков RED
    //if (датчик сработал) {  
    if (digitalRead(pin_datchik_red[i]) == LOW) {
      zator_red[i] = 1;
    }
    else zator_red[i] = 0;
  }

  for(i=0; i<NUM_D; i++) {  // проверка датчиков YEL
    //if (датчик сработал) {  
    if (digitalRead(pin_datchik_yel[i]) == LOW) {
      zator_yel[i] = 1;
    }
    else zator_yel[i] = 0;
  }

  sum_red = 0; sum_yel = 0;

  for(i=0; i<NUM_D; i++) {  // зажигаем светодиоды RED
    if (zator_red[i]) {
      digitalWrite(pin_led_red[i], HIGH);
      sum_red++;
    }
    else digitalWrite(pin_led_red[i], LOW);
  }

  for(i=0; i<NUM_D; i++) {  // зажигаем светодиоды YEL
    if (zator_yel[i]) {
      digitalWrite(pin_led_yel[i], HIGH);
      sum_yel++;
    }
    else digitalWrite(pin_led_yel[i], LOW);
  }

  if ((sum_red > 0) || (sum_yel > 0)) {  // включаем зуммер
    digitalWrite(PIN_ZUM, HIGH);
  }
  else digitalWrite(PIN_ZUM, LOW);
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

arduinec У ТС один датчик на сопло- зерносып . Просто желтый загорается если перестало сыпаться, а красный если перестало сыпаться через 1 секунду. Зумер если загорелся хоть один ЖЕЛТЫЙ !!!!.  Правильно или неправильно это кто его знает. Этот проект надо создавать лично, а не со слов на форуме.

Sbalakirev
Offline
Зарегистрирован: 23.12.2017

qwone пишет:

arduinec У ТС один датчик на сопло- зерносып . Просто желтый загорается если перестало сыпаться, а красный если перестало сыпаться через 1 секунду. Зумер если загорелся хоть один ЖЕЛТЫЙ !!!!.  Правильно или неправильно это кто его знает. Этот проект надо создавать лично, а не со слов на форуме.

немного не так.

Датчик один в сопло зерносыпе (воронке). - Верно

Желтый загорается если перестало сыпаться, нес сингнала к примеру 3 секунды - Верно

Красный загорается, если сопло наполнилось зерном и закрыло сам датчик, и он подает непрерывный с сигнал.

В рабочем состоянии датчик производит примерно 150 в секунду - по количеству пролетающих зерен. + - может что-то пропуститью

Пищалка срабатывает в обеих случаях, хоть при загорании красного, хоть желтого светодиода.

Плохо виде не выкладывается :-((

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Цитата:
Датчик один в сопло зерносыпе (воронке). - Верно
У вас всего один сенсор. От него и надо плясать

Цитата:
Желтый загорается если перестало сыпаться, нес сингнала к примеру 3 секунды - Верно
Сенсор показавает пустоту - засвечен в длительностью 3 секунды

Цитата:
Красный загорается, если сопло наполнилось зерном и закрыло сам датчик, и он подает непрерывный с сигнал.
Сенсор показывает полноту постояно. 

А вот когда семена сыпятся то тоже идет таже полнота. Ну чуть посветлее. Тогда надо использовать аналоговые выходы cенсоров.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
А я еще с одной сумашедшей рацухой
Смоделируем ситуацию: человек работае загорелсяк примеру 5й - водитель (запомнил не запомнил)остановился а у него все горит, или пока вылез взял ключи, кто то отвлек, (опять забыл), сами же пишете что люди пожылые.
Решение: установить кнопку на коробку передач - передачу включили кн-вк. выключили кн-вык. в прграме записать что только при включеной кнопке (тоесть при движении) делать проверку.
Выгода: 1) При остановке будет гореть только поломка.
        2) Если все нормально и человек остановился на перекур - ничего не пищит
        2) Вы как роботодатель можете в любое время остановить и проверит - не халурит ли он 
evgta
Offline
Зарегистрирован: 02.09.2016

Круче рацуха.

Водила будет всегда халтурить, а поэтому надо прикрутить GSM модуль и слать либо смс либо че мелочиться сразу на сервер пакеты о состоянии системы в релтайм

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

а еще можно GPS модуль прикрутить чтобы мониторить когда стоит и откключать мониторинг , заодно и скорость конролировать и по превышению тлже штрафовать, да и если слишком медленно также лишать премии.

блин, чем-то мне РЖД начинает навевать

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

И дефибриллятор к водителю подключить.  Чтоб шустрее ездил.  Без перекуров. 

Sbalakirev
Offline
Зарегистрирован: 23.12.2017

vosara пишет:

А я еще с одной сумашедшей рацухой
Смоделируем ситуацию: человек работае загорелсяк примеру 5й - водитель (запомнил не запомнил)остановился а у него все горит, или пока вылез взял ключи, кто то отвлек, (опять забыл), сами же пишете что люди пожылые.
Решение: установить кнопку на коробку передач - передачу включили кн-вк. выключили кн-вык. в прграме записать что только при включеной кнопке (тоесть при движении) делать проверку.
Выгода: 1) При остановке будет гореть только поломка.
        2) Если все нормально и человек остановился на перекур - ничего не пищит
        2) Вы как роботодатель можете в любое время остановить и проверит - не халурит ли он 

ВОдитель остановился, загорятся только желтые. После остановки по любой причине водитель поднимает комплекс, чтобы вывести из зацепления с почвой (при трогании сцепление меньше палишь). Если он забыл № Первым делом он крутанет приводное колесо и визуально все и сразу увидит и показания датчика и реальное положение дел.

Идея правильная, но думаю на первый сезон надо сделать проще некуда, а на следующий год доработать имеющиеся неджочеты.

Sbalakirev
Offline
Зарегистрирован: 23.12.2017

qwone пишет:

Цитата:
Датчик один в сопло зерносыпе (воронке). - Верно
У вас всего один сенсор. От него и надо плясать

Цитата:
Желтый загорается если перестало сыпаться, нес сингнала к примеру 3 секунды - Верно
Сенсор показавает пустоту - засвечен в длительностью 3 секунды

Цитата:
Красный загорается, если сопло наполнилось зерном и закрыло сам датчик, и он подает непрерывный с сигнал.
Сенсор показывает полноту постояно. 

А вот когда семена сыпятся то тоже идет таже полнота. Ну чуть посветлее. Тогда надо использовать аналоговые выходы cенсоров.

Когда сыпется идет не полнота, а колебания, свнтодиод постоянно мерцает, и релюшка трещит.

Скинь почту я видео вышлю

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

del

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
Вот еще один совет
Датчиков и диодов у Вас МНОГО, на обработку каждого - необходимо какоето время, для того чтобы сократить время обработки ГУРУ советуют работать с портами на прямую. Вот пример на три датчика
//  Датчики 8-9-10
//  Светодиод Желтый  = 2, 4, 6 
//  Светодиод Красный = 3, 5, 7

uint8_t dat_portB;
uint8_t temp_portB;
uint8_t rezult_portB;
uint8_t zumer;

void setup(){
  DDRB = B00000000; //   PORTB, подключенный- как выход,
  DDRD = DDRD | B11111100; //   PORTD, подключенный как выход 0й и 1й не трогаем
}

//Переменные функции паузы или дребезга, с разным временем опроса
unsigned long currentPause[16];   //массив данных. Количество элементов - количеству таймеров
bool fl_pause[16];//массив данных. Количество элементов - количеству таймеров

//Функция дребезга или паузы (time-время задержки, nomer-номер таймера)
boolean my_pausa(unsigned long time, byte nomer){
  bool x = 0;
  if (fl_pause[nomer] == 0)currentPause[nomer] = millis(), fl_pause[nomer] = 1;
  if (millis() - currentPause[nomer] >= time) x = 1, fl_pause[nomer] = 0;
  return x;
}

void loop(){
    static uint8_t j;
    dat_portB = PINB;
    rezult_portB = dat_portB ^ temp_portB;
    temp_portB = dat_portB;

    zumer = PIND; // Проверяем порт если диоды не горят
    if(!zumer) PORTB &= ~(1<<5); // Звук выключаем
    else  PORTB |= (1<<5); // Звук включаем

    for(uint8_t i=0;i<3;i++)
    {
     if(!i) j=2;
     else j+=2;
     
     if (rezult_portB & (1 << i)){ // Если все нормально
       fl_pause[i] = 0; //Сброс таймера
       PORTD &= ~(1<<j); // Выключаем желтый
       PORTD &= ~(1<<(j+1)); // Выключаем красный
     }
     else{		//Чтото пошло не так!!!
      if (dat_portB & (1 << i)){
       if (my_pausa(1000, i))PORTD |= (1<<j); // Включаем желтый 
      }
      if (~(dat_portB) & (1 << i)){
       if (my_pausa(500, i))PORTD |= (1<<(j+1)); // Включаем красный
      }
     }
    }
}