Search code examples
c#serial-portgrasshopperg-code

Sending the right Gcode string to a Serial Port?


I am trying to send the gcode g28 to my RepRap 3D printer through the line port.Write("g28");.

My program connects to the right serial port however when I try sending the information as string the access to the com port gets denied. This is strange because the Serial port was open before sending the Gcode to it. It even sent some data back. What is the problem there and how could i fix it?

Below are the lines of code that I am using. The list of gcode commands are available on this page.

I have tried adding a "\n" at the end of the string but it did not work.

    //Fields
    List<string> myReceivedLines = new List<string>();


    //subscriber method for the port.DataReceived Event
    private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        while (sp.BytesToRead > 0)
        {
            try
            {
                myReceivedLines.Add(sp.ReadLine());
            }
            catch (TimeoutException)
            {
                break;
            }
        }
    }


    protected override void SolveInstance(IGH_DataAccess DA)
    {

        string selectedportname = default(string);
        DA.GetData(1, ref selectedportname);
        int selectedbaudrate = default(int);
        DA.GetData(2, ref selectedbaudrate);
        bool connecttodevice = default(bool);
        DA.GetData(3, ref connecttodevice);
        bool homeall = default(bool);
        DA.GetData(5, ref homeall);

        SerialPort port = new SerialPort(selectedportname, selectedbaudrate, Parity.None, 8, StopBits.One); 

        port.DtrEnable = true;   
        port.Open();             

        if (connecttodevice == true)
        {
            port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            DA.SetDataList(0, myReceivedLines);
        }

        if (homeall == true)
        {
            port.Write("g28");
        }

    }

Solution

  • Usually when I create a Com Port it is a Class level object that I initialize once during startup. I would move your Initialization Code out of your method and into the Constructor or a Method that you can call once during your startup. That should prevent you from trying to open it more than once and still leave it available to respond to Received data.


    I am not sure of your architecture it looks like you may be planning to have multiple ports but to answer your question in the comments, everything that you are doing to create the SerialPort. At the bare minimum the declaration for the SerialPort should be a Class Level variable. You could then check to see if it was nothing and create it the first time.

    string selectedportname = default(string); 
    DA.GetData(1, ref selectedportname); 
    int selectedbaudrate = default(int); 
    DA.GetData(2, ref selectedbaudrate); 
    bool connecttodevice = default(bool); 
    DA.GetData(3, ref connecttodevice); 
    
    SerialPort port = new SerialPort(selectedportname, selectedbaudrate, Parity.None, 8, StopBits.One);   
    port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    
    DA.SetDataList(0, myReceivedLines);   
    
    port.Open();  // optional  I usually open it at the time that I initialize it. you can check `port.IsOpen()`
                  // and Open it if it is false.
    

    second option with a Class Level SerialPort Try something like this:

    protected override void SolveInstance(IGH_DataAccess DA)
    {
        if(port == null)
        {
            string selectedportname = default(string);
            DA.GetData(1, ref selectedportname);
            int selectedbaudrate = default(int);
            DA.GetData(2, ref selectedbaudrate);
            bool connecttodevice = default(bool);
            DA.GetData(3, ref connecttodevice);
            port = new SerialPort(selectedportname, selectedbaudrate, Parity.None, 8, StopBits.One);
            if (connecttodevice == true)
            {
                port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                DA.SetDataList(0, myReceivedLines);
            }
    
            port.DtrEnable = true;
            port.Open();
        }
    
    
        bool homeall = default(bool);
        DA.GetData(5, ref homeall);
    
        if (homeall == true)
        {
            port.Write("g28");
        }
    
    }