如何通过接受当前位置作为第一个坐标来重新启动电机

How to restart motors by accepting current position as first coordinate

提问人:Ozzie 提问时间:11/16/2023 更新时间:11/17/2023 访问量:42

问:

我有一个 C# 代码,可以生成一些 x 和 y 坐标,我将这些坐标作为 g 代码发送到针对 2 轴 cnc 代码编程的 arduino。

我在列表框中列出了所有坐标,并在 750 毫秒后将每个坐标发送到 arduino。

我的问题是,当所有坐标都发送到arduino时,我想一次又一次地重新发送所有坐标,直到发送停止命令。但是,当坐标重新发送到 arduino 时,电机会按预期移动到第一个坐标的位置。 但是,我想要的是电机将当前坐标作为列表框中的第一个坐标,而不是移回第一个起点。

请帮我如何重新调整代码。

我正在将当前代码添加到下面。

        private void btnSendData_Click(object sender, EventArgs e)
        {
            
            if (serialPort1.IsOpen && listBox1.Items.Count > 1)
            {
                currentIndex = 0; // Reset the index to start from the first item
                timer1.Interval = 750;  // in mili-second
                timer1.Start();

            }
            else
            {
                MessageBox.Show("Port Closed or Not Enough Data");
            }
        }

        private void SendDataToArduino()
        {
            if (currentIndex < listBox1.Items.Count)
            {
                string command = listBox1.Items[currentIndex].ToString(); // Get the item as a string
                command = command.Replace(": ", ""); // Remove the colon
                command = command.Replace(",", ""); // Remove comma if needed

                serialPort1.WriteLine(command);

                textBox3.Text = command;

                currentIndex++; // Move to the next item

            }
            else
            {
                // Tüm veriler gönderildi, işlemi yeniden başlat
                currentIndex = 0;
            }

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            SendDataToArduino();
        }

我尝试将每个 x 值添加到每个循环中的第一个坐标中。但这太荒谬了。

C# 坐标 重复 G 代码 CNC

评论

0赞 Andrew S 11/16/2023
代码最终设置回 0。而且可能是起始位置?为什么要设置回 0?currentIndexcurrentIndex == 0
0赞 Ozzie 11/16/2023
@AndrewS再次重新开始发送数据,我将 currentIndex 重置为 0。然后连续地将所有数据再次发送到arduino。
0赞 Andrew S 11/16/2023
也许数据结构不正确?也许使用队列而不是列表?新命令被添加到队列中(并在发送时弹出),因此下一个命令将从最后一个位置开始(而不是再次浏览具有旧位置的整个列表)。
0赞 jarmanso7 11/16/2023
我正在努力了解您的问题,以便为您提供帮助。为什么您的机器一次遍历所有坐标还不够?“以当前坐标为第一个坐标”,您能更详细地解释一下这部分吗?我的意思是,一旦电机旋转了所有可能的坐标并形成了一个循环,如果不做第二个循环,我就无法想象它会发生什么,其中起点是第一个坐标的位置。看起来这不是你想要的,但我不明白你的替代动作或行为是什么。
0赞 jarmanso7 11/16/2023
我只是在这里猜测,但你是否试图让它一旦到达终点就倒退?即,如果您的电机正在通过 A、B、C、D 点,现在它正在做 A、B、C、D、A、B、C、D、A、B、C、D......你想让它做A、B、C、D、C、B、A、B、C、D、C、B、A...?或。。。?
1赞 Ozzie 11/29/2023
@jarmanso7感谢您的帮助,我忘了接受您的回答。

答:

0赞 jarmanso7 11/17/2023 #1

根据我们在评论中讨论的内容,我创建了一个小型 Winforms 项目来模拟您要实现的目标。

首先,我添加了几个控件:

  1. listBox2:保存电机要重复的图案的位置
  2. btnCalculatePattern:单击时,根据您在 listBox1 中设置的坐标计算重复模式
  3. btnAvatar:这只是通过移动按钮在屏幕上显示电机的运动。

我还启用了控制台窗口,以便查看发送到电机的命令。

首先,在向电机发送命令之前,单击“计算模式”来计算模式。之后,单击“发送数据”,这将激活计时器(如原始代码中)并开始发送数据:

enter image description here

