測距センサ

シャープの測距センサ(GP2Y0A21YK0F)の値をLPC1768のADで読み取りLEDを点灯させる。


#include "mbed.h"


//-----------------------------------------------------------
Serial pc(USBTX, USBRX);
DigitalOut myled(LED1);

//-----------------------------------------------------------
class Led
{
public:
    Led()
    {
        led[0] = new DigitalOut(LED1);
        led[1] = new DigitalOut(LED2);
        led[2] = new DigitalOut(LED3);
        led[3] = new DigitalOut(LED4);
    }
    
    ~Led()
    {
        for(int i=0;i<4;i++){
            delete led[i];
        }
    }

    // level : 0 - 4
    void indicator(int level)
    {
        switch(level){
        case 0: *led[0] = 0; *led[1] = 0; *led[2] = 0; *led[3] = 0; break;
        case 1: *led[0] = 1; *led[1] = 0; *led[2] = 0; *led[3] = 0; break;
        case 2: *led[0] = 1; *led[1] = 1; *led[2] = 0; *led[3] = 0; break;
        case 3: *led[0] = 1; *led[1] = 1; *led[2] = 1; *led[3] = 0; break;
        case 4: *led[0] = 1; *led[1] = 1; *led[2] = 1; *led[3] = 1; break;
        }
    }
    
    void flasher() {
        for(int i=0;i<4;i++){
            *led[i] = 1;
            wait(0.25);
        }
        for(int i=0;i<4;i++){
            *led[i] = 0;
            wait(0.25);
        }
    };

private:
    DigitalOut *led[4];
};




//-----------------------------------------------------------
class DistanceSensor
{
public:
    DistanceSensor(PinName in)
    {
        gp2y = new AnalogIn(in);
    };
    
    ~DistanceSensor()
    {
        delete gp2y;
    };

    uint16_t value(void)
    {
        return gp2y->read_u16();
    };

private:
    AnalogIn *gp2y;
};

//-----------------------------------------------------------
int main() {

    Led leds;
    DistanceSensor *sensor = new DistanceSensor(P1_31);
    
    leds.flasher();
    
    while(1) {
        uint16_t v = sensor->value();
        pc.printf("DISTANCE : %d\n", v);
        
        int level = 0;
        if (v < 10000) level = 0;
        else if (v < 20000) level = 1;
        else if (v < 30000) level = 2;
        else if (v < 40000) level = 3;
        else                level = 4;
        
        leds.indicator(level);
        
        wait(0.2);
    }
}

素因数分解

素朴な素因数分解Haskell
Integerを使っているので桁数を気にしなくてよい。

--------------------------------------------------
-- factors.hs
--------------------------------------------------
import System.Environment(getArgs)


--------------------------------------------------
-- num : dividend
-- i : first divisor
-- return minimum factor
--------------------------------------------------
findMinFactor :: Integer -> Integer -> Integer
findMinFactor num i
  | (mod num i) == 0  = i
  | otherwise         = findMinFactor num (i+1)

--------------------------------------------------
-- num : dividend
-- return : list of factors
--------------------------------------------------
findFactors :: Integer -> [Integer]
findFactors num
  | f == num     = [num]
  | otherwise    = f : findFactors (div num f)
  where f = findMinFactor num 2


--------------------------------------------------
-- argument : dividend
-- print list of factors
--------------------------------------------------
main = do
  arg1:rest <- getArgs
  let x = read arg1 :: Integer
  let factors = findFactors x
  print factors

素因数の素朴な求め方

C++で力技で素因数分解するプログラム
使用する場合はfactors(100)とかすれば、
コンソールに素因数が出力される。

再帰を使っているので、因数が多すぎるとスタックオーバーフローするかも。
数値はuint64_tを使っているので64bitまでが適用範囲。

#include "stdafx.h"
#include <iostream>
#include <stdint.h>
#include <vector>

// create a vector includes prime factors
std::vector<uint64_t> *findPrime(uint64_t num)
{
	for (uint64_t i = 2; i < num; i++) {
		if ((num % i) == 0) {
			std::vector<uint64_t> *vc;
			vc = findPrime(num / i);
			vc->push_back(i);
			return vc;
		}
	}

	std::vector<uint64_t> *v = new std::vector<uint64_t>();
	v->push_back(num);
	return v;
}


int factors(uint64_t num)
{
	std::cout << "--- " << num << " ---" << std::endl;
	std::vector<uint64_t> *v = findPrime(num);
	std::vector<uint64_t>::iterator it = v->begin();
	while (it != v->end()) {
		std::cout << *it << " ";
		++it;
	}
	std::cout << std::endl;
	return 0;
}

bashの改行

デフォルトではCygwinbashの改行が2行に渡る。
=>環境変数PS1を修正する。

$ env | grep PS1
でPS1の内容を調べ、そこから"\n"を削除する(2つある)。
その削除したものを.bashrcに
PS1="..."
と書いておけば以降改行は1つになる。

自走式光追尾カー

CdSフォトトランジスタサーボモータの上につけ、光の最も強い方向を探す。
見つけた方向に車体を回転させ、少し前進。
を繰り返し、光源に近づいていく。


#include "mbed.h"

Serial pc(USBTX, USBRX);

//-----------------------------------------------------------
// CLASS for DC moter driver TA7291P
class MoterDrive
{
public:
    MoterDrive(PinName in1, PinName in2)
    {
        mIn1 = new PwmOut(in1);
        mIn2 = new PwmOut(in2);

        mIn1->period(0.020);
        mIn2->period(0.020);
    };

    ~MoterDrive()
    {
        delete mIn1;
        delete mIn2;
    };

    // parameter degree takes the value -1.0 ^ 1.0
    // 0.0 means stop
    // positive value means go forward
    // negative value means fo backward
    void run(double degree)
    {
        if (degree < -1.0)
        degree = degree < -1.0 ? -1.0 : degree;
        degree = degree >  1.0 ?  1.0 : degree;
        
        if (0.0 < degree){ // go forward
            mIn1->write(degree);
            mIn2->write(0.0);
        }
        else if (degree < 0.0){ // go back
            degree = fabs(degree);
            mIn1->write(0.0);
            mIn2->write(degree);
        }
        else { // degree == 0.0 , then stop
            mIn1->write(0.0);
            mIn2->write(0.0);
        }
    };
        
private:
    PwmOut *mIn1, *mIn2;
};

//-----------------------------------------------------------
// CLASS for servo moter SG90
class ServoMoter
{
public:
    ServoMoter(PinName in)
    {
        servo = new PwmOut(in);

        servo->period(0.020);
    };

    ~ServoMoter()
    {
        delete servo;
    };
    
    // parameter degree takes -90 ~ 90
    // it represents axis
    // About SG90
    // duty range is 0.5ms ~ 2.4ms corresponds to -90 degree to 90 degree.
    // especially, 1.45ms means 0 degree.
    // the relation degree and duty cycle is below.
    // y = (1.9/180)*x + 1.45
    void run(int degree)
    {
        degree = degree < -90 ? -90 : degree;
        degree = degree >  90 ?  90 : degree;
        double duty = (1.9/180)*(double)degree + 1.45;
        servo->pulsewidth(duty/1000.0);
    };
        
private:
    PwmOut *servo;

};



//-----------------------------------------------------------
// CLASS for Photo register CDS MI5 series
class PhotoRegister
{
public:
    PhotoRegister(PinName in)
    {
        photo = new AnalogIn(in);
    };
    
    ~PhotoRegister()
    {
        delete photo;
    };

    uint16_t value(void)
    {
        return photo->read_u16();
    };

private:
    AnalogIn *photo;
};


//-----------------------------------------------------------
class CarControl
{
public:

    CarControl(MoterDrive *l, MoterDrive *r)
    {
        left = l;
        right = r;
    };
    
    ~CarControl(){}
    
    void stop(void)
    {
        left->run(0.0);
        right->run(0.0);
    };

    void forward(void)
    {
        left->run(degree);
        right->run(degree);
    };

    void backward(void)
    {
        left->run(degree*(-1));
        right->run(degree*(-1));
    };
    
    void rotate(int angle)
    {
        stop();
        if(angle > 0){
            left->run(degree);
            right->run(degree*(-1));
        }
        else if(angle < 0){
            left->run(degree*(-1));
            right->run(degree);
        }
        double waitTime = ((double)abs(angle)) * rotateDeg;
        pc.printf("rotate time : %f\n", waitTime);
        wait(waitTime);
        stop();
    };

private:
    MoterDrive *left, *right;
    
    static const double degree = 0.5;
    static const double rotateDeg = 0.02;
};


