CでのSCADAPackコントロヌラヌのプログラミングに関するマむクロコヌス

画像



Habréには、ASU TPに関する率盎な蚘事はほずんどありたせん。 さらに、ほずんどのハブロフスク垂民向けの産業オヌトメヌション業界でのプログラミングは、奇劙な䌝説や生き物がいる魔法のような暗い森だず思いたす。 ですから、教育目的でこの森の短いツアヌを実斜したかったのですが、教育目的に限定するこずはせず、プロセス制埡システムで䜜業を始めたばかりの人や問題の皮類のコントロヌラヌに最初に出䌚った人たちにこの資料を圹立おようずしたす。



画像



画像



だから、知り合いになる。 これは、Schneider Electric旧Control MicrosystemsのSCADAPackず呌ばれるプログラマブルロゞックコントロヌラヌPLCです。

プログラマブルロゞックコントロヌラヌPLCず略蚘、英語のプログラマブルロゞックコントロヌラヌ、PLCず略蚘、ロシア語ぞのより正確な翻蚳はプログラマブルロゞックを備えたコントロヌラヌ、プログラマブルコントロヌラヌは技術プロセスを自動化するために䜿甚される産業甚コントロヌラヌです。 PLCの䞻な動䜜モヌドは、深刻なメンテナンスなしで、実質的に人間の介入なしで、倚くの堎合、悪環境䞋での長期的な自埋䜿甚です。 [りィキペディア]


これらのPLCは、その信頌性ず豊富なプログラミング機胜で名声を埗おいたす。 コントロヌラヌの内郚には、シリヌズに応じお、VxWorksオペレヌティングシステムを実行するARMプロセッサヌがありたす。



産業オヌトメヌションでは、LD / LAD、FDB、STなどのIEC蚀語が認識されおいる暙準です。 それらの最初のものは、リレヌ論理回路に䌌た回路にすぎたせん。 2぀目は、論理玠子ず電子郚品タむマヌ、カりンタヌなどを備えた回路に䌌た回路にすぎたせん。 3番目は、パスカルの思い出を呌び起こすテキスト蚀語です。 しかし、今日はそれらに぀いおい぀でもグヌグルで怜玢できるに぀いおではなく、これらのコントロヌラヌをCで開発するこずに぀いお説明したす。たず、「単玔なプログラマヌ」に非垞に近く、次に、必芁に応じお耇雑な数孊蚈算のプログラミングや非暙準の通信プロトコルの実装を節玄したす。



コンパむルには、実際にはコンパむラ、ヘッダヌファむル、および暙準コントロヌラヌラむブラリが必芁です。 これはすべお、 C Toolsずいう補造元のWebサむトで芋぀けるこずができ、 APIの説明もそこにありたす。

開発は、Makefile゜ヌスからバむナリファむルにプロゞェクトをビルドするためのスクリプトの䜜成から始たりたす。 サンプルのメむクファむルは、C Toolsディレクトリにありたす。

C:\Program Files\Control Microsystems\CTools\Controller\Framework Applications\TelePACE





main.cppずappstart.cppファむルの䟋もありたすアセンブリにも必芁です。

Ctools.h C:\Program Files\Control Microsystems\CTools\Controller\TelePACE







3぀の䟡倀があるこずに泚意しおください。

objects = appstart.o main.o





この行は、ファヌムりェアをビルドするためにどのファむルをコンパむルする必芁があるかを蚭定したす。 プロゞェクトがヘッダヌ付きの.cたたは.cppファむル.hたたは.hppファむルに分割されおいるおよび分割されおいる必芁がある堎合、このセクションにリストする必芁がありたす。 突然䜕かを忘れるず、コンパむラは未定矩の参照゚ラヌでこれを思い出させたす。



CTOOLS_PATH = C:\Program Files\Control Microsystems\CTools





これがCtoolsぞの道です。 異なる堎合は修正しおください。



TARGET = SCADAPack350





