Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.06.2023, 20:37   #1
Rasool
 
Регистрация: 27.03.2015
Сообщений: 5
По умолчанию Управление с помощью потоков шаговыми двигателями через параллельный порт

Я создал 4 потока для каждого из 4-х шаговых двигателей отдельно, где будет крутиться бесконечный цикл с заданными Dir и Step и с задержками, зависящими от текущей скорости для каждого двигателя. Каждый вызов Out32 будет находиться в критической секции. В процедуре TLPTEngine.ApplyHardware для каждого двигателя будут задаваться RotDir[i], RotateStep[i] и скорость (задержка) TimeOut[i].
Приведенный ниже код должен начать вращение двигателей при запуске программы, но не делает этого. При вызове процедуры OutToLptThread[i].Execute в процедуре TLPTEngine.InitializeHardware выдается ошибка:
Цитата:
"Exception EAccessViolation in module MyProgram.exe at 001CE279. Access violation at address 005CE279 in module MyProgram.exe'. Read of address 00000000."
и выполнение программы прекращается.

Код:
uses
    SysUtils, Math, TraceLog, MDriveEngines, SyncObjs;
 
const
    numOfEngines = 4;
 
type
    // Class of threads that control motors
    TOutToLptThread = class(TThread)
    private
    { Private declarations }
    protected
        procedure Execute; override;
    public
        LPTEngineNum: integer; // Number of engine and thread
    end;
 
    // Class of stepper motors
    TLPTEngine = class(TEngine)
    public
        procedure InitializeHardware; override;
        procedure FinalizeHardware; override;
        procedure ApplyHardware; override;
    end;
 
var
    RotateStep: array [1 .. numOfEngines] of Integer; // Stepper motor rotation pulse via LPT-port
    RotDir: array [1 .. numOfEngines] of Integer; // Direction of rotation of stepper motor via LPT-port
    Time_out: array [1 .. numOfEngines] of Integer; // Delays in the supply of pulses to the stepper motor through the LPT-port - for different motor speeds
 
    FSynchronizer: TCriticalSection;
    OutToLptThread: array[1..numOfEngines] of TOutToLptThread; // Array of threads that control numOfEngines engines
    OutToLPTData: Byte; // Common byte with all Dir and Step for tumOfEngines engines, issued to the LPT port
 
procedure TOutToLptThread.Execute;
 
    procedure Delay_mcs(time_out: double); // Delay in microseconds
    var
        iCounterPerSec: TLargeInteger;
        T1, T2: TLargeInteger; // Values of counter before and after operation
    begin
        QueryPerformanceFrequency(iCounterPerSec);
        // We defines a frequency of counter
        QueryPerformanceCounter(T1); // Recorded the start time of the operation
        T2 := T1;
 
        while (T2 - T1) * 1000000 / iCounterPerSec < time_out do
            QueryPerformanceCounter(T2); // Recorded the end time of the operation
    end;
 
var
    PortAdr: word;
begin
    PortAdr := $EEFC; // Address of LPT-port
 
    while true do
    begin
        OutToLPTData := RotDir[1] * 2 + RotDir[2] * 8 + RotDir[3] * 32 + RotDir[4] *
          128; // Data that output to LPT-port
        FSynchronizer.Enter; // = Acquire;
        try
            Out32(PortAdr, OutToLPTData);
        finally
            FSynchronizer.Leave; // = Release
        end;
        Delay_mcs(Time_out[LPTEngineNum]);
        OutToLPTData := RotateStep[1] + RotateStep[2] * 4 + RotateStep[3] * 16 +
          RotateStep[4] * 64 +
          RotDir[1] * 2 + RotDir[2] * 8 + RotDir[3] * 32 +
          RotDir[4] * 128; // Data that output to LPT-port
        FSynchronizer.Enter; // = Acquire;
        try
            Out32(PortAdr, OutToLPTData);
        finally
            FSynchronizer.Leave; // = Release
        end;
        Delay_mcs(Time_out[LPTEngineNum]);
    end;
end;
 
procedure TLPTEngine.InitializeHardware; // Called at the start of program execution
var
    i: integer;
begin
    IsSoftwareControlEngine := true;
 
    for i := 1 to numOfEngines do
    begin
        RotateStep[i] := 1; // Initial pulses of rotation of the stepper motor
        RotDir[i] := 0; // Initial direction of rotation of motors
        Time_out[i] := 500; // Delay in microseconds for each stepper motor
        OutToLptThread[i] := TOutToLptThread.Create(False);
        OutToLptThread[i].LPTEngineNum := i; // The thread number corresponds to the engine number, used in the assignment Time_out[LPTEngineNum]
        OutToLptThread[i].Priority := tpNormal;
//        OutToLptThread[i].Execute; // This command causes a message "Exception EAccessViolation in module MyProgram.exe at 001CE279. Access violation at address 005CE279 in module MyProgram.exe'. Read of address 00000000."
    end;
 
    inherited;
end;
 
procedure TLPTEngine.ApplyHardware; // Called when the value of Velocity changes.
var
    i: Integer;
begin
    i := AxisNum; // Number of engine
    if Velocity > 0 then // Direction of Rotation
    begin
        RotDir[i] := 0;
        RotateStep[i] := 1
    end
    else if Velocity < 0 then // Another direction of Rotation
    begin
        RotDir[i] := 1;
        RotateStep[i] := 1
    end
    else
    begin
        RotDir[i] := 0;
        RotateStep[i] := 0
    end;
end;
Вот описание платы CNC TB6560HQT 4V3, с помощью которой осуществляется управление:
https://www.duxe.ru/load/red%20TB6560HQT%204V3.pdf
Rasool вне форума Ответить с цитированием
Старый 01.07.2023, 01:27   #2
jillitil
Форумчанин
 
Аватар для jillitil
 
Регистрация: 17.10.2018
Сообщений: 184
По умолчанию

Цитата:
Сообщение от Rasool Посмотреть сообщение
При вызове процедуры OutToLptThread[i].Execute в процедуре TLPTEngine.InitializeHardware выдается ошибка:

и выполнение программы прекращается.
Естественно.

Вы же создали поток не в режиме ожидания, а уже запущенным:
Код:
 OutToLptThread[i] := TOutToLptThread.Create(False);
Цитата:
Delphi syntax:
constructor Create(CreateSuspended: Boolean);

Код:
        OutToLptThread[i] := TOutToLptThread.Create(TRUE);
        OutToLptThread[i].LPTEngineNum := i;
        OutToLptThread[i].Priority := tpNormal;
        OutToLptThread[i].Execute;
        OutToLptThread[i].RESUME;
jillitil вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[C++] Реализовать последовательно-параллельный запуск потоков в ОС Linux или Mac OS X с использованием средств POSIX для запуска и синхронизации потоков Кристина1998 Фриланс 2 25.03.2019 20:45
Кто работал с шаговыми двигателями С++ в Visual Studio для МК STM32? zoono Микроконтроллеры, робототехника, схемотехника, 3D принтеры 2 07.10.2018 15:59
нужна программа для управления шаговыми двигателями lolike Фриланс 8 11.07.2016 08:19
Управление 2-мя шаговыми двигателями, регулируя ускорение Evgeni7 Микроконтроллеры, робототехника, схемотехника, 3D принтеры 33 17.11.2012 11:09
Управление ШД через LPT - порт remz Общие вопросы Delphi 17 06.10.2010 22:39