
Saya jarang melakukan sesuatu "level rendah." Perkiraan hari kerja saya terdiri dari pengembangan aplikasi seluler untuk bisnis dan banyak item manajerial yang beragam. Tentu saja, kadang-kadang saya ingin terganggu. Ternyata ini jarang terjadi, dan, mungkin, karena itu, memberikan kesenangan khusus. Kali ini diputuskan untuk terganggu menggunakan Amperka. Tetra ”, yang ditujukan untuk anak-anak dan dengan bantuannya Anda dapat mempelajari dasar-dasar sirkuit, nama-nama sensor apa pun, dan mencoba memprogram sesuatu yang bekerja di dunia nyata, dan bukan di layar komputer. Secara umum, ketika Anda seorang pria berjanggut dewasa - secara umum itu.
, , ( ), , 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"