SSブログ

Lazurite 920Jを立ち上げてみる 其の11 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

めちゃくちゃ久しぶりの更新

PRO MINI相当に変換する基板の資料を置いておきますね。
lazrite920j_pro_mini_001.png

lazrite920j_pro_mini_002.png


プログラムの書き換えは以下のリンク先を読んでみてください。
http://hamayan.blog.so-net.ne.jp/2016-10-21

これが有ると便利です。
スルホール用テストワイヤ TP-200
http://akizukidenshi.com/catalog/g/gC-09830/

使用コネクタ関しては以下のリンク先を読んでみてください。
http://hamayan.blog.so-net.ne.jp/2016-10-17

nice!(0)  コメント(1) 

Lazurite 920Jを立ち上げてみる 其の10 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

lazuriteImage_003.jpg
変換基板の配布をしようと思っています。数量は20~30セットくらい。

いやぁ、某店舗での委託販売で交渉をしていましたが、「常時在庫を持つ!」「1年間の継続販売必須!」と言う事で売り切りができず、個人ではもっとも辛いところの在庫を持つ!必要があり、いまのところ断念しています。

セット内容は、基板と1.27mmピッチのコネクタ、2mmピッチ、2.54mmピッチのコネクタになります。

価格ですが、委託販売を行わない事から某店への手数料などが無くなるので、1000円ポッキリを考えています。※送料は別です!

どうでしょうかね?
※勿論サポートもここで行います。
※好評?だったら別タイプの変換基板も企画を進めます。

コメントに書いていただくか、以下から連絡先のファイルを入手してください。
https://dl.dropboxusercontent.com/u/60463387/contact/contact.txt

※変換基板と言えば、ESP8266をXBeeのピン配置に変換する基板も用意しているんですよ。でも半田付け、結構大変です。こちらも良かったら要望を送ってください。
ESP8266_BEE.jpg

Lazurite 920Jを立ち上げてみる 其の9 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

lazuriteImage_025.png

マルチタスクで行こう!

例によってマルチタスク化。例によってノンプリエンプティブ。


〇ドキュメントの在処
ネットを検索しても見つからないなぁ、、、と思っていたら、東大元暮らしでした!
ついついネット上に有ると思い込んでしまいますね。

▼FJUL-U16-100-INST-02.pdf
アーキテクチャの解説とアセンブラ命令コードの解説

▼FJXTCCU8_UM-08.pdf
コンパイラ・ユーザーズマニュアル

▼FJXTCCU8_PG-03.pdf
コンパイラ・プログラミングガイド

▼FJXTCCU8_LR-03.pdf
コンパイラ・ランゲージリファレンス


〇CPUについてまとめると
▼16bit RISCマイコン、記述が見つからなかったけれどハーバードアーキテクチャかもしれない。
一応1命令1クロック。

▼3段パイプライン。パイプラインストールを頻発しなければ結構速いかもしれない。

▼メモリ空間に関してsmallモデルとLargeモデルが有るが、今回はsmallモデルを対象としている。
ROM 64kbyte、RAM 6kbyte


〇ディスパッチャーを作る
どうでもイイことを勘違いして一日悩んだが、smallモデルであればわりと簡単だと思う。
/****************************************************************************/
/* dispatcher                                                               */
/****************************************************************************/
void sta_ctx( void *exe )  /*exe=ER0*/
{
  __asm( "L ER2,[ER0]\n" );  /**/
  __asm( "MOV SP,ER2\n" );  /**/

  __asm( "POP QR8\n" );  /*R8-R15 8bytes*/
  __asm( "POP XR4\n" );  /*R4-R7 4bytes*/
  __asm( "POP LR\n" );  /*link register 2bytes*/
}

void swi_ctx( void *pre, void *post )  /*pre=ER0,post=ER2*/
{
  __asm( "PUSH LR\n" );  /*link register*/
  __asm( "PUSH XR4\n" );  /*R4-R7*/
  __asm( "PUSH QR8\n" );  /*R8-R15*/

  __asm( "MOV ER4,SP\n" );  /**/
  __asm( "ST ER4,[ER0]\n" );  /**/

  __asm( "L ER0,[ER2]\n" );  /**/
  __asm( "MOV SP,ER0\n" );  /**/

  __asm( "POP QR8\n" );  /*R8-R15*/
  __asm( "POP XR4\n" );  /*R4-R7*/
  __asm( "POP LR\n" );  /*link register*/
}



〇サンプルプログラム
lazuriteImage_028.png

黄色タスクが250ms周期、青タスクが500ms周期、赤タスクが1000ms周期でLEDを点滅させているだけのプログラム
#include "multiTaskDemo_ide.h"		// Additional Header
#include  <mul_tsk.h>
#include "delivertive.h"

#define  BLUE_LED       26
#define  RED_LED        20
#define  YELLO_LED      25

void led_yello( void );
void led_blue( void );
void led_red( void );

char tsk1_stk[ 256 ];
char tsk2_stk[ 256 ];
char tsk3_stk[ 256 ];

