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-програм із зовнішнім світом, але цей, мабуть, найпростіший.

Leave a Reply

[flagcounter image]