您可以在此 GitHub 存储库中找到整个解决方案,也可以在此处将其下载为 zip 文件。如果您在打开它时遇到任何问题,请告诉我。

我不知道您以什么格式将数据发送到电机,所以我只使用了格式为“X.Y”的字符串,用点“.”分隔,因此您可能需要使用您正在使用的字符串格式调整此部分。

这是具有新更改的 Form1 代码。我不得不将命令变量移出 SendDataToArduino,对此方法进行了一些更改,并添加了其他方法btnCalculatePattern_Click 和 UpdateCoordinates:

public partial class Form1 : Form
{
    bool serialPortIsOpen = true;

    int currentIndex = 0;

    string command = "";

    public Form1()
    {
        InitializeComponent();

        //Move the visual avatar to the starting position
        MoveAvatar(listBox1.Items[0].ToString());
    }

    private void MoveAvatar(string point)
    {
        var currentCoordinates = point.Split('.');
        var current_x = Convert.ToInt32(currentCoordinates[0]);
        var current_y = Convert.ToInt32(currentCoordinates[1]);
        btnAvatar.Location = new System.Drawing.Point(current_x, current_y);
    }

    private void btnSendData_Click(object sender, EventArgs e)
    {
        if (serialPortIsOpen && listBox1.Items.Count > 1)
        {
            currentIndex = 0; // Reset the index to start from the first item
            timer1.Interval = 750;  // in mili-second
            timer1.Start();

        }
        else
        {
            MessageBox.Show("Port Closed or Not Enough Data");
        }
    }

    private void btnCalculatePattern_Click(object sender, EventArgs e)
    {
        // The first item of the pattern is always (0,0)
        listBox2.Items.Add($"0.0");

        for (int i = 0; i < listBox1.Items.Count - 1; i++)
        {
            var currentCoordinates = listBox1.Items[i].ToString().Split('.');
            var current_x = Convert.ToInt32(currentCoordinates[0]);
            var current_y = Convert.ToInt32(currentCoordinates[1]);

            var nextCoordinates = listBox1.Items[i + 1].ToString().Split('.');
            var next_x = Convert.ToInt32(nextCoordinates[0]);
            var next_y = Convert.ToInt32(nextCoordinates[1]);

            var x = next_x - current_x;
            var y = next_y - current_y;

            listBox2.Items.Add($"{x}.{y}");
        }

        btnCalculatePattern.Enabled = false;
        btnSendData.Enabled = true;
    }
    private void UpdateCoordinates(string startingPoint)
    {
        // The startingPoint is the ending point of the last iteration
        listBox1.Items[0] = startingPoint;

        var startingPointSplit = startingPoint.Split(".");
        var startingPoint_x = Convert.ToInt32(startingPointSplit[0]);
        var startingPoint_y = Convert.ToInt32(startingPointSplit[1]);

        // Calculate the rest of the coordinates for this iteration from
        // the starting point and the pattern

        var x = startingPoint_x;
        var y = startingPoint_y;

        for (int i = 0; i < listBox1.Items.Count; i++)
        {
            var pattern = listBox2.Items[i].ToString().Split('.');
            var pattern_x = Convert.ToInt32(pattern[0]);
            var pattern_y = Convert.ToInt32(pattern[1]);

            x += pattern_x;
            y += pattern_y;

            listBox1.Items[i] = $"{x}.{y}";
        }
    }

    private void SendDataToArduino()
    {
        // Send commands with the current state of Coordinates

        if (currentIndex < listBox1.Items.Count)
        {
            command = listBox1.Items[currentIndex].ToString();
            command = command.Replace(": ", ""); // Remove the colon
            command = command.Replace(",", ""); // Remove comma if needed

            //We move the visual avatar and print the coordinates to the console
            // to simulate the motor receiving the commands 
            // serialPort1.WriteLine(command);
            Console.WriteLine(command);
            MoveAvatar(command);

            textBox3.Text = command;

            currentIndex++; // Move to the next item

        }
        else
        {
            // Tüm veriler gönderildi, işlemi yeniden başlat
            currentIndex = 0;

            // Update the Coordinates in the listBox with the Pattern information
            // passing the last point of the current iteration
            // as the starting point of the next iteration.
            UpdateCoordinates(command);
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        SendDataToArduino();
    }
}