
Raramente hago algo de "bajo nivel". Mi jornada laboral aproximada consiste en desarrollar aplicaciones móviles para empresas y un montón de piezas gerenciales diversas. Por supuesto, a veces quiero distraerme. Resulta que esto es raro y, probablemente, por lo tanto, da un placer especial. Esta vez se decidió distraerse con el Amperka. Tetra ", que está destinado a niños y con la ayuda de los cuales puedes aprender los conceptos básicos de los circuitos, los nombres de los sensores y tratar de programar algo que funcione en el mundo real y no en la pantalla de una computadora. En general, cuando eres un hombre barbudo adulto, en general lo es.
, , ( ), , Bluetooth, - ( , ), , . , , .
, , . ( Arduino Leonardo) Scratch ( , ), S4A, … , , , , - . . ? .
Toys That Made Us Lego, «». , , ( ) System. TECHNIC «», . , , , , , « , ..?», , , .
«Troyka», , . , , , . . , .
« » (!)
. , , ( , ), , «!!!», , , . , , —  , . , , , -   !
, . «» Troyka- , , : 8 8, , . , , - .

( , , ? ), , «, » , , , , « ». —  S4A (Scratch for Arduino), , . , S4A macOS ( , ), apt-get’ ( ), ( , , ), .
«», . , , , - LED, . .
, . , - , , . —  . , , , . , . :
- . , , 13, 12 10, 11   ? _
- , , . , « », , , .
- ( , , ) S4A , . /, , . WeDo ( - ) ( ), — , AnalogN/DigitalN. , .
. , S4A .
, - :
- -, , ( , ?!).
- -, ( , - , , , ). . , . , . Breadboard’ . Troyka-. , !
S4A , , .
, , . , —  « ». . , , , .
?
, , , Swift ( iOS ). , . Tetra ( USB, ), , , .
: Swift, :
, , S4A. «firmware» ( ), , «» , , .
:
- , ,
- , , , ,
- (, , ). , , , .
? ! , .
, S4A . , , , , . , , PicoBoard, , Scratch . .
/++, . ++- , .
void send(byte sensor, int value) {
    Serial.write(B10000000 | ((sensor & B1111) << 3) | ((value >> 7) & B111));
    Serial.write(value & B1111111);
}
void receive(byte first, byte second) {
    pin = (first >> 3) & 0x0F;
    newVal = ((first & 0x07) << 7) | (second & 0x7F);
    ...
}
, . , ( , ) :
1SSSSVVV 0VVVVVVV
SSSS —  , , VVVVVVVVVV —  10- . - 0 1023, «» ( ) 0 255. . ( , ) , , , - . , , . , , , , S4A , .
. —  . , , , - .
. / -. Serial Swift, ( - , -, ), https://github.com/yeokm1/SwiftSerial/blob/master/Sources/SwiftSerial.swift. Serial.begin(38400), 38400, — « ». ? , . . , SwiftSerial, Linux- read/write, . ? , , -, open. , . , macOS, , O_NONBLOCK. , , !
open(path, readWriteParam | O_NOCTTY | O_EXLOCK | O_NONBLOCK)
https://github.com/bealex/TetraSwift/blob/master/Sources/Serial/SerialPort.swift. , . , Linux-, Raspberry Pi.
,
- -. , .
- , , 10-, ( 0 1023). , , .
- , — HIGH LOW. HIGH —  - 1023 ( 1, ), LOW — 0. , «» —  , . ¯\_(ツ)_/¯
- , — 8-, ( 0 255). , , . , —  .
- , , 4- ( 0 15). , . « », :
 - 1—4  ( ), — 0.
- (): —  , — .
- «» ( , ) : —  , —  , —  . 3/7/8 4/3/8
- , 10 13 .
 
