[lwptoc skipHeadingLevel=”h3,h4″ skipHeadingText=””]
前面简单说了下整个工程的文件,这篇文章主要记录下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 ;
}
}
}
暂无评论