質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

PICがPIDの処理中に落ちます。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 184

ron4256

score 5

ron4256と申します。よろしくお願い致します。

 

現在、PICの18F24K20を使用してPID制御のプログラムを作って一応は動作させるところまで出来たのですが、
動作中に突然PICが止まります。

入力で接続しているのはAD変換用にポテンショメータとPIC12F1822からエンコーダの値をシリアル通信での取得のみです。
(シリアル通信で取得した値は利用していません)
出力はPID出力確認用でPORTBの0、1とPORTAの1、2、3にLEDを接続しています。

PIDの処理を追加してから問題が発生したので、ADとシリアル通信に絞って動作させたときは問題がありませんでした。
また、PIDの処理はArduino microで実装した時に問題がなかったので、計算値が問題なのか?ということまで考えたのですが、
お手上げ状態でここへ来た次第です。

前置きを長々と書きましたが、止まる原因が分からないため問題が起こる箇所の指摘等を頂きたいと考えています。
よろしくお願い致します。

 

PICのMPLAB X IDEでコンパイラはXC8を使用しています。

以下ソースコードです。

#include <xc.h>
#include<stdlib.h>
#include<math.h>

// CONFIG1H
#pragma config FOSC = INTIO67   // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = ON       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 18        // Brown Out Reset Voltage bits (VBOR set to 1.8 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF       // Watchdog Timer Enable bit (WDT is always enabled. SWDTEN bit has no effect)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config HFOFST = OFF      // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = OFF       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF// Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.


#define _XTAL_FREQ 64000000

int enc_data = 0;
unsigned char error_flag = 0;

int AD_data = 0;
//

void interrupt Data_acquisition(void)
{

    RCIE = 0;
    PEIE = 0;
    GIE  = 0;

    error_flag = 0;

    //serial interrupt
    if(RCIF == 1)
    {
        if(RCSTAbits.FERR || RCSTAbits.OERR){
            if(RCSTAbits.FERR == 1){
                error_flag = 0xFE;
            }
            else if(RCSTAbits.OERR == 1){
                error_flag = 0xFF;
            }
            RCSTA = 0;
            RCSTA = 0x90;
        }

        else{
            enc_data = RCREG;//encoder data
            if(enc_data > 1000){
                enc_data = 0;
            }
        }
    }

    RCIE = 1;
    PEIE = 1;
    GIE  = 1;
}