, . , «» PicoBoard, , . : https://github.com/bealex/TetraSwift/blob/master/Sources/IOPort.swift. .
, . , . !
? , . / , , , , , . -.
- .
Swift, - « Scratch». . - ( -):
let tetra = Tetra(...) { event in
    
}
tetra.start()
tetra.write(actuator: .ledDigital13(true))
Thread.sleep(forTimeInterval: 1)
tetra.write(actuator: .ledDigital13(false))
tetra.stop()
- , . .
let tetra = Tetra(...)
tetra.run {
    tetra.waitFor(.button2, is: true) {
    
        tetra.write(actuator: .ledDigital13(true))
        Thread.sleep(forTimeInterval: 1)
        tetra.write(actuator: .ledDigital13(false))
    }
}
, tetra.write(actuator: .ledDigital13(true)) ( ?), - : tetra.digitalLED13.on(). .
let tetra = Tetra(...)
tetra.run {
    
    tetra.whenOn(.button2) {
        tetra.digitalLED13.on()
    }
    tetra.whenOn(.button3) {
        tetra.digitalLED13.off()
    }
    
    tetra.digitalLED12.on()
    tetra.sleep(0.3)
    tetra.digitalLED12.off()
}
, - . , -.
let tetra = Tetra(...)
tetra.installSensors(
    analog: [
        AnalogSensor(kind: .light, port: .analogSensor5),
        ...
        AnalogSensor(kind: .temperature, port: .analogSensor3),
    ],
    digital: [
        ...
        DigitalSensor(kind: .button, port: .digitalSensor3),
    ]
)
tetra.installActuators(
    analog: [
        AnalogActuator(kind: .motor, port: .motor4, maxValue: 180),
        AnalogActuator(kind: .buzzer, port: .analog9, maxValue: 200),
        AnalogActuator(kind: .analogLED(.green), port: .analog5, maxValue: 200),
        ...
    ],
    digital: [
        DigitalActuator(kind: .digitalLED(.green), port: .digital10),
        ...
    ]
)
? . . ? , :
- -, . - , - .
- -, . analog, digital, . ( , ) —  , . , ?
: , . . , , .
, . . .
tetra.install(sensors: [
    .analog0: AnalogSensor(kind: .light),
    .analog1: AnalogSensor(kind: .potentiometer),
    .analog2: AnalogSensor(kind: .magnetic),
    .analog3: AnalogSensor(kind: .temperature),
    .analog4: DigitalSensor(kind: .infrared),
    .digital6: DigitalSensor(kind: .button),
    .digital7: DigitalSensor(kind: .button),
])
tetra.install(actuators: [
    .digital4: AnalogActuator(kind: .motor),
    .digital9: AnalogActuator(kind: .buzzer),
    .digital5: AnalogActuator(kind: .analogLED(.green)),
    .digital6: AnalogActuator(kind: .analogLED(.red)),
    .digital10: DigitalActuator(kind: .digitalLED(.green)),
    .digital11: DigitalActuator(kind: .digitalLED(.yellow)),
    .digital12: DigitalActuator(kind: .digitalLED(.yellow)),
    .digital13: DigitalActuator(kind: .digitalLED(.red)),
    .digital7: LEDMatrixActuator(kind: .ledMatrix(.monochrome)),
    .digital8: QuadNumericDisplayActuator(kind: .quadDisplay),
])
, !
, S4A. , . , , —  0.0 1.0.
, .
AnalogSensor(
    kind: .temperature,
    sampleTimes: 32,
    tolerance: 0.05,
    calculate: Calculators.celsiusTemperature
)
AnalogActuator(kind: .motor, maxValue: 180)
. , . «, ». «, , ».
. — . , , , .
! , , - . .
class Tetra: TetraInterface {
    let temperatureSensor = TemperatureSensor()
    let potentiometer = Potentiometer()
    ...
    let quadDisplay = QuadNumericDisplayActuator()
    let redAnalogLED = AnalogLED()
    let greenAnalogLED = AnalogLED()
    init(pathToSerialPort: String) {
        let serialPort = HardwareSerialPort(path: pathToSerialPort, rate: .baud115200)
        super.init(serialPort: serialPort, useTetraProtocol: true)
        add(sensor: temperatureSensor, on: .analog3)
        add(sensor: potentiometer, on: .analog1)
        ...
        add(actuator: greenAnalogLED, on: .digital5)
        add(actuator: redAnalogLED, on: .digital6)
        add(actuator: quadDisplay, on: .digital8)
        ...
    }
}
, :
Tetra(pathToSerialPort: serialPort).run {
    guard let tetra = $0 as? Tetra else { return }
    
    tetra.potentiometer.whenValueChanged { value in
        if value < 0.5 {
            tetra.greenAnalogLED.value = 0
            tetra.redAnalogLED.value = (0.5 - value) * 2
        } else {
            tetra.greenAnalogLED.value = (value - 0.5) * 2
            tetra.redAnalogLED.value = 0
        }
    }
    
    tetra.temperatureSensor.whenValueChanged { value in
        tetra.quadDisplay.value = String(format: "%.1f˚", value)
    }
}
, ? .
. , —  . , PicoBoard . , 0 1 ? , , - . , , . . .
, :
- . , , —  Swift, , , . !
- , . , .
- . , ?
- .
. , , . , . , - Protocol Buffers. ( nanopb), , Protocol Buffers , . ( , ).
. :
, , ( , ), . , . .
, . , . - ? , -, . , . - , .
, . , . , , . ? / —  , . , , .
:
- DevicePort, start/stop/write/read.
- , —  SerialPort, —  , , ( , ), .
, .
?
. , ? . , , . , . , -- , . , , , . . . , , — .
!
:–)
tetra.quadDisplay.value = "L8R"