リアルタイムアプリケーションでのBresenhamのアルゴリズム-パート2

投稿「 リアルタイムアプリケーションでのBresenhamのアルゴリズム 」の続き。



レーザースキャナー用の出力プログラムを書いていることを思い出してください

画像



私の場合、レーザースキャナーは、いわゆるレーザーステレオリソグラフィーの設置に使用されます。ここでは、液体フォトポリマーの表面にUVレーザービームで描画が行われます。 紫外線を目で見ることは不可能ですが、 高調波基本的な波長ではないレーザーで発生する可視領域の比較的低いパワーの放射)と、フォトポリマーまたは普通の白いコート紙からの蛍光を見ることができます。

画像

この写真では、わずかにフォトポリマーを含浸させたコート紙に、厚さ約1 mmのフォトポリマーの層がカバーガラス上に堆積し、その上にHabréのお気に入りの言葉が描かれています。 左側は、描画後にビームが進む「堆積ポイント」です。 パターンとスラッジポイントの間のトレースはアイドルビーム転送です 。これは、紙の蛍光の著しい残光のためにのみ見られます。 前述のアルゴリズムの観点から、この転送は順次実行として表すことができます

putXY(x,y, wait); // , x=32000, y=32000 putXY(x0,y0, wait); // y, x0=100, y0=100 -  
      
      







優れたスキャナーでは、「ジグザグ」や「ループ」は見られません。 少なくとも目で。



近くに携帯電話などの電磁干渉の原因がある場合は、これを取得できます

画像



コート紙なしでは、アイドル状態の転写は見られません

画像



アルゴリズムに戻りましょう。 ブレゼンハムアルゴリズムの提案された実装の実装の結果として、最初の部分のコメントで誰も推測しませんでした。

そして、私たちはそのようなものを見るでしょう

画像



左側に表示されるもの(これはPhotoshopであり、良心が間違ったプログラムをコントローラーにアップロードすることを許可していません)、右側に表示されるものです。

短い明るい線は、スキャン速度が時々低下することを示しています。 コントローラーにマルチタスクとオペレーティングシステムがない場合、どのように減らすことができますか? 非常にシンプル-中断があります! DACに発行する以外に、コントローラーに他の機能が読み込まれていない場合でも、制御コンピューターとの通信に関連する中断があります。 たとえば、UART(COMポート)またはイーサネット経由。 中断にはそれほど時間はかからないようで、調査をそれほど頻繁に行わないようです。 ラインを短くしてポイントに変えることもできますが、そのような遅延の実装では完全にそれらを取り除くことは不可能です



 void putpixel(int x, int y, int wait)) { outPortX(x); //    X  x outPortY(y); //    Y  y delay(wait); //  wait   }
      
      







多くの場合、マイクロコントローラーのプログラミングの遅延は単純なカウンターで行われます

 void delay(int wait) //  wait  "" { int i; for(i=0;i<wait; i++); }
      
      







安くて怒っている。 中断が発生した場合、そのような遅延の実装は、プログラムが別の場所に「移動」し、必要な時間が経過したことを知ることはありません。 イデオロギー的に正確な遅延は、ハードウェアタイマーカウンターを使用します

 void delay(int wait) { unsigned int t0; t0 = /LPC_TIM1->TC //LPC_TIM1->TC -          LPC 17xx while(LPC_TIM1->TC - t0 < wait); }
      
      







この場合、遅延機能は、発生した割り込みについて自動的に学習しますが、プロセッサの「ビートに合わせた」絶対精度を保証するものではありません。 プログラムがほとんどの時間を遅延に費やす場合、これは制限される可能性がありますが、動きが速い場合、ハードウェアタイマーの使用はエンドツーエンドである必要があります。

 /* real time Bresenham alg. implementation */ void Line(int x1, int y1, int x2, int y2, int wait) { int x1,y1,dx,dy,sx,sy,d,d1,d2; unsigned int t0 = LPC_TIM1->TC; int i, x,y; if( x2 >= x1) { dx = x2 - x1; sx = 1; } else { dx = x1 - x2; sx = -1; } if( y2 >= y1) { dy = y2 - y1; sy = 1; } else { dy = y1 - y2; sy = -1; } /****************************/ if(dy <= dx) { d = (dy << 1) - dx; d1 = dy << 1; d2 = (dy - dx) << 1; for(x=x1+sx,y=y1,i=1; i <= dx ; i++,x+=sx) { if(d > 0) { d += d2; y += sy; putXY(x,y,wait,&t0); } else { d += d1; putX(x, wait, &t0); } } } else { d = (dx << 1) - dy; d1 = dx << 1; d2 = (dx - dy) << 1; for(x=x1,y=y1+sy,i=1;i <= dy ; i++,y += sy) { if(d > 0) { d += d2; x += sx; putXY(x,y,wait, &t0); } else { d += d1; putY(y, wait, &t0); } } } /* endif(dy <=dx) */ } void putXY(int x, int y, int wait, unsigned int *pT0) { outPortXY(x,y); //    X  Y  x  y //    #define outPortXY(x,y) outPortX(x); outPortY(y); /*  wait   */ while(LPC_TIM1->TC - *pT0 < wait); *pT0 += wait; } void putX(int x, int wait, unsigned int *pT0) { outPortX(x); //    X  x /*  wait   */ while(LPC_TIM1->TC - *pT0 < wait); *pT0 += wait; } void putY(int y, int wait, unsigned int *pT0) { outPortY(y); //    Y  y /*  wait   */ while(LPC_TIM1->TC - *pT0 < wait); *pT0 += wait; }
      
      







このオプションでは、1チャンネルまたは2チャンネルのDACへの出力の異なる時間の両方が自動的に考慮され、出力が準備完了になるまで使用される場合の出力時間の広がりも考慮されることに注意してください。



この実装では、可能性のある割り込みがLine()関数内で考慮されます;この関数の外部では、実行時間に対する割り込みの影響を明示できます。 一般的なケースで何をすべきかを読者が推測するのが難しくないことを願っています。



そして最後に-プログラムをだまされた場合、予想されるテストの円と正方形の代わりに、最も予期しない波線を見ることができます。

画像

この場合、「ほとんどすべてが機能しました」、奇妙な歯だけが現れました。 結局のところ 、1行はy + = syです。 x + = sxに置き換えられました 。 ところで、ラップトップのランダムなタッチパッドが原因です。



All Articles