二つのLEDをマルチタスクで別々に光らせる

簡単なマルチタスクを用いる



同じLEDのタスクを動かすので、共通部分を親クラスにして、実際に動くクラスは、この親クラスから継承させて作ります。

親のLEDタスク LEDtask.h
#ifndef _LEDTASK
#define _LEDTASK

#include "Task.h"
#include "ColorLED.h"

class LEDtask : public Task
{
public:
  char *name;
  LEDtask ( char* name, PinName r, PinName g, PinName b );
  void show ( char* text );

protected:
  virtual void execute ();
  ColorLED *ColLED;
  static const int state0=0;
  static const int state1=1;
  static const int state2=2;
};

#endif


親のLEDタスク LEDtask.cpp
#include "LEDtask.h"
#include <math.h>
extern Serial pc;

LEDtask::LEDtask ( char* name, PinName r, PinName g, PinName b )
{
    this->name = name ;
    ColLED = new ColorLED(r, g, b);
}

void LEDtask::show ( char* text )
{
    pc.printf ("%s : %s\n", name, text ) ;
}


void LEDtask::execute () {
} //execute


子供のLEDタスク1 LEDtask1.h
#ifndef _LEDTASK1
#define _LEDTASK1

#include "Task.h"
#include "ColorLED.h"
#include "LEDtask.h"

class LEDtask1 : public LEDtask
{
public:
  LEDtask1 ( char* name, PinName r, PinName g, PinName b );

protected:
  void execute ();
private:
  float p;
};

#endif




子供のLEDタスク1 LEDtask1.cpp
#include "LEDtask1.h"
#include <math.h>
extern Serial pc;
LEDtask1::LEDtask1 ( char* name, PinName r, PinName g, PinName b )
: LEDtask(name, r, g, b)
{
    p = 0.0f;
}

void LEDtask1::execute () {
   float y=2*M_PI/3.0;
   switch ( state ) {
      case state0:
        show ( "Initial state" ) ;

        if(p < M_PI*2.0f)
        {
          ColLED->setColor((cosf(p)+1)/2,(cosf(p+y)+1)/2,
              (cosf(p+y*2)+1)/2);
          wait(0.5);
          nextState ( 0 ) ;
          p+=0.2f;
          break ;
        }
        nextState ( state1 ) ;
        break ;

      case state1:
        show ( "State 1" ) ;
        ColLED->setColor(0.0f, 1.0f, 0.0f);
        wait(0.5);
        nextState ( state2 ) ;
        break ;

      case state2:
        show ( "State 2" ) ;
        ColLED->setColor(0.0f, 0.0f, 1.0f);
        wait(0.5);
        p=0.0f;
        nextState ( state0 ) ;
        //stop () ;
        break ;

      default:    // 異常な状態を捕獲し停止するためにdefaultにする
        stop () ;
        break;
    } // switch
} //execute



子供のLEDタスク2 LEDtask2.h
#ifndef _LEDTASK2
#define _LEDTASK2

#include "Task.h"
#include "ColorLED.h"
#include "LEDtask.h"

class LEDtask2 : public LEDtask
{
public:
  LEDtask2 ( char* name, PinName r, PinName g, PinName b );
protected:
  void execute ();
};

#endif


子供のLEDタスク2 LEDtask2.cpp
#include "LEDtask2.h"
#include <math.h>
extern Serial pc;

LEDtask2::LEDtask2 ( char* name, PinName r, PinName g, PinName b )
: LEDtask(name, r, g, b)
{
}

void LEDtask2::execute () {

  if(state>6) nextState ( state0) ;
  else {
    ColLED->setColor(state+1);
    wait(0.5);
    nextState ( state+1) ;
  }
} //execute


メインプログラム



メインプログラム main.cpp
#include "mbed.h"
#include "ColorLED.h"
#include <math.h>
#include "LEDtask1.h"
#include "LEDtask2.h"

DigitalOut myled(LED1);
//ColorLED ColLED(p21,p22,p23);
//               赤 青 緑
//ColorLED ColLED2(p24,p25,p26);
//               赤 青 緑

Serial pc(USBTX, USBRX); // tx, rx

int main()
{
  pc.baud(115200);
  new LEDtask1 ( "Task 1" ,p21,p22,p23) ;
  new LEDtask2 ( "Task 2" ,p24,p25,p26) ;

  Task::TaskManager () ;
  pc.printf( "All done\n" ) ;
}


もう一つのマルチタスクで光らせる

簡単なマルチタスクを用いる



TaskLightGenerator.h
#ifndef TASKGENERATOR
#define TASKGENERATOR

#include "TimerTask.h"
#include "mbed.h"

/**
 * TaskManagerを用いたカラーLED発光器
 *
 * TaskTimerサポートを用いて指定された期間LEDを発光させる。
 */
class TaskLightGenerator : public TimerTask {
  protected:
    PwmOut* Red ;
    PwmOut* Green ;
    PwmOut* Blue ;
    PinName R, G, B ;
    int* lights ;
    int  lightsLength;
    int lightsIndex ;
    bool pwmRunning;
    int halfCycleTime;

/**
 * 色を設定する
 *
 * 入力:unsigned int color 3原色(RGB:8bit)
 */
  void setLight ( unsigned int color );
  void update(int r, int g, int b);
  void playNow ( int color, int time );
  void pwmstop();
  /* 内部ルーチン  */
  void startNextLight ();
public:
  static int endLight;  // 終了時の状態
  static int noMoreLights;

// 各PWMに色を設定する
  TaskLightGenerator ( PinName R,  PinName G, PinName B );
/**
 * タスク名を得る
 *
 * 戻り:char* タスク名
 */
  char* name ();

/**
 * 固定時間だけ色を発生する
 *
 * 入力:int color     RGBの色
 * 入力:int time      ミリ秒単位の持続時間
 */
  void play (int frequency, int time);
/**
 * 色の組を発生する。配列は偶数個の要素が含まれる。
 * 要素の始めの値は色情報
 * 二番目は持続時間
 * 配列に少なくとも二つないと何もしない。
 *
 * 入力:int[] lights: 音の配列(color, duration)の対
 */
  void playArrays ( int lights[], int n);
/**
 * 色が出ていれば色の発生を切る
 */  void stopLights ();
/**
 * 色が出ていれば色の発生を切る。TimerTaskからの override
 *
 * 入力:int interruptValue: 無視される
 *
 * 戻り:タスクが停止したときfalse
 */  bool handleInterrupt ( int interruptValue );
/**
 * TaskManagerで呼ばれるタスク実行ルーチン
 *
 * 戻り:boolean: 終了したときfalse、残りがあるときtrue
 */
  bool handleTimeout ();
  bool running();
};

#endif




TaskLightGenerator.cpp
#include "TaskLightGenerator.h"
#include "mbed.h"

/**
 * TaskManagerを用いたカラーLED発光器
 *
 * TaskTimerサポートを用いて指定された期間LEDを発光させる。
 */
/**
 * 色を設定する
 *
 * 入力:unsigned int color 3原色(RGB:8bit)
 */
void TaskLightGenerator::setLight ( unsigned int color ) {
  update ( (color>>16)&0xff, (color>>8) &0xff, color&0xff);
}

// 各PWMに色を設定する
void TaskLightGenerator::update(int r, int g, int b)
{
  Red->pulsewidth_us( r ) ;
  Green->pulsewidth_us( g );
  Blue->pulsewidth_us( b );
}
/* Internal routine */
void TaskLightGenerator::playNow ( int color, int time ) {
    // PWMを設定する
  setLight ( color ) ;
    // PWMとタスクがすでに入っているかどうかチェックする
  if ( ! pwmRunning ) {
     pwmRunning = true ;
  }

  /* 指定した時間Sleepする
   * 後でtimerRunningのstatusを設定するからtimerRunning
   * のチェックをした後に実行しなければならない
   */
  TimerTask::sleep(time) ;
}
void TaskLightGenerator::pwmstop()
{
  update(0,0,0);
}

  // 内部ルーチン
void TaskLightGenerator::startNextLight () {
  // lightsIndexはいつも正しい対を参照する
  playNow ( lights[lightsIndex], lights[lightsIndex+1] ) ;
  lightsIndex += 2 ;
  // リストの中の最後の音かどうかlightsIndexを調整する
  if (( lightsIndex + 2 ) > lightsLength ) {
    lightsIndex = noMoreLights ;
  }
}

TaskLightGenerator::TaskLightGenerator ( PinName R,  PinName G, PinName B) {
  pwmRunning = false ;
  this->R = R ;
  this->G = G ;
  this->B = B ;
  Red   = new PwmOut ( R ) ;
  Green = new PwmOut ( G ) ;
  Blue  = new PwmOut ( B ) ;
  Red->period_us(256);
  Green->period_us(256);
  Blue->period_us(256);
}

/**
 * タスク名を得る
 *
 * 戻り:String タスク名
 */
char* name () {
  return "TaskLightGenerator" ;
}


/**
 * 固定時間だけ色を発生する
 *
 * 入力:int color     RGBの色
 * 入力:int time      ミリ秒単位の持続時間
 */
void TaskLightGenerator::play (int color, int time) {
  lightsIndex = noMoreLights ;
  playNow ( color, time ) ;
}

/**
 * 色の組を発生する。配列は偶数個の要素が含まれる。
 * 要素の始めの値は色情報
 * 二番目は持続時間
 * 配列に少なくとも二つないと何もしない。
 *
 * 入力:int[] lights: 音の配列(color, duration)の対
 */
void TaskLightGenerator::playArrays ( int lights[], int n) {
  lightsLength = n;
  if ( lightsLength >= 2 )
  {
    this->lights = lights ;
    lightsIndex = 0 ;
    startNextLight () ;
  }
}

/**
 * 色が出ていれば色の発生を切る
 */
void TaskLightGenerator::stopLights () {
  Interrupt ( 0 ) ;
}

/**
 * 色が出ていれば色の発生を切る。TimerTaskからの override
 *
 * 入力:int interruptValue: 無視される
 *
 * 戻り:タスクが停止したときfalse
 */
bool TaskLightGenerator::handleInterrupt ( int interruptValue ) {
  if ( pwmRunning ) {
    lightsIndex = noMoreLights ;  //次のタイムアウトでdisableにする
    handleTimeout () ;            //タイムアウトさせる
  }
  return false ;
}

/**
 * TaskManagerで呼ばれるタスク実行ルーチン
 *
 * 戻り:boolean: 終了したときfalse、残りがあるときtrue
 */
bool TaskLightGenerator::handleTimeout () {
  if ( lightsIndex == noMoreLights ) {
    // 残りの光情報がないときPWMを切る
    pwmRunning = false ;
    pwmstop();          // LEDを消す
    return false ;     // タスクを停止
  } else {
    // Get next tone
    startNextLight () ; // タイマーと次の音を開始
    return true ;      // タスクを続ける
  }
}

/**
 *
 */
bool TaskLightGenerator::running() {
    if( pwmRunning ) return true;
    return false;
}

int TaskLightGenerator::endLight=1;  // 終了時の状態
int TaskLightGenerator::noMoreLights=-1;




MultitaskingTest3a.h
#include "Task.h"
#include "TaskLightGenerator.h"
#include "common.h"

class MultitaskingTest3a : public InterruptTask
{
  static const int waitDone = 1 ;
  static const int waitForDone = 2 ;
private:
  int numberOfColor;
 public:
    int *toneList ;
    TaskLightGenerator* lightGenerator;

    MultitaskingTest3a();
    MultitaskingTest3a( PinName R,  PinName G, PinName B, int* list, int n);
protected:
  void execute ();
};




MultitaskingTest3a.cpp
#include "MultitaskingTest3a.h"

MultitaskingTest3a::MultitaskingTest3a()
{
  lightGenerator = new TaskLightGenerator ( p24, p26, p25 ) ;
  state = 0;
  numberOfColor=7;
  toneList = (int*)malloc(numberOfColor*2*sizeof(int));
  int *p = toneList;
  for(int i=1; i<=numberOfColor; i++){
    int r = (i&0x04) ? 0xff0000: 0;
    int g = (i&0x02) ? 0x00ff00: 0;
    int b = (i&0x01) ? 0x0000ff: 0;
    *p++ = r|g|b;
    *p++ = 600;
  }
}
MultitaskingTest3a::MultitaskingTest3a( PinName R,  PinName G, PinName B, int* list, int n)
{// p24, p26, p25
  lightGenerator = new TaskLightGenerator ( R, G, B  ) ;
  state = 0;
  numberOfColor=n;
  toneList = list;
}
void MultitaskingTest3a::execute () {
  switch ( state ) {
    case initialState:
      pc.printf ( "Initial state\n" ) ;
      lightGenerator->play (  0xffffff, 1000 ) ;
      nextState ( waitDone ) ;
      break ;

    case waitDone:
      if ( lightGenerator->running ()) {
        pc.printf ( "Waiting for tone to end\n" ) ;
      } else {
        lightGenerator->playArrays ( toneList, numberOfColor*2 ) ;
        nextState ( waitForDone ) ;
      }
      break ;

    case waitForDone:
      if ( lightGenerator->running ()) {
        //pc.printf ( "Waiting for tone list to end2\n" ) ;
      } else {
        nextState ( waitDone ) ;
        //stop () ;
      }
      break ;

    default:    // 異常な状態を捕獲し停止するためにdefaultにする
      stop () ;
      break;
  }
}




main.cpp
#include "mbed.h"
#include "MultitaskingTest3a.h"

Serial pc(USBTX, USBRX); // tx, rx

int main()
{
  pc.baud(115200);
  int numberOfColor=32;
  int *toneList = (int*)malloc(numberOfColor*2*sizeof(int));
  int *p = toneList;
  int r, g, b;
  float x;
  float diff=2*M_PI/3;
  float delta=2*M_PI/numberOfColor;
  for(int i=0; i<numberOfColor; i++){
    x = delta*i;
    r = (int)((cosf(x)+1)*127)<<16;
    g = (int)((cosf(x+diff)+1)*127)<<8;
    b = (int)((cosf(x+diff*2)+1)*127);
    *p++ = r|g|b;
    *p++ = 75;
  }

  int numberOfColor2=7;
  int *toneList2 = (int*)malloc(numberOfColor2*2*sizeof(int));
  p = toneList2;
  for(int i=1; i<<=numberOfColor2; i++){
    r = (i&0x04) ? 0xff0000: 0;
    g = (i&0x02) ? 0x00ff00: 0;
    b = (i&0x01) ? 0x0000ff: 0;
    *p++ = r|g|b;
    *p++ = 500;
  }
  MultitaskingTest3a Mt3( p21, p23, p22, toneList , numberOfColor );
  MultitaskingTest3a Mt3a(p24, p26, p25, toneList2, numberOfColor2) ;
  Task::TaskManager() ;
  pc.printf( "All done\n" ) ;
}