Форум программистов, компьютерный форум, киберфорум
Arduino
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28

Как максимально просто обойтись без delay? Не вовремя срабатывает одна функция

02.03.2020, 19:35. Показов 4244. Ответов 53

Студворк — интернет-сервис помощи студентам
Приветствую всех! Кратко опишу задачу, а затем проблему, которая возникает при попытке её реализации на Arduino. Я делаю макет лифта, а в данный момент привод дверей лифта.

Двери лифта работают по следующему сценарию:
1) Нажатие кнопки вызова
2) Открытие мотором (при помощи специальной отводки) замков на дверях кабины и этаже (замедленное вращение)
3) Открытие мотором самой двери на нормальной скорости (более быстрой чем при открытии замков), до тех пор пока дверь не наедет на концевик (при нажатии на который прекращается подача питания на мотор)
4) Ожидание двери открытой 5 секунд
5) Закрытие двери на нормальной скорости
6) Закрытие дверных замков (резкий рывок с более сильной подачей напряжения) и дожатие двери до концевика с последующим прекращением подачи питания на мотор
7) В случае попадания препятствия в дверной проём - открыть дверь

И вот с пунктом №7 возникают проблемы. Я использую механические концевики, по нажатию на которые откоючается питание при открытии или закрытии двери. Функция фотореверса (обратного открытия двери при попадении в дверной проём препятствия) у меня реализована с помощью лазерного модуля, который светит на фоторезистор. Если луч попадает на фоторезистор - ничего не происходит. Если луч на него перестаёт попадать - выполнить открытие двери. Сначала всё работало, но после добавления в код разных скоростей вращения мотора (для плавного открытия и резкого закрытия дверных замков), прошивка перестала реагировать на пересечение лазерного луча. Методом проб выявил что это связано с функцией delay в строчке №46. Когда я убираю её, прошивка реагирует на пресечение лазерного луча.

Приведу ниже свой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 //Порты
int CallElevator = 50;    // Кнопка вызова лифта, подключена к пин 50
int OpenDoors = 6;        // Вращение мотора по часовой стрелке для открытия двери. Подключение от пин 6 к драйверу
int CloseDoors = 7;       // Вращение мотора против часовой стрелки для закрытия двери. Подключение от пин 7 к драйверу
int LaserReverce = 40;    // Для фоторезистора (работает как кнопка на замыкание контактов)
int OpenEnd = 32;         // Концевик для остановки мотора когда двери полностью откроются
int CloseEnd = 30;        // Концевик для остановки мотора когда двери полностью закроются
 
// Переменные
int StopOpeningDoors; // Переменная для остановки мотора при нажатом концевике
int StopClosingDoors; // Переменная для остановки мотора при нажатом концевике
int LaserOFF;         // Переменная при пересечении лазерного луча препятствием
int CallButton;       // Переменная кнопки вызова лифта
 
void setup() {
 
  pinMode(OpenDoors, OUTPUT);
  pinMode(CloseDoors, OUTPUT);
  pinMode(LaserReverce, INPUT);
  pinMode(OpenEnd, INPUT);
  pinMode(CallElevator, INPUT);
 
 Serial.begin(9600);
}
 
void loop() {
  StopOpeningDoors = digitalRead(OpenEnd);
  StopClosingDoors = digitalRead(CloseEnd);
  LaserOFF = digitalRead(LaserReverce);
  CallButton = digitalRead(CallElevator);
{
 
 
   if (!LaserOFF == HIGH) // Если на фоторезистор светит лазер - ничего не делать, если лазерный луч перекрыт то:
  { 
    analogWrite(OpenDoors, 120);  // Открыть дверь в чуть более ускоренном темпе
    analogWrite(CloseDoors, LOW);
  }
   
   if  (StopOpeningDoors == HIGH) //Если нажался концевик остановки открытия дверей
  { 
    digitalWrite(OpenDoors, LOW); //Мотор на открытие дверей выключается
    delay(5000); // Ожидание дверей открытыми (5 секунд)
    {
      analogWrite(CloseDoors, 100);  // По прошествию 5-и секунд - закрытие двери на нормальной скорости
      delay(2400);                   // Закрытие двери длится 2,4 сек
      analogWrite(CloseDoors, 200);  // Закрытие дверных замков (сведение отводки большей подачей напряжения на мотор)  
    }  
  } 
 
  if (StopClosingDoors == HIGH)     // Если нажался концевик остановки закрытия дверей
   {
    digitalWrite(OpenDoors, LOW);   // Отключить подачу питания на открытие двери
    digitalWrite(CloseDoors, LOW);  // Отключить подачу питания на закрытие двери
   }
   
  if  (CallButton == HIGH) //Если кнопка вызова нажалась
   { 
      analogWrite(OpenDoors, 30);   // Мотор включается на малой скорости для открытия замков на дверях 
      delay(500);                   // Открытие замков длится пол секунды  
      analogWrite(OpenDoors, 100);  // Мотор открывает двери на нормальной скорости  
      delay(2300);                  // Открытие двери длится 2,3 секунды
      analogWrite(OpenDoors, 190);  // По прошествию 2,3 сек открытия двери, подача большего напряжения для прижатия вери к концевику
      analogWrite(CloseDoors, LOW); // Не подавать напряжение на закрытие двери (только на открытие)
   } 
 
 
  } 
}
По некоторым урокам мне удалось заменить delay в 46-й строчке функцией millis(), введя переменные "unsigned long TimeCloseNormalSpeed" для отсчёта времени, сколько дверь будет закрываться и "bool CloseNormalSpeed" для индикации закрытия двери (true - дверь открыта и закрывается, false - дверь уже закрыта) вот таким образом:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 analogWrite(OpenDoors, LOW); // Мотор на открытие дверей выключается
      delay(5000);                                // Ожидание дверей открытыми (5 секунд)   
        {
          analogWrite(CloseDoors, 100);  // Закрытие двери с нормальной скоростью
          CloseNormalSpeed = true;
          TimeCloseNormalSpeed = millis();
        }
    
     
     if(CloseNormalSpeed && millis() - TimeCloseNormalSpeed > 2400) //Закрытие двери продолжается 2,4 сек.
       {
          analogWrite(CloseDoors, LOW);
          CloseNormalSpeed = false;
          analogWrite(CloseDoors, 200);  // Сведение отводки (большая подача напряжения на мотор)
       }
Но почему-то после этой "махинации" всё равно отсутствует реакция на пресечение лазерного луча. Помогите, пожалуйста, разобраться как сделать так чтобы в момент закрытия двери, при пересечении лазерного луча сделать так чтобы она резко начала открываться назад, но так чтобы сохранились разные скорости вращения мотора.

И ещё второй вопрос: как сделать так чтобы программа отсчитывала через сколько секунд после начала закрытия двери был пересечён лазерный луч с последующим открытием двери? Это нужно мне для того чтобы мотор дожал дверь до механического концевика большим усилием. Например дверь закрывается 2,4 сек. И допустим когда дверь уже на половину закрылась (т.е. прошло 1,2 сек) программа запомнила что прошло 1,2 сек и затем открывала дверь на нормальной скорости 1,2 сек (или любое другое время, которое пройдёт с момента начала закрытия двери до пересечение лазерного луча) и по прошествию этого времени подала на мотор большее напряжение для полноценного нажатие двери на механический концевик.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
02.03.2020, 19:35
Ответы с готовыми решениями:

Функция abs и как обойтись без нее
Нужна помощь. При написании кода столкнулся с некой проблемой, что при использовании функции abs работает все отлично, но мне ее...

Аналог цикла FOR без delay() с millis() не срабатывает корректно
Здравствуйте! Возникла проблема с циклом FOR. Поскольку не смог его подружить цикл for с millis(), я нашел аналог этого цикла в интернете,...

Имеет ли значение функция eof, или можно обойтись без нее?
Никогда не использовала eof ранее и считаю, что при решении некоторых задач с файлами можно прекрасно обойтись без нее. Не понимаю, почему...

53
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
04.03.2020, 13:03
Студворк — интернет-сервис помощи студентам
Не вижу подавления дребезга.