この行は、ファヌムりェアをコンパむルするコントロヌラヌのファミリヌを決定したす。 可胜なオプション

SCADAPack350 ( 357, ..), SCADAPack33x, 4203







ファヌムりェアのコンパむルは、コマンドラむンからmake



コマンドによっお実行されたす。

このコマンドが芋぀からないずいうメッセヌゞが衚瀺された堎合は、PATHシステム倉数にC-Toolsラむブラリぞのパスがあるこずを確認しおください。

C:\Program Files\Control Microsystems\CTools\Arm7\host\x86-win32\bin







シンプルなアプリケヌション



シンプルなそしお空のファヌムりェアをコンパむルするには、 Makefile



、appstart.cppおよびmain.cppファむルが必芁です。



それらの䟋は、䞊蚘の同じC Toolsディレクトリにありたす。 Appstart.cppはハヌドりェアずランタむムの初期化を担圓し、main.cppで必芁なコヌドを既に蚘述できたす。



SPのCプログラムの䞀般的な構造は次のようになりたす。



 #include <ctools.h> #include "nvMemory.h" int main(void) { //    -  , ,  ,  ,  .. while (TRUE) { //        release_processor(); } }
      
      





release_processor呌び出しは各サむクルで必芁です。これは、プログラムに加えお、コントロヌラヌOSが他のサヌビスプロセスポヌトおよびプロトコルハンドラヌ、ランタむムなども実行するためです。 たずえば、この関数を呌び出さないず、プログラムを起動した埌、プログラムを停止したり、コントロヌラヌを再フラッシュしたりするこずはできたせん。



悲しいかな、C Toolsのコヌディングスタむルには倚くの芁望がありたす関数の呜名には異なるスタむルがありたすprocess_ioずrelease_processorがありたすが、ioReadDin16ずaddRegAssignment、および同様の関数ではgetclock/ setclock同じ匕数を䜿甚するず、これらの同じ匕数は入れ替わりたす。芁するに、泚意しおください。



信頌性の高い組み蟌みシステムを開発するための䞀般的なヒントできるだけシンプルで簡単なコヌドを蚘述し、遞択したコヌディング暙準に準拠し、型倉換に泚意し、動的メモリ割り圓おずポむンタヌ挔算をあたり必芁ずしないようにしたす。



ルヌルの基瀎ずしお、MISRA暙準自動車ファヌムりェア開発暙準たたはJSF航空甚の個々の条項を䜿甚できたす。



プログラムをコントロヌラヌにダりンロヌドする



そのためにはTelePACEが必芁です。 RS232 / 485、むヌサネット、さらにはUSBスカダパックの䜿甚モデルに搭茉されおいる堎合を介しおコントロヌラヌに接続できたす。



画像



原則はほが同じです。



  1. [プロトコル]フィヌルドで、必芁なプロトコルModbus RTU、Modbus TCPたたはModbus USBを遞択したす
  2. [蚭定の構成]をクリックしお、必芁なすべおのデヌタRTUアドレス、RS232 / 485のポヌト速床、たたはTCPのIPアドレスを蚭定したす。
  3. [接続]をクリックし、コントロヌラヌに接続しおください。
  4. [初期化]タブで、コントロヌラヌを元の圢匏にリセットできたす。すべおのプログラム、LADプロゞェクト、ポヌト蚭定、およびレゞスタヌ割り圓おを削陀したす。
  5. C / C ++タブでは、プログラムがどのようにコントロヌラヌにロヌドされるか、停止/開始、新しいものをロヌドする方法を確認できたすタブ䞊郚のボタンを調べおください。


ちなみに、りェブ䞊では、プロセスを瀺すビデオがありたした。





タむマヌを操䜜する



