[Из песочницы] Управление виртуальной 3D моделью через микроконтроллер на JavaScript
Добрый день, хочется представить очередное свое произведение рукотворчества, свою подделку »3D-Quarter-the-Espruino» и рассказать о проблемах с которыми я столкнулся в процессе изготовления устройства.
Первая трудность с которой я столкнулся была совсем неочевидной я даже не думал о том что у Espruino всего один аналоговый пин, так как для моего устройства потребуется минимум два таких пина, но я не растерялся и придумал костыль.
Я решил что можно решить эту проблему путем последовательного переключения между переменными резисторами путем использования транзисторов.
Но как бы не так, транзисторы не справились с этой задачей (ибо нужна Гальваническая развязка), да и как оказалось их у меня почти не осталось для опытов.
На помощь пришла оптопара никогда до этого я ее не использовал, оказался очень даже практичный компонент.
Теперь схема выглядит так.
Теперь немного JavaScript кода, увы Espruino не поддерживает ES6.
эта функция собирает в массив информацию с единственного аналогового пина в массив, после того как 3 позиции в массиве заполнены он формируется в объект и передается в callback.
function Listener(obj, callback) {
var indexPin = 0, dataPins = [];
setInterval(function () {
if (indexPin == 1) {
digitalWrite(obj.pin3, 0);
// переключаемся между пинами отключая один
digitalWrite(obj.pin1, 1);
// и включая следующий
}
if (indexPin == 2) {
digitalWrite(obj.pin1, 0);
digitalWrite(obj.pin2, 1);
}
if (indexPin == 3) {
digitalWrite(obj.pin2, 0);
digitalWrite(obj.pin3, 1);
}
if (indexPin > 2) { indexPin = 0; }
indexPin++;
dataPins.push(analogRead(0).toFixed(3));
// считываем пин и ограничиваем дробное до 3 чисел после точки
// (чтобы не трясло)
if (dataPins.length > 2) {
callback({
y: dataPins[0],
x: dataPins[1],
z: dataPins[2]
});
dataPins = [];
}
}, obj.speed); // скорость считывания пина
}
следующая проблема с которой я столкнулся была более тривиальной это — ограниченная память микроконтроллера.
Изначально я хотел вообще хранить часть кода на ПК и запуская сервер на Node.JS хостить страничку, а на Esp только цеплять веб сокеты Страничка подгружается с GitHub, но даже этой «оптимизации» не хватает чтоб записать в память весь код, уже не говоря о минификации самого JavaScript кода. поэтому устройство может работать только после загрузки в него кода и до того пока не будет отключено.
Код готовый к записи:
function Listener(obj, callback) {
var indexPin = 0, dataPins = [];
setInterval(function () {
if (indexPin == 1) {
digitalWrite(obj.pin3, 0);
digitalWrite(obj.pin1, 1);
}
if (indexPin == 2) {
digitalWrite(obj.pin1, 0);
digitalWrite(obj.pin2, 1);
}
if (indexPin == 3) {
digitalWrite(obj.pin2, 0);
digitalWrite(obj.pin3, 1);
}
if (indexPin > 2) { indexPin = 0; }
indexPin++;
dataPins.push(analogRead(0).toFixed(3));
if (dataPins.length > 2) {
callback({
y: dataPins[0],
x: dataPins[1],
z: dataPins[2]
});
dataPins = [];
}
}, obj.speed);
}
function Connect(obj, callback) {
const wifi = require("Wifi");
wifi.connect(obj.ssid, { password: obj.password },function(err) {
if(err){return;}
wifi.getIP(function(res) {
console.log(res.ip);
callback();
});
});
}
function Server(port, callback) {
const Http = require("http");
Http.createServer(callback).listen(port);
}
function WebSocket(port, callback) {
const WS = require("ws");
const server = WS.createServer();
server.listen(port);
server.on("websocket", callback);
}
function HTML_Page(config, req, res) {
const pos = config.correction_position;
const HTML = "";
res.writeHead(200, {'Content-type':'text/html'});
res.end(HTML);
}
function init (config) {
Connect(config.wifi, function () {
digitalWrite(2,0);
console.log("Connect wifi: "+config.wifi.ssid);
Server(config.server_port, function (req, res) {
HTML_Page(config, req, res);
});
Listener(config.listen_pin, function (data) { Data = data; });
WebSocket(config.socket_port,function (Ws) {
Ws.on('message', function () {
Ws.send(JSON.stringify(Data));
});
});
});
}
/*
* функция в которую передаются все
* необходимые настройки для старта программы
*/
init({
wifi: {
ssid: "Имя точки доступа",
password: " Пароль точки доступа"
},
socket_port: 8000,
server_port: 80,
listen_pin: {
pin1: 13,
pin2: 12,
pin3: 15,
speed: 30
},
correction_position: {
x: 0.3,
y: 0.025,
z: -0.03
} // объект для коррекции позиции модели
});
Минифицированный код можно найти на GitHub.
Вот так выглядит схема готового устройства.
Результат.
И еще парочка фото.
Я собирал из тех компонентов которые у меня были, а оптопару вообще мне пришлось долго искать. И они вовсе не самые оптимальные для этого устройства, поэтому не буду указывать точные названия компонентов их будет очень просто подобрать.
Поки чмоки.