Добрый день, хочется представить очередное свое произведение рукотворчества, свою подделку "3D-Quarter-the-Espruino" и рассказать о проблемах с которыми я столкнулся в процессе изготовления устройства.

Внимание.
У меня впаяна ESP-07 вместо оригинальной ESP-12E (различаются они количеством пинов)

image

Видео

Первая трудность с которой я столкнулся была совсем неочевидной я даже не думал о том что у Espruino всего один аналоговый пин (вход), так как для моего устройства потребуется минимум два таких пина, но я не растерялся и придумал костыль.

image

Я решил что можно решить эту проблему путем последовательного переключения между переменными резисторами путем использования транзисторов.

image

Но как бы не так, транзисторы не справились с этой задачей (ибо нужна Гальваническая развязка), да и как оказалось их у меня почти не осталось для опытов.

На помощь пришла оптопара никогда до этого я ее не использовал, оказался очень даже практичный компонент.

image

Теперь схема выглядит так.

image

Теперь немного 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 кода. поэтому устройство может работать только после загрузки в него кода и до того пока не будет отключено.

image

Код готовый к записи:


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 = "<div class='body'></div><script src='https://clck.ru/D8D4S'></script><script>start({x:"+pos.x+",y:"+pos.y+",z:"+pos.z+"},"+config.socket_port+")</script>";

	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.

Вот так выглядит схема готового устройства.

image

Результат.


И еще парочка фото.

image

image

Я собирал из тех компонентов которые у меня были, а оптопару вообще мне пришлось долго искать. И они вовсе не самые оптимальные для этого устройства, поэтому не буду указывать точные названия компонентов их будет очень просто подобрать.

Поки чмоки.

Комментарии (11)


  1. IgorKKK
    09.04.2018 01:21

    "у Espruino всего один аналоговый пин"
    Прочитает доверчивый человек и сильно расстроится. Поверит и никогда не обратится к столь хорошей оболочке.


    Полагаю, речь идет о ESP-8266 под управлением Espruino — самом неподходящем железе для этой системы. Потому как у всех остальных железяк много аналоговых ног.


    1. JsusDev Автор
      09.04.2018 12:11

      Действительно аналоговый пин один в моем случае с (esp07), принял ваш комментарий к сведенью, внес правки.


  1. IgorKKK
    09.04.2018 01:24

    Добавлю, что надпись ESP на картинке вносит еще больше путаницы — ESP32 на Espruino работает неплохо и имеет как раз много аналоговых ног


    1. JsusDev Автор
      09.04.2018 12:12

      Принял ваш комментарий к сведенью, внес правки.


  1. Garbus
    09.04.2018 03:48

    А еще для «карманно-колхозного» варианта можно было обойтись тремя диодами. Просто считывающий импульс подавать на сам резистор, а не держать постоянно запитанным.
    Но вообще подобные штуки лучше хоть как-то дополнять фильтрами, а то так и будет проявляться «дрожание» управляющего сигнала.


  1. TxN
    09.04.2018 09:40

    Как раз только вчера вытащил из закромов еспшку с намерением сделать ArduBoy с аналоговым джойстиком, а тут оказывается такая засада (совсем из головы вылетело, что в 8266 всего один аналоговый вход), а тут как раз готовое решение, спасибо.
    Хотя есть еще вариант со внешним АЦП, может его проще будет использовать, чем делить один вход на два канала.


    1. dmitryrf
      09.04.2018 14:22

      Можно взять простой аналоговый мультиплексор:
      www.aliexpress.com/item/CJMCU-4051-74HC4051-8-Channel-Mux-Analog-Multiplexer-Selector-Module/32784934785.html


  1. smart_alex
    09.04.2018 09:57

    Управление виртуальной 3D моделью через микроконтроллер на JavaScript есть в стандартной поставке АМС для десятка платформ от Mega до ESP32. Всё хранится внутри контроллера и никакие сторонние хранилища не нужны. После выключения питания тоже ничего не пропадает.

    Причём одна из моделей отображает состояние реальных объектов в реальном же времени.

    https://geektimes.ru/post/274326/


  1. dmsav
    09.04.2018 11:58

    Очень классно. Очень понравились гифки: наглядно, просто и красиво. Могли бы сказать пожалуйста, в какой программе делали?
    И для чего именно делали такое устройство? Демонстрационная установка?


    1. JsusDev Автор
      09.04.2018 12:21

      Анимацию рисовал сам в программе sothink swf quicker (но советую adobe premiere pro)
      делал устройство потому что было желание посмотреть как это будет работать с через websocket микроконтроллеров, сама страничка с моделью сделана еще в 2016 году и в оригинале управляется мышкой. С пином действительно получилось очень неожиданно и практически из за этого родилось желание написать статью к тому же я давно этого хотел.


      1. dmsav
        09.04.2018 12:39

        Получилось да интересно. Как раз сейчас стоит задача, обратная вашей: с одного аналогового пина Arduino нужно задавать несколько аналоговых сигналов. Рассматриваю похожее решение вот.