2017-08-11 9 views
2

システムは基本的ですが、私はひどい問題を抱えています。私はそれを解決できません。 私のシステムが動作しているとき、PICは動作し続けますが、レジスタを1日に4〜5回クリアします。システムがどのように動作するかをPIC 16F628Aはレジスタをクリアしますか?

-Iは、PIC、空気圧シリンダおよび3センサー(24V DCで動作します)を持っています。 - メインセンサーが別のシステムから信号を受け取ります。 - 主センサーから信号が来たとき、シリンダーが後方にあるとき、前方センサーがそれを見るまでシリンダーは前進し、シリンダーが前方であれば、シリンダーは後方センサーがそれを見るまで後退するはずです。

プログラム:

#include <16F628A.h> 

#FUSES NOWDT     //No Watch Dog Timer 
#FUSES NOBROWNOUT    //No brownout reset 
#FUSES NOLVP     //No low voltage prgming, B3(PIC16) or 
B5(PIC18) used for I/O 

#use delay(crystal=4000000) 

#use fast_io(a) 
#use fast_io(b) 

#define goForward PIN_A0 
#define comeBackward PIN_A1 
#define main_sensor PIN_B0 
#define positionSensorForward PIN_B5 
#define positionSensorBackward PIN_B4 

int1 pistonPositionedForward=0, pistonPositionedBackward=1; 
int1 positionForwardReg=0, positionBackwardReg=0; 
int1 pistonForwarding=0, pistonBackwarding=0; 

#priority rb,ext 

#int_RB NOCLEAR 
void B_change() 
{ 

    positionForwardReg=input(positionSensorForward); 
    positionBackwardReg=input(positionSensorBackward); 

if(positionForwardReg&&pistonForwarding) //if forwarding and forward sensor see 
{ 
    disable_interrupts(INT_RB); 

    output_low(goForward); 
    pistonPositionedForward=1; 
    pistonPositionedBackward=0; 

    write_eeprom(0,1); 
    write_eeprom(1,0); 

    pistonForwarding=0; 
    pistonBackwarding=0; 

    clear_interrupt(int_ext); 
    enable_interrupts(INT_EXT); 
} 

else if(positionBackwardReg&&pistonBackwarding) //if backwarding and backward sensor see 
{ 
    disable_interrupts(INT_RB); 

    output_low(comeBackward); 
    pistonPositionedForward=0; 
    pistonPositionedBackward=1; 

    write_eeprom(0,0); 
    write_eeprom(1,1); 

    pistonForwarding=0; 
    pistonBackwarding=0; 

    clear_interrupt(int_ext); 
    enable_interrupts(INT_EXT); 
} 

clear_interrupt(int_rb); 

} 

#int_ext NOCLEAR 
void ext_interrupt() 
{ 

    disable_interrupts(INT_EXT); 

    positionForwardReg=input(positionSensorForward); 
    positionBackwardReg=input(positionSensorBackward); 

    if(positionForwardReg^positionBackwardReg) //if one of position sensor is see then position according to sensor, else position according to memory 
    { 
    pistonPositionedForward=positionForwardReg; 
    pistonPositionedBackward=positionBackwardReg; 
    } 

    if(pistonPositionedForward) 
    { 
    pistonBackwarding=1; 
    pistonForwarding=0; 
    output_high(comeBackward); 

    clear_interrupt(int_rb); 
    enable_interrupts(INT_RB); 
    } 
    else if(pistonPositionedBackward) 
    { 
    pistonForwarding=1; 
    pistonBackwarding=0; 
    output_high(goForward); 

    clear_interrupt(int_rb); 
    enable_interrupts(INT_RB); 
    } 
    clear_interrupt(int_ext); 
} 

void main() 
{ 
    //to remember last position after power off 
    pistonPositionedForward=read_eeprom(0); 
    pistonPositionedBackward==read_eeprom(1); 

    set_tris_a(0x00); 
    set_tris_b(0xFF); 

    output_a(0x00); 
    delay_ms(1000); 

    ext_int_edge(L_TO_H); 

    clear_interrupt(int_ext); 
    enable_interrupts(INT_EXT); 

    enable_interrupts(GLOBAL); 

    while(TRUE) 
    { 

    } 

} 