Добавлено через 41 секунду
Цитата Сообщение от Daminskii Посмотреть сообщение
Ну тут для меня уже совсем тёмный лес. Может есть какие-то пути по-проще?
Да проще можно закажите разработку скетча у фрилансера за денюшку.
А нет - начинайте думать.
0
518 / 410 / 188
Регистрация: 08.04.2013
Сообщений: 1,751
04.03.2020, 13:54
Разбираем код, комментарии
C++
1
2
3
4
5
6
7
8
  if  (StopOpeningDoors == HIGH)  //да это сработает при начале но условие дальше не сработает потому что сюда мы больше при повторных циклах не поподем, и что написано ниже бессмысленно
  {
  if (millis() - DoorsOpenedTime >= 1000)    // таймер на 1 сек
    {   
    DoorsOpenedTime = millis();              // сброс таймера
    Serial.println("Действие");              // выполняем действие
    }
  }
Добавлено через 3 минуты
Правильное решение переключение системы в определенные состояния и анализ через switch case
0
Тутошний я
 Аватар для Grey
2147 / 1202 / 225
Регистрация: 03.11.2009
Сообщений: 4,424
Записей в блоге: 2
04.03.2020, 13:57
Daminskii, delay это програмная задержка. пока она не закончится остальной код работать не будет.
но программу может прервать аппаратное прерывание. почему не повесить датчик лазера на INT?
0
518 / 410 / 188
Регистрация: 08.04.2013
Сообщений: 1,751
04.03.2020, 14:11
И не надо страшиться кода
C++
1
2
3
4
5
#define STATE_WHIT 0
#define STATE_OPEMING 1// открываем двери
#define STATE_OPEN 2 // держим открытой 5 секунд
#define STATE_CLOSING 3 // дверь закрываем
#define STATE_CLOSE 4 // дверь закрыта
Директива #define определяет идентификатор и последовательность символов, которой будет за­мещаться данный идентификатор при его обнаружении в тексте программы. Нормальная практика, тем более в ардуино чтоб не перебирать код при изменении каких то параметров
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
04.03.2020, 14:18
Цитата Сообщение от marat_miaki Посмотреть сообщение
Нормальная практика,
Нифига не нормальная для языка С++. А Ардуина это именно С++.
0
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28
04.03.2020, 14:18  [ТС]
Цитата Сообщение от Grey Посмотреть сообщение
delay это програмная задержка. пока она не закончится остальной код работать не будет.
Да это я понимаю, по этому ищу пути как его не использовать.

Цитата Сообщение от Grey Посмотреть сообщение
но программу может прервать аппаратное прерывание. почему не повесить датчик лазера на INT?
Я тоже думал об этом варианте, но как его реализовать? А датчик лазера и так на int (переменной), или вы имели ввиду что-то другое?
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
04.03.2020, 14:26
#define же это нормально для языка Си


C
1
2
3
4
5
#define STATE_WHIT 0
#define STATE_OPEMING 1// открываем двери
#define STATE_OPEN 2 // держим открытой 5 секунд
#define STATE_CLOSING 3 // дверь закрываем
#define STATE_CLOSE 4 // дверь закрыта

C++
1
enum class State{  whit, opening, open, closing, close };
0
Тутошний я
 Аватар для Grey
2147 / 1202 / 225
Регистрация: 03.11.2009
Сообщений: 4,424
Записей в блоге: 2
04.03.2020, 14:33
А датчик лазера и так на int (переменной),
но пока задержка не закончится переменная не работает.
вот и предлагаю открывать дверь в прерывании.
а чтоб понять как программировать, нужно правильно алгоритм написать.
0
518 / 410 / 188
Регистрация: 08.04.2013
Сообщений: 1,751
04.03.2020, 14:35
Avazart, Язык программирования устройств Ардуино основан на C/C++, в коде ТС и моем пока вроде ничего нет только из с++ (классы, шаблоны) ТС в классах пока вроде и не разбирается
0
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28
04.03.2020, 14:39  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
C++Выделить код
1
enum class State{  whit, opening, open, closing, close };
Спасибо, так становится немного понятнее. А как дальше прописать состояния работы привода дверей? Может этим способом получится реализовать задумку
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
04.03.2020, 14:44
Цитата Сообщение от Daminskii Посмотреть сообщение
А как дальше прописать состояния работы привода дверей? Может этим способом получится реализовать задумку
Что Вы имеете ввиду? Это и есть состояние. Или Вы имеете ввиду switсh/case?