void tsk_ini( void )
{
  reg_tsk( ID_led_yello,led_yello, tsk1_stk, sizeof(tsk1_stk), (VP_INT)0,(VP_INT)0,(VP_INT)0,(VP_INT)0 );
  reg_tsk( ID_led_blue, led_blue, tsk2_stk, sizeof(tsk2_stk), (VP_INT)0,(VP_INT)0,(VP_INT)0,(VP_INT)0 );
  reg_tsk( ID_led_red,  led_red, tsk3_stk, sizeof(tsk3_stk), (VP_INT)0,(VP_INT)0,(VP_INT)0,(VP_INT)0 );

  sta_tsk( ID_led_yello );
  sta_tsk( ID_led_blue );
  sta_tsk( ID_led_red );
}

void setup(void)
{
  Serial.begin( 115022UL );

  tsk_ini();  //タスクの初期化
  sta_rdq( ID_led_yello );  /*ラウンドロビン開始*/
}

// Arduino loop sequence
void loop(void)
{
}

void led_yello( void )
{
  pinMode( YELLO_LED, OUTPUT );
  digitalWrite( YELLO_LED, LOW );
  while( 1 )
  {
    digitalWrite( YELLO_LED, HIGH );
    dly_tsk( 125UL );
    digitalWrite( YELLO_LED, LOW );
    dly_tsk( 125UL );
    Serial.print( "task1 time=" );
    Serial.print_long( millis(), DEC );
    Serial.println( "ms" );
  }
}

void led_blue( void )
{
  pinMode( BLUE_LED, OUTPUT );
  digitalWrite( BLUE_LED, LOW );
  while( 1 )
  {
    digitalWrite( BLUE_LED, HIGH );
    dly_tsk( 250UL );
    digitalWrite( BLUE_LED, LOW );
    dly_tsk( 250UL );
    Serial.print( "task2 time=" );
    Serial.print_long( millis(), DEC );
    Serial.println( "ms" );
  }
}

void led_red( void )
{
  pinMode( RED_LED, OUTPUT );
  digitalWrite( RED_LED, LOW );
  while( 1 )
  {
    digitalWrite( RED_LED, HIGH );
    dly_tsk( 500UL );
    digitalWrite( RED_LED, LOW );
    dly_tsk( 500UL );
    Serial.print( "task3 time=" );
    Serial.print_long( millis(), DEC );
    Serial.println( "ms" );
  }
}


※IDEにプロジェクトの設定ファイルってのがあるんだけれど、ここに書きこんだからと言ってコンパイルオプションに展開されるわけではなく、悲しかった。

※ライブラリのデバックをしたくてSerial.printって書いても、「何それ?美味しいの?」ってコンパイラに言われて、悲しかった。

Lazurite 920Jを立ち上げてみる 其の7 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

lazuriteImage_004.jpg

まず言って置きます。LazuriteのI2Cの標準の速度は400kHzだぁ。つまずく事間違いなし。勿論私もつまづいた!
※setupの中で100kHzに落としてねー!

さて今日のお題はArudinoとかGR-KURUMIとか用に作成したライブラリの移植の話。

LazuriteはC++をサポートしていないので、ライブラリは全てCソースで記述しなければならない。
この辺を参照して欲しい。
http://hamayan.blog.so-net.ne.jp/2016-10-17

つまりArduinoのライブラリを持って来てもコンパイルすら通らないので、地道にコツコツCソースへの置き換えが必要となる。きっとここでめげる人多数、、、

とは言え買っちゃったのでなんとか使いこなす必要性から、なんとかしてみたいと思う。

今回移植するライブラリはGR-KURUMI用に作成したOLED表示器のライブラリです。
※ArduinoのライブラリをGR-KURUMIに持ってきた場合、かなりの確率でそのまま動く。修正が必要となったとしても、それ程手間ではない。

以下にGR-KURUMI用のソースを掲載します。
US2066.cpp ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/*********************************************************************************/
/* US2066を使用したOLED SO1602AWGBの初期化と表示                                 */
/*                                         designed by hamayan since 2015/04/21  */
/*********************************************************************************/
#include  <RLduino78.h>
#include  <iodefine.h>
#include  <iodefine_ext.h>
#include  <US2066.h>

extern "C" {
  #include  <mul_tsk.h>
}

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

US2066::US2066()
{
}

/****************************************************************************/
/* I2C block Write                                                          */
/****************************************************************************/
int US2066::blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len)
{
  Wire.beginTransmission(addr);
  Wire.write(dat,len);
  return Wire.endTransmission();
}

/*************************************************************************/
/* write command         */
/*************************************************************************/
int US2066::writeCommand(unsigned char t_command)
{
  unsigned char cmd[2];

  cmd[0] = 0x00;
  cmd[1] = t_command;

  return blkWrite( i2cAddress, cmd, sizeof(cmd) );
}

/*************************************************************************/
/* write data                                                            */
/*************************************************************************/
int US2066::writeData(unsigned char t_data)
{
  unsigned char dat[2];

  dat[0] = 0x40;
  dat[1] = t_data;

  return blkWrite( i2cAddress, dat, sizeof(dat) );
}

/*************************************************************************/
/* US2066初期化                                                          */
/*************************************************************************/
void US2066::init( unsigned char adr )
{
  i2cAddress = adr;  /*I2C address set*/

  dly_tsk(100);
  writeCommand( 0x01 );  //clear display
  dly_tsk(20);
  writeCommand( 0x02 );  //return home
  dly_tsk(2);
  writeCommand( 0x0f );  //send display on command
  dly_tsk(2);
  writeCommand( 0x01 );  //clear display
  dly_tsk(20);
}

/*************************************************************************/
/* clear display                                                         */
/*************************************************************************/
void US2066::clear( void )
{
  dly_tsk(100);
  writeCommand( 0x01 );  //clear display
  dly_tsk(20);
}

/*************************************************************************/
/* display on/off                                                        */
/*************************************************************************/
void US2066::OnOff( unsigned char onoff )
{
  writeCommand( onoff | 0x08 );  //display on/off,cursor on/off,blink on/off
  dly_tsk(20);
}

/*************************************************************************/
/* locate                                                                */
/*************************************************************************/
void US2066::locate( int x, int y )
{
  int temp = x + (y * 20);

  if(temp >= 20) temp = (temp - 20) + 0x20;

  writeCommand( (unsigned char)temp | 0x80 );  //set ddram address
  dly_tsk(20);
}

/*************************************************************************/
/* set contrast         */
/*************************************************************************/
void US2066::contrast( unsigned char cnt )
{
  //コントラスト調整
  writeCommand( 0x2a );  //RE=1
  writeCommand( 0x79 );  //SD=1
  writeCommand( 0x81 );  //contrast set
  writeCommand( cnt );  //contrast max
  writeCommand( 0x78 );  //SD=0
  writeCommand( 0x28 );  //set character size is normal.
  dly_tsk(100);
}

/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
int US2066::writeString( const char *str )
{
  unsigned char dat[1 * SO2002A_COLUMN + 1];
  int len = strlen(str);

  dat[0] = 0x40;
  len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len;
  memcpy( &dat[1], str, len );

  return blkWrite( i2cAddress, dat, len + 1 );
}

/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
int US2066::writeString( const char *str, unsigned int len )
{
  unsigned char dat[1 * SO2002A_COLUMN + 1];

  dat[0] = 0x40;
  len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len;
  memcpy( &dat[1], str, len );

  return blkWrite( i2cAddress, dat, len + 1 );
}

/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
int US2066::writeString( String str )
{
  return writeString( (const char *)&str[0], str.length() );
}

/*********************************************************************************/
/* end of file                                                                   */
/*********************************************************************************/

US2066.h ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/****************************************************************************/
/* ssd1305  header                                                          */
/*                         Copyright (C) 2014 hamayan All Rights Reserved.  */
/****************************************************************************/
#ifndef US2066_h
#define US2066_h

#include <wire.h>

extern "C" {
}

//#define  US2066_0_ADR         0x3C
#define  SO2002A_LINES        2
#define  SO2002A_COLUMN       16
#define  SO2002A_DISPLAY_ON   0x04
#define  SO2002A_DISPLAY_OFF  0x00
#define  SO2002A_CURSOR_ON    0x02
#define  SO2002A_CURSOR_OFF   0x00
#define  SO2002A_BLINK_ON     0x01
#define  SO2002A_BLINK_OFF    0x00

class US2066 {
private:
  unsigned char i2cAddress;

  int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len);
  int writeCommand(unsigned char t_command);
  int writeData(unsigned char t_data);

public:
  US2066();
  void init( unsigned char adr );
  void clear( void );
  void OnOff( unsigned char onoff );
  void locate( int x, int y );
  void contrast( unsigned char cnt );
  int  writeString( const char *str );
  int  writeString( const char *str, unsigned int len );
  int  writeString( String str );
};

#endif  /*US2066_H*/
/****************************************************************************/
/*                         Copyright (C) 2014 hamayan All Rights Reserved.  */
/****************************************************************************/


さてこれを移植するのですが、まずC++の記述スタイルはCには適用できない事が多い!
例えば関数のオーバーライド
  int  writeString( const char *str );
  int  writeString( const char *str, unsigned int len );
  int  writeString( String str );

なんてもろにダメですね!

  Wire.endTransmission();

こう言った省略もダメです。
まぁ実際にコンパイル掛けてみると色々エラーや警告出ますんで、一つ一つ潰していくしかない。

クラスのメッソッドっぽく記述し直す必要があります。例えば
US2066 oled;
 oled.init( 10 );

みたいに書きたいとすれば、関数名のリストを作った構造体を用意して、それで呼び出す事になります。

結局以下の様になりました。
US2066.c ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/*********************************************************************************/
/* US2066を使用したOLED SO1602AWGBの初期化と表示                                 */
/*                                         designed by hamayan since 2015/04/21  */
/*********************************************************************************/
#include  <US2066.h>

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

static unsigned char i2cAddress;

static int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len);
static int writeCommand(unsigned char t_command);
static int writeData(unsigned char t_data);

/****************************************************************************/
/* I2C block Write                                                          */
/****************************************************************************/
static int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len)
{
  Wire.beginTransmission(addr);
  Wire.write(dat,len);
  return Wire.endTransmission( true );
}

/*************************************************************************/
/* write command         */
/*************************************************************************/
static int writeCommand(unsigned char t_command)
{
  unsigned char cmd[2];

  cmd[0] = 0x00;
  cmd[1] = t_command;

  return blkWrite( i2cAddress, cmd, sizeof(cmd) );
}

/*************************************************************************/
/* write data                                                            */
/*************************************************************************/
static int writeData(unsigned char t_data)
{
  unsigned char dat[2];

  dat[0] = 0x40;
  dat[1] = t_data;

  return blkWrite( i2cAddress, dat, sizeof(dat) );
}

