Hello Guest it is April 20, 2024, 02:30:33 AM

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - CWare

Pages: 1
1
Hi everyone,


this took me a few days to figure out...

I must thank rhtuttle for pointing me in the right direction
and ART for giving me a list of commands and a few more tips.
If you found this helpful make sure to thank those guys.

The following code will
Connect to Mach 3
reset mach
, home the axes
, close any open file
, load a specified file
,rewind it
, set feedrate to 300%
and CycleStart

          

If anyone has a full list with the button numbers that would be a great help, Mach needs to ref all home before cyclestart idk what the buttonr is though...

If you spot any errors or have suggestions or found something cool to add  please post them below.
What should be added is some way to check if mach is ready to cyclestart that usleep is ugly and also reset should check if the reset already occurred...




Compiled In Code::Blocks with the MinGW compiler->linker settings
-lole32
-loleaut32
-luuid



Code: [Select]
#include <iostream>
#include <ole2.h>
#include <Windows.h>
#include <Objbase.h>
#include <OleAuto.h>
#include <cstring>
#include <string.h>
#include <unistd.h>



CLSID   clsid,clsid2;
bool connected;

using namespace std;


TCHAR *GetLastErrorMessage(DWORD last_error)
{
    static TCHAR errmsg[512];
    if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,last_error,0,errmsg,511,NULL)) {
        return (GetLastErrorMessage(GetLastError()));
    }

    return errmsg;
}



HRESULT OLEMethod(int nType, VARIANT *pvResult,
                  IDispatch *pDisp,LPOLESTR ptName, int cArgs...)
{
    if(!pDisp) return E_FAIL;

    va_list marker;
    va_start(marker, cArgs);

    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    DISPID dispID;
    char szName[200];

    // Convert down to ANSI
    WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);

    // Get DISPID for name passed...
    HRESULT hr= pDisp->GetIDsOfNames(IID_NULL, &ptName, 1,
                                     LOCALE_USER_DEFAULT, &dispID);
    if(FAILED(hr)) {
        return hr;
    }
    // Allocate memory for arguments...
    VARIANT *pArgs = new VARIANT[cArgs+1];
    // Extract arguments...
    for(int i=0; i<cArgs; i++) {
        pArgs[i] = va_arg(marker, VARIANT);
    }

    // Build DISPPARAMS
    dp.cArgs = cArgs;
    dp.rgvarg = pArgs;

    // Handle special-case for property-puts!
    if(nType & DISPATCH_PROPERTYPUT) {
        dp.cNamedArgs = 1;
        dp.rgdispidNamedArgs = &dispidNamed;
    }

    // Make the call!
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                       nType, &dp, pvResult, NULL, NULL);
    if(FAILED(hr)) {
        return hr;
    }

    // End variable-argument section...
    va_end(marker);
    delete [] pArgs;
    return hr;
}



void CloseMach(LPDISPATCH &InterfPtr)
{
    HRESULT ivres;

    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    ivres=InterfPtr->Invoke(0x4, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                            DISPATCH_METHOD, &dp, NULL, NULL, NULL);


    cout<<GetLastErrorMessage(ivres)<<endl;



}


void LoadFile(LPDISPATCH &InterfPtr, OLECHAR*Filename)
{
    HRESULT ivres;

    VARIANT vtFileName;
    vtFileName.vt = VT_BSTR;
    vtFileName.bstrVal = SysAllocString(Filename);


    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"LoadGCodeFile", 1, vtFileName );             // reversed order is using more options


    cout<<GetLastErrorMessage(ivres)<<endl;



}


void CloseFile(LPDISPATCH &InterfPtr)
{
    HRESULT ivres;

    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    ivres=InterfPtr->Invoke(0x2, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                            DISPATCH_METHOD, &dp, NULL, NULL, NULL);


    cout<<GetLastErrorMessage(ivres)<<endl;

}


void CycleStart(LPDISPATCH &InterfPtr)
{
    HRESULT ivres;

    DISPPARAMS dp = { NULL, NULL, 0, 0 };


    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"CycleStart", NULL, dp );
    cout<<"CycleStart"<<GetLastErrorMessage(ivres)<<endl;

}



void RewindGcode(LPDISPATCH &InterfPtr)
{
    HRESULT ivres;

    DISPPARAMS dp = { NULL, NULL, 0, 0 };


    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"RewindGcode", NULL, dp );
    cout<<GetLastErrorMessage(ivres)<<endl;

}


void SetFRO(LPDISPATCH &InterfPtr,double FeedOverride)
{
    HRESULT ivres;

    VARIANT FRO;
    FRO.vt = VT_R8;
    FRO.dblVal = FeedOverride;


    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"SetFRO", 1, FRO );             // reversed order is using more options


    cout<<GetLastErrorMessage(ivres)<<endl;


}


void Reset(LPDISPATCH &InterfPtr)
{
    HRESULT ivres;


    VARIANT BNnr;
    BNnr.vt = VT_I2;
    BNnr.iVal = 21;

    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"DoButton",1,BNnr );             // reversed order is using more options

    cout<<GetLastErrorMessage(ivres)<<endl;


}



