2014年12月27日土曜日

mbedでブラックベリーのトラックボールを使う

mbedでブラックベリーのトラックボールを使う方法です


配線が面倒なので、ブレッドボードに直載せです
トラックボールに使用するのをピンヘッダではなくピンソケットにすればブレッドボードすら不要です
トラックボール以外何も載せられなくなりますけどね

下記のソースコードはトラックボールで色を変更するというものです
色はHSVで管理され、横に動かすとHが、S,Vは縦に動かすと変更できます
SとVの選択はボタンを押すことにより行います
LEDはPWMで調光していますが、輝度を直線的に見せる部分の関係でV0にしても完全には消灯されません
また白色LEDは使用していません

とりあえずこんな感じで動くよ 程度なので ソースコードはごちゃごちゃしてますが まぁ参考までに…

また、HSVからRGBへ変換するソースコードはwikipediaより引用しています




#include "mbed.h"
#include "math.h"

DigitalOut TB_VCC(p10);
DigitalOut TB_GND(p11);
DigitalIn  TB_BTN(p12);
DigitalIn  TB_RHT(p13);
DigitalIn  TB_LFT(p14);
DigitalIn  TB_DWN(p15);
DigitalIn  TB_UP (p16);
DigitalOut TB_WHT(p17);
DigitalOut TB_GRN(p18);
DigitalOut TB_RED(p19);
DigitalOut TB_BLU(p20);

uint8_t stts;
Ticker read;
Ticker wled;
int x, y, b;
float RGB[3];

void HSV2RGB(const float *HSV, float *RGB);
void read_IRQ();
void wled_IRQ();

int main() {
    Serial pc(USBTX, USBRX);
    pc.baud(115200);
    
    TB_VCC = 1;
    
    stts = 0;
    x = y = b = 0;
    
    read.attach(read_IRQ, 1.0 / 250);
    wled.attach(wled_IRQ, 1.0 / 10000);
    
    float HSV[3] = { 0, 0, 0 };
    int SV = 0;
    
    while(1) {
        int s = SV ? 1 : 2;
        if (b) { SV = !SV; b = 0; }
        
        HSV[0] += x * 0.01;
        HSV[s] += y * 0.02;
        
        if (HSV[0] < 0) { HSV[0] += 1; }
        if (HSV[0] > 1) { HSV[0] -= 1; }
        
        if (HSV[s] < 0) { HSV[s] = 0; }
        if (HSV[s] > 1) { HSV[s] = 1; }
        
        x = y = 0;
        
        HSV2RGB(HSV, RGB);
        
        printf("SV:%c H%.2f S%.2f V%.2f R%.3f G%.3f B%.3f\n", 
            SV ? 'S' : 'V',
            HSV[0], HSV[1], HSV[2], RGB[0], RGB[1], RGB[2]);
            
        wait(0.25);
    }
}

void HSV2RGB(const float *HSV, float *RGB) {
    float h = HSV[0];
    float s = HSV[1];
    float v = HSV[2];
    
    float r = v;
    float g = v;
    float b = v;
    
    if (s > 0.0f) {
        h *= 6.0f;
        int i = (int) h;
        float f = h - (float) i;
        switch (i) {
            default:
            case 0:
                g *= 1 - s * (1 - f);
                b *= 1 - s;
                break;
            case 1:
                r *= 1 - s * f;
                b *= 1 - s;
                break;
            case 2:
                r *= 1 - s;
                b *= 1 - s * (1 - f);
                break;
            case 3:
                r *= 1 - s;
                g *= 1 - s * f;
                break;
            case 4:
                r *= 1 - s * (1 - f);
                g *= 1 - s;
                break;
            case 5:
                g *= 1 - s;
                b *= 1 - s * f;
                break;
        }
    }
        
    RGB[0] = r;
    RGB[1] = g;
    RGB[2] = b;
}

void read_IRQ() {
    uint8_t now = 0;
    now |= (TB_RHT ? 1 : 0) << 0;
    now |= (TB_LFT ? 1 : 0) << 1;
    now |= (TB_UP  ? 1 : 0) << 2;
    now |= (TB_DWN ? 1 : 0) << 3;
    now |= (TB_BTN ? 0 : 1) << 4;
    uint8_t xors = now ^ stts;
    stts = now;
    
    if (xors & 0x01) { x++; }
    if (xors & 0x02) { x--; }
    if (xors & 0x04) { y--; }
    if (xors & 0x08) { y++; }
    if (xors & 0x10 && stts & 0x10) { b = 1; }
}

void wled_IRQ() {
    static float val = 0;
    
    TB_RED = (1 - sin(1.57f + RGB[0] * 1.57f)) > val;
    TB_GRN = (1 - sin(1.57f + RGB[1] * 1.57f)) > val;
    TB_BLU = (1 - sin(1.57f + RGB[2] * 1.57f)) > val;
    
    val += 1.0f / 200;
    if (val >= 1) { val = 0; }
}

4 件のコメント:

  1. このコメントは投稿者によって削除されました。

    返信削除
  2. 先日は、ソースコードをご教授いただきありがとうございます。
    ブラックベリーのトラックボールを制御するソースコードを教えて頂いた者です。

    PIC18F4550で動かそうと教えて頂いたコードから色々やってみましたが、動かすことができませんでした。私の知識不足により出来ないことなのですが、
    調べながらやっていくにも八方ふさがりの状態で、どこをどう直していいものかもわからなくなってしまい、迷惑だとは思いましたが、PICで動かす方法をご存知であれば、教えて頂きたく再度、コメントさせて頂きました。

    何かヒントでもご存知でしたらご教授お願いします。

    返信削除
  3. PICはしばらく触っていなくて適切な説明ができないと思います
    とりあえずトラックボールの2軸入力を読みたいということであれば
    まずはタクトスイッチ4個の操作された回数(押した時、離した時の両方でインクリメント)を表示するプログラムを作ってみてください(タクトスイッチのチャタリングについては気にしなくてもいいです)
    スイッチの監視についてはタイマ割り込みで前回の割り込み時のスイッチの状態と今回の割り込み時のスイッチの状態をxorして1ならインクリメント という感じになると思います
    それができるようになったらタクトスイッチをトラックボールの出力に置き換えてみてください
    もしも正常に動作していれば右に動かしたらカウンタ1が増える 左に動かしたらカウンタ2が増える 上に動かしたらカウンタ3が増える 下に動かしたらカウンタ4が増える という動作をするはずです
    それができれば、左右の位置=カウンタ1-カウンタ2、上下の位置=カウンタ3-カウンタ4 という感じで読めるはずです
    とりあえず入力を読みたいだけならこれで良いはずです

    返信削除
  4. ご回答ありがとうございます。
    本当に助かります。

    ご教授頂いたことをさっそくやってみます。教えて頂ける事ではないのに、親切にご教授いただきありがとうございます。

    私のような知識の無い馬鹿者のために本当にありがとうございます。
    感謝いたします。

    返信削除