/*************************************************************************/
/* US2066初期化                                                          */
/*************************************************************************/
static void init( unsigned char adr )
{
  i2cAddress = adr;  /*I2C address set*/

  dly_tsk(100);
  writeCommand( 0x01 );  //clear display
  dly_tsk(20);
  writeCommand( 0x02 );  //return home
  dly_tsk(2);
  writeCommand( 0x0f );  //send display on command
  dly_tsk(2);
  writeCommand( 0x01 );  //clear display
  dly_tsk(20);
}

/*************************************************************************/
/* clear display                                                         */
/*************************************************************************/
static void clear( void )
{
  dly_tsk(100);
  writeCommand( 0x01 );  //clear display
  dly_tsk(20);
}

/*************************************************************************/
/* display on/off                                                        */
/*************************************************************************/
static void OnOff( unsigned char onoff )
{
  writeCommand( onoff | (unsigned char)0x08 );  //display on/off,cursor on/off,blink on/off
  dly_tsk(20);
}

/*************************************************************************/
/* locate                                                                */
/*************************************************************************/
static void locate( int x, int y )
{
  int temp = x + (y * 20);

  if(temp >= 20) temp = (temp - 20) + 0x20;

  writeCommand( (unsigned char)temp | (unsigned char)0x80 );  //set ddram address
  dly_tsk(20);
}

/*************************************************************************/
/* set contrast         */
/*************************************************************************/
static void contrast( unsigned char cnt )
{
  //コントラスト調整
  writeCommand( 0x2a );  //RE=1
  writeCommand( 0x79 );  //SD=1
  writeCommand( 0x81 );  //contrast set
  writeCommand( cnt );  //contrast max
  writeCommand( 0x78 );  //SD=0
  writeCommand( 0x28 );  //set character size is normal.
  dly_tsk(100);
}

/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
static int writeString( const char *str )
{
  unsigned char dat[1 * SO2002A_COLUMN + 1];
  int len = strlen(str);

  dat[0] = 0x40;
  len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len;
  memcpy( &dat[1], str, len );

  return blkWrite( i2cAddress, dat, len + 1 );
}

/*************************************************************************/
/* メンバー関数のリスト                                                  */
/*************************************************************************/
const t_US2066_I2C oled =
{
  init,
  clear,
  OnOff,
  locate,
  contrast,
  writeString,
};

/*********************************************************************************/
/* end of file                                                                   */
/*********************************************************************************/

US2066.h ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/****************************************************************************/
/* ssd1305  header                                                          */
/*                         Copyright (C) 2014 hamayan All Rights Reserved.  */
/****************************************************************************/
#ifndef US2066_h
#define US2066_h

#include <Wire.h>

//#define  US2066_0_ADR         0x3C
#define  SO2002A_LINES        2
#define  SO2002A_COLUMN       16
#define  SO2002A_DISPLAY_ON   0x04
#define  SO2002A_DISPLAY_OFF  0x00
#define  SO2002A_CURSOR_ON    0x02
#define  SO2002A_CURSOR_OFF   0x00
#define  SO2002A_BLINK_ON     0x01
#define  SO2002A_BLINK_OFF    0x00

#if 0
class US2066 {
private:
  unsigned char i2cAddress;

  int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len);
  int writeCommand(unsigned char t_command);
  int writeData(unsigned char t_data);

public:
  US2066();
  void init( unsigned char adr );
  void clear( void );
  void OnOff( unsigned char onoff );
  void locate( int x, int y );
  void contrast( unsigned char cnt );
  int  writeString( const char *str );
  int  writeString( const char *str, unsigned int len );
  int  writeString( String str );
};
#else
typedef struct
{
  void (*init)( unsigned char adr );
  void (*clear)( void );
  void (*OnOff)( unsigned char onoff );
  void (*locate)( int x, int y );
  void (*contrast)( unsigned char cnt );
  int  (*writeString)( const char *str );
} t_US2066_I2C;

extern const t_US2066_I2C oled;
#endif

#endif  /*US2066_H*/

/****************************************************************************/
/*                         Copyright (C) 2014 hamayan All Rights Reserved.  */
/****************************************************************************/

※関数のオーバーライドの代替関数はめんどうくさいので止めちゃいました!
※BME280の移植をしていて気付いたのですが、long long型が使えない、、、

上記ソースを、Lazurite IDEが入っているフォルダーの中のlibraries以下に、ソースと同じ名前にしたフォルダーを生成し、そこに収納します。
lazuriteImage_022.png

この状態でIDEを起動するとこのライブラリが左端のライブラリリストに表示されますので、チェックします。
※I2CなのでWireにもチェックを入れます。
lazuriteImage_023.png


で、冒頭の表示プログラムが以下になります。
blue_led.c ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
#include "blue_led_ide.h"		// Additional Header
#include  "mcu.h"

#define  BLUE_LED		26
#define  US2066_ADDRESS (0x3C << 0)

void setup(void)
{
  digitalWrite(BLUE_LED,HIGH);
  pinMode(BLUE_LED,OUTPUT);

  Wire.begin();
  I21MD=0;  /*100khz setup*/

  oled.init( US2066_ADDRESS );
  oled.contrast( 0xff );
  oled.clear();
  oled.OnOff( SO2002A_DISPLAY_ON | SO2002A_CURSOR_OFF | SO2002A_BLINK_OFF );
  oled.writeString( "Lazurite 920J" );
  oled.locate( 0, 1 );
  oled.writeString( "  with OLED" );
}

void loop(void)
{
  digitalWrite(BLUE_LED,HIGH);
  delay(1000);
  digitalWrite(BLUE_LED,LOW);
  delay(1000);
}

冒頭でmcu.hをインクルードしていますが、I2Cの速度を落とす為に必要です。
またsetupの先頭の
  Wire.begin();
  I21MD=0;  /*100khz setup*/

も必要です。

※まぁこれくらいのコード量なら移植はそれほどでもですが、もっと複雑なコードだと厳しいですね。BME280の移植はそれなりに手間でしたよ。

※IDEのライブラリにBME280は登録されていますが、、、SPIで動かした時のライブラリで、I2Cではありませんでしたorz。

※いや、最大の問題はこんなライブラリの移植ではなく、フォーラムのレスポンスの悪さだったりして。


Lazurite 920Jを立ち上げてみる 其の6 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

lazuriteImage_003.jpg

外部から低消費電力状態を解除したい!

sleep関数は時間が来ると低消費電力状態から解除されますが、それ以外に外部からこの低消費電力状態を解除したい時も多いかと思います。

この様な場合、wait_event関数を使う様です。
以下にサンプルを上げておきます。
Arduino同様外部割り込み端子として2番と3番が使用できますが、今回は2番に押しボタンスイッチを接続しています。
#define BLUE_LED       26
#define RED_LED        20
#define YELLO_LED      25

bool eventFlag = false;

void pin2Int( void )
{
  eventFlag = true;
}

void setup(void)
{
  pinMode( BLUE_LED, OUTPUT );
  pinMode( 2, INPUT_PULLUP );
  attachInterrupt( 0, pin2Int, FALLING );
}

void loop(void)
{
  digitalWrite(BLUE_LED, LOW);
  delay( 500 );
  digitalWrite(BLUE_LED, HIGH);
  eventFlag = false;
  wait_event( &eventFlag );
}

端子割り込みの中でbool型のフラグをtrueにしているだけの簡単なプログラムですね。

※低消費電力状態に入るとPower LEDは消灯されるが、青LEDは直前の端子の状態を維持している模様。

※では時間と外部割り込みの併用はできるのか?
先ほどのコードの wait_event( &eventFlag ); を sleep( 10 * 1000UL ); に変更してみましたが、外部割り込みでは起きない様です。うーん、、、一応sleepのマニュアルでは外部割り込みは有効と書いてあるので、低消費電力状態の解除方法が提供されていれば良いのですけれどね。


Lazurite 920Jを立ち上げてみる 其の5 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

2016-10-27 11.23.34.jpg

どんくらい転送できるんだろう?

気になるのは「らずらいと姫」の解説ページに、送信時間は1時間当たり360秒(10%)に制限されるって書いてある点。
http://www.lapis-semi.com/lazurite-jp/lazurite/2473.html

そこで写真の様に2つのLazurite 920Jを並べています。ラベルを見て判るように、左が送信、右が受信ですね!
lazuriteImage_017.png lazuriteImage_018.png

ええっと、送信データサイズが839543byte、送信時間合計が1452933ms、1048回エラー、送信数40279回。
受信データ数が8586536byte、受信数40124回。

あ、合わない、、、

1回のペイロードサイズが214byte、ヘッダーの11byteを考慮すると839543byteの全体サイズは882697byte。
ビットに直して1秒辺りのレートに換算すると、約4860bps。
無線の設定では100kbpsなので10%にも達していない結果。
※流れる時はやけに流れる(50kbpsとか60kbps)、流れない時はまったく流れない!ムラっけのある通信。

※あれぇ?これ、アンテナの向きとか距離(近過ぎる)とか影響されている感じがする。マルチパスとかも!


SubGHz.sendのマニュアルを読む限り、
http://www.lapis-semi.com/lazurite-jp/contents/reference/subghz_send.html

標準で250-11=239byteがデータのペイロードサイズに思えるが、実際にそのサイズを送信すると受信側は214byteしか受けていない。
なんで???
lazuriteImage_016.png



※試験やり直し
無線モジュール同士の距離とか、アンテナの向きを調整して比較的安定している状態にして再度約1時間の転送レートを求めてみた。
lazuriteImage_019.png lazuriteImage_020.png

約50kbps以上は出ている計算になった。じゃあ「らずらいと姫」のあの解説は一体なんだったんだろう?
送信のデータ数と受信のデータ数とかカウントが一致しないのは、もう無線だからとしか言いようがないなぁ。
なので、過信せずに自分で上位プロトコルを実装した方がいいでしょう。少なくともシーケンス番号のチェックは必要に思える。

送信側プログラム
#define SUBGHZ_CH      36
#define SUBGHZ_PANID   0xABCD
#define CLIENT_ID      0x405D
#define SERVER_ID      0x406A
#define BLUE_LED       26
#define TEST_PERIOD    (60UL * 60UL * 1000UL)
//#define TEST_PERIOD    (10UL * 60UL * 1000UL)

uint8_t tx_data[ 200 ];
unsigned long totalTime = 0;
unsigned long startTime = 0;
unsigned long totalBytes = 0;
unsigned long totalCount = 0;
unsigned long totalError = 0;

void setup(void)
{
  int i;
  SUBGHZ_MSG msg;

  Serial.begin(115200);
	
  msg = SubGHz.init();
  if(msg != SUBGHZ_OK)
  {
    SubGHz.msgOut(msg);
    while(1) {}
  }

  msg = SubGHz.begin( SUBGHZ_CH, SUBGHZ_PANID,  SUBGHZ_100KBPS, SUBGHZ_PWR_20MW );
  if(msg != SUBGHZ_OK)
  {
    SubGHz.msgOut(msg);
    while(1) {}
  }
  msg = SubGHz.rxEnable(NULL);
  if(msg != SUBGHZ_OK)
  {
    SubGHz.msgOut(msg);
    while(1){ }
  }

  //dummy data
  for( i = 0; i < sizeof(tx_data); i++ )
  {
    tx_data[ i ] = (uint8_t)i;
  }

  Serial.println("transmit rate test SEME!");

  delay( 10000UL );
  startTime = millis();
  pinMode( BLUE_LED, OUTPUT );
  digitalWrite( BLUE_LED, HIGH );
}

void loop(void)
{
  unsigned long baseTim,diffTime;
  SUBGHZ_MSG msg;

  if( (millis() - startTime) >= TEST_PERIOD )
  {
    Serial.print( "transmit end:" );
    Serial.print_long( totalBytes, DEC );
    Serial.print( "bytes / " );
    Serial.print_long( totalTime / 1000UL, DEC );
    Serial.print( "ms " );
    Serial.print_long( totalError, DEC );
    Serial.print( "errors / " );
    Serial.print_long( totalCount, DEC );
    Serial.println( "counts" );
    while( 1 ) {}
  }

  //transmit message
  digitalWrite( BLUE_LED, LOW );
  baseTim = micros();
  msg = SubGHz.send( SUBGHZ_PANID, SERVER_ID, tx_data, sizeof(tx_data), NULL );  // send data
  diffTime = micros() - baseTim;
  digitalWrite( BLUE_LED, HIGH );

  if( msg == SUBGHZ_OK )
  {
    totalTime += diffTime;
    totalBytes += sizeof(tx_data);
  }
  else
  {
    totalError++;
    SubGHz.msgOut(msg);
  }
  totalCount++;
}


受信側プログラム
#define SUBGHZ_CH      36
#define SUBGHZ_PANID   0xABCD
#define CLIENT_ID      0x405D
#define SERVER_ID      0x406A
#define BLUE_LED	   26

uint8_t rx_data[ 512 ];
uint32_t last_recv_time = 0;
unsigned long startTime = 0;
unsigned long totalCount = 0;
SUBGHZ_STATUS rx;

void setup(void)
{
  SUBGHZ_MSG msg;

  Serial.begin(115200);
	
  msg = SubGHz.init();
  if(msg != SUBGHZ_OK)
  {
    SubGHz.msgOut(msg);
    while(1) {}
  }
	
  msg = SubGHz.begin(SUBGHZ_CH, SUBGHZ_PANID,  SUBGHZ_100KBPS, SUBGHZ_PWR_20MW);
  if(msg != SUBGHZ_OK)
  {
    SubGHz.msgOut(msg);
    while(1) {}
  }
  msg = SubGHz.rxEnable(NULL);
  if(msg != SUBGHZ_OK)
  {
    SubGHz.msgOut(msg);
    while(1){ }
  }

  pinMode(BLUE_LED,OUTPUT);
  digitalWrite(BLUE_LED,HIGH);
	
  Serial.println("transmit rate test UKE!");
}

void loop(void)
{
  static unsigned long tolatLength = 0;
  short rx_len;
	
  rx_len = SubGHz.readData(rx_data,sizeof(rx_data));
	
  if( rx_len > 0 )
  {
    totalCount++;
    digitalWrite( BLUE_LED, LOW );
    tolatLength += rx_len - 9;

    Serial.print( "recieve size:" );
    Serial.print_long( tolatLength, DEC );
    Serial.print( " count:" );
    Serial.println_long( totalCount, DEC );

    digitalWrite( BLUE_LED, HIGH );
  }
}


Lazurite 920Jを立ち上げてみる 其の4 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

変換基板を作りました!
P1010010.JPG

一つの基板で、XBee変換と、DIP変換のどちらかを選べるようにしています。
DIP変換は0.1inchグリッドに載せているので、ブレッドボードに刺さります。ただし、Lazurite 920Jの全ての端子を引き出す事はできませんでした。

専用のWriterやハーフピッチのケーブル/コネクタが無くても書き込み、シリアル送受信ができるようになっています。
2016-10-26 13.10.56.jpg

勿論専用のWriterも接続できまっす。
2016-10-26 13.11.42.jpg

回路図
lazuriteImage_013.png




Lazurite 920Jを立ち上げてみる 其の3 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

今日のお題は、Writerをなんとかできないのか?って話です。
lazuriteImage_002.jpg

できるか、できないのか?と言う話なら、こうやってネタにしているのだから出来ます。

やっていいのか、悪いのかは判りません。自己責任でお願いします。

わりとお得に実現できるので、複数台の対向でデバックとかの時に役に立つでしょう。
※と言うか、対向でデバックする時は2つ以上無いと効率悪くて仕方がないよね。

さて、普通にWriterを買うと、高いですよね。一個くらいは仕方ないとしても、それ以上はどうかと思います。
しかも接続がハーフピッチの10pinコネクタと、使い辛い。
Lazurite Mini writer Type B(Lazurite Miniシリーズ)
https://www.switch-science.com/catalog/2956/

しかしこのWriterに使用しているICはおなじみのFT232RLですんで、2000円以下のFT232RLを使ったUSB/シリアル変換基板は、マルツとか秋月とか、まぁ色々なショップに並んでいます。
マルツ
http://www.marutsu.co.jp/pc/i/52777/
秋月
http://akizukidenshi.com/catalog/g/gK-01977/

さて、ハードウエアから見ると、Writerで使用している接続は電源を除けば4本です。
TXD、RXD、TEST0、TEST1N
です。
それぞれFT232RLのどこに接続する?ですが、以下になります。
Lazurite MiniFT232RL
VCC5V5Vまたは3.3V出力
GNDGND
TXD(1)RXD
RXD(0)TXD
TEST0CBUS0
TEST1NCBUS1

わりと簡単ですね。


ただ、配線だけなんとかすれば使える!と言う訳ではありません。FT232RLの設定をいくつか変更します。

FT232RLの設定はFTDIから無償で配布されているユーティリティで変更可能です。FT_Progを使用します。
http://www.ftdichip.com/Support/Utilities.htm#FT_PROG

FT232RLを使ったUSB/シリアル変換基板をPCに接続し、FT_Progを起動してデバイスのスキャンを行います。
ディスクリプション(USB String Descriptorをクリック)を以下の赤枠の様に変更します。
lazuriteImage_011.png


FT232RLのGPIO(Hardware SpecificからIO Controlsをクリック) を以下の赤枠の様に変更します。
lazuriteImage_012.png

変更したらデバイスにプログラムして、その後一旦USB/シリアル変換基板をPCから抜き挿しします。
この時、COMポート番号が変更されてしまうので注意してね。

あとはLazurite IDEから書き込みが出来るようになります。

現状、Lazurite 920Jの2.54mmピッチのDIP変換基板等が出ていないのであれですが、XBee ShieldとXBeeのDIP変換基板を使用する事でできますね。





Lazurite 920Jを立ち上げてみる 其の2 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

あれを動かしてみる。
「展示会で大活躍!920MHz無線お手軽電波ポリス★」
http://www.lapis-semi.com/lazurite-jp/lazurite/359.html

スイッチ等は実装が面倒なので、3秒くらいで自動的にチャネルが切り替わる様にした。
2016-10-19 14.34.28.jpg


もちろん電波が出ていないと上手く行っているのか、いないんだか判らんので、もう一つのLazurite 920Jには参考例の送信のプログラムを書き込んである。

※リンク先のページでは、配線はI2Cとスイッチの読み込み以外にLCDのRESETへの接続が行われているが、実際にはRESETの操作をしていない。だからLCDのRESETはVCCに固定してしまった。

※SPIは要らないだろう!

※よくよく見たらMsTimer2も要らないじゃん。ラズライトひめぇ~





Lazurite 920Jを立ち上げてみる 其の1 #LAZURITE920J #ラピスセミコンダクタ [Lazurite]

なんか、其の一しか書かない予感、、、
lazurite920jBee_002.png



Lazurite FAQ
新掲示板
http://www.lapis-semi.com/lazurite-jp/forums/forum/lazurite-basicsub-ghz%e3%81%ae%e3%82%bd%e3%83%95%e3%83%88%e3%82%a6%e3%82%a8%e3%82%a2%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a62
すげぃリンクだなぁ、、

旧掲示板(こっちも読む必要有り!)
http://www.lapis-semi.com/lazurite-jp/forums/forum/lazurite-basicsub-ghz%e3%81%ae%e3%82%bd%e3%83%95%e3%83%88%e3%82%a6%e3%82%a8%e3%82%a2%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6

Lazurite IDEの掲示板
http://www.lapis-semi.com/lazurite-jp/forums/forum/lazurite-ide%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6

何気に重要な事が書いてあるんじゃないかい?
「らずらいと姫の挑戦日記」
http://www.lapis-semi.com/lazurite-jp/%E3%82%89%E3%81%9A%E3%82%89%E3%81%84%E3%81%A8%E5%A7%AB%E3%81%AE%E6%8C%91%E6%88%A6%E6%97%A5%E8%A8%98/9912.html


〇ハーフピッチコネクタの選択

シングルライン10pinレセプタクルならこれでいいかな?最安。ただし、ヘッダー部の高さが3.4mmで、ここが他のコネクタと一致しない。@30円
http://akizukidenshi.com/catalog/g/gC-08695/

Digi-Keyならこれになるが、ややお高め@170円
http://www.digikey.jp/product-search/ja?keywords=S9008E-10-ND

デュアルライン2×5極のピンソケットならこれ。@98円
http://www.digikey.jp/product-detail/ja/sullins-connector-solutions/GRPB052VWVN-RC/S9015E-05-ND/1786455

デュアルライン2×5極のレセプタクルならこれ。@89円
http://www.digikey.jp/product-search/ja?keywords=609-3754-nd

※廣杉にも有った!高さが3.4mmなので秋月の物に合わせられる。
http://hirosugi.co.jp/products/N/FSS-70.html#bx2
モノタロウで買える
https://www.monotaro.com/p/1129/5357/ @56円
https://www.monotaro.com/p/1129/5305/ @54円
https://www.monotaro.com/p/1155/5513/ ちがう!
https://www.monotaro.com/g/01213751/ こっち!@28円

〇純正開発ツール(ハードウエア)
Lazurite 920J
http://www.lapis-semi.com/lazurite-jp/products/lazurite-920j
基板上のLDO(BH33PB1WHFV)は3.3V/150mA、入力最大5.5V、最低1.7V
端子配置図
lazuriteImage_006.png

表にしてみるか!
U4
Pin numberPin nameArduino number
1LDO3VLDO3V
2GNDGND
3P20/A414
4P21/A515
5P22/A616
6P03/A1117
7P34/A0/SDA18
8P35/A1/SCL19
9P533
10P502


U3
Pin numberPin nameArduino number
1P424
2P435
3P326
4P337
5P578
6P529
7P37/SS10
8P44/MOSI11
9P45/MISO12
10P36/SCK13


920Mhz用の外付けアンテナがリストされているが、これらを組み合わせた場合の技適はどうなんだろう?

XBeeシールド
http://www.lapis-semi.com/lazurite-jp/products/lazurite-920j-xbee-shield
XBeeシールド上でWriterからの5V電源がXBeeのVCC(3.3V電源)端子に接続されてしまっているが、実際にUSBからの5VがVCC5Vに出てしまっているので、なんと嫌らしい、、、
「3.3V以下で使用すると無線の電波強度は弱くなります。」だそうだ、、、

Writer
http://www.lapis-semi.com/lazurite-jp/products/lazurite-mini-writer-type-b
WriterのVID、PIDはFTDIのそれから変更はされていない。
lazuriteImage_002.png


Lazurite Basic(参考用)
http://www.lapis-semi.com/lazurite-jp/products/lazurite-basic

Lazurite 920JとXBeeシールドを組み合わせるとこんな(-ω-;)ウーンな感じ。
lazuriteImage_001.jpg



〇Lazureite IDEの入手とインストール
http://www.lapis-semi.com/lazurite-jp/contents/InstallGuide.html
説明の通りに進めばOK!


〇Lazureite IDEの使用方法
※最大の問題は、このIDEがC++をサポートしていない事。

http://www.lapis-semi.com/lazurite-jp/contents/IDE/How_to_use.html
このBasic用のページの説明で基本的には構わないが、ときおり出る脅し文句は一体何だろう?無視しているが。
また、ツール→オプション→LAZURITE mini seriasもクリックが必要。
書き込みが終わると、青いLEDが1秒で点灯、1秒で消灯を繰り返す。
書き込み中は黄色LEDのみ点灯から青LEDがチラチラ点灯。多分書き込みが終了すると電源LEDらしい赤LEDが点灯する。

シリアルモニターは、改行コードを受信しないと表示しないみたいだ。トホホ

〇コンパイラ使用上の注意点
lazuriteImage_004.png



〇標準ライブラリについて
標準ライブラリリファレンス
http://www.lapis-semi.com/lazurite-jp/contents/reference/Lazurite_Reference.html

▼C言語でArduinoのライブラリっぽく作っていいるので、大分無理が有る感じ。
例えば
Serial.print( 100,DEC );
は記述できず、同じ事は以下になる。
Serial.print_long( (long)100,DEC );
ようするにオーバーライドができない。だってC言語だから。

▼C99に部分対応で基本的にC89なので、コードの途中に変数の宣言ができない。つらい、、、

▼「Serial.print」とかクラスメソッドの様に見えているが、実際は静的に生成された構造体の関数ポインタを呼び出しているとの事。


〇スタック領域
RAM領域は全体で6kbyte有る!。
標準で512byteの領域をスタックに割り当てている。そこで大域変数に約2kbyteの領域を確保したmap出力を見てみる。
lazuriteImage_005.png

スタック領域はRAMの底に配置されるのではなく、先頭に持ってこられているが、それ以外のデータ領域はスタック領域の後に配置される。
キャプチャのグレーのところにSTACKと書かれており、サイズが512になっている。その上のGAPが事実上のRAM領域の余りになっており、なんで1244.0と小数点が付くのか判らないが1244byteは余っているらしい。
なのでスタックの伸長による暴走の懸念は、まずこのmap出力を見ると良いかも。


〇通信
▼ブロードキャストする為にはPANID=0xFFFF、相手先アドレス=0xFFFFでいいのか?

▼自機16bitアドレスは、モジュールの半田面に手書き(笑)で記載されている。本来は64bitアドレスも在るのだと思う。

▼モジュールに中継機能は、無いんだろうなぁ、、、

▼ZigBeeと異なり無線チャネルは自力でどうぞ!なので、実運用を想定するなら事前に周囲の無線環境を調べる何かが必要。だからこんなの作ったのか(笑)。
http://www.lapis-semi.com/lazurite-jp/lazurite/359.html

▼チャネルと周波数とビットレートの関係
http://www.lapis-semi.com/lazurite-jp/contents/IEEE802154/about_frequency.html




XBee Shieldの回路図が見難くて辛いので、清書してみた。
lazuriteImage_003.png







この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。