IDispatch* GetScriptDispatch(LPDISPATCH &InterfPtr)
{
    HRESULT ivres;


    VARIANT result;
    VariantInit(&result);
    ivres=    OLEMethod(DISPATCH_PROPERTYGET, &result, InterfPtr, L"GetScriptDispatch", NULL, NULL );             // reversed order is using more options
    return(result.pdispVal);

    cout<<GetLastErrorMessage(ivres)<<endl;


}


void HomeAll(LPDISPATCH &InterfPtr)
{

    HRESULT ivres;


    VARIANT BNnr;
    BNnr.vt = VT_I2;
    BNnr.iVal = 24;

    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"DoButton",1,BNnr );             // reversed order is using more options

    cout<<GetLastErrorMessage(ivres)<<endl;


    BNnr.vt = VT_I2;
    BNnr.iVal = 23;

    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"DoButton",1,BNnr );             // reversed order is using more options

    cout<<GetLastErrorMessage(ivres)<<endl;


    BNnr.vt = VT_I2;
    BNnr.iVal = 22;

    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"DoButton",1,BNnr );             // reversed order is using more options

    cout<<GetLastErrorMessage(ivres)<<endl;

    BNnr.vt = VT_I2;
    BNnr.iVal = 25;

    ivres=OLEMethod(DISPATCH_METHOD, NULL, InterfPtr, L"DoButton",1,BNnr );             // reversed order is using more options

    cout<<GetLastErrorMessage(ivres)<<endl;

}





void OnBnClickedConnect()
{
    LPUNKNOWN lpUnk;
    LPDISPATCH lpDispatch=NULL;
    LPDISPATCH Scripter=NULL;

    //COleException e;
    HRESULT res;

// Initialize COM for this thread...
    CoInitialize(NULL);


    // Get CLSID for our server...

    if (CLSIDFromProgID(L"Mach4.Document", &clsid) != NOERROR)

    {
        cout << "error CLSIDFromProgID" << endl;
        return;
    }

    if (res = GetActiveObject( clsid, NULL, &lpUnk) == NOERROR) {
        HRESULT hr = lpUnk->QueryInterface(IID_IDispatch,
                                           (LPVOID*)&lpDispatch);  //get a pointer to the object's IDispatch interface.

        lpUnk->Release();

        if (hr == NOERROR) {


            connected = true;
            cout << "connected" << endl;


            Scripter=GetScriptDispatch(lpDispatch);


            if(Scripter!=NULL) {

                cout << "gotScripter" << endl;
                Reset(Scripter);
                HomeAll(Scripter);
                CloseFile(lpDispatch);
                LoadFile(lpDispatch, L"C:\\R1.ngc");
                RewindGcode(lpDispatch);
                SetFRO(lpDispatch,300.0);
                usleep(300000);
                CycleStart(lpDispatch);


            }








        }

        //m_Status = "Connected to Mach3.";
        // UpdateData(false);
        // SetTimer( NULL,1, 200, NULL );





        return ;
    } else {

        cout << "error GetActiveObject" << endl;

    }
    //m_Status = "No Connection to Mach3.";
    //UpdateData(false);
    // Uninitialize COM for this thread...
    CoUninitialize();
   if(lpDispatch!=NULL){
    free(lpDispatch);
    
   }
   if(Scripter!=NULL){
    free(Scripter);
    }

}







int main()
{
    connected = false;

    OnBnClickedConnect();

    return 0;
}




Mach3 should be running. If this fails to connect make sure you got all registry keys...


Code: [Select]
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{CA7992B2-2653-4342-8061-D7D385C07809}]
@="Mach4.Document"

[HKEY_CLASSES_ROOT\CLSID\{CA7992B2-2653-4342-8061-D7D385C07809}\InprocHandler32]
@="ole32.dll"

[HKEY_CLASSES_ROOT\CLSID\{CA7992B2-2653-4342-8061-D7D385C07809}\LocalServer32]
@="C:\\Mach3\\Mach3.exe"

[HKEY_CLASSES_ROOT\CLSID\{CA7992B2-2653-4342-8061-D7D385C07809}\ProgID]
@="Mach4.Document"

[HKEY_CLASSES_ROOT\Mach4.Document]
@="Mach4.Document"

[HKEY_CLASSES_ROOT\Mach4.Document\CLSID]
@="{CA7992B2-2653-4342-8061-D7D385C07809}"

Thanks to machpendant for that regfix.



Use at your own risk...

2
Trying to figure out if mach is the right choice. Tldr in bold^^
Not exactly a hobby mill i'm running its a fast cutting machine (F15000) with a toolchanger...


Because of a limited step frequency (125khz) of the controller i'm using (EdingCnc) I'm considering switching to Mach3/4 on a VitalSystem DSPMC 7762 controller.

I would need to control mach from an external cam like program though.
I can alter that program if needed (c++).

I want mach just to launch on startup(thats no problem) sit in the background shut up and execute gcode when it recieves it.


The way I achieved this on the EdingCnc controller...
EdingCnc watches for filechange on a specified path.
When it detects a filechange you have the option in setup that it refreshes and starts execution immediately.

Is that possible with mach? If not i'll have to write something like mach for the DSPMC 7762   T.T (would take a while)
Or any tips on a real time fast controller  which is highly configurable? DSPMC  seemed to be the closest, idk what a siemens  costs or if it is better.

Also is there some conditional statement that can't be realized with macros?Is it burdensome to use?












Pages: 1