2013年6月30日

PICでBluetooth SPP - UARTコンバータ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

BluetoothのSPPが使えるモジュール、技適マーク付きの物を買うと5000円以上したりします。
これを市販のUSBドングル型Bluetoothモジュールを使ってなんとかしようというネタ。

使うのはPIC24FJ64GB002というUSB OTGが使えるマイコンで、今のところ買えるのはRSやDigiKeyを除いて共立電子のみ。


回路はこんな感じでOK
USBコネクタ部分の配線がよく分からない順番になってますが、実際は
1 - VCC
2 - D- (図の茶色線)
3 - D+ (図の黄色線)
4 - GND
という感じでAメスコネクタと配線してください。

電圧は3.3V。
PicKit3から電源供給する際はプロジェクトのプロパティから電源供給をONに。(MPLAB X)
Arduinoのシールド化する際は3.3Vから引きます。
(本当はあんまり良くないけど)RX/TXは直でArduinoと接続しても問題なし。

実際に使う場合は、右上のFTDI breakooutが繋がってるRX、TX、GNDをUART通信したいデバイスに接続します。


Arduinoと接続してAndroidとSPPで通信している様子。
ここでは、ONと送るとArduinoの13番pinのLEDが点灯、OFFと送ると消灯というスケッチをArudinoに書き込んでいます。

PIC側のプログラムは、hrdakinori氏のPIC24F_btstackをベースに、UARTからの受信をBuetooth SPPに渡すコードを追加すればOKです。

具体的にはこんな感じで、まずbt_spp.cのbt_spp_recive_callbackを以下の様な感じに。

int bt_spp_recive_callback(uint16_t channel, uint8_t *packet, uint16_t size)
{
 packet[size] = 0;
        
        //SPP to UART
        UART2PrintString(packet);
        
 return 0;
}

更に、main.cのsw_processを以下の様な感じに。

static int sw_process(struct data_source *ds)
{
    if(IFS1bits.U2RXIF == 1){
 char text[100]={0};
        int i = 0;
        char c = 0;

        while(1){
            while(U2STAbits.URXDA) {
                c = U2RXREG;
                text[i] = c;
                i++;
            }
            if (c == '\n') break;
            else if(c == 0) break; // if UART no Connect, break while(1)
        }
        text[i] = 0; //

        //UART2PrintString(text); //debug and callback

        //Bluetooth Send
        bt_spp_send((uint8_t*)text,strlen(text));

        IFS1bits.U2RXIF = 0;

 if ( U2STAbits.OERR) {
  U2STAbits.OERR = 0;
 }
    }
 return 0;
}

あと、コンパイル時にundefined reference to packet_handlerが出るので、btstackのhci.c内のstatic void packet_handlerをvoid packet_handlerに変更します。

PICとのシリアル通信は57600bpsで、Bluetooth側は特に制約は無い(はず)。


こんな感じでSwitch Scienceさんのバニラシールドに載せてしまえば、Arduino UNOやMEGAのシールドとして普通に使えます。

2013年5月19日

Arduino+74HC595+LED16個でPOV

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

Arduinoとシフトレジスタ74HC595でLED16個を制御してPOVを作ろうという今更感漂うネタ。
実は4月末に作っていたものですが、なかなか時間がとれず今頃ブログに投稿です...


配線はこんな感じ。 #LED16個への配線で非常に見づらくなっております...


シフトレジスタ1個で8個のLEDが制御可能、2段にすると16個、3段で24個、4段で32個...と言う具合に(電源容量の限り)8の倍数ずつ増やすことができます。

プログラムは、Arduinoのチュートリアルも参考にしながら下記のような感じで。

int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

word data;
word dataArray[][10] = {
  {
    0b0000000000000000,
    0b0000001111110000,
    0b0000110000001100,
    0b0001000000000010,
    0b0001000000000010,
    0b0001000000000010,
    0b0001000000000010,
    0b0000110000001100,
    0b0000001111110000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000000000000000,
    0b0000000000000000,
    0b0001000000000100,
    0b0001000000000010,
    0b0001111111111110,
    0b0001000000000000,
    0b0001000000000000,
    0b0000000000000000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0001100000000100,
    0b0001010000000010,
    0b0001001000000010,
    0b0001000100000010,
    0b0001000010000010,
    0b0001000001000100,
    0b0001000000111000,
    0b0000000000000000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000100000000100,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000001000010,
    0b0000100010100010,
    0b0000011100011100,
    0b0000000000000000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000001100000000,
    0b0000001011000000,
    0b0000001000100000,
    0b0000001000011000,
    0b0000001000000100,
    0b0001111111111110,
    0b0000001000000000,
    0b0000001000000000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000100001111110,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000010000010,
    0b0000100010000010,
    0b0000011100000010,
    0b0000000000000000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000011111110000,
    0b0000100010001000,
    0b0001000001000100,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000001000010,
    0b0000100010000010,
    0b0000011100000100,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000000000000010,
    0b0001100000000010,
    0b0000011000000010,
    0b0000000110000010,
    0b0000000001000010,
    0b0000000000110010,
    0b0000000000001010,
    0b0000000000000110,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000011100000000,
    0b0000100010111100,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000001000010,
    0b0001000001000010,
    0b0000100010111100,
    0b0000011100000000,
    0b0000000000000000
  }
  ,
  {
    0b0000000000000000,
    0b0000100000111000,
    0b0001000001000100,
    0b0001000010000010,
    0b0001000010000010,
    0b0001000010000010,
    0b0000100010000010,
    0b0000010001000100,
    0b0000001111111000,
    0b0000000000000000
  }
};

void setup() {
  pinMode(latchPin, OUTPUT);
}

void loop() {
  for (int i = 0; i <=9; i++){
    for (int j = 0; j <= 9; j++) {
      data = dataArray[i][j];
      digitalWrite(latchPin, 0);
      shiftOut(dataPin, clockPin, data);
      digitalWrite(latchPin, 1);
      delay(3);
    }
  }
}

void shiftOut(int myDataPin, int myClockPin, word myDataOut) {

  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  for (i=16; i>=0; i--)  {
    digitalWrite(myClockPin, 0);
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else { 
      pinState= 0;
    }
    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  digitalWrite(myClockPin, 0);
}
これで、0123456789という数字が連続して表示されるはず。


dataArrayの中身を書き換えることで、数字以外にもアルファベットや漢字、ひらがな、記号などを表示させることができます。


「Talkspace」と表示させた例 (青い点はeneloopモバイルブースターのLEDランプ)

最終目標は自転車のホイールへの搭載なので、次は回転に同期させる部分を作っていきます。

2013年4月16日

フレキシブル太陽電池 TX3-25

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

少し前にSwitch ScienceでSunModというテレビなどのリモコンを太陽電池式に改造するキットが販売開始されたのですが、これに使われている(と思われる)太陽電池を偶然共立エレショップで見つけて買ってしまった訳です。


ご覧の通り非常にフレキシブルで薄いので、円筒形の物の表面に貼り付けたりするのも問題なさそう。(日の当たり具合とかは取りあえず無視して)


さっそく両極にリード線を付けてチェック。日中の屋内でも1.7Vくらいの出力が得られる。


少し曇った日の正午過ぎに西向きの窓の網戸越しに置いて1.9Vくらい。
ちなみに定格は「開放電圧/短絡電流:4.1V/40mA 操作電圧/電流:3V/25mA」だそうで、日光のガシガシ当たるところでは普通に3V出るっぽい。

追記:直射日光を当てると4V出ました。

SunModの様に直列接続のニッケル水素電池2本に並列に接続する形で蓄電して、何かに電源供給するという使い方が良さそうですが、実際に充電できる&どのくらい充電できるのかは謎...
#そのうち検証してみるつもり

2013年3月31日

ミニブレッドボードで遊ぶ (温湿度計)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

秋月電子にて1個150円(2個以上買うと1個あたり150円)で売ってあるミニブレッドボードBB-601
これにどれだけ詰め込めるかという遊びを思いついたので、早速何か簡単なものを作ってみました。

ATmega328P-PU、温度センサ(LM61CIZ)、湿度センサ(HIH4030)、極小キャラクタ液晶、セラロック(16MHz)、抵抗(10kΩ)、コンデンサ(0.1µF)という構成。
#流石に電源まで詰めるのは無理


この状態でUSARTとSPIは空いているので、更に拡張や連携も可能だったり。
温度・湿度センサもデジタル(I2CやSPI)接続の物を利用すれば、もう少し他の物を接続できる。


LCD裏はこんな感じ。
買ってきてすぐは1mmピッチのFFCが付いていますが、何だかんだで扱いにくいので、細めで少し硬いビニル絶縁電線に付け替えました。(自立可能)

このサイズで何か面白いものが出来れば掲載しようと思っているものの、如何せんネタが無いのである(~_~;)

追記:サイズ比較にiPhone4Sの上に載せて1枚。


2013年3月22日

ArduinoISPでUSBasp-Bをアップデート

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

aitendoでUSBasp-Bを買ったものの、Arduino IDEからバージョン古いと怒られる&書き込み速度が遅いのでバージョンアップを試みた時のメモ。

ArduinoISPでUSBasp-Bをアップデートする試みは既にこちらなどで挑戦されているようですが、今のところ成功したという記事は見かけなかったのでチャレンジしてみることに。

1. ArduinoにArduinoISPを焼く
ファイル→スケッチの例→ArduinoISPを選択し、あとは普通にいつもの通り書き込む。

2. Auto Resetの無効化
ArduinoのAuto Resetを無効化するために、ArduinoのRESETとGND間にコンデンサを入れる。(0.1µFとか1µFでOK)
ちなみに、110Ω程度の抵抗をRESET-GND間に入れるというduemilanoveで使える技はUNOでは使えませんでした。

3. ArduinoとUSBasp-Bを接続
USBasp-BのJP3とJP4(3つのジャンパのうち真ん中以外の2つ)をONにしてファームウェア書き換えモードにする。
ArduinoとUSBasp-Bの接続はストレート(ArduinoのMOSIはUSBasp-BのMOSIに、MISOはMISOに接続)
ここで、USBasp-BのRESETはArduinoの10番pinに接続する。
ちなみに、この記事の一番上の写真は間違った接続をしていて、正解はこんな感じ。


ArduinoのICSPコネクタ5番pinはRESET(Arduinoの1番pin)に繋がっているため、USBasp-B側のRESETが(Auto Reset無効化の影響で)うまく効かず、

avrdude: stk500_recv(): programmer is not responding

を吐く原因となります。

4. 書き込み
USBaspのウェブサイトから最新版のファームウェアをダウンロード、展開し、ターミナルから下記コマンドで書き込み。

avrdude -P/dev/tty.usbmodemfd121 -b 19200 -c avrisp -p m8 -U flash:w:usbasp.atmega8.2011-05-28.hex:i

「/dev/tty.usbmodemfd121」は各自の環境に合わせて変更してください。
「usbasp.atmega8.2011-05-28.hex」も最新バージョンが出たらそれに合わせて適宜。

うまく書き込めたら下記の様な結果が返ってくると思います。
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.06s

avrdude: Device signature = 0x1e9307
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "usbasp.atmega8.2011-05-28.hex"
avrdude: writing flash (4700 bytes):

Writing | ################################################## | 100% 5.73s

avrdude: 4700 bytes of flash written
avrdude: verifying flash memory against usbasp.atmega8.2011-05-28.hex:
avrdude: load data flash data from input file usbasp.atmega8.2011-05-28.hex:
avrdude: input file usbasp.atmega8.2011-05-28.hex contains 4700 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 5.41s

avrdude: verifying ...
avrdude: 4700 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

最後にヒューズビット(hfuse)を書き換える。

avrdude -P/dev/tty.usbmodemfd121 -b 19200 -c avrisp -p m8  -U hfuse:w:0xC9:m

これも、うまくいけば下記の様な結果が返ってくる。
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x1e9307
avrdude: reading input file "0xC9"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.07s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xC9:
avrdude: load data hfuse data from input file 0xC9:
avrdude: input file 0xC9 contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

以上でバージョンアップ終わり。

Auto Resetの影響を受ける可能性を思いつくまで30分、ICSPの5番pinがRESETに接続されているのを思い出すまで30分...
0x14歳にして脳が衰退し始めていることを思い知らされた1時間でしたorz