由于mBot主要的市场应该是针对儿童的,故提供了便于上手的“积本式”开发环境,通过自己组织积木,进行逻辑分配,便可以实现自己需要的功能,并且提供了基础的入手手册,可以帮助“孩子们”更快的接触编程,更快的实现自己的想法。但作为一个“大孩子”,还有想多问一个为什么,想要知道到底它是怎么实现的,由上一篇帖子知道,虽然在mBlock集成开发环境中,提供了arduino和积木两种共存的模式,但相互切换后,并不能看到真正的代码实现。故需要探究下其几部到底是怎么实现的。
一 mbot底板代码
在mBlock的安装目录下,进入firmware目录,发现了如下所示的目录结构,即mblock针对不同的板子,设计了不同的板载固件。
进入mbot_firmware,用arduino打开mbot_firmware,可以清楚的看到有mbot的代码结构,也就是mbot通过arduino怎么实现其功能的。由于代码较多,现帖子主要的代码进行分享下:
(一 )头文件
在mbot_firmware.ino中,只包括了这3个头文件,每一个应该是控制伺服电机的,第二个应该是控制一线或二线协议的,第三个似乎是针对
开发板的,应该是很重要的一个头文件,具体分析见下面的第二部分。
- #include
- #include
- #include
(二 )模块变量
在mbot_firmware.ino中,定义了如下所示的变量,从字面意思来看,都是和mBot相关的扩展模块,也就是说,mBlock,采用C++的语言,将mbot的扩展模块进行了封装,而为了在mBlock上,首先对需要的,支持的模块进行了定义或初始化,然后根据具体的条件或命令进行操作或控制这些模块的行为。
- Servo servos[8];
- MeDCMotor dc;
- MeTemperature ts;
- MeRGBLed led(0,30);
- MeUltrasonicSensor us;
- Me7SegmentDisplay seg;
- MePort generalDevice;
- MeLEDMatrix ledMx;
- MeBuzzer buzzer;
- MeIR ir;
- MeGyro gyro;
- MeJoystick joystick;
- MeCompass Compass;
- MeHumiture humiture;
- MeFlameSensor FlameSensor;
- MeGasSensor GasSensor;
(三)启动函数
在经典的setup函数中,分别进行初始化的设置,也就是默认启动时的操作,设置13引脚,它对应着板子上的RGB三色灯,即下面的执行顺序依次为:点亮RGB三色灯,延时300毫秒后熄灭,启动串口,使蜂鸣器发声50毫秒后停止,然后开启红外接收,led显示无色,最后启动陀螺仪。也就是说,把该用到模块,都启动了,并且通过指示灯和蜂鸣器来表示启动过程。
- void setup(){
- pinMode(13,OUTPUT);
- digitalWrite(13,HIGH);
- delay(300);
- digitalWrite(13,LOW);
- Serial.begin(115200);
- delay(500);
- buzzer.tone(500,50);
- delay(50);
- buzzerOff();
- ir.begin();
- led.setpin(13);
- led.setColor(0,0,0);
- led.show();
- gyro.begin();
- }
(四)主循环函数
在主循环中,首先判断是否接收到红外的信号;然后读取串口的数据,也就是蓝牙模块的数据,也就是
手机端控制的数据;最后根据调用parseData函数,根据不同的控制命令,进行不同的响应。
- void loop(){
- currentTime = millis()/1000.0-lastTime;
- if(ir.decode())
- {
- irRead = ((ir.value>>8)>>8)&0xff;
- lastIRTime = millis()/1000.0;
- irPressed = true;
- if(irRead==0xa||irRead==0xd){
- irIndex = 0;
- irReady = true;
- }else{
- irBuffer+=irRead;
- irIndex++;
- if(irIndex>64){
- irIndex = 0;
- irBuffer = "";
- }
- }
- irDelay = 0;
- }else{
- irDelay++;
- if(irRead>0){
- if(irDelay>5000){
- irRead = 0;
- irDelay = 0;
- }
- }
- }
- readSerial();
- if(isAvailable){
- unsigned char c = serialRead&0xff;
- if(c==0x55&&isStart==false){
- if(prevc==0xff){
- index=1;
- isStart = true;
- }
- }else{
- prevc = c;
- if(isStart){
- if(index==2){
- dataLen = c;
- }else if(index>2){
- dataLen--;
- }
- writeBuffer(index,c);
- }
- }
- index++;
- if(index>51){
- index=0;
- isStart=false;
- }
- if(isStart&&dataLen==0&&index>3){
- isStart = false;
- parseData();
- index=0;
- }
- }
- }
以上就是对mbot_firmware.ino的一个简单认识,可以对该代码进行修改、加工,完成自己想要的功能,而不用去拖动“积木”。但具体的模块的实现,还要找到其对应的实现源码,不然对具体接口的调用,还是无从下手。
二 mbot模块代码
从上面的分析中,mbot主要包括了meMCore.h这个头文件,可见要想知道它们是怎么实现,就需要找到该文件,看看到底里面包括了些什么东西。在mBlock的安装目录下,,依次进Arduino-》ibraries-》makeblock-》src,可以看到如下图所示的源码。
从图中可知,mBlock根据不同的模块,封装了不同的代码实现,且它们都是以Me开头,以具体的模块名字结束,如MeRGBLed,表示该代码实现了对RGB Led灯的控制。我们找到刚才需要的meMCore.h这个头文件,打开后,它主要包括3部分,具体如下
(一)公共头文件
其实,mBlock中的的代码由两部分组成,一部分是基于Arduino的,一部分是针对封装了mBlock中使用的模块代码。在meMCore.h只包括了如下两个头文件,而Meconfig,主要包括了utility目录下的文件和一些配置引脚定义。
- #include
- #include "MeConfig.h"
(二)模块头文件
如下所示,在meMCore.h中,包括了所有的模块头文件,这也说明了,在每个mBlock实现中,都包括这一头文件的原因。
- /* Supported Modules drive needs to be added here */
- #include "Me7SegmentDisplay.h"
- #include "MeUltrasonicSensor.h"
- #include "MeMbotDCMotor.h"
- #include "MeRGBLed.h"
- #include "Me4Button.h"
- #include "MePotentiometer.h"
- #include "MeJoystick.h"
- #include "MePIRMotionSensor.h"
- #include "MeShutter.h"
- #include "MeLineFollower.h"
- #include "MeSoundSensor.h"
- #include "MeLimitSwitch.h"
- #include "MeLightSensor.h"
- #include "MeSerial.h"
- #include "MeBluetooth.h"
- #include "MeWifi.h"
- #include "MeTemperature.h"
- #include "MeGyro.h"
- #include "MeInfraredReceiver.h"
- #include "MeCompass.h"
- #include "MeUSBHost.h"
- #include "MeTouchSensor.h"
- #include "MeStepper.h"
- #include "MeEncoderMotor.h"
- #include "MeEncoderNew.h"
- #include "MeIR.h"
- #include "MeLEDMatrix.h"
- #include "MeBuzzer.h"
- #include "MeHumitureSensor.h"
- #include "MeFlameSensor.h"
- #include "MeGasSensor.h"
(三)引脚映射
除了以上的头文件,在meMCore.h中,还定义了相对了mbot板上的引脚映射,纯数字代码数字引脚,带A的代表模拟引脚,具体为什么这样定义,应该看到下图就知道了。
- /********************* Mbot Board GPIO Map *********************************/
- MePort_Sig mePort[11] =
- {
- { NC, NC }, { 11, 12 }, { 9, 10 }, { A2, A3 }, { A0, A1 },
- { NC, NC }, { NC, NC }, { A7, 13 }, { 8, A6 }, { 6, 7 },
- { 5, 4 }
(四)模块封装
其实对于具体的模块,都会用到引脚,而mBlock针对引脚,封装了MePort基类,其他的的功能类,基本上都继承了该类,具体的分析,查看源码,应该更加清楚。
太晚了,明天还要上班,经过这几天的努力,总算是搞明白了mblock的代码框架,接下来就是实现自己的功能了!