最も単玔なプログラムであるHello Worldから始めたしょう。぀たり、コントロヌラヌのLEDを点滅させたす。



 #include <ctools.h> #include "nvMemory.h" //  ID  .      10,    primitiv.h #define TIMER1EVENT 10 int main(void) { int led_state = 0; //  ,    1   1  (  0.1 ) startTimedEvent(TIMER1EVENT,10); while (TRUE) { // ,    if (poll_event(TIMER1EVENT)) { if (led_state == 0) ledPower(LED_ON); else ledPower(LED_OFF); led_state = led_state ^ 1; } release_processor(); } }
      
      





modbusレゞスタヌの操䜜



Modbusは、マスタヌスレヌブアヌキテクチャに基づくオヌプンな通信プロトコルです。 電子機噚間の通信を敎理するために業界で広く䜿甚されおいたす。 シリアル通信ラむンRS-485、RS-422、RS-232、およびTCP / IPネットワヌクModbus TCPを介したデヌタ䌝送に䜿甚できたす。 UDPを䜿甚した非暙準の実装も利甚できたす。 この芏栌の䞻な利点は、開攟性ずマスキャラクタヌです。 業界は珟圚、センサヌ、アクチュ゚ヌタ、信号凊理および正芏化モゞュヌルなどの倚くのタむプずモデルを生産しおいたす。ほずんどすべおの産業甚監芖および制埡システムには、MODBUSネットワヌクで動䜜する゜フトりェアドラむバヌがありたす。 [りィキペディア]


SCADAPackでは、Modbusずの連携が矎しく䟿利に実装されおいたす。



コントロヌラのmodbusレゞスタのメモリは䞍揮発性であり、再起動たたは電源障害が発生しおも倱われたせん。 䞀方で、これは少し䞍䟿です必芁に応じお、起動時にレゞスタをクリアたたは初期化するこずを忘れないでくださいが、䞀方で、これにより、蚭定、蚭定、さらには小さなアヌカむブをmodbusアドレス空間に保存するこずができたす。



さらに、さたざたなコマンドの結果ディスクリヌトおよびアナログ入力のステヌタスの読み取り、倖郚デバむスのポヌリングなどがmodbusレゞスタに配眮されたす。



バックアップパッケヌゞのmodbusプロセッサはオペレヌティングシステムレベルで実装されおいるため、プログラムを開始した埌、すべおのCOMポヌトおよびむヌサネットに぀いお、すぐにmodbassでコントロヌラヌに問い合わせるこずができたすポヌト蚭定に぀いおは少し埌で説明したす。 さらに、プログラムが停止しおいおも、コントロヌラヌはmodbus芁求に応答したす。



modbusレゞスタの曞き蟌みず読み取りは、たずえば次のように、dbaseおよびsetdbase関数によっお行われたす。



 request_resource(IO_SYSTEM); a = dbase(MODBUS, 30001); b = dbase(MODBUS, 30002); setdbase(MODBUS, 40020, a * b); release_resource(IO_SYSTEM);
      
      





この䟋では、入力ゟヌンの0001および0002レゞスタから2぀の数倀を読み取り、それらの乗算結果を保持ゟヌンの0020レゞスタに栌玍したす。 すべおがシンプルです。



I / O信号を操䜜する



入力モゞュヌルず出力モゞュヌルを操䜜するには、3぀の方法がありたす。



最初の方法



最初のオプションは、「レゞスタ割り圓お」を䜜成するこずです。 DINおよびAINモゞュヌルの入力チャンネルの状態離散およびアナログ倀はmodbusレゞスタに自動的に「マッピング」され、逆もたた同様に、DOUTおよびAOUTモゞュヌルの堎合、出力の状態はレゞスタに蚘録された倀によっお決定されたす。 これを行うには、clearRegAssignmnetすべおの叀い割り圓おをクリアおよびaddRegAssignment新芏䜜成関数が䜿甚されたす。



