Sketch for Scratch
У зв’язку з активізацією інтересу батьків до того, щоб у дітей був інтерес до програмування/електроніки/… у поле мого зору знову потрапив Scratch. Але як людина, яка не вміє налагоджувати програми без осцилографа :-), я відразу почав шукати можливість підключити до нього якісь зовнішні пристрої.
Перше, що трапилося — плата PicoBorad. Необхідні для роботи з нею блоки інсталюються разом з системою Scratch. Але ціна на неї відлякує (після ознайомлення з можливостями ще й дивує).
На щастя, і сама плата, і програма до неї доступні на GitHub та ще й під вільними ліцензіями, тому ними можна скористатися. Для варіанту «зробити за вечір, щоб увімкнути і подивитися» я вибрав Arduino nano та макетну плату для монтажу дротиками. Змінні резистори з припаяними штирями у мене вже були зроблені раніше, тому паяти не довелося зовсім.
Оскільки і у платі PicoBoard, і в Arduino nano стоїть однаковий процесор, не було потреби навіть перепризначати ніжки і можна було б просто зашити готовий .hex. Але то було б зовсім нецікаво і я вирішив переписати ту коротку програму як arduino-sketch. Ну сподобалася мені назва Sketch for Scratch 🙂 Заради цього я навіть встановив оболонку Arduino і відновив у платі стертий раніше bootloader.
Вийшов коротенький, на пів сотні рядків (коментарів спочатку не було), sketch. Знайти всі потрібні компоненти та об’єднати їх у макетці зайняло більше часу.
Sketch for Scratch
Arduino-based Scratch interface to hardware sensors in Sparkfun PicoBoard style
(c) 2016 Oleksandr Redchuk aka ReAl
CC-BY-SA 4.0 (http://creativecommons.org/licenses/by-sa/4.0/)
Based on Sparkfun PicoBoard firmware
https://github.com/sparkfun/PicoBoard/tree/master/firmware
2016-04-18 initial release
2016-04-19 some comments, code cleanup
*/
const unsigned SCRATCH_BAUD = 38400U;
const uint8_t SCRATCH_DATA_REQUEST = 0x01;
const uint8_t SCRATCH_ID_CHAN = 15;
const uint8_t SCRATCH_ID_VAL = 0x04;
const uint8_t Button = 2;
const uint8_t Slider = A0;
const uint8_t channels = 8;
const uint8_t chan_order[channels] = {
A1, // Scratch RD
A2, // Scratch RC
A4, // Scratch RB
Button, // Scratch Button
A5, // Scratch RA
A6, // Scratch LIGHT
A3, // Scratch SOUND
Slider // Scratch SLIDER
};
static void sendScratchPacket(uint8_t chan, unsigned value)
{
Serial.write( 0x80 | (chan<<3) | ((value>>7) & 0x07) );
delayMicroseconds(400);
Serial.write(value & 0x7F);
delayMicroseconds(400);
}
void setup()
{
pinMode(Button, INPUT_PULLUP);
Serial.begin(SCRATCH_BAUD);
Serial.write("Start\r\n");
}
void loop()
{
if (Serial.available() > 0) {
if (Serial.read() == SCRATCH_DATA_REQUEST) {
sendScratchPacket(SCRATCH_ID_CHAN, SCRATCH_ID_VAL);
for (uint8_t i = 0 ; i < channels; ++i) {
unsigned value;
uint8_t channel = chan_order[i];
if (channel == Button) {
value = digitalRead(channel) ? 0xFFFF : 0;
} else {
value = analogRead(channel);
if (channel == Slider) value = 1023 - value;
}
sendScratchPacket(i, value);
}
}
}
}
p.s. Є і кращі варіанти для комунікації Scratch-програм із зовнішнім світом, але цей, мабуть, найпростіший.