Добавлено через 1 минуту
Цитата Сообщение от marat_miaki Посмотреть сообщение
Avazart, Язык программирования устройств Ардуино основан на C/C++, в коде ТС и моем пока вроде ничего нет только из с++ (классы, шаблоны) ТС в классах пока вроде и не разбирается
Нет языка Ардуино. В Ардуино используется именно С++ (компилятор gcc) + пару незначительных (и тупых) расширений от разработчиков Arduino.
0
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28
04.03.2020, 14:45  [ТС]
Цитата Сообщение от Grey Посмотреть сообщение
вот и предлагаю открывать дверь в прерывании.
Я пробовал вариант со срабатыванием фотореверса (открытия закрывающейся двери по условию пресечения лазерного луча препятствием в дверном проёме) с помощью прерывания (писал этот код выше), но почему-то он тоже не сработал... Возможно я где-то допустил ошибку?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "timer-api.h"
 
 //Порты
int CallElevator = 50; // Кнопка вызова лифта, подключена к пин 50
int LaserReverce = 40; // Для фоторезистора (работает как кнопка на замыкание контактов)
 
// Переменные
int LaserOFF;         // Переменная при пересеченни лазерного луча препятствием
int CallButton;       // Переменная кнопки вызова лифта
 
void setup() {
 
 
    Serial.begin(9600);
 
    // частота=1Гц, период=1с
    timer_init_ISR_2Hz(TIMER_DEFAULT);
    
    pinMode(LaserReverce, INPUT);
    pinMode(CallElevator, INPUT);
 
}
 
void loop() {
 
    LaserOFF = digitalRead(LaserReverce);
    CallButton = digitalRead(CallElevator);
 
    if  (CallButton == HIGH)
    {
    Serial.println("Кнопка нажата на 5 сек");
    delay(5000);
    }
 
}
 
void timer_handle_interrupts(int timer) {
    if (!LaserOFF == HIGH)
    Serial.println("Фотореверс сработал");
}
0
518 / 410 / 188
Регистрация: 08.04.2013
Сообщений: 1,751
04.03.2020, 14:47
Daminskii,
вот 2 способа реализации одна в вашем стиле вторая с millis() которая сработает точно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  void doOpening () { // ниже можно и ваш вариант
      analogWrite(OpenDoors, 30);   // Мотор включается на малой скорости для открытия замков на дверях 
      delay(500);                   // Открытие замков длится пол секунды  
      analogWrite(OpenDoors, 100);  // Мотор открывает двери на нормальной скорости  
      delay(2300);                  // Открытие двери длится 2,3 секунды
      analogWrite(OpenDoors, 190);  // По прошествию 2,3 сек открытия двери, подача большего напряжения для прижатия вери к концевику
      analogWrite(OpenDoors, LOW );//  У вас этой строки нет СТРАННО!  Добавлю мало ли что взбредет потом включить
      analogWrite(CloseDoors, LOW); // Не подавать напряжение на закрытие двери (только на открытие)
      Status = STATE_OPEN; // переводим в следующее состояние
      openON = true;   // разрешение на отсечку времени открытия Важно!!!
 }
  void doOpen (int offTime) {
    if (openON){openON=false; openOnTime =millis();}   // запустили отсечку сработает один раз
    if(millis() - openOnTime > offTime) {   Status = STATE_CLOSING;   } // в конце переводим систему в следующее состояние - Закрываем двери
 }
а в кокой case и что вставлять ваша задача
1
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28
04.03.2020, 14:48  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Или Вы имеете ввиду switсh/case?
Да, наверное это имею ввиду. Чтобы программа понимала, что в состоянии ожидания она ничего не делает и ждет команд (например нажатие кнопки вызова лифта), в состоянии открытия двери она открывала дверь, в состоянии срабатывания фотореверса она обрывала другие процессы и включала мотор на открытие двери.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
04.03.2020, 14:50
Вы до сих пор не обрабатываете дребезг.
0
518 / 410 / 188
Регистрация: 08.04.2013
Сообщений: 1,751
04.03.2020, 15:37
Цитата Сообщение от Daminskii Посмотреть сообщение
состоянии срабатывания фотореверса
не будет такого состояния, это состояние закрывания двери, где может сработать датчик, тогда надо экстренно открыть( поменять состояние)
1
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28
04.03.2020, 15:38  [ТС]
Цитата Сообщение от marat_miaki Посмотреть сообщение
вот 2 способа реализации одна в вашем стиле вторая с millis() которая сработает точно