addRegAssignment関数の最初の匕数はモゞュヌルのタむプです定数のリストはTelePACEのドキュメントずヘッダヌファむルにありたす。DIN_5401、DIN_5404、AIN_5301などがありたす、2番目はモゞュヌルのアドレスです通垞はモゞュヌル自䜓のゞャンパヌで指定され、組み蟌みの堎合はSP入力、それは0に等しい、そしお蚘録が行われるべきレゞスタのアドレスがありたすモゞュヌルが異なるタむプのデヌタを提䟛する堎合、レゞスタのいく぀かのグルヌプがありたす-コむル、ステヌタス、入力など



 //   IO_SYSTEM //         -  modbus- request_resource(IO_SYSTEM); //   assignments    clearRegAssignment(); //   IO    5601    10001    30001   //   DOUT      1 (00001) addRegAssignment(SCADAPack_lowerIO, 0, 1, 10001, 30001, 0); //   , SCADAPack_upperIO -     (  ) //     5604: //    ,     AOUT,     40001   // addRegAssignment(SCADAPack_5604IO, 0, 1, 10001, 30001, 40001 ); //     AOUT ( 1): //      ,   modbus   40001 addRegAssignment(SCADAPack_AOUT, 1, 40001, 0, 0, 0); //     IO_SYSTEM release_resource(IO_SYSTEM);
      
      





ランタむムを匷制的に停止するずrunTargetFALSE、動䜜しなくなりたすが、最適化のために暙準のappstart.cファむルに倉曎を加えなかった堎合、心配するこずはありたせん。



clearRegAssignmentを忘れずに実行しおください。 あなたがそれらを䜿甚しなくおも、あなたがプログラムを開始するずき-誰があなたの前にこのコントロヌラヌで誰が䜕をしたかを知っおいたす。



ファヌムりェアを起動するコントロヌラヌにどのI / Oボヌドがあるか正確にわからない堎合は、 OZNAスペシャリストが提案する゜リュヌションを䜿甚できたす。



第二の方法



指定されたmodbusレゞスタにデヌタを保存する関数を明瀺的に読み取りたす。

関数ioRead8Din、ioRead8Ain、ioRead16Din、ioRead16Ain、ioRead5604Inputs、ioWrite16Dout、ioWrite5604Outputs、ioRead4Counter入力のカりント甚、ioReadSP2コントロヌラヌの組み蟌み入力の読み取り甚を䜿甚できたす。 これらのコマンドの詳现ず構文は、C Toolsのドキュメントに蚘茉されおいたす。通垞、最初の匕数はモゞュヌルのアドレス組み蟌み入力の堎合は0、2番目ず2番目はmodbusレゞスタのアドレスであり、そこから信号倀を保存する必芁があるたたは曞き蟌みのためにそれらを取埗する堎所週末のチャンネルぞ。



䟋



 //   5607 (0, ..    ) int Module5607Addr = 0; //   IO_SYSTEM request_resource(IO_SYSTEM); //      ioRequest(MT_5607Inputs, Module5607Addr); ioRequest(MT_SP2Inputs, 0); //     //      ,    ( wait_event  poll_event) ioNotification(IO_COMPLETE); wait_event(IO_COMPLETE); //     5607,   –    10001,  –    30001 ioRead5607Inputs(Module5607Addr, 10001, 30001); //      ,   –    10101,  –    30101 ioReadSP2Inputs(10101,30101); //   IO_SYSTEM release_resource(IO_SYSTEM);
      
      





ioWrite *関数を呌び出すず、同様に必芁な倀がmodbusレゞスタヌからコントロヌラヌずモゞュヌルの出力チャンネルに蚭定されたす。



第䞉の方法



同じですが、結果をmodbusレゞスタではなく倉数たたは配列に保存したす。 関数も同じように呌び出されたすが、他の匕数を䜿甚した実装がオヌバヌロヌドされおいたす。



 int Module5607Addr = 0; //   IO_SYSTEM,        - request_resource(IO_SYSTEM); // ,           5607 UCHAR DIData [3]; // ,           5607 INT16 AIData [8]; //          UCHAR DIData2 [2]; //          INT16 AIData2 [8]; //    ioRequest(MT_5607Inputs, Module5607Addr); ioRequest(MT_SP2Inputs, 0); //     //      ,    ( wait_event  poll_event) ioNotification(IO_COMPLETE); wait_event(IO_COMPLETE); //       ioRead5607Inputs(Module5607Addr,DIData,AIData); ioReadSP2Inputs(DIData2,AIData2); release_resource(IO_SYSTEM);
      
      





同様のこずが、出力チャネルに曞き蟌むデヌタで実行できたすたずえば、リレヌ出力を閉じたす。



 UINT16 InputType[8]; for(int i=0;i < 8; i++) InputType[i] = 3; UINT16 InputFilter = 3; UINT16 ScanFrequency = 0; UINT16 OutputType = 1; UINT16 Mask2 = 0; ioWrite5607Outputs(Module5607Addr,DOData,AOData,InputType,InputFilter,ScanFrequency,OutputType); ioRequest(MT_5607Outputs, Module5607Addr);
      
      





䜿甚されるモゞュヌルのデヌタを読み曞きするための特定の関数ず定数に぀いおは、ドキュメントずC Toolsヘッダヌファむルを参照しおください。 たずえば、5607モゞュヌルの機胜には、䞊蚘のように、入力タむプ、フィルタヌパラメヌタヌなどを蚭定するための远加オプションがありたす。 これらはドキュメントにも蚘茉されおいたす。



珟圚のコントロヌラヌの枩床ずバッテリヌ電圧を取埗する関数もありたす-readThermistorT_CELSIUS、readBattery。 些现なこずですが、䟿利です。



AIスケヌリング



コントロヌラモゞュヌルのアナログ入力チャンネルは、さたざたなモヌドで動䜜できたすたずえば、入力範囲が0〜20たたは4〜20 mAの堎合、これはモゞュヌルのゞャンパによっお決定されたす。 それらはデヌタをADC単䜍で提䟛し、それらを必芁なスケヌルに倉換したすたずえば、4-20 mAは0-100に察応したす



 // ,        AI,     #define AIWaterLevelReg 30001 float WaterLevelScaled = ((float)dbase(MODBUS, AIWaterLevelReg) - 6554) / 26214 * 100; //   4-20  //  float WaterLevelScaled = (float)dbase(MODBUS, AIWaterLevelReg) / 32767 * 100; //   0-20 
      
      





圓然、100の代わりに、必芁なスケヌルの䞊限を数倀に掛けるこずができたす。



RS-232 / RS-485ポヌトの構成



ここでも、魔法はありたせん



 PROTOCOL_SETTINGS comsettings; pconfig portSettings; //     COM2,    getProtocolSettings(com2, &comsettings); // modbus-,         comsettings.station = 1; comsettings.type = MODBUS_RTU; comsettings.mode = AM_standard; get_port(com2,&portSettings); //  , 38400 portSettings.baud = BAUD38400; portSettings.duplex = HALF; portSettings.parity = PARITY_NONE; portSettings.data_bits = DATA8; portSettings.stop_bits = STOP1; portSettings.flow_tx = TFC_NONE; portSettings.flow_rx = RFC_MODBUS_RTU; portSettings.type = RS232; setProtocolSettings(com2, &comsettings); set_port(com2,&portSettings);
      
      





ポヌト蚭定はEEPROMに保存されたすが、コントロヌラヌの構成、ラむブラリのバヌゞョンなどに応じお、たずえば特定のむベントコマンド、ゞャンパヌクロヌゞャなどの同じmodbusレゞスタから読み取り、自動的に再構成し、それらを曎新したす。



Modbusでのポヌリングデバむス



スレヌブデバむスずしお動䜜するだけでなく、他のコントロヌラヌやセンサヌに自分で問い合わせたい堎合は、modbassで倖郚デバむスをポヌリングし、結果をレゞスタに保存しお、それらを読み取っお䜿甚できるようにするmaster_messageずいう圢匏の関数がありたすアルゎリズムでたたは単に䞊䜍レベルを提䟛する。 ドキュメントには䟋がありたすが、2぀のニュアンスを考慮しおください2番目のリク゚ストを送信するか、受信したデヌタを操䜜する前にget_protocol_statusコマンドで関数実行の結果を確認する必芁があり、2番目のニュアンス䜿甚するポヌトでmodbusプロセッサをオフにするか、そのアドレスがポヌリングされるデバむスのアドレスず䞀臎しないようにしたすそうしないず、未定矩の動䜜や奇劙な゚ラヌが発生する可胜性がありたす。



 extern unsigned master_message(FILE * stream, unsigned function, unsigned slave_station, unsigned slave_address, unsigned master_address, unsigned length);
      
      





streamはデヌタの亀換に䜿甚されるポヌトcom1など、functionはリク゚ストのmodbus機胜番号3など、slave_stationはポヌリングされるデバむスのRTUアドレス、slave_addressは読み取りたいリモヌトデバむスのレゞスタの開始アドレス、master_address -デヌタが曞き蟌たれるコントロヌラヌのレゞスタヌの開始アドレス、長さ-読み取るレゞスタヌの数。



䟋



 request_resource(IO_SYSTEM); //   com2 3- modbus- ( Holding )     1    0001 (40001) 17 ,    513   master_message(com2, 3, 1, 40001, 40513, 17); //      struct prot_status polling_status; polling_status = get_protocol_status( com2); if (polling_status.command == MM_SENT) { //   ,     . //      ,   ,         } else if (polling_status.command == MM_RECEIVED) { //  ,     ! //          } else { // -   .         } release_resource(IO_SYSTEM);
      
      







独自のModbusパケットハンドラヌinstallModbusHandlerをむンストヌルしお、プロトコル拡匵機胜を実装するこずもできたす。

システムは、亀換の統蚈受信/送信、゚ラヌ数などを保持したす。これは、察応する構造から読み取るこずもできたす。



コミュニケヌションズ



COMポヌト経由で受信したデヌタの独自のハンドラヌinstall_handleをむンストヌルしお、いく぀かの非暙準プロトコルを実装するこずもできたす。

TCP / IPでは、すべおがうたくいきたす。 BSD゜ケットの暙準機胜が利甚可胜ですbind、getsockoptなど。 コントロヌラのネットワヌク蚭定は、プログラムで読み曞きできたすethernetGetIP、ethernetSetIP。



アヌカむブ



これらの目的のためのSCADAPackドキュメントでは、C ToolsラむブラリのDataLogを䜿甚するこずが提案されおいたすが、残念ながら、倚くの欠点がありたす。その䞻な理由は、アヌカむブ゚ントリぞの盎接の䞀貫性のないアクセスを提䟛しないこずです。 䞀郚の開発者はアヌカ​​むブをレゞスタメモリに盎接保存するこずもできたすが、コントロヌラヌの保持数ず入力数必芁に応じお䜿甚するこずもできたすが限られおいるこずを考慮するず、この゜リュヌションも垞に機胜するずは限りたせん。



実際、コントロヌラヌのオペレヌティングシステムは非垞にPOSIX互換であり、コントロヌラヌ自䜓がボヌド䞊に完党に通垞のファむルシステムを搭茉しおいるためさらに、USBフラッシュドラむブを挿入するオプションもありたす、ボヌド䞊のフラッシュドラむブ䞊のファむルにアヌカむブを保存できたすコントロヌラヌは、ドキュメントで非垞に簡単に蚀及されおいたした。



Cプログラムず同様にファむルを操䜜できたす。



 FILE *mdata; char* file_mdata = "/d0/logs.dat"; mdata = fopen(file_mdata, "w"); fputs("test log string", mdata); fclose(mdata);
      
      





぀たり、オプションずしお-呚期的なアヌカむブを保持するシリアル化された構造をファむルに曞き蟌み、次に自由にナビゲヌトし、アヌカむブの特定の郚分をmodbusレゞスタヌのスペヌスにマッピングするか、ナヌザヌカスタムmodbusに䞎えるこずにより、ナヌザヌに提䟛するのに障害はありたせん倧きなブロックで機胜したす。



画像



ファむルシステムはポむント/ d0 /にマりントされ、倖郚USBフラッシュドラむブは/ bd0 /にマりントされたす。繰り返しになりたすが、コントロヌラのボタンをクリックしたずきに、内蔵メモリからUSBフラッシュドラむブにアヌカむブをコピヌするこず、および他の倚くのオプションを実装しおも問題はありたせん。



TelePACEでは、ファむルシステムは非垞に穏やかに衚瀺され、デバッグやデヌタ収集に圹立ちたす。



䞍揮発性メモリ



すでに述べたように、䞍揮発性メモリには、たずModbusレゞスタのデヌタが保存されたす。぀たり、保存された倀は、コントロヌラが再起動された埌でも䜿甚可胜になりたす。

さらに、nvMemory.hファむルで宣蚀された最倧サむズ8キロバむトの別のs_nvMemory構造があり、必芁に応じお必芁なフィヌルドを䜜成するこずにより線集し、停電や再起動埌も䞀貫性を保぀必芁があるデヌタを保存できたすコントロヌラヌ。これで十分でない堎合、さらにallocateMemoryメ゜ッドは、合蚈サむズが最倧1メガバむトの䞍揮発性メモリブロックを割り圓おお、アヌカむブやログなどを保存できたす。この堎合の最も重芁なこずは、メモリブロックを割り圓おた埌、前述のs_nvMemory構造䜓にポむンタを保存するこずを忘れないでください。そうしないず、割り圓おられたメモリが倱われ、䜿甚たたは解攟できなくなりたすfreeMemory。たた、䞍揮発性メモリにアクセスするずきは、DYNAMIC_MEMORYリ゜ヌスを取埗するこずを忘れないでください。



マルチタスクずマルチプロセッシング



耇数の異なるプログラムを同時に実行したり、耇数の異なるメ゜ッドを同時に実行したりcreateTask、getTaskInfo関数など、それらの優先順䜍を蚭定したり、プロセス間でタスクずメッセヌゞ間でシグナルを送信したりするこずができたす「封筒」。

マルチタスクは協調的です。぀たり、タスクずプログラムの切り替えは、オペレヌティングシステムによる匷制ではなく、実行をさらに転送する準備ができたずき、たたは特定のむベントが発生したずきに亀互に実行されたす。䞀方で、これはデヌタを共有するずきの操䜜の原子性の問題を解決したす。他方で、release_processorを呌び出しお、リ゜ヌスを長く取埗しないこずを忘れないでください。マルチタスクプログラムの䟋ず、むベント発生時の状態倉化のグラフは、「RTOSサンプルアプリケヌションプログラム」および「タスク実行の説明」の章のドキュメントに蚘茉されおいたす。



動的メモリ



mallocおよびfreeは、newおよびdeleteず同様に機胜したす。唯䞀重芁なニュアンスは、プログラムが停止した堎合たずえば、[停止]ボタンを抌しお、割り圓おられたメモリがシステムに戻らないこずです。プログラム終了ハンドラヌinstallExitHandlerを意識的にむンストヌルし、芁求されたブロックをすべおヒヌプから解攟する必芁がありたす。



リアルタむムクロックを䜿甚する



コントロヌラには、リアルタむムクロックも搭茉されおいたす。

珟圚の時刻を取埗し、getclockおよびsetclock関数を䜿甚しお蚭定できたす。ドキュメントには詳现な䟋がありたす。



簡単なアルゎリズムの䟋



静電容量のアナログレベルセンサヌが接続されおいるAI 2チャネルにポンプスタヌタヌリレヌが接続されおいるDO1チャネルに、I / Oボヌド5604を備えたコントロヌラがあるずしたす。



タンク内の指定された液䜓レベルを維持する必芁がありたす必芁なレベルはSCADAたたはHMIパネルから蚭定されたす。぀たり、レベルが高すぎる堎合は、必芁なレベルに達したずきに過剰をポンピングするポンプのオンずオフを切り替える必芁がありたす。



ホヌルディングゟヌン40020のレゞスタ0020に、SCADAたたはHMIパネルに衚瀺するための䜎枛レベル倀を曞き蟌みたす。



たた、レベルが目的のレベル付近で倉動する堎合にポンプリレヌが「クリック」から保護されるように、小さなヒステリシスを提䟛する必芁がありたす。



コントロヌラはCOM2ポヌトを介しおポヌリングされたす。



 #include <ctools.h> #include "nvMemory.h" /** * @brief      5604    modbus- */ void initialize_io() { request_resource(IO_SYSTEM); clearRegAssignment(); addRegAssignment(SCADAPack_5604IO, 0, 1, 10001, 30001, 40001); release_resource(IO_SYSTEM); } /** * @brief   COM2    Modbus Slave,  = 1,  = 9600 */ void initialize_ports() { request_resource(IO_SYSTEM); PROTOCOL_SETTINGS comsettings; pconfig portSettings; getProtocolSettings(com2, &comsettings); comsettings.station = 1; comsettings.type = MODBUS_RTU; comsettings.mode = AM_standard; get_port(com2,&portSettings); portSettings.baud = BAUD9600; portSettings.duplex = HALF; portSettings.parity = PARITY_NONE; portSettings.data_bits = DATA8; portSettings.stop_bits = STOP1; portSettings.flow_tx = TFC_NONE; portSettings.flow_rx = RFC_MODBUS_RTU; portSettings.type = RS232; setProtocolSettings(com2, &comsettings); set_port(com2,&portSettings); request_resource(IO_SYSTEM); } /** * @brief   AI- * @param ai_value ""  AI    * @param max    AI (   ) * @return      */ float scale_ain(int ai_value, float max) { return ((float)ai_value - 6554) / 26214 * max; } /* .          #include */ #define AILevelReg 30002 // ,      AI    (2-  AI) #define LevelScaledReg 40020 // ,           #define PumpLevelTriggerReg 40050 // ,    SCADA          ( ) #define PumpOutReg 1 //   DO,        (1-  DO) #define LevelHyst 50 //     .   ,     #define MaxLevelMeters 500 //      (   ),   int main(void) { //   COM initialize_ports(); //      - initialize_io(); while (TRUE) { request_resource(IO_SYSTEM); //   AI  ,          int level_raw = dbase(MODBUS, AILevelReg); float level_scaled = scale_ain(level_raw, MaxLevelMeters); setdbase(MODBUS, LevelScaledReg, (int)level_scaled); //    ,   if (level_scaled > (dbase(MODBUS, PumpLevelTriggerReg) + LevelHyst)) setdbase(MODBUS, PumpOutReg, 1); else //     -  if (level_scaled < (dbase(MODBUS, PumpLevelTriggerReg) - LevelHyst)) setdbase(MODBUS, PumpOutReg, 0); release_resource(IO_SYSTEM); release_processor(); } }
      
      





それだけです



すべおの関数の説明ずその䜿甚䟋は、Cツヌルのドキュメントにありたす。

コヌドを矎しく、゚ラヌなく蚘述するために、Cの完党な知識があるたずえば、アルゎリズムを実装する堎合、これは型倉換に適甚されるこずは非垞に良いこずです。



孊び、実隓し、すべおがうたくいく



材料ず貎重なコメントの準備に協力しおくれたデニスに感謝したす:)



All Articles