void main(void) {
    int i = 0;

    float P = 4.0;
    float I = 1.0;
    float D = 1.0;

    int target = 512;

    //difference
    float diff1 = 0;
    float diff2 = 0;
    float diff3 = 0;

    float PID_calc = 0;
    int motor_on = 0;
    int motor_off = 0;

    unsigned char flag_p = 0;
    unsigned char flag_n = 0;
    //oscirator setting
    OSCCON = 0b01110000; //inter osc 64Mhz maybe
    OSCTUNEbits.PLLEN = 1;

    //PORTA setting
    ANSEL = 0x01;   //PORTA 0pin analog
    TRISA = 0x01;   //RA0 AD convert
    PORTA = 0;
    //AD setting
    ADCON0 = 0x01;  //AN0 a/d ADON set
    ADCON1 = 0x00;  //
    ADCON2 = 0b00111110;;  //Fosc/64
    ADCON2bits.ADFM = 1;    //0 left justfited/ 1 right justfited

    //PORTB setting
    ANSELH = 0x00;      //PORTB I/O digital
    TRISB = 0x00;
    PORTB = 0;

    //PORTC setting
    TRISC  = 0x80;   // RC7 input(rx))
    PORTC  = 0x00;

    //Serial setting
    TXSTA   = 0x24;         // TXEN = 1, BRGH = 1
    RCSTA   = 0x90;         // SPEN = 1, CREN = 1
    BAUDCON = 0x08;         // 16bitmode

    // 16Bitmode
    SPBRG  = 0x40;          // 19.2k
    SPBRGH = 0x03;          // 19.2k

    RCIF = 0;

    RCIE = 1;
    PEIE = 1;
    GIE  = 1;

    while(1){
        ADCON0bits.GO = 1;
        while(ADCON0bits.GO);
        AD_data = ADRESH * 256 + ADRESL;

        /////////

        if (target > AD_data){
            flag_p = 1;
            flag_n = 0;
            diff1 = target - AD_data;
        }
        else if (target < AD_data){
            flag_p = 0;
            flag_n = 1;
            diff1 = AD_data - target;
        }
        else if(target == AD_data){
            flag_p = 1;
            flag_n = 0;
            diff1 = 1;
        }

        PID_calc = P * (diff1 - diff2)
                 + I * diff1
                 + D * (diff1 - 2.0 * diff2 + diff3);

        //float control = P * diff1;
        // return the distance for this axis:
        PID_calc = 100 * PID_calc / target;
        if (PID_calc > 100){
          PID_calc = 99;
        }

        if (PID_calc< -100){
          PID_calc = -99;
        }

        diff3 = diff2;
        diff2 = diff1;

        //////

        //duty width on
        motor_on = abs(PID_calc);
        //duty width off
        motor_off = 100 - motor_on;


        if (flag_p == 1){
            RA1 = 1;
            i = 0;
            for (i = 0; i < 100; i = i + 1){
                if (motor_on > 0){
                    //select motor output port
                    RB0 = 1;
                    RB1 = 0;
                    //select delay timer
                    motor_on -= 1;
                }
                else if(motor_off > 0){
                    RB0 = 0;
                    RB1 = 0;
                    motor_off -= 1;
                }
            }
            RA1 = 0;
        }

        else if (flag_n == 1){
            RA2 = 1;
            i = 0;
            for (i = 0; i < 100; i = i + 1){
                if (motor_on > 0){
                    RB0 = 0;
                    RB1 = 1;
                    motor_on -= 1;
                }
                else if(motor_off > 0){
                    RB0 = 0;
                    RB1 = 0;
                    motor_off -= 1;
                }
            }
            RA2 = 0;
        }
        //maybe default
        else if(flag_n == 0 && flag_p == 0){
            motor_on = 0;
            motor_off = 0;
            diff1 = 0;
            diff2 = 0;
            diff3 = 0;

            RA3 = 1;
        }
        RA3 = 0;

    }
    return;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • y_waiwai

    2020/07/02 20:35

    このままではコードが読めません。質問を編集し、<code>ボタンを押し、出てきた’’’の枠の中にコードを貼り付けてください

    キャンセル

  • ron4256

    2020/07/02 21:12

    コードの部分を確認しました。よろしくお願いします。

    キャンセル

回答 2

checkベストアンサー

+1

Read-modify-write 命令による誤作動を疑います

< 対策 >

RA1 -> LATA1
RA2 -> LATA2
RA3 -> LATA3

RB0 -> LATB0
RB1 -> LATB1

参考
[PIC]PICの資料にある”R-M-W”の意味

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

そのPICの電源はどこからどうとってるでしょうか。
あるあるなのが、なんかの拍子に電流消費量が増えて、電圧がドロップして、リセットがかかってしまう、あるいはリセットがかかりっぱなしになってしまうということがあります

まずはオシロスコープなどで、リセットラインのレベルのチェック、また、電源ラインが変動してないかなどをチェックしていきましょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/02 21:15

    電源は安定化電源から取っています。電源の電流値をモニタリングしても急激な電流の増減はありませんでした。

    すいません。オシロがないので各波形の確認ができない状態です。

    キャンセル

  • 2020/07/02 21:27

    止まる、といってますが、そのときになにが起きてるのかを追求しましょうよ。
    それができてない時点で、あんまし言ってることは鵜呑みにできないですね

    キャンセル

  • 2020/07/02 21:41

    確かにy_waiwaiさんの仰るとおりです。ただ言い訳になって申し訳ないのですが、ただただ動作が止まるしか言いようがないとしか言いようがなかったです。調べるにしても手元にテスターしかなく、LEDでフラグ代わりにしても、変数の型を見直しや、PIDの計算方法の正誤の確認程度で済まして質問してしまったことを深く謝罪します。

    キャンセル

  • 2020/07/03 08:20

    問題を解決する気がない、ってことですか。
    なんだかなあ

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る