そして、私の回路: CIRCUIT

* J2、J3接続selonoidバルブ

* J4、J5、J6は、3つのセンサー1ピン+ 24VDC、2を接続。ピンGND、3.ピンセンサーデータ

*** B1とB2の接続が変更されました。今、B1〜B5に接続され、接続されたB2は

を〜B4は、これらは私が試している:

-Iは、それらのすべてが

-Iは、24V電源

を変更し、同じことを行う3 PICを持っています - 私は7805と7812をキャンセルし、7805の別個の5V電源のisteadを接続しました。

私はLEDでデバッグしています。時には、システムが停止しているだけで、いずれかの位置で待機しています。メインセンサの信号を取得しますが、何もしません。そして、pistonPositionedForwardとpistonPositionedBackwardレジスタの値は0です。これらのレジスタをクリアするには問題が見つかりませんか?

答えて

2

RBには、内部プルアップが設定されていない入力として設定された未接続ピンがあります。電気的ノイズは、起こることが知られているPORTBの望ましくない割り込みを引き起こす可能性があります。

割り込みを使用すると、そのような単純なデバイスでは全体のロジックを少し難しくしています。割り込みを使わないでプログラムを書き直そうとしましたか?それは長くかかりません。物理システムのパフォーマンスに影響を与えることなく、信頼性と保守性を大幅に向上させることができると思います。

まず、未使用のPORTAピンとPORTBピンを出力として設定し、問題が解消するかどうかを確認することをお勧めします。それが失敗した場合、割り込みを使用しない書き換えは1時間を超えてはなりません。これはおそらく、あなたがすでに問題を追いかけていた時よりも短いのでおそらく意味をなさないでしょう。

説明を読んで、私はこの解決策を考え出しました。

#include <16F628A.h> 

#FUSES NOWDT     //No Watch Dog Timer 
#FUSES NOBROWNOUT    //No brownout reset 
#FUSES NOLVP     //No low voltage prgming, B5(PIC18) used for I/O 

#use delay(crystal=4000000) 

#use fast_io(a) 
#use fast_io(b) 

#define FWD_MOVE  PIN_A0 
#define BACK_MOVE  PIN_A1 
#define PORTA_RESET  (0x00) // outputs=LO, unused pins as outputs 
#define PORTA_TRISTATE (0x00) 

#define EXT_SENSOR  PIN_B0 
#define FWD_REST  PIN_B5 
#define BACK_REST  PIN_B4 
#define PORTB_RESET  (0xCE) // can't use pull ups because of HW logic... 
#define PORTB_TRISTATE (0x31) 

#define EEPROM_STATUS_ADDR (0x0000) 
#define EEPROM_STATUS_FWD (0x01) 
#define EEPROM_STATUS_BACK (0x00) 

int1 extLast; 
int1 extCur; 

void main() 
{ 
    // setup 
    output_a(PORTA_RESET): 
    output_b(PORTB_RESET): 

    // setting to last known state... 

    // safety check. 
    output_low(FWD_MOVE); 
    output_low(BACK_MOVE); 

    // This will activate the outputs to make sure we have good 
    // positioning. 
    switch(eeprom_read(EEPROM_STATUS_ADDR)) 
    { 
    default: // EEPROM error... I'll let you decide what to do here. 
      // either move forward or back. 
      // this implementation goes back by default. 

     eeprom_write(EEPROM_STATUS_ADDR, EEPROM_STATUS_BACK); 
     disable_interrupts(GLOBAL); 

     // falling through... 

    case EEPROM_STATUS_BACK: 
     output_high(BACK_MOVE); 
     break; 
    case EEPROM_STATUS_FWD: 
     output_high(FWD_MOVE); 
     break; 
    } 

    // activate outputs... watch your fingers! 
    set_tris_a(PORTA_TRISTATE); 
    set_tris_b(PORTB_TRISTATE); 

    extLast = input(EXT_SENSOR); 
    for (;;) 
    { 
     // read external sensor, take action. 
     extCur = input(EXT_SENSOR); 
     if (extCur && !extlast) 
     { 
      // safety check. 
      output_low(FWD_MOVE); 
      output_low(BACK_MOVE); 

      // control logic 
      switch(eeprom_read(EEPROM_STATUS_ADDR)) 
      { 
      default: // should never happen. 

       // falling through... 

      case EEPROM_STATUS_BACK: 
       output_high(FWD_MOVE); 
       eeprom_write(EEPROM_STATUS_ADDR, EEPROM_STATUS_FWD); 
       disable_interrupts(GLOBAL); 
       break; 

      case EEPROM_STATUS_FWD: 
       output_high(BACK_MOVE); 
       eeprom_write(EEPROM_STATUS_ADDR, EEPROM_STATUS_BACK); 
       disable_interrupts(GLOBAL); 
       break; 
      } 
     } 
     extLast = extCur; 

     // mechanical interface: 
     // read the limit guards and stop movement when done. 
     if (input(FWD_REST)) 
     { 
      output_low(FWD_MOVE); 
     } 
     if (input(BACK_REST)) 
     { 
      output_low(BACK_MOVE); 
     } 
    } 
} 

もちろん、上記のコードはオンサイトで確認できませんでした。

回路図を確認した後、逆電圧スパイクに対してより良い保護を与えるために、2出力MOSFETの並列に1N4001ダイオードを追加するようアドバイスしなければなりません。MOSFETの内蔵ダイオードはあまり頑丈ではありません。 1N4148または1N914もそこで動作します。

16F628のスタックスペースは非常に限られています。 write_eepromの呼び出し中にスタックオーバーフローが発生しているようです。結局、write_eepromを割り込みから呼び出すことは、あまり良い考えではないかもしれません。

古いCCSコンパイラには、write_eepromの使用に関するバグがありました。 write_eepromは呼び出し中に割り込みを有効にしているようです。書き込み後に割り込みを無効にするための呼び出しを追加しました。私はCCSを使用していないので、そのバグが修正されたかどうかわかりません。

[編集] HWを確認した後。私は、HWロジックが正に進行しているため、内部プルアップを使用できないことに気付きました。 PICのプルアップは、オープンコレクタ構成のNPNトランジスタ(エミッタ - グラウンド)で動作するように設計されています。それに応じてコードを変更しました。

EEPROMに書き込む方法は良くありません。 eeprom書き込みには時間がかかり、2回目の書き込みは通常eeprom割り込みで処理されます。グローバル割り込みを有効にし、eeprom_writeでEEIEのマスクを解除するCCSのバグは役に立ちません。未処理の割り込みはリセットを生成します。

+0

最初に割り込みなしで書き込みましたが、同じ問題が発生しました。その後、私は割り込みでそれを書きます。しかし、出力未使用ピンとして構成しようとします。私はこの次のプロジェクトを覚えています、ありがとう。しかし、私はプログラムを探していますどのbピンが割り込みプログラムを呼び出すと思っても変わっていないと思います..例えばb7ピンの呼び出しがレジスタをクリアできない割り込みを引き起こした場合、それは可能ですか? –

+0

「レジスタをクリアする」ということはまったく明確ではありません。出力に接続されていないピンを設定するか、少なくともプルアップを高く設定するのが標準的な方法です。 PIC入力ピンは非常に敏感です。たぶんあなたは私たちがそれを見ることができるように質問に割り込みなしであなたのコードを投稿するべきです。 –

+0

私は、あなたが見るように、位置を暗記する2つのビットがあることを意味します。 pistonPositionedForwardおよびpistonPositionedBackwardです。システムが稼動しているときは、そのうちの1つは1(真)でなければならないが、systamは1日に4〜5回失敗し、両方とも0(偽)であり不可能と思われる。私は予期せぬ割り込みのいずれかが0(偽)に両方を変更することはできないと思います。私はあなたの提案を月曜日にお試しいただき、ありがとうございます –

関連する問題