C++

 
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void doOpening () { // ниже можно и ваш вариант
      analogWrite(OpenDoors, 30);   // Мотор включается на малой скорости для открытия замков на дверях 
      delay(500);                   // Открытие замков длится пол секунды  
      analogWrite(OpenDoors, 100);  // Мотор открывает двери на нормальной скорости  
      delay(2300);                  // Открытие двери длится 2,3 секунды
      analogWrite(OpenDoors, 190);  // По прошествию 2,3 сек открытия двери, подача большего напряжения для прижатия вери к концевику
      analogWrite(OpenDoors, LOW );//  У вас этой строки нет СТРАННО!  Добавлю мало ли что взбредет потом включить
      analogWrite(CloseDoors, LOW); // Не подавать напряжение на закрытие двери (только на открытие)
      Status = STATE_OPEN; // переводим в следующее состояние
      openON = true;   // разрешение на отсечку времени открытия Важно!!!
 }
  void doOpen (int offTime) {
    if (openON){openON=false; openOnTime =millis();}   // запустили отсечку сработает один раз
    if(millis() - openOnTime > offTime) {   Status = STATE_CLOSING;   } // в конце переводим систему в следующее состояние - Закрываем двери
 }
а в кокой case и что вставлять ваша задача
Спасибо, но как активировать "void doOpening ()" или "void doOpen()"?
0
518 / 410 / 188
Регистрация: 08.04.2013
Сообщений: 1,751
04.03.2020, 16:07
посмотрите пост 14. Это функция, которую запускаем в соответствующем состоянии, т.е case е
0
483 / 275 / 57
Регистрация: 08.10.2015
Сообщений: 1,190
04.03.2020, 16:58
Возможно, что вопрос глупый, сигнал при освещении датчика это LOW или у там инверсия и на выходе HIGH?
Вопрос в связи с
Цитата Сообщение от Daminskii Посмотреть сообщение
if (!LaserOFF == HIGH) // Если на фоторезистор светит лазер - ничего не делать, если лазерный луч перекрыт то:
Если инверсии нет, то при засветке будет выполнятся
Цитата Сообщение от Daminskii Посмотреть сообщение
{
    analogWrite(OpenDoors, 120);  // Открыть дверь в чуть более ускоренном темпе
    analogWrite(CloseDoors, LOW);
  }
0
0 / 0 / 0
Регистрация: 10.10.2019
Сообщений: 28
04.03.2020, 18:01  [ТС]
Цитата Сообщение от САлександр Посмотреть сообщение
Возможно, что вопрос глупый, сигнал при освещении датчика это LOW или у там инверсия и на выходе HIGH?
Я инвертировал сигнал для удобства понимания. Если луч светит на фоторезистор, я сделал чтобы показывало LOW, а если лазерный луч будет пересечён, то будет HIGH и выполнение экстренного открытия двери
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.03.2020, 18:01
Помогаю со студенческими работами здесь

Кофемашина Miele CVA 645-2, не вовремя срабатывает дозатор
Не срабатывал дозатор, заменил uln2003a, начал работать, но сначала кофе сыпет в ЗУ, затем варит и в этот момент повторно сыпет кофе, т.е....

Как максимально просто сохранить настройки программы в файл
Добрый день! В проекте много текстбоксов и радиоботтонов для заполнения настроек. Пользователь выставлят эти настройки через...

Как обойтись без x
Есть алгоритм (см. прикрепления) Нужно обойтись без x Речь идет о замене элементов находящихся на четных и нечетных местах. (поменять...

Как обойтись без x
Есть алгоритм (см. прикрепления) Нужно обойтись без x Речь идет о замене элементов находящихся на четных и нечетных местах. (поменять...

Как можно максимально просто и быстро реализовать команды в консоли?
Я хочу реализовать команды в консоли, к примеру чтобы при вводе "/help" с клавиатуры выводился список других доступных команд, как это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru