4

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");
        }

    }
Arthur Mamou-Mani
  • 2,303
  • 10
  • 43
  • 69
  • *"the access to the com port gets denied when it was not before."* - Before what? Have you tried a *capital* (aka upper case) "G"? – sawdust Oct 14 '12 at 23:08
  • @sawdust Before sending the Gcode to the Serial Port, I have just updated the question. Thank you very much. – Arthur Mamou-Mani Oct 14 '12 at 23:12
  • 1
    *"port.Write("g28")"* - "g28" is not even listed as a valid operation; what operation are you trying to do? The "G" or "M" has to be capitalized, and you do need to terminate the line with a "\n". *"It even sent some data back."* - What was that message? – sawdust Oct 14 '12 at 23:21
  • @sawdust the `G28`command is used to bring all the axis back to the origin 0 (hence "home all"). You are right, I didn't even realize that I used `g` instead of `G`. I have now sent `port.Write("G28"+"\n");` to the machine from my program but it still changes the access to the Com Port and does not work... – Arthur Mamou-Mani Oct 14 '12 at 23:27
  • 1
    I am presuming that SolveInstance is being called just one time, otherwise the port will be locked by the Com Port being created during the first time it was called. – Mark Hall Oct 14 '12 at 23:37
  • @MarkHall how could I check if SolveInstance is called several times? It is very possible that it is called every time the `if` statement is running (which is the condition for the gcode to be sent). How could I prevent that from happening. I think that is a possible reply. – Arthur Mamou-Mani Oct 14 '12 at 23:49
  • 1
    @ArthurMamou-Mani Try putting a port.Close() at the end of your Method. – Mark Hall Oct 14 '12 at 23:51
  • Thanks a lot @MarkHall, does this mean that I will need to connect again to the Serial Port every time SolveInstance runs? Connecting more than once to serial port might block access to it... Is it not possible to separate the if statements from the SolveInstance method instead? I have tried the port.Close() and now I am not receiving feedback from the machine but the access is not denied anymore when running the Gcode commands. This might be a progress? – Arthur Mamou-Mani Oct 15 '12 at 00:05

1 Answers1

3

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");
    }

}   
Mark Hall
  • 53,938
  • 9
  • 94
  • 111
  • Thank you very much, what would you include in the `Initialization Code` from the code above? – Arthur Mamou-Mani Oct 15 '12 at 00:22
  • Sorry if I take out all the `if` statements from the SolveInstance, how will I be able to access them from my program as the SolveInstance() method is the place where I can assign data to it? Thanks so much. – Arthur Mamou-Mani Oct 15 '12 at 00:31
  • @ArthurMamou-Mani See the second option, the main thing is to keep from creating multiple SerialPorts. – Mark Hall Oct 15 '12 at 00:42
  • Thank you very much @MarkHall, with the second option I get an error when turning `HomeAll` on: `Error: Solution exception: A device attached to the system is not functioning` Then when I turn on other commands and while the port is supposed to be connected I get: `Error:Solution exception: The port is closed.` The errors disapear when all the commands are on false. I only want to connect to one device. I don't get the message `access denied` anymore which is a positive thing even when turning off and on the `ConnecttoDevice` buttton multiple times. – Arthur Mamou-Mani Oct 15 '12 at 09:57
  • Update: Thanks to your reply I managed to send the gcode and the machine reacted in the right way (so this is the correct answer) but I don't get the feedback anymore. i will work on that. – Arthur Mamou-Mani Oct 15 '12 at 11:23
  • @ArthurMamou-Mani Glad to be of some help. – Mark Hall Oct 15 '12 at 11:44