Help us understand the problem. What is going on with this article?

Arduinoでクラスを使ったファンクションデコーダ(随時バージョンアップ)

More than 1 year has passed since last update.

概要

Arduinoで、ステートマシーンを使ってファンクションデコーダを設計中
12FXもあるので、OPPのクラスを使って設計中
なんとなく、仮想関数を使ってみた。


動作

・LEDのグループ
・常時点灯モード
・Forward/Reverseによる区別
・調光を実装


今後

Forward/Reverseによる調光で混乱中(^^;
シーケンス点灯を実装


StateMachine.cpp
#include "Arduino.h"
#include "StateMachine.h"
//#include "ini.h"
#include "define.h"
#include "NmraDcc.h"

extern uint8_t g_Direction;
extern uint8_t g_SpeedRef;

// コンストラクタ(初期化処理)
state_machine::state_machine(uint8_t fn, uint8_t og, uint8_t fc, uint8_t di, uint8_t st) // fn:gState_F1 og:gCV35_OL fc:gCV49_FC di:gCV112_FC st:gCV126_FC
{
    FunctionCommand = fn;
    FunctionGroup = og;
    FunctionConfig = fc;
    Dimm = di;
    SpeedThreshold = st;
    state = ST_IDLE;
}

void state_machine::StateCheck()
{
  static l_Dir;

  switch(state){
    case ST_NONE:
                  break;
    case ST_IDLE:
                  if(FunctionConfig & ALWAYS){          // 常に点灯ビットon?
                    state = ST_ALWAYSON;
                    break;
                  }
                  if(FunctionCommand > 0) {           // F1 = ON?
                    if(FunctionConfig & DIRCON) {       // For/Rev 有効フラグ?
                        if(FunctionConfig & FORREV) {   // Reverse ?
                          if( g_Direction == REVERSE){ // Reverse 後進(DCS50Kで確認)                         
                            if(FunctionConfig & DIMCON) { // 調光あり?
                              state = ST_RUN_Lo;
                            } else {
                              state = ST_RUN_Hi;
                            }
                          }
                        } else {
                          if( g_Direction == FORWARD ){ // Forward 前進
                            state = ST_RUN;
                          }                          
                        }
                    }
                    state = ST_RUN;    
                  }
                  break;

    case ST_ALWAYSON:                                 // 常に点灯処理
                  high();
                  state = ST_NONE;
                  break;                  

    case ST_RUN_Lo:
                  l_Dir = g_Direction;                // 現在のFor/Revを記録
                  dimming(Dimm & 0x0f);
                  state = ST_RUN_Lo_STAY;
                  break;

    case ST_RUN_Lo_STAY:                              // 調光あり状態
                  if( g_SpeedRef > SpeedThreshold ){
                    state = ST_RUN_Hi;
                    break;
                  }
                  if(FunctionConfig & DIRCON) {       // For/Rev 有効フラグ?
                      if(FunctionConfig & FORREV) {   // Reverse ?
                        state = ST_RSTAY;
                      } else {
                        state = ST_FSTAY;                      
                      }
                  } else {                  
                    state = ST_STAY;  
                  }
                  break;

    case ST_RUN_Hi:   // 今んところ点灯するだけ
                  high();
                  if(FunctionConfig & DIRCON) {       // For/Rev 有効フラグ?
                      if(FunctionConfig & FORREV) {   // Reverse ?
                        state = ST_RSTAY;
                      } else {
                        state = ST_FSTAY;                      
                      }
                  } else {                  
                    state = ST_STAY;  
                  }
                  break;    
    case ST_FSTAY:                             // 前進点灯状態
                  if( g_Direction == 0 ){       // Reverse 後進(DCS50Kで確認)                         
                    state = ST_STOP;
                  }
                  if( FunctionCommand == 0 ) {
                    state = ST_STOP;
                  }
                  break;
    case ST_RSTAY:                             // 後進点灯状態
                  if( g_Direction > 0){        // Forward 前進                         
                    state = ST_STOP;
                  }
                  if( FunctionCommand == 0 ) {
                    state = ST_STOP;
                  }
                  break;
    case ST_STAY:
                  if( FunctionCommand == 0 ) {
                    state = ST_STOP;
                  }
                  break;
    case ST_STOP:
                  low();
                  state = ST_IDLE;  
                  break;
    default:
                  break;
  }
}

void state_machine::low(){};
void state_machine::high(){};
void state_machine::dimming(uint8_t){};
StateMachine.h
#ifndef _STATEMACHINE_H_
#define _STATEMACHINE_H_

// クラスの定義
class state_machine {
  enum{
    ST_NONE = 0,
    ST_IDLE,
    ST_ALWAYSON, // 常に点灯
    ST_ALWATSON_STAY,
    ST_RUN,
    ST_RUN_Lo,     // low点灯
    ST_RUN_Lo_STAY,
    ST_RUN_Hi,     // high点灯
    ST_RUN_Hi_STAY,
    ST_STAY,     // 点灯状態を保持
    ST_FSTAY,    // 前進保持
    ST_RSTAY,    // 後進保持
    ST_STOP      // 消灯
  };

private:
  uint8_t state;
  uint8_t FunctionConfig;
  uint8_t FunctionCommand;
  uint8_t Direction;
  uint8_t cnt;
  uint8_t FuncPort;
  uint8_t Dimm;

  virtual void low();
  virtual void high();
  virtual void dimming(uint8_t);

public:
  uint8_t FunctionGroup;
  state_machine(uint8_t og, uint8_t fc, uint8_t fn, uint8_t di,  uint8_t st,uint8_t dr );
  void StateCheck();
};
#endif// _STATEMACHINE_H_
fnf-3.h
//
// Forward Headlight,Function 1,2,3 のグループ
// Bi1 PWM , Bi2 PWM , AUX1 PWM , AUX2 PWM , AUX3 PWM
// 速度のイベントが設定できるグループ
//

#ifndef _FNF3_H_
#define _FNF3_H_

#include "StateMachine.h"
#include "define.h"


//uint8_t dimm[16]={0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255};
uint8_t DIMMx[16]={0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd , 0xee, 0xff};


class CFnf_3 : public state_machine{
private:
  void low();
  void high();
  void dimming(uint8_t);

public:
    CFnf_3(uint8_t og, uint8_t fc, uint8_t fn , uint8_t di, uint8_t dr ):state_machine(og,fc,fn,di,dr){};
};

void CFnf_3::low()
{
  if(FunctionGroup & 0x01)
    digitalWrite(Bi1,LOW);
  if(FunctionGroup & 0x02)
    digitalWrite(Bi2,LOW);
  if(FunctionGroup & 0x04)
    digitalWrite(AUX1,LOW);
  if(FunctionGroup & 0x08)
    digitalWrite(AUX2,LOW);
  if(FunctionGroup & 0x10)
    digitalWrite(AUX3,LOW);
  if(FunctionGroup & 0x20)
    digitalWrite(AUX4,LOW);  
  if(FunctionGroup & 0x40)
    digitalWrite(AUX5,LOW);  
  if(FunctionGroup & 0x80)
    digitalWrite(AUX6,LOW);  
}

void CFnf_3::high()
{
  if(FunctionGroup & 0x01)
    digitalWrite(Bi1,HIGH);
  if(FunctionGroup & 0x02)
    digitalWrite(Bi2,HIGH);
  if(FunctionGroup & 0x04)
    digitalWrite(AUX1,HIGH);
  if(FunctionGroup & 0x08)
    digitalWrite(AUX2,HIGH);
  if(FunctionGroup & 0x10)
    digitalWrite(AUX3,HIGH);
  if(FunctionGroup & 0x20)
    digitalWrite(AUX4,HIGH);  
  if(FunctionGroup & 0x40)
    digitalWrite(AUX5,HIGH);  
  if(FunctionGroup & 0x80)
    digitalWrite(AUX6,HIGH);  
}

void CFnf_3::dimming(uint8_t di)
{
  if(FunctionGroup & 0x01)
    analogWrite(Bi1,DIMMx[di]);    // analog
  if(FunctionGroup & 0x02)
    analogWrite(Bi2,DIMMx[di]);    // analog
  if(FunctionGroup & 0x04)
    analogWrite(AUX1,DIMMx[di]);   // analog
  if(FunctionGroup & 0x08)
    analogWrite(AUX2,DIMMx[di]);   // analog
  if(FunctionGroup & 0x10)
    analogWrite(AUX3,DIMMx[di]);   // analog
  if(FunctionGroup & 0x20)
    analogWrite(AUX4,DIMMx[di]);   // analog  
  if(FunctionGroup & 0x40)
    digitalWrite(AUX5,DIMMx[di]);   // digital  
  if(FunctionGroup & 0x80)
    digitalWrite(AUX6,DIMMx[di]);   // digital  
}

#endif // _FNF3_H_
ini.h
//http://www.bitsavers.org/pdf/chromatics/CGC_7900_C_Programmers_Manual_Mar82.pdf
//https://www.nmra.org/sites/default/files/standards/sandrp/pdf/s-9.2.2_decoder_cvs_2012.07.pdf
//http://www.snjpn.com/ngdcc/docs/DF19x4bp_CVLIST.pdf

uint8_t gCV1_SAddr = 3; 

uint8_t gCV7_ManVer = 0;      // Manufacturer Version No. 
uint8_t gCV8_ManId = 0x0d;    // Manufactured ID : Public Domain & Do-It-Yourself Decoders
//                +--------0:Mulifunction Decoder 1:Accessory Decoder
//                |+-------0:
//                ||+------0:2digit address 1:4digt address 
//                |||+-----0:speed table off 1:speed table on
//                ||||+----
//                |||||+---0:analog off 1:analog on   
//                ||||||+--0:14step 1:28/9128step
//                |||||||+-0:normal 1:reversed
uint8_t gCV29 = 0b10000000;

// CV33-46 Output Location(グループ)
//        (MSB)edcba987654321(LSB)
//                   87654321
uint8_t gCV33_OL = 0b00000001;   // Forward Headlinght FL(f)
uint8_t gCV34_OL = 0b00000010;   // Reverse Headlinght FL(r)
uint8_t gCV35_OL = 0b00000100;   // Function 1
uint8_t gCV36_OL = 0b00001000;   // Function 2
uint8_t gCV37_OL = 0b00010000;   // Function 3

//                   ba987654
uint8_t gCV38_OL = 0b00000100;   // Function 4
uint8_t gCV39_OL = 0b00001000;   // Function 5
uint8_t gCV40_OL = 0b00010000;   // Function 6
uint8_t gCV41_OL = 0b00100000;   // Function 7
uint8_t gCV42_OL = 0b01000000;   // Function 8
//                   edcba987
uint8_t gCV43_OL = 0b00010000;   // Function 9
uint8_t gCV44_OL = 0b00100000;   // Function 10
uint8_t gCV45_OL = 0b01000000;   // Function 11
uint8_t gCV46_OL = 0b10000000;   // Function 12

// CV47- Function Config
// 
//                   +--------0x80 0:fb3 1001:patern10 , 1010:patern11 , 1011:patern12 , 1100:patern13 , 1101:14 , 1110:15, 1111:patern16パンタスパーク
//                   |+-------0x40 0:fb2 0101:patern6 , 0110:patern7 , 0111:patern8 , 1000:patern9
//                   ||+------0x20 0:fb1 0001:patern2 , 0010:patern3 , 0011:patern4 , 0100:patern5  
//                   |||+-----0x10 0:fb0 0000:patern1 
//                   ||||+----0x08 0:Event調光無効 1:Event調光有効
//                   |||||+---0x04 0:Disable 1:enable (方向制御For/Rev) 
//                   ||||||+--0x02 0:Forward 1:Reverse 
//                   |||||||+-0x01 0:normal 1:常に点灯
//                   ||||||||
uint8_t gCV47_FC = 0b00000000;   // Forward Headlinght FL(f)
uint8_t gCV48_FC = 0b00000000;   // Reverse Headlinght FL(f)
uint8_t gCV49_FC = 0b00000000;   // Function 1
uint8_t gCV50_FC = 0b00000000;   // Function 2
uint8_t gCV51_FC = 0b00000000;   // Function 3
uint8_t gCV52_FC = 0b00000000;   // Function 4
uint8_t gCV53_FC = 0b00000000;   // Function 5
uint8_t gCV54_FC = 0b00000000;   // Function 6
uint8_t gCV55_FC = 0b00000000;   // Function 7
uint8_t gCV56_FC = 0b00000000;   // Function 8
uint8_t gCV57_FC = 0b00000000;   // Function 9
uint8_t gCV58_FC = 0b00000000;   // Function 10
uint8_t gCV59_FC = 0b00000000;   // Function 11
uint8_t gCV60_FC = 0b00000000;   // Function 12

// 0x80 PTNB3
// 0x40 PTNB2
// 0x20 PTNB1
// 0x10 PTNB0
// 0x08 DIMCON
// 0x04 DIRCON
// 0x02 FORREV
// 0x01 ALWAYS
//                    +--------0:Db3
//                    |+-------0:Db2
//                    ||+------0:Db1
//                    |||+-----0:Db0 Event側 調光 (0000-1111) 16段階
//                    ||||+----0:Db3  
//                    |||||+---0:Db2   
//                    ||||||+--0:Db1
//                    |||||||+-0:Db0 Normal側 調光 (0000-1111) 16段階
//                    ||||||||
uint8_t gCV112_FC = 0b00000000;   // Forward Headlinght FL(f)
uint8_t gCV113_FC = 0b00000000;   // Reverse Headlinght FL(f)
uint8_t gCV114_FC = 0b00000000;   // Function 1
uint8_t gCV115_FC = 0b00000000;   // Function 2
uint8_t gCV116_FC = 0b00000000;   // Function 3
uint8_t gCV117_FC = 0b00000000;   // Function 4
uint8_t gCV118_FC = 0b00000000;   // Function 5

uint8_t gCV119_FC = 0b00000000;   // Function 6
uint8_t gCV120_FC = 0b00000000;   // Function 7
uint8_t gCV121_FC = 0b00000000;   // Function 8
uint8_t gCV122_FC = 0b00000000;   // Function 9
uint8_t gCV123_FC = 0b00000000;   // Function 10
uint8_t gCV124_FC = 0b00000000;   // Function 11
uint8_t gCV125_FC = 0b00000000;   // Function 12

//                    +--------0:
//                    |+-------0:
//                    ||+------0:
//                    |||+-----0:
//                    ||||+----0:Sb3
//                    |||||+---0:Sb2   
//                    ||||||+--0:Sb1
//                    |||||||+-0:Sb0 速度閾値 (0000-1111) 16段階 Threshold
//                    ||||||||
uint8_t gCV126_FC = 0b00000000;   // Forward Headlinght FL(f)
uint8_t gCV127_FC = 0b00000000;   // Reverse Headlinght FL(f)
uint8_t gCV128_FC = 0b00000000;   // Function 1
uint8_t gCV129_FC = 0b00000000;   // Function 2
uint8_t gCV130_FC = 0b00000000;   // Function 3
uint8_t gCV131_FC = 0b00000000;   // Function 4
uint8_t gCV132_FC = 0b00000000;   // Function 5
uint8_t gCV133_FC = 0b00000000;   // Function 6
uint8_t gCV134_FC = 0b00000000;   // Function 7
uint8_t gCV135_FC = 0b00000000;   // Function 8
uint8_t gCV136_FC = 0b00000000;   // Function 9
uint8_t gCV137_FC = 0b00000000;   // Function 10
uint8_t gCV138_FC = 0b00000000;   // Function 11
uint8_t gCV139_FC = 0b00000000;   // Function 12



//FX効果
//Cmd,Time,Val
//I:初期状態,O:出力,S:スイープ,L:ループ,E:終了
uint8_t ptn1[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn2[10][3]={{'I',0,5},{'S',100,255},{'E',0,255}}; //10ms もやっと点灯
uint8_t ptn3[10][3]={{'I',0,5},{'S',50,255},{'S',50,5},{'L',0,5}}; //10ms 三角波
uint8_t ptn4[10][3]={{'I',0,0},{'O',10,255},{'O',10,125},{'O',10,255},{'O',10,80},{'L',0,0}}; // ランダム
uint8_t ptn5[10][3]={{'I',0,0},{'S',50,255},{'S',50,0},{'S',50,128},{'S',50,0},{'L',0,0}};//マーズライト
uint8_t ptn6[10][3]={{'I',0,0},{'O',30,255},{'S',20,128},{'L',0,0}};//フラッシュライト
uint8_t ptn7[10][3]={{'I',0,0},{'O',20,255},{'O',80,0},{'L',0,0}}; //シングルパルスストロボ
uint8_t ptn8[10][3]={{'I',0,0},{'O',10,255},{'O',20,0},{'O',10,255},{'O',60,0},{'L',0,0}}; //ダブルパルスストロボ
uint8_t ptn9[10][3]={{'I',0,0},{'O',25,128},{'O',40,255},{'O',25,128},{'O',40,0},{'L',0,0}}; //ミディアムパルスストロボ
uint8_t ptn10[10][3]={{'I',0,0},{'O',1,255},{'O',1,0},{'O',1,255},{'O',30,0},{'O',10,50},{'O',100,255},{'E',0,0}}; //グロー管蛍光灯
uint8_t ptn11[10][3]={{'I',0,0},{'O',1,255},{'O',1,0},{'O',1,255},{'O',30,0},{'O',30,40},{'O',50,255},{'O',70,0},{'L',0,0}}; //グロー管蛍光灯切れそう
uint8_t ptn12[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn13[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn14[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn15[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t (*ptn)[3];

//
// stateマシンを実行させるファンクッション
// b0:Head
// b1:Tail
// b2:Function 1
//      :
// b13:Function 12
//
//uint16_t FunctionStateEna = 0b0000000000000011;
define.h
#ifndef _DEFINE_H_
#define _DEFINE_H_


//各種設定、宣言

#define DECODER_ADDRESS 3
#define DCC_ACK_PIN 2   // 32 PD2 INT0  
#define AUX1 9          // 13 PB1 PWM_C OC1A
#define AUX2 10         // 14 PB2 PWM_D OC1B
#define AUX3 5          //  9 PD5 PWM_E OC0B
#define AUX4 6          // 10 PD6 PWM_F OSC1
//#define AUX5 A2         // 25 PC2
//#define AUX6 A3         // 26 PC3
//#define AUX7 A4         // 27 PC4
//#define AUX8 A5         // 28 PC5
#define AUX5 1         // 25 PC2
#define AUX6 2         // 26 PC3
#define AUX7 3         // 27 PC4
#define AUX8 4         // 28 PC5
#define Bi1 11          // 15 PB3 PWM_A OC2A
#define Bi2 3           //  1 PD3 PWM_B OC2B

#define PTNB3 0x80      //
#define PTNB2 0x40      //
#define PTNB1 0x20      //
#define PTNB0 0x10      //
#define DIMCON 0x08     // 0:Event調光無効 1:Event調光有効
#define DIRCON 0x04     // 0:Disable 1:enable (方向制御For/Rev)
#define FORREV 0x02     // 0:Forward 1:Reverse
#define ALWAYS 0x01     // 0:normal 1:常に点灯

#define FORWARD 1
#define REVERSE 0

#endif// _DEFINE_H_
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away