Страница 1157 из 1177 ПерваяПервая ... 157657105711071147115511561157115811591167 ... ПоследняяПоследняя
Показано с 11,561 по 11,570 из 11767

Тема: ВОПРОС-ОТВЕТ (отвечаем на простые вопросы от новичков)

  1. #11561

    По умолчанию

    И снова я) Подскажите как получается такой адрес?
    Если в плк имеем адрес 78:11 Включение вентилятора 18
    изображение_2025-07-16_114009150.png

    то в панели на кнопке включения этого же вентилятора имеем адрес 0x 1259
    Снимок экрана 2025-07-16 111800.png


    1.png
    Последний раз редактировалось atomo2; 16.07.2025 в 07:49.

  2. #11562

    По умолчанию

    Цитата Сообщение от atomo2 Посмотреть сообщение
    И снова я) Подскажите как получается такой адрес?
    Если в плк имеем адрес 78:11 Включение вентилятора 18
    изображение_2025-07-16_114009150.png

    то в панели на кнопке включения этого же вентилятора имеем адрес 0x 1259
    Снимок экрана 2025-07-16 111800.png


    1.png
    Есть руководство по программированию ПЛК1ХХ, там много чего описано:
    изображение_2025-07-16_115111520.png

  3. #11563

    По умолчанию

    Цитата Сообщение от atomo2 Посмотреть сообщение
    И снова я) Подскажите как получается такой адрес?
    Если в плк имеем адрес 78:11 Включение вентилятора 18
    то в панели на кнопке включения этого же вентилятора имеем адрес 0x 1259
    В каждом регистре по 16 бит, 78 *16 бит =1248, это нулевой бит в 78 регистре
    Регистр 78 *16 бит +N (номер бита) =1248+11 =1259, это 11 бит в 78 регистре
    N=1259-1248=11
    Последний раз редактировалось kondor3000; 16.07.2025 в 08:00.

  4. #11564

    По умолчанию

    Всем спасибо большое , разобрался


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

    Снимок экрана 2025-07-16 152845.png



    Код:
    import tkinter as tk 
    from tkinter import ttk, messagebox, filedialog
    
    class ModbusAddressCalculatorOrder(tk.Tk):
        def __init__(self):
            super().__init__()
            self.title("Калькулятор адресов")
            self.geometry("750x650")
            self.resizable(True, True)
    
            self.blocks = []
    
            self.create_widgets()
    
            self.columnconfigure(0, weight=1)
            self.columnconfigure(1, weight=1)
            self.rowconfigure(3, weight=1)
            self.rowconfigure(6, weight=1)
    
        def create_widgets(self):
            padding = {'padx': 10, 'pady': 5}
    
            ttk.Label(self, text="Тип блока:").grid(column=0, row=0, sticky="w", **padding)
            self.type_var = tk.StringVar()
            self.type_combo = ttk.Combobox(self, textvariable=self.type_var,
                                           values=["Float", "2 byte", "8 bit", "4 bytes"], state="readonly")
            self.type_combo.grid(column=1, row=0, sticky="ew", **padding)
            self.type_combo.current(0)
    
            ttk.Label(self, text="Количество:").grid(column=0, row=1, sticky="w", **padding)
            self.count_entry = ttk.Entry(self)
            self.count_entry.grid(column=1, row=1, sticky="ew", **padding)
            self.count_entry.insert(0, "1")
    
            self.btn_add = ttk.Button(self, text="Добавить блок", command=self.add_block)
            self.btn_add.grid(column=0, row=2, columnspan=2, pady=10, sticky="ew")
    
            self.btn_load_exp = ttk.Button(self, text="Загрузить .EXP", command=self.load_exp_file)
            self.btn_load_exp.grid(column=0, row=7, columnspan=2, pady=10, sticky="ew")
    
            tree_frame = ttk.Frame(self)
            tree_frame.grid(column=0, row=3, columnspan=2, sticky="nsew", padx=10, pady=5)
            tree_frame.columnconfigure(0, weight=1)
            tree_frame.rowconfigure(0, weight=1)
    
            self.tree = ttk.Treeview(tree_frame, columns=("Тип", "Количество"), show="headings")
            self.tree.heading("Тип", text="Тип блока")
            self.tree.heading("Количество", text="Количество")
            self.tree.column("Тип", width=250)
            self.tree.column("Количество", width=100)
            self.tree.grid(column=0, row=0, sticky="nsew")
    
            tree_scrollbar = ttk.Scrollbar(tree_frame, orient="vertical", command=self.tree.yview)
            tree_scrollbar.grid(column=1, row=0, sticky="ns")
            self.tree.configure(yscrollcommand=tree_scrollbar.set)
    
            btn_frame = ttk.Frame(self)
            btn_frame.grid(column=0, row=4, columnspan=2, pady=10, sticky="ew")
            btn_frame.columnconfigure((0, 1, 2), weight=1)
    
            ttk.Button(btn_frame, text="Удалить блок", command=self.delete_block).grid(column=0, row=0, padx=5, sticky="ew")
            ttk.Button(btn_frame, text="Вверх", command=self.move_up).grid(column=1, row=0, padx=5, sticky="ew")
            ttk.Button(btn_frame, text="Вниз", command=self.move_down).grid(column=2, row=0, padx=5, sticky="ew")
    
            self.btn_calc = ttk.Button(self, text="Рассчитать адреса", command=self.calculate_addresses)
            self.btn_calc.grid(column=0, row=5, columnspan=2, pady=10, sticky="ew")
    
            self.text_frame = ttk.Frame(self)
            self.text_frame.grid(column=0, row=6, columnspan=2, sticky="nsew", padx=10, pady=5)
            self.text_frame.columnconfigure(0, weight=1)
            self.text_frame.rowconfigure(0, weight=1)
    
            self.result_text = tk.Text(self.text_frame, wrap="none", font=("Consolas", 10))
            self.result_text.grid(column=0, row=0, sticky="nsew")
    
            self.scrollbar_v = ttk.Scrollbar(self.text_frame, orient="vertical", command=self.result_text.yview)
            self.scrollbar_v.grid(column=1, row=0, sticky="ns")
            self.result_text.configure(yscrollcommand=self.scrollbar_v.set)
    
            self.scrollbar_h = ttk.Scrollbar(self.text_frame, orient="horizontal", command=self.result_text.xview)
            self.scrollbar_h.grid(column=0, row=1, sticky="ew")
            self.result_text.configure(xscrollcommand=self.scrollbar_h.set)
    
            self.result_text.config(state="normal")
    
        def add_block(self):
            t = self.type_var.get()
            c = self.count_entry.get()
            try:
                c = int(c)
                if c <= 0:
                    raise ValueError
            except ValueError:
                messagebox.showerror("Ошибка", "Введите корректное положительное число для количества!")
                return
            self.blocks.append({"type": t, "count": c})
            self.refresh_tree()
    
        def refresh_tree(self):
            self.tree.delete(*self.tree.get_children())
            for idx, block in enumerate(self.blocks):
                self.tree.insert("", "end", iid=idx, values=(block["type"], block["count"]))
    
        def delete_block(self):
            selected = self.tree.selection()
            if not selected:
                messagebox.showinfo("Информация", "Выберите блок для удаления.")
                return
            idx = int(selected[0])
            del self.blocks[idx]
            self.refresh_tree()
    
        def move_up(self):
            selected = self.tree.selection()
            if not selected:
                messagebox.showinfo("Информация", "Выберите блок для перемещения.")
                return
            idx = int(selected[0])
            if idx == 0:
                return
            self.blocks[idx], self.blocks[idx - 1] = self.blocks[idx - 1], self.blocks[idx]
            self.refresh_tree()
            self.tree.selection_set(idx - 1)
    
        def move_down(self):
            selected = self.tree.selection()
            if not selected:
                messagebox.showinfo("Информация", "Выберите блок для перемещения.")
                return
            idx = int(selected[0])
            if idx == len(self.blocks) - 1:
                return
            self.blocks[idx], self.blocks[idx + 1] = self.blocks[idx + 1], self.blocks[idx]
            self.refresh_tree()
            self.tree.selection_set(idx + 1)
    
        def calculate_addresses(self):
            addr = 0
            lines = []
            for idx, block in enumerate(self.blocks):
                t = block["type"]
                c = block["count"]
                if t in ["Float", "4 bytes"]:
                    length = 2
                    total_length = c * length
                elif t == "2 byte":
                    length = 1
                    total_length = c * length
                elif t == "8 bit":
                    total_length = (c + 1) // 2
                else:
                    messagebox.showerror("Ошибка", f"Неизвестный тип блока: {t}")
                    return
    
                start_block = addr
                end_block = addr + total_length - 1
                lines.append(f"{idx + 1}. {t} ({c} шт.): от регистра {start_block} до {end_block}")
    
                if t in ["Float", "2 byte", "4 bytes"]:
                    for i in range(c):
                        start_el = addr + i * length
                        end_el = start_el + length - 1
                        if length == 1:
                            lines.append(f"   Элемент {i + 1}: регистр {start_el}")
                        else:
                            lines.append(f"   Элемент {i + 1}: регистры {start_el} - {end_el}")
                elif t == "8 bit":
                    for i in range(c):
                        reg = addr + i // 2
                        bit_pos = (i % 2) * 8
                        bit_addresses = [reg * 16 + bit_pos + b for b in range(8)]
                        bit_addresses_str = ", ".join(str(b) for b in bit_addresses)
                        lines.append(f"   Элемент {i + 1}: регистр {reg}, биты {bit_pos}-{bit_pos + 7} → битовые адреса [{bit_addresses_str}]")
    
                addr = end_block + 1
    
            if lines:
                lines.append(f"\nИтоговый конечный адрес регистра: {addr - 1}")
            else:
                lines.append("Список блоков пуст")
    
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, "\n".join(lines))
    
        def load_exp_file(self):
            filepath = filedialog.askopenfilename(
                title="Выберите файл .EXP",
                filetypes=[("EXP files", "*.exp"), ("Все файлы", "*.*")]
            )
            if not filepath:
                return
    
            blocks_from_file = self.parse_exp_modules(filepath)
            if blocks_from_file:
                self.blocks = []
                for count, block_type in blocks_from_file:
                    self.blocks.append({"type": block_type, "count": count})
                self.refresh_tree()
                messagebox.showinfo("Готово", f"Загружено {len(blocks_from_file)} блоков из файла.")
            else:
                messagebox.showwarning("Внимание", "Не удалось найти подходящие блоки в файле.")
    
        def parse_exp_modules(self, filename):
            results = []
            count = 0
            prev_module = None
    
            module_aliases = {
                'float': 'Float',
                '2 byte': '2 byte',
                '8 bits': '8 bit',
                '4 byte': '4 bytes'  # поддержка _MODULE_NAME: '4 byte'
            }
    
            encodings = ['utf-8', 'cp1251', 'latin1']
            for enc in encodings:
                try:
                    with open(filename, 'r', encoding=enc) as f:
                        for line in f:
                            line = line.strip()
                            if line.startswith("_MODULE_NAME:"):
                                start = line.find("'")
                                end = line.rfind("'")
                                if start != -1 and end != -1 and end > start:
                                    raw = line[start + 1:end].strip().lower()
                                    block_type = module_aliases.get(raw)
    
                                    if not block_type:
                                        if prev_module is not None:
                                            results.append((count, prev_module))
                                            prev_module = None
                                            count = 0
                                        continue
    
                                    if block_type == prev_module:
                                        count += 1
                                    else:
                                        if prev_module is not None:
                                            results.append((count, prev_module))
                                        prev_module = block_type
                                        count = 1
                        if prev_module is not None:
                            results.append((count, prev_module))
                    break
                except Exception:
                    continue
            return results
    
    
    if __name__ == "__main__":
        app = ModbusAddressCalculatorOrder()
        app.mainloop()
    Последний раз редактировалось atomo2; 17.07.2025 в 08:02.

  5. #11565

    По умолчанию

    Добрый день, подскажите пожалуйста вот такой момент.


    Если я добавлю в модбас fix еще 1 адрес , то у меня все адреса что ниже сдвинуться? Или то что я добавляю в модбаск fix на адресацию не повлияет.

    изображение_2025-07-28_120401471.png

  6. #11566

    По умолчанию

    Цитата Сообщение от atomo2 Посмотреть сообщение
    Добрый день, подскажите пожалуйста вот такой момент.


    Если я добавлю в модбас fix еще 1 адрес , то у меня все адреса что ниже сдвинуться? Или то что я добавляю в модбаск fix на адресацию не повлияет.
    Не влияет, это было проще самому проверить, чем писать.
    В модбас fix вы добавляете новый порт или интерфейс, а не адрес слейва.
    Последний раз редактировалось kondor3000; 28.07.2025 в 08:11.

  7. #11567

    По умолчанию

    Имею контроллер ОВЕН ПЛК 110-60 и среду программирования CoDeSys V2.3. Настройка фильтров входных сигналов распространяется на все входы (кроме быстрых)? У быстрых своя настройка. Или можно настраивать индивидуально каждую группу из 8 входов Discrete inputs[FIX] AT %IB.0, AT %IB.1, AT %IB.2 и AT %IB.3? Я что-то не нашел индивидуальную настройку для AT %IB.0, AT %IB.1, AT %IB.2 и AT %IB.3.

  8. #11568

    По умолчанию

    Цитата Сообщение от vsa Посмотреть сообщение
    Имею контроллер ОВЕН ПЛК 110-60 и среду программирования CoDeSys V2.3. Настройка фильтров входных сигналов распространяется на все входы (кроме быстрых)? У быстрых своя настройка. Или можно настраивать индивидуально каждую группу из 8 входов Discrete inputs[FIX] AT %IB.0, AT %IB.1, AT %IB.2 и AT %IB.3? Я что-то не нашел индивидуальную настройку для AT %IB.0, AT %IB.1, AT %IB.2 и AT %IB.3.
    Для быстрых входов и обычных дискретных входов, фильтры общие на все входы.
    Кроме энкодеров и быстрых счётчиков
    Последний раз редактировалось kondor3000; 06.08.2025 в 22:06.

  9. #11569

    По умолчанию

    Добрый день, подскажите бредмаузер может блокировать связь между онлайн симулятором панели weintek и codesys 2.5 режиме эмуляции. Раньше все работало , теперь нет

  10. #11570

    По умолчанию

    Цитата Сообщение от atomo2 Посмотреть сообщение
    Добрый день, подскажите бредмаузер может блокировать связь между онлайн симулятором панели weintek и codesys 2.5 режиме эмуляции. Раньше все работало , теперь нет
    Симулятор панели работает с живым ПЛК, а не симулятором в codesys 2.3.
    В codesys 3.5 можно работать с виртуальным ПЛК.

Страница 1157 из 1177 ПерваяПервая ... 157657105711071147115511561157115811591167 ... ПоследняяПоследняя

Метки этой темы

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •