Автоматика для посева саженцев

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

Если всё хорошо то ждём команду с оптического датчика A0 который определяет вырытую лунку, как только определил, D3 останавливает на 10 сек и опускает фартук (для засыпания землёй который также активирует микрик посадки саженца, после этого открывается и закрывается посадочный лючок D4, и в лунку падает саженец и засыпается фартуком, через 6 сек на всякий повторим сброс по D4, если заело и на D2 + то ждем физическое вмешательство по извлечению саженца, если всё хорошо то поднимаем фартук и отводим микрик по D3, далее D5 подаёт в люльку следующий саженец с магазина. Примерно вот так. Понятно что это не шедевр, но нам нужно показать идею.

может вместо хреновой поделки сделать красивый мультик? комиссия один хрен не будет пялиться в код, оно либо работает идеально либо не работает, есть большая вероятность что не заработает, а мультик завсегда красивый останется в аналах так сказать)

Не. мультики уже не катят, им прототип нужен. Пусть и криво работающий.

Как по мне, тут главная проблема в том, что саженцы очень “упрямые”. Они постоянно цепляются между собой, и за всё вокруг корнями и ветками.

Подкидывай лучше .elf, там и текст программы будет. Можно отладить. А в Proteus 8 можно даже в нём код писать и компилировать.

Вечер добрый. Простите чуть отвлёкся, дело молодое. Поставлена задача, создать проект на вольную тему. Лесов сгорело куча, есть потребность, возникла идея, хотим попробовать, может зацепит. Про саженцы в курсе, поэтому такой контроль, Я не прошу много коментов, если есть возможность помочь с кодом то помогите, если нет, то скажите сколько. Поймите, я не главный инженер КБ, мне почти 20 и образование пока 11 классов. Наставника с кадетки нет, он на СВО, помочь некому. Простите, может груб оказался.

Seyalka.pdsprj (21,3 КБ)
Так ?

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

К сожалению я не умею пока описывать задание, если меня попросят создать 3 де модель с описанием на пальцах я тоже проблематично пойму, что нужно товарищу, поэтому я понимаю, что в моем кавардаке может многое быть не понятно. Но я так понимаю, сопоставив код и моё корявое описание в принципе можно понять истину! Хотя и сложно ))))))) Поймите правильно, и простите)))

В принципе у вас уже есть код, работающий в соответствии с описанием, т.е. странно.

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

Ведь, если при заказе пиццы, не сможете объяснить какую хотите, будете есть рандомную.

Видимо я не могу правильно описать задачу. Ибо мой наставник (товарищ) дал мне код который подходил под его задачи. Я его чуть подправил, но не смог довести до идеала. Ибо только начал изучать, на сколько я понимаю, то проблема начинается после currentState = STATE_CHECK_FOTO; после этого момента перестаётся опрашиваться D2, так же проблема в case STATE_CHECK_FOTO: тут нет многозадачности, то есть нужно чтоб отработал свои 10 сек D3 и нужно чтоб отработал через 2 сек сброс саженца D4 и потом ещё раз, а он отрабатывает только ЕЩЁ раз. Вот .

Всё очень затягивается и сложно. Скажите сколько будет стоить такое с нуля? Я понимаю, что я должен зубрить к примеру Gyver, но времени нет особо, и домой охота.

Миллиона три, если не больше. Так что просто забей и ехай домой.

Если Вы не можете внятно сформулировать, что Вам нужно, то вариант разового договора отпадает, остается повремянка, в лучшем случае 150000 - 200000 в месяц.

Всем привет, слинял с пар, что отписаться.
Попробую ещё раз описать задание. Есть два входа, первый цифровой D2 принимает логическую (1- флаг поднят) или логическую (0 - флаг опущен), второй аналоговый A0 принимает (5 вольт = 1023, флаг опущен) или (4 вольта ±= 800, флаг поднят).
Есть четыре выхода для нагрузки D3, D4, D5, D6, умолчанию на LOW.

Должно работать так.

1). Если подачи питания, на входе D2 логическая (1- флаг поднят), то на D3 и D6 - HIGH.

2). Если при подачи питания на входе D2 логическая (0 - флаг опущен) то длительностью 1 секунда на D5 - HIGH, далее ждём команду на вход A0.

3). Если если в процессе ожидания на D2 опять появится логическая (1- флаг поднят), а на A0 (5 вольт = 1023, флаг опущен), то на D3 и D6 - HIGH, A0 при этом игнорируется, пока на D2 не появится логическая (0 - флаг опущен).

4). Если на D2 логическая (0 - флаг опущен), а на A0 (4 вольта ±= 800, флаг поднят), то на с разницей в 2 секунды на D3-HIGH длительностью 10 секунд, а на D4-HIGH длительностью 1 секунда.

После отработки 10 секундного таймера D3, на D4-HIGH длительностью 1 секунда.

Ждём 2 секунды.
5). Если на D2 логическая (1- флаг поднят) то на D3 и D6 - HIGH, ждем появления логической (0 - флаг опущен).

6). Если на D2 логическая (0 - флаг опущен) то на D5 - HIGH длительностью 1 секунда.

Переходим к пункту 3.

Сейчас у меня работает так.

1). Если подачи питания, на входе D2 логическая (1- флаг поднят), то на D3 и D6 - HIGH.

2). Если при подачи питания на входе D2 логическая (0 - флаг опущен) то длительностью 1 секунда на D5 - HIGH, далее ждём команду на вход A0.

3). Если если в процессе ожидания на D2 опять появится логическая (1- флаг поднят), а на A0 (5 вольт = 1023, флаг опущен), то на D3 и D6 - HIGH, A0 при этом игнорируется, пока на D2 не появится логическая (0 - флаг опущен).

4). Если на D2 логическая (0 - флаг опущен), а на A0 (4 вольта ±= 800, флаг поднят), то на с разницей в 2 секунды на D3-HIGH длительностью 10 секунд, а на D4-HIGH длительностью 1 секунда.

После отработки 10 секундного таймера D3, на D4-HIGH длительностью 1 секунда.

Ждём 2 секунды.

5). Если на D2 логическая (1- флаг поднят) то на D3 и D6 - HIGH, ждем появления логической (0 - флаг опущен).

6). Если на D2 логическая (0 - флаг опущен) то на D5 - HIGH длительностью 1 секунда.

Переходим к пункту 3.

Жирным текстом я выделил, что у меня не работает, а нужно.

Это мой доработанный код, он отличный от первого поста. Но в нём не хватает того, что выделил жирным текстом. Как мне дополнить в него эти функции ???

const int zamokPin = 2;        // Цифровой пин "замок"
const int fotoPin = A0;        // Аналоговый пин "фото"
const int podgotovkaPin = 3;   // Пин "подготовка"
const int otkritiePin = 4;     // Пин "открытие"
const int podachaPin = 5;      // Пин "подача"
const int alarmPin = 6;        // Пин "аларм"

// Переменные для хранения времени
unsigned long previousMillis = 0; // Время последнего изменения состояния
unsigned long interval = 0;       // Интервал для таймеров

// Состояния системы
enum SystemState {
  STATE_IDLE,               // Ожидание
  STATE_CHECK_ZAMOK,        // Проверка входа "замок"
  STATE_CHECK_FOTO,         // Проверка входа "фото"
  STATE_ALARM,              // Состояние "аларм"
  STATE_PODACHA,            // Состояние "подача"
  STATE_PODGOTOVKA,         // Состояние "подготовка"
  STATE_OTKRITIE,           // Состояние "открытие"
  
};

SystemState currentState = STATE_IDLE; // Текущее состояние системы

void setup() {
  // Настройка пинов
  pinMode(zamokPin, INPUT);
  pinMode(fotoPin, INPUT);
  pinMode(podgotovkaPin, OUTPUT);
  pinMode(podachaPin, OUTPUT);
  pinMode(otkritiePin, OUTPUT);
  pinMode(alarmPin, OUTPUT);

  // Инициализация выходов
  digitalWrite(podachaPin, LOW);
  digitalWrite(podgotovkaPin, LOW);
  digitalWrite(podachaPin, LOW);
  digitalWrite(otkritiePin, LOW);
  digitalWrite(alarmPin, LOW);
}

void loop() {
  unsigned long currentMillis = millis(); // Текущее время

  // Обработка состояний
  switch (currentState) {
    case STATE_IDLE:
      // Начальное состояние, переход к проверке "замок"
      currentState = STATE_CHECK_ZAMOK;
      break;

    case STATE_CHECK_ZAMOK:
      if (digitalRead(zamokPin)) {
        // Если флаг поднят, переходим в состояние "аларм"
        digitalWrite(alarmPin, HIGH);
        digitalWrite(podgotovkaPin, HIGH);
        currentState = STATE_ALARM;
      } else {
        // Если флаг опущен, включаем "подача" и ждем 3 секунды
        digitalWrite(alarmPin, LOW);
        digitalWrite(podgotovkaPin, LOW);
        digitalWrite(podachaPin, HIGH);
        previousMillis = currentMillis;
        interval = 1000; // 1 секунды
        currentState = STATE_PODACHA;
      }
      break;

    case STATE_PODACHA:
      if (currentMillis - previousMillis >= interval) {
        // По истечении 1 секунды переходим к проверке "фото"
        digitalWrite(podachaPin, LOW);
        currentState = STATE_CHECK_FOTO;
      }
      break;

    case STATE_CHECK_FOTO:
      if (analogRead(fotoPin) <= 800) { // 4 В +-= 800 (при 5 В = 1023)
        // Если флаг поднят, включаем "подготовку" и ждем 10 секунд
        digitalWrite(podgotovkaPin, HIGH);
        previousMillis = currentMillis;
        interval = 10000; // 10 секунд
        currentState = STATE_PODGOTOVKA;
      }
      break;
  
    case STATE_PODGOTOVKA:
      if (currentMillis - previousMillis >= interval) {
        // По истечении 10 секунд проверяем "замок"
        if (digitalRead(zamokPin)) {
          digitalWrite(alarmPin, HIGH);
        }
        // Включаем "открытие" и ждем 3 секунды
        digitalWrite(otkritiePin, HIGH);
        previousMillis = currentMillis;
        interval = 1000; // 1 секунды
        currentState = STATE_OTKRITIE;
      }
      break;

    case STATE_OTKRITIE:
      if (currentMillis - previousMillis >= interval) {
        // По истечении 3 секунд выключаем "открытие" и ждем 2 секунды
        digitalWrite(otkritiePin, LOW);
        previousMillis = currentMillis;
        interval = 2000; // 2 секунды
        currentState = STATE_CHECK_ZAMOK; // Возврат к проверке "zamok"
      }
      break;

    case STATE_ALARM:
      // Ожидание опускания флага на "замок"
      if (!digitalRead(zamokPin)) {
        digitalWrite(alarmPin, LOW);
        currentState = STATE_CHECK_ZAMOK; // Возврат к проверке "замок"
      }
      break;
  }
}

В общем. Победил ещё одну болезнь :stuck_out_tongue_winking_eye:, в четвертом пункте. прибегнул к функции delay.
1). Если подачи питания, на входе D2 логическая (1- флаг поднят), то на D3 и D6 - HIGH.

2). Если при подачи питания на входе D2 логическая (0 - флаг опущен) то длительностью 1 секунда на D5 - HIGH, далее ждём команду на вход A0.

3). Если если в процессе ожидания на D2 опять появится логическая (1- флаг поднят), а на A0 (5 вольт = 1023, флаг опущен), то на D3 и D6 - HIGH, A0 при этом игнорируется, пока на D2 не появится логическая (0 - флаг опущен).

4). Если на D2 логическая (0 - флаг опущен), а на A0 (4 вольта ±= 800, флаг поднят), то на с разницей в 2 секунды на D3-HIGH длительностью 10 секунд, а на D4-HIGH длительностью 1 секунда.

После отработки 10 секундного таймера D3, на D4-HIGH длительностью 1 секунда.

Ждём 2 секунды.

5). Если на D2 логическая (1- флаг поднят) то на D3 и D6 - HIGH, ждем появления логической (0 - флаг опущен).

6). Если на D2 логическая (0 - флаг опущен) то на D5 - HIGH длительностью 1 секунда.

Переходим к пункту 3.

const int zamokPin = 2;        // Цифровой пин "замок"
const int fotoPin = A0;        // Аналоговый пин "фото"
const int podgotovkaPin = 3;   // Пин "подготовка"
const int otkritiePin = 4;     // Пин "открытие"
const int podachaPin = 5;      // Пин "подача"
const int alarmPin = 6;        // Пин "аларм"

// Переменные для хранения времени
unsigned long previousMillis = 0; // Время последнего изменения состояния
unsigned long interval = 0;       // Интервал для таймеров

// Состояния системы
enum SystemState {
  STATE_IDLE,               // Ожидание
  STATE_CHECK_ZAMOK,        // Проверка входа "замок"
  STATE_CHECK_FOTO,         // Проверка входа "фото"
  STATE_ALARM,              // Состояние "аларм"
  STATE_PODACHA,            // Состояние "подача"
  STATE_PODGOTOVKA,         // Состояние "подготовка"
  STATE_OTKRITIE,           // Состояние "открытие"
  
};

SystemState currentState = STATE_IDLE; // Текущее состояние системы

void setup() {
  // Настройка пинов
  pinMode(zamokPin, INPUT);
  pinMode(fotoPin, INPUT);
  pinMode(podgotovkaPin, OUTPUT);
  pinMode(podachaPin, OUTPUT);
  pinMode(otkritiePin, OUTPUT);
  pinMode(alarmPin, OUTPUT);

  // Инициализация выходов
  digitalWrite(podachaPin, LOW);
  digitalWrite(podgotovkaPin, LOW);
  digitalWrite(podachaPin, LOW);
  digitalWrite(otkritiePin, LOW);
  digitalWrite(alarmPin, LOW);
}

void loop() {
  unsigned long currentMillis = millis(); // Текущее время

  // Обработка состояний
  switch (currentState) {
    case STATE_IDLE:
      // Начальное состояние, переход к проверке "замок"
      currentState = STATE_CHECK_ZAMOK;
      break;

    case STATE_CHECK_ZAMOK:
      if (digitalRead(zamokPin)) {
        // Если флаг поднят, переходим в состояние "аларм"
        digitalWrite(alarmPin, HIGH);
        digitalWrite(podgotovkaPin, HIGH);
        currentState = STATE_ALARM;
      } else {
        // Если флаг опущен, включаем "подача" и ждем 3 секунды
        digitalWrite(alarmPin, LOW);
        digitalWrite(podgotovkaPin, LOW);
        digitalWrite(podachaPin, HIGH);
        previousMillis = currentMillis;
        interval = 1000; // 1 секунды
        currentState = STATE_PODACHA;
      }
      break;

    case STATE_PODACHA:
      if (currentMillis - previousMillis >= interval) {
        // По истечении 1 секунды переходим к проверке "фото"
        digitalWrite(podachaPin, LOW);
        currentState = STATE_CHECK_FOTO;
      }
      break;

    case STATE_CHECK_FOTO:
      if (analogRead(fotoPin) <= 800) { // 4 В +-= 800 (при 5 В = 1023)
        // Если флаг поднят, включаем "подготовку" и ждем 10 секунд
        (digitalWrite(podgotovkaPin, HIGH));
        delay(500);
        (digitalWrite(otkritiePin, HIGH));
        delay(500);
        (digitalWrite(otkritiePin, LOW));
        previousMillis = currentMillis;
        interval = 10000; // 1 секунды
        currentState = STATE_PODGOTOVKA;
        }
      break;
  
    case STATE_PODGOTOVKA:
      if (currentMillis - previousMillis >= interval) {
        // По истечении 10 секунд проверяем "замок"
        if (digitalRead(zamokPin)) {
          digitalWrite(alarmPin, HIGH);
        }
        // Включаем "открытие" и ждем 3 секунды
        digitalWrite(otkritiePin, HIGH);
        previousMillis = currentMillis;
        interval = 1000; // 1 секунды
        currentState = STATE_OTKRITIE;
      }
      break;

    case STATE_OTKRITIE:
      if (currentMillis - previousMillis >= interval) {
        // По истечении 3 секунд выключаем "открытие" и ждем 2 секунды
        digitalWrite(otkritiePin, LOW);
        previousMillis = currentMillis;
        interval = 2000; // 2 секунды
        currentState = STATE_CHECK_ZAMOK; // Возврат к проверке "zamok"
      }
      break;

    case STATE_ALARM:
      // Ожидание опускания флага на "замок"
      if (!digitalRead(zamokPin)) {
        digitalWrite(alarmPin, LOW);
        currentState = STATE_CHECK_ZAMOK; // Возврат к проверке "замок"
      }
      break;
  }
}

Осталось победить третий пункт и переход к нему.

Дяденьки помогите в этом коде сделать приоритетным вдод D2, чтоб если на нём появлялся HIGH, то на D3 и D6 висело HIGH, а если на D2 LOW то вся программа обнулялась. Я так понимаю что нужно искать выход в Обработке состояний, но ума дать не могу.

if (digitalRead(2) {
  digitalWrite(3, HIGH);
  digitalWrite(6, HIGH);
} else {
  asm volatile ("jmp 0x0000");
}