其实两三年前就接触过Scratch,只是没有想到Scratch也逐渐开始硬件编程。第一个硬件来自Sparkfun,然后是Lego WeDo,接下来是一大堆创客硬件:Arduino......相对应的,衍生除了基于Scratch的Scratch for Arduino(s4a),以及ScratchX(eXtensions)
不过还没有mbed。好可惜,我来补上这块拼图。
PicoBoard
由于PicoBoard基本上也是公开的,硬件很简单:FTDI + ATMEGA328P,和一堆按键,滑杆之类的。所以.....没有难度。
PicoBoard最初采用C语言编程,源码在Github上。如果要使用Arduino,也可以模拟它的通讯协议:
// DigitalSandboxPico
//
// PicoBoard Firmware modified for the DigitalSandBox
// Arduino Learning Platform.
// Ported over from original C code.
//
// Modified by: Brian Huang, Sparkfun Electronics
// Date: August 7, 2014
#define SCRATCH_DATA_REQUEST 0x01
char request = 0;
unsigned int sensor_value = 0;
char data_packet[2]= "";
int SLIDER = A3; // Slider on DS Board
int SOUND = A2; // Microphone on DS Board
int LIGHT = A1; // Light Detector on DS Board
int BUTTON = 12; // Push Button on DS Board
int RA = A0; // Temp
int RB = 2; // Switch
int RC = 3; // D3 -- Side Port
int RD = A4; // A4 -- Top Port
void setup()
{
pinMode(BUTTON, INPUT_PULLUP); // enable internal pull-up resistor
pinMode(RB, INPUT_PULLUP); // enable internal pull-up resistor
Serial.begin(38400);
}
void loop()
{
request = Serial.read();
if(request == SCRATCH_DATA_REQUEST)
{
// send the ID packet
buildScratchPacket(data_packet, 15, 0x04);
sendScratchPacket(data_packet);
// Do not change the order of this sequence. Scratch expects the data
// to be organized in this order.
//Read/Report channel 0 (Resistance-D)
sensor_value=analogRead(RD);
buildScratchPacket(data_packet, 0, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 1 (Resistance-C)
sensor_value=analogRead(RC);
buildScratchPacket(data_packet, 1, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 2 (Resistance-B)
sensor_value=1023*digitalRead(RB);
buildScratchPacket(data_packet, 2, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 3 (Button)
sensor_value = 1023*(1 - digitalRead(BUTTON));
buildScratchPacket(data_packet, 3, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 4(Resistance-A)
sensor_value=analogRead(RA);
buildScratchPacket(data_packet, 4, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 5(LIGHT)
sensor_value=1023 - analogRead(LIGHT);
buildScratchPacket(data_packet, 5, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 6(Sound)
sensor_value=analogRead(SOUND);
buildScratchPacket(data_packet, 6, sensor_value);
sendScratchPacket(data_packet);
//Read/Report Channel 7(Slider)
sensor_value=analogRead(SLIDER);
buildScratchPacket(data_packet, 7, sensor_value);
sendScratchPacket(data_packet);
}
}
void buildScratchPacket(char * packet, int channel, int value)
{
char upper_data=(char)((value&(unsigned int)0x380)>>7); //Get the upper 3 bits of the value
char lower_data=(char)(value&0x7f); //Get the lower 7 bits of the value
*packet++=((1<<7)|(channel<<3)|(upper_data));
*packet++=lower_data;
}
void sendScratchPacket(char * packet)
{
Serial.write(*packet++);
delayMicroseconds(400);
Serial.write(*packet++);
delayMicroseconds(400);
}
它的协议超级简单,波特率38400bps,8-N-1。上位机Scratch发送0x01,PicoBoard就把N路模拟量上传。原始设计中一共是八路模拟量,分别是:电阻、按键、光感、声音、滑动电阻。
LPC800迷你板
我的LPC812可以使用mbed编程,直接改一改Arduino代码就可以了对接Scratch了。可以LPC812没有ADC,所以要么外接一块ADC,或者直接使用LPC824/STM32F030来替代。
更新
首先使用mbed编译了NUCLEO-STM32F103RB,修改代码后便宜很顺利,但是Scratch安装了Picoboard扩展后,Picoboard提示没有识别,而F103RB处也提示没有上位机下发指令。比较怀疑Picoboard驱动可能会锁定VID/PID。
接下来使用Python模拟Picoboard下发指令,发现F103RB返回的数值长短不一,这是一件奇怪的事情。需要深入到Debugger中看看问题出在哪里。