Single

MakeCode For Micro:Bit插件设计从入门到放弃(四)–开始编程


前面简单说了下整个工程的文件,这篇文章主要记录下TriodeCar的main.ts的开发过程

小车原理


如图所示,当小车偏离轨道向左时,右边的光敏电阻会来到黑色跑道的上方,光敏电阻阻值变高,而左边的光敏电阻处于白色地面,此时,LL点的电压会比LR点的电压低,此时,比较器U1A的正向电压高于反向电压,1号引脚输出高电平。同理,U1B的正向电压低于反向电压,7号引脚输出低电平。从而控制左边电机正转,小车右拐,R6和D2离开黑色跑道,直到左边的传感器探测到黑跑道,原理与前面类似。小车在前进过程中不断重复以上动作,从而达到前进的目的。

巡线积木

TriodeCar中,巡线传感器用是光敏电阻,所以需要模拟输入引脚,这里接的是P1和P2。根据这里的JavaScript例子,读取引脚的代码为pins.analogReadPin(AnalogPin.P2)

export enum Patrol {                                                  //两个下拉选项
    //% blockId="patrolLeft" block="left"
    PatrolLeft = 2,
    //% blockId="patrolRight" block="right"
    PatrolRight = 1
}

/**
* Read line tracking sensor.                                           //备注
*/

//% weight=20                                                          //block权重,决定了block的显示顺序。
//% blockId=read_Patrol block="read |%patrol line tracking sensor"     //block的名字,block的ID(ID在多语言适配的时候用得到)。
//% patrol.fieldEditor="gridpicker" patrol.fieldOptions.columns=2      //下拉选项
export function ReadLDR(patrol: Patrol): number {                      //这里类型是number,返回模拟引脚的数值
     if (patrol == Patrol.PatrolLeft) {                                //如果下拉选的是左边,就读取P2数值
          return pins.analogReadPin(AnalogPin.P2)
          } 
     else if (patrol == Patrol.PatrolRight) {                          //如果下拉选的是右边,就读取P1数值
          return pins.analogReadPin(AnalogPin.P1)
        } 
     else {
          return -1
     }
}

车的方向

由于TriodeCar是三极管驱动的小车,只有前进和停止选项,高电平停止,低电平转动,左拐是右边电机转,右拐是左边电机转。根据原理图P15是右边电机,P14是左边电机。

export enum direction {                                            //四个选项,前进,后退,左拐,右拐
    //% blockId="foward" block="go foward"
    foward = 1,
    //% blockId="stop" block="stop"
    stop = 2,
    //% blockId="turnleft" block="turn left"
    left = 3,
    //% blockId="turnright" block="turn right"
    right = 4,
}

/**
* CarDirection.
*/

//% blockId=IR_Enable block="let the car |%direction"
//% direction.fieldEditor="gridpicker" direction.fieldOptions.columns=4 
//% weight=93 blockGap=8
export function CarDirection(Direction: direction): void {
    if (Direction == direction.foward) {
        pins.servoSetPulse(AnalogPin.P14, 4000)    //left
        pins.servoSetPulse(AnalogPin.P15, 4000)    //right
    } 
    else if (Direction == direction.stop) {
        pins.digitalWritePin(DigitalPin.P14, 1)    //left
        pins.digitalWritePin(DigitalPin.P15, 1)    //right
   } 
    else if (Direction == direction.left) {
        pins.digitalWritePin(DigitalPin.P14, 1)    //left
        pins.servoSetPulse(AnalogPin.P15, 4000)    //right
   }  
   else if (Direction == direction.right) {
        pins.servoSetPulse(AnalogPin.P14, 4000)    //left
        pins.digitalWritePin(DigitalPin.P15, 1)    //right
    } 
}

控制车速

这里控制车速用的是pwm,利用占空比来调速

export enum motor {                                                //两个选项,左电机和右电机
    //% blockId="leftmotor" block="Left Motor"
    left = 1,
    //% blockId="rightmotor" block="Right Motor"
    right = 2,
}

/**
* Set the speed of Triode-Car motor.
*/

//% weight=90
//% blockId=motor_MotorRun block="|%motor|move Foward at speed|%speed"
//% speed.min=0 speed.max=10
//% motor.fieldEditor="gridpicker" motor.fieldOptions.columns=2
export function motorRun(Motor: motor, speed: number = 5): void {
    let pulsetime = Math.map(speed, 1, 10, 12000, 0)               //将1到10映射到12000到0,从而达到控制速度
    if (Motor == motor.left) {
        if (speed == 0) {
             pins.digitalWritePin(DigitalPin.P14, 1)    //left
        } 
        else {
            pins.servoSetPulse(AnalogPin.P14, pulsetime)
        } 
    } 
    if (Motor == motor.right) {
        if (speed == 0) {
             pins.digitalWritePin(DigitalPin.P15, 1)    //right
        } 
        else {
            pins.servoSetPulse(AnalogPin.P15, pulsetime)
        } 
    } 
}

最终代码

/** 
 * @file pxt-triodecar/main.ts
 * @brief BananaPi's triodecar makecode library.
 * @n This is a MakeCode graphical programming education robot.
 * 
 * @copyright    [BananPi](http://banana-pi.org), 2021
 * @copyright    MIT Lesser General Public License
 * 
 * @author [email](1445788683@qq.com)
 * @date  2021-03-23
*/
enum PingUnit {
    //% block="cm"
    Centimeters,
    //% block="inches"
    Inches
}


//% weight=0 color=#FF7256 icon="\uf1b9" block="TriodeCar"
namespace triodecar {

    export enum Patrol {
        //% blockId="patrolLeft" block="left"
        PatrolLeft = 2,
        //% blockId="patrolRight" block="right"
        PatrolRight = 1
    }


    export enum direction {
        //% blockId="foward" block="go foward"
        foward = 1,
        //% blockId="stop" block="stop"
        stop = 2,
        //% blockId="turnleft" block="turn left"
        left = 3,
        //% blockId="turnright" block="turn right"
        right = 4,
    }

    export enum motor {
        //% blockId="leftmotor" block="Left Motor"
        left = 1,
        //% blockId="rightmotor" block="Right Motor"
        right = 2,
    }


     /**
     * Read line tracking sensor.
     */

    //% weight=20
    //% blockId=read_Patrol block="read |%patrol line tracking sensor"
    //% patrol.fieldEditor="gridpicker" patrol.fieldOptions.columns=2 
    export function ReadLDR(patrol: Patrol): number {
        if (patrol == Patrol.PatrolLeft) {
            return pins.analogReadPin(AnalogPin.P2)
        } else if (patrol == Patrol.PatrolRight) {
            return pins.analogReadPin(AnalogPin.P1)
        } else {
            return -1
        }
    }


   /**
    * CarDirection.
    */

   //% blockId=IR_Enable block="let the car |%direction"
   //% direction.fieldEditor="gridpicker" direction.fieldOptions.columns=4 
   //% weight=93 blockGap=8

    export function CarDirection(Direction: direction): void {
        if (Direction == direction.foward) {
            pins.servoSetPulse(AnalogPin.P14, 4000)    //left
            pins.servoSetPulse(AnalogPin.P15, 4000)    //right
        } 
        else if (Direction == direction.stop) {
            pins.digitalWritePin(DigitalPin.P14, 1)    //left
            pins.digitalWritePin(DigitalPin.P15, 1)    //right
       } 
        else if (Direction == direction.left) {
            pins.digitalWritePin(DigitalPin.P14, 1)    //left
            pins.servoSetPulse(AnalogPin.P15, 4000)    //right
       }  
       else if (Direction == direction.right) {
        pins.servoSetPulse(AnalogPin.P14, 4000)    //left
            pins.digitalWritePin(DigitalPin.P15, 1)    //right
       } 
   }


    /**
     * Set the speed of Triode-Car motor.
     */

    //% weight=90
    //% blockId=motor_MotorRun block="|%motor|move Foward at speed|%speed"
    //% speed.min=0 speed.max=10
    //% motor.fieldEditor="gridpicker" motor.fieldOptions.columns=2
    export function motorRun(Motor: motor, speed: number = 5): void {
        let pulsetime = Math.map(speed, 1, 10, 12000, 0)
        if (Motor == motor.left) {
            if (speed == 0) {
                 pins.digitalWritePin(DigitalPin.P14, 1)    //left
            } 
            else {
                pins.servoSetPulse(AnalogPin.P14, pulsetime)
            } 
        } 
        if (Motor == motor.right) {
            if (speed == 0) {
                 pins.digitalWritePin(DigitalPin.P15, 1)    //right
            } 
            else {
                pins.servoSetPulse(AnalogPin.P15, pulsetime)
            } 
        } 
    }


    /**
     * Read ultrasonic sensor.
     */

    //% blockId=ultrasonic_sensor block="read ultrasonic sensor |%unit "
    //% weight=95 advanced=true

    export function Ultrasonic(unit: PingUnit, maxCmDistance = 500): number {
        let d
        pins.digitalWritePin(DigitalPin.P12, 1);
        basic.pause(1)
        pins.digitalWritePin(DigitalPin.P12, 0);
        if (pins.digitalReadPin(DigitalPin.P13) == 0) {
            pins.digitalWritePin(DigitalPin.P12, 0);
            //sleep_us(2);
            pins.digitalWritePin(DigitalPin.P12, 1);
            //sleep_us(10);
            pins.digitalWritePin(DigitalPin.P12, 0);
            d = pins.pulseIn(DigitalPin.P13, PulseValue.High, maxCmDistance * 58);//readPulseIn(1);
        } else {
            pins.digitalWritePin(DigitalPin.P12, 0);
            pins.digitalWritePin(DigitalPin.P12, 1);
            d = pins.pulseIn(DigitalPin.P13, PulseValue.Low, maxCmDistance * 58);//readPulseIn(0);
        }
        let x = d / 39;
        if (x <= 0 || x > 500) {
            return 0;
        }
        switch (unit) {
            case PingUnit.Centimeters: return Math.idiv(d, 58);
            case PingUnit.Inches: return Math.idiv(d, 148);
            default: return d ;
        }

    }
}

暂无评论

发表评论