ラベル mini の投稿を表示しています。 すべての投稿を表示
ラベル mini の投稿を表示しています。 すべての投稿を表示

2016年6月11日土曜日

SmartLaser用のアプリを0から開発する。その3

SmartLaserCO2というのを研究開発目的で購入、
ソフトウェアの研究開発を開始です。
さて、codeを書いてみます。
ちょっと書きっぱなしな感じなのですが、テストとしてはこんな感じです。
起動して移動させてそれからリセット(HOMEへの移動)をさせてますが、
たぶん、このままではうまく動かないです。
タイミングをうまくとらないと、ダメですね。
ここらへんは、SleepやらRecieveのバイト数やら、いろいろやることになります。
実際にはデバッガでところどころ止めながらやってみたので、うまく動作したですね。

謎の文字列はどっから引っ張ってきたかというと、実際に元々のソフトウエァを動かして、
SerialPortMonitorなるものでキャップったからですね(o^^o)

int aCom::test01(void){
 HANDLE cPort = ::CreateFileA("\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
 DCB dcb;     // シリアルポート構成情報STRUCT
 ::GetCommState(cPort, &dcb);// 現在の設定値をGET
/*
 dcb.BaudRate  = 57600;  // 速度
 dcb.ByteSize  = 8;   // データ長
 dcb.Parity   = NOPARITY;  // パリティ
 dcb.StopBits  = ONESTOPBIT; // ストップビット長
 dcb.fOutxCtsFlow = 0;   // 送信時CTSフロー
 dcb.fRtsControl  = RTS_CONTROL_ENABLE; // RTSフロー
*/
 ::SetCommState(cPort, &dcb); // 取得したまま書き込む。こうしないと、データが戻らない?

 unsigned long errors = 0;
 COMSTAT comStat;
 ::ClearCommError(cPort, &errors, &comStat);
 int lenR = comStat.cbInQue; // 受信したメッセージ長を取得する

 for(int w=0;w<20;w++){
  if(lenR) break;
  ::Sleep(500);
  ::ClearCommError(cPort, &errors, &comStat);
  lenR = comStat.cbInQue;
 }
 if(!lenR){
  // Error
  printf("error-01\n");
//  return 0;
 }
 if(lenR > 100){
  // Error
  printf("error-02\n");
//  return 0;
 }
 char rBuf[10000];
 memset(rBuf,0,sizeof(rBuf));
 unsigned long nPut = 0;
 unsigned long nRead = 0;
 ::ReadFile(cPort, rBuf, lenR, &nPut, 0); // バッファからREAD
 // テスト環境では、【# LasaurGrbl 14.01\x0a】
 if(!strstr(rBuf,"LasaurGrbl")){
  // Error
  printf("error-03\n");
//  return 0;
 }else{
  printf("LasaurGrbl OK!\n");
 }

 ::WriteFile(cPort, "\x14", 1, &nPut, 0); // ポートへPUT
 memset(rBuf,0,sizeof(rBuf));

 ::ReadFile(cPort, rBuf, 10, &nRead, 0);  // バッファからREAD

 // 謎の文字列送信
 ::WriteFile(cPort, "\x5e\x9f\x3f\x0a\x2a\x9f\x3f\x0a", 8, &nPut, 0);
 memset(rBuf,0,sizeof(rBuf));

 ::ReadFile(cPort, rBuf, 100, &nRead, 0); // バッファからREAD

//::Sleep(2000);




 ::WriteFile(cPort, "G90\x0aM80\x0aG0F8000\x0aG1F1500\x0aS77\x0a", 28, &nPut, 0);
 memset(rBuf,0,sizeof(rBuf));
 ::ReadFile(cPort, rBuf, 100, &nRead, 0); // バッファからREAD



 // 移動させてみる。
 ::WriteFile(cPort, "G0X150.0Y150.0\x0a", 15, &nPut, 0);
 memset(rBuf,0,sizeof(rBuf));
 ::ReadFile(cPort, rBuf, 100, &nRead, 0); // バッファからREAD

 // レーザーさせてみる。
 ::WriteFile(cPort, "G1X130.0Y130.0\x0a", 15, &nPut, 0);
 memset(rBuf,0,sizeof(rBuf));
 ::ReadFile(cPort, rBuf, 100, &nRead, 0); // バッファからREAD


 // 戻す
 ::WriteFile(cPort, "M81\x0aS0\x0aG0X0Y0F8000\x0a", 19, &nPut, 0);
 memset(rBuf,0,sizeof(rBuf));
 ::ReadFile(cPort, rBuf, 100, &nRead, 0); // バッファからREAD





//::Sleep(2000);

 // 謎の文字列送信原点の移動?
 ::WriteFile(cPort, "\x21\x0a", 2, &nPut, 0);
 ::WriteFile(cPort, "\x5e\x80\x7e\x0a\x2a\x80\x7e\x0a\x5e\x95\x47\x33\x30\x0a\x2a\x95\x47\x33\x30\x0a", 20, &nPut, 0);

 memset(rBuf,0,sizeof(rBuf));

 nRead = 0;
 while(nRead == 0)
 ::ReadFile(cPort, rBuf, 100, &nRead, 0); // バッファからREAD

 printf("%s\n",rBuf);
 ::CloseHandle(cPort); // シリアルポートを閉じる
 return 0;
}

2016年6月8日水曜日

SmartLaser用のアプリを0から開発する。その2

SmartLaserCO2というのを研究開発目的で購入、
ソフトウェアの研究開発を開始したのですが、、、、
いろいろ試してみて、現時点で品質を決定づける要因と、
ソフトウェアでカバーできうる可能性を考えます。

今回気づいた点をあげてみますと、
【1】 ラスタモードでの実用性はどうなのか?
【2】 VLS2.30との品質の比較で負けている点はカバーできるのか?
まず、出来上がりを見てみましょう。
以下の2つはVLS2.30というキカイで、MakersBaseというところでやってみたものです。
 
かなりキレイです。
但し、これ、全て閉領域の塗り(FILL)でデータをつくっています。
これを加工していて気づいた点は、全て、走査線のように、
キカイが動いていたという点です。

次にSmartLaserCO2での加工を見てみます。
まず、画像をラスタで加工してみました。
 
うぅーーん。かなり残念の結果です。
これ、このキカイにおける(というかArduinoにのってるソフトウェア?)ラスタデータの宿命なのかもしれません。
DOTを打っているかの如く、点々の集合のようになってしまいました。
もちろんすべてが画像データなので、走査線のように、キカイが動いていました。

次に、閉領域の如く、ハッチをつけたデータにしてみます。

ううぅぅぅーーん。これはまた究極的に残念な結果です。
走査線のように、キカイが動いているわけではありませんでした。
まぁもちろん、Arduino側でうまくソートがかかっているのかもしれませんが、
ここは時間を犠牲にしてでも、走査線のように動いて欲しかったですね。
とにかく美しくない仕上がりです。

さて、まぁまだ試作段階なので、これからがチューンです。
そもそもVLS2.30レベルの品質まであげることがソフトウェアだけでできるかどうかは、
現時点ではまだわかりません。
例えば、レーザー出力管の出力安定性が劣る場合には、それをソフトウェアでカバーすることは不可能です。

とりあえず方針をたて、さらにテストしながらトライ&エラー的に進めるしかないようです。

(1)データを、画像、閉領域、ベクタ図形の3種類にわけて読み込む。
(2)画像はBITフィールドのようなRAWデータと、走査線的なデータ変換の2種類のGコードの出力が可能なようにする。
(3)走査線の感覚は指定できるようにする。
(4)線幅に対応する。これはズラしてベクタデータを2重3重4重、、、、、に描かれているかのごとくヘッドが動くように考える。


現段階では、【カットには使えるけれど、彫刻的にはこのままの品質だと残念過ぎる 】
とい感じですね。


つづく

2016年6月3日金曜日

SmartLaser用のアプリを0から開発する。その1

SmartLaserCO2というのを研究開発目的で購入したのですが、

出力用のアプリがかなり残念な出来なので、
これを0からというか1から開発してみます。
まぁもちろん、前情報としてかなり問題があること自体はわかっていて
手持ちのイラレで作ったSVGがかなりの確率で読み込めませんし、
閉領域もNGだし、画像もかなりアバウトです。

※Pythonコードに手を入れるというメンドイことはやりません。^^;



最初の段階でやってみるのは、解析とテストです。
幸い、現状のアプリにはGコード出力機能があるので、それを多少の手がかりにして進めます。


今回は、SmartlaserCo2(mini)は、USB接続によるCOMポート出力なので、
COMポート一覧を取得してSmartLaserが接続されているCOMポートかどうかを判断する部分から始めます。
ということで、C++(Windows)で書くと、こんな感じ。
JSONを扱うクラスが数か所でてきますが、これは値を保存する構造体代わりに使っています。
取得したサンプルはこんな感じ。
/*
    COMポートリスト取得
    ↓結果サンプル
{
    "comlist":[
        {
            "friendlyname":"通信ポート (COM1)"
            ,"name":"COM1"
        }
    ]
}
*/
コードはこんな感じです

int aCom::getComList(aDom8* pZ){
    aDom8& Z = *pZ;    //    JSON-Object
    char    buffer[256];
    memset(buffer,0,sizeof(buffer));
    DWORD    Length = 0;
    HDEVINFO hDevInfo = ::SetupDiGetClassDevs( &GUID_DEVINTERFACE_COMPORT, NULL, 0/*hwnd*/, ( DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ) );
    DWORD w=0;
    SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};
    for(w=0; ::SetupDiEnumDeviceInfo( hDevInfo, w, &DeviceInfoData ); w++){
        ::SetupDiGetDeviceRegistryPropertyA( hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, 0, (unsigned char*)buffer,sizeof(buffer),&Length );
        Z[w]["friendlyname"] = (const char*)buffer;    //    JSON-Object
        HKEY key = ::SetupDiOpenDevRegKey( hDevInfo, &DeviceInfoData,  DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE );
        if(key){
            DWORD type = 0;
            DWORD size = sizeof( buffer );
            ::RegQueryValueExA(key,  "PortName", 0, &type, (unsigned char*)buffer, &size);
            Z[w]["name"] = (const char*)buffer;    //    JSON-Object
        }
    }
    return    w;
}

っと、ここまではよかったのです。
きっと、【Arduino Mega 2560(COM3)】みたいな感じで、friendlynameが取れると思ってたのです。
しかし、、、残念ながらこのやりかたでは、仮想COMが取れませんでした。
んーーー。
仕方ない。。。WDKいれて、やるか。。。(>_<)

つづく。