//-----------------------------------------------------------
class SearchLihgt
{
public:
    SearchLihgt(PhotoRegister *sensor, ServoMoter *servo)
    {
        pr = sensor;
        sm = servo;
        
        measures[0].angle = 90;
        measures[1].angle = -90;
        measures[2].angle = 75;
        measures[3].angle = -75;
        measures[4].angle = 60;
        measures[5].angle = -60;
        measures[6].angle = 45;
        measures[7].angle = -45;
        measures[8].angle = 30;
        measures[9].angle = -30;
        measures[10].angle = 15;
        measures[11].angle = -15;
        measures[12].angle = 0;
    };

    ~SearchLihgt(){}
    
    int search(void)
    {
        int index;
        int maxCandidate = 0;
        uint16_t candidateValue = 0;
        for(index = 0;index<13;index++){
            sm->run(measures[index].angle);
            wait(0.5);
            measures[index].value = pr->value();
            
            if(measures[index].value > candidateValue){
                maxCandidate = index;
                candidateValue = measures[index].value;
            }
//            pc.printf("search() %d : %d : %d\n", index, measures[index].angle, measures[index].value);

        }
//        pc.printf("Found min pos : %d\n", maxCandidate);
        
        sm->run(measures[maxCandidate].angle);
        return measures[maxCandidate].angle;
    };

    struct pair
    {
        int angle;
        uint16_t value;
    };
    
    struct pair measures[13];
        
private:
    PhotoRegister *pr;
    ServoMoter *sm;
    
};



//-----------------------------------------------------------
class Led
{
public:
    Led(PinName pin)
    {
        led = new DigitalOut(pin);
        *led = 0;
        state = 0;
    };

    void toggle(void)
    {
        if (state == 0){
            *led = 1;
            state = 1;
        }
        else{
            *led = 0;
            state = 0;
        }
    };

private:
    DigitalOut *led;
    int state;
};


//-----------------------------------------------------------
void autoDrive(void)
{
    MoterDrive *md1 = new MoterDrive(P2_1, P2_0);
    MoterDrive *md2 = new MoterDrive(P2_3, P2_2);
    ServoMoter *sm  = new ServoMoter(P2_5);
    PhotoRegister *pr = new PhotoRegister(P1_31);

    CarControl *cc = new CarControl(md1, md2);
    SearchLihgt *sl = new SearchLihgt(pr, sm);
    
    Led *led = new Led(LED1);
    
    for(int count=0;;count++){

        cc->stop();
        int angle = sl->search();
        wait(1.0);
        led->toggle();
        pc.printf("DC_moter %d : %d\n", count / 100, angle);
        cc->rotate(angle);
        wait(1.0);
        led->toggle();
        cc->forward();
        wait(2.0);
        led->toggle();
    }
}


//-----------------------------------------------------------
int main() {
    autoDrive();

    while(1){}
}

LPC1768 モータドライブ

mbed LPC1768にモータドライバ()TA7291Pを接続。
可変抵抗の電圧をADで読み取り、TA7291Pの入力にPWMとして流し込む。
合わせ別のPWMでサーボモー^他の出力を生成。
結果、可変抵抗のつまみに応じてモーターの回転速度が変化し
サーボが動く。

#include "mbed.h"

DigitalOut myled(LED1);
PwmOut redLed(P2_5);
PwmOut moterIN1(P2_1);
PwmOut servo(P2_2);
AnalogIn ain(A5);

Serial pc(USBTX, USBRX);

int main() {
    int count = 0;
    int ledOn = 0;
    
    redLed.period(0.020);
    moterIN1.period(0.020);
    servo.period(0.020);
    
    while(1) {
        double degree = ain;
        double value;
        value = 1.7*degree - 0.3;

        redLed.write(value);
        moterIN1.write(value);

        double y = 3.17*degree - 0.133;
        
        servo.pulsewidth(y/1000);

        if((count % 100) == 0){
            pc.printf("DC_moter %d : %f : %f : %f\n", count / 100, degree, value, y);
            if(ledOn == 0){
                myled = 1;
                ledOn = 1;
            }
            else{
                myled = 0;
                ledOn = 0;
            }        
        }

        wait(0.01);
        count++;
    }
}

Debian8.2へのGuestAdditionのインストール

Debian8.2をnetinstでインストール。
その状態でGuestAdditionをインストールしようとすると失敗する。

/var/log/vboxadd-install.logには
unable to find the sources of your current Linux kernel.
のようにある。

GuestAdditionのインストールに必要なカーネルのヘッダなどをインストール

$ apt-get install dkms
$ apt-get install build-essential
$ apt-get install linux-headers-486

linux-headers-486の486はアーキテクチャによってamd64 、 686-pae 、 486 などから選択。

その後、GuestAdditionのインストールを行えば成功。