- PVSM.RU - https://www.pvsm.ru -

Веб-камера из оптической мыши

Для отслеживания перемещений в оптической мыши используется небольшая камера-сенсор. В этой статье я покажу как можно вывести изображение с этой камеры в браузер.

Для эксперимента я использовал старый манипулятор Logitech RX 250 с чипом ADNS-5020. Этот сенсор может записывать серые изображения с разрешением 15x15 точек, а также рассчитывать перемещения по осям X-Y.

Веб камера из оптической мыши

Для эксперимента понадобятся:
— микроконтроллер arduino
— ethernet шилд
— оптическая мышь с сенсором ADNS-5020
— резистор 10 кОм

Собираем схему

Отсоедините от печатной платы мыши следующие выводы ADNS-5020: NRESET(3), NCS(4), SDIO(1), SCLK(8) при помощи паяльника или обычными кусачками.
Веб камера из оптической мыши
Припаяйте резистор 10 кОм между выводами NRESET и +5В. К выводам NCS, DSIO, SCLK, +5V, GND припаяйте провода необходимой длины (20 см).
В результате мы получим такую схему соединений:
Веб камера из оптической мыши

Подсоедините Ethernet шилд к контроллеру arduino и подсоедините его к сети.
Затем соедините сенор с arduino как указано ниже:
+5V — Arduino +5V
GND — Arduino GND
NCS — Arduino digital pin 7
SDIO — Arduino digital pin 6
SCLK — Arduino digital pin 5

Скетч для Arduino

Замените в этом скетче IP адрес (192.168.1.102) на адрес вашего компьютера.
Загрузите скетч в arduino.

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

byte arduinoMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress arduinoIP(192, 168, 1, 177); // desired IP for Arduino
unsigned int arduinoPort = 8888;      // port of Arduino

IPAddress receiverIP(192, 168, 1, 102); // IP of udp packets receiver
unsigned int receiverPort = 6000;      // port to listen on my PC

EthernetUDP Udp;

int SCLK = 5;
int SDIO = 6;
int NCS  = 7;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(arduinoMac,arduinoIP);
  Udp.begin(arduinoPort);
  
  pinMode(SCLK, OUTPUT);
  pinMode(SDIO, OUTPUT);
  pinMode(NCS, OUTPUT);
  
  mouse_reset();
  delay(10);
}

void loop() {
  char img[225];
  for (int i=0;i<225;i++){
      img[i]=readLoc(0x0b);
      img[i] &= 0x7F;
      img[i]+=1;//if there is 0 value, part of udp package is lost
      Serial.print(img[i], DEC);
      Serial.print(",");
      delay(2);
  }  
  Serial.println();
  Udp.beginPacket(receiverIP, receiverPort); //start udp packet
  Udp.write(img); //write mouse data to udp packet
  Udp.endPacket(); // end packet

  delay(500);
}

void mouse_reset(){
  // Initiate chip reset
  digitalWrite(NCS, LOW);
  pushbyte(0x3a);
  pushbyte(0x5a);
  digitalWrite(NCS, HIGH);
  delay(10);
  // Set 1000cpi resolution
  digitalWrite(NCS, LOW);
  pushbyte(0x0d);
  pushbyte(0x01);
  digitalWrite(NCS, HIGH);
}

unsigned int readLoc(uint8_t addr){
  unsigned int ret=0;
  digitalWrite(NCS, LOW);
  pushbyte(addr);
  ret=pullbyte();
  digitalWrite(NCS, HIGH);
  return(ret);
}

void pushbyte(uint8_t c){
  pinMode(SDIO, OUTPUT);
  for(unsigned int i=0x80;i;i=i>>1){
    digitalWrite(SCLK, LOW);
    digitalWrite(SDIO, c & i);
    digitalWrite(SCLK, HIGH);
  }
}

unsigned int pullbyte(){
  unsigned int ret=0;
  pinMode(SDIO, INPUT);
  for(unsigned int i=0x80; i>0; i>>=1) {
    digitalWrite(SCLK, LOW);
    ret |= i*digitalRead(SDIO);
    digitalWrite(SCLK, HIGH);
  }
  pinMode(SDIO, OUTPUT);
  return(ret);
}

Открыв окно последовательного интерфейса можно увидеть данные приходящие от мыши:
Веб камера из оптической мыши

Установите библиотеки Node.js и Socket.IO

Для показа данных в браузере мы должны установить на компьютер библиотеки node.js и socket.io. Установите node.js отсюда: nodejs.org [1] и наберите в командной строке:
npm install socket.io

Код для вебсайта Node.js

В следующей программе мы получаем данные по udp от arduino и посылаем их в браузер используя простой web сервер.

var dgram = require("dgram");
var server = dgram.createSocket("udp4");

var io = require('socket.io').listen(8000); // server listens for socket.io communication at port 8000
io.set('log level', 1); // disables debugging. this is optional. you may remove it if desired.

server.on("message", function (msg, rinfo) { //every time new data arrives do this:
  //console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port); 
  //console.log("server got:" + msg); 
  io.sockets.emit('message', msg);
});

server.on("listening", function () {
  var address = server.address();
  console.log("server listening " + address.address + ":" + address.port);
});

server.bind(6000); //listen to udp traffic on port 6000

var http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs")
    port = process.argv[2] || 8888;

http.createServer(function(request, response) {

  var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);

  var contentTypesByExtension = {
    '.html': "text/html",
    '.css':  "text/css",
    '.js':   "text/javascript"
  };

  fs.exists(filename, function(exists) {
  
	if(!exists) {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.write("404 Not Foundn");
      response.end();
      return;
    }
	
    if (fs.statSync(filename).isDirectory()) filename += '/index.html';

    fs.readFile(filename, "binary", function(err, file) {
      var headers = {};
      var contentType = contentTypesByExtension[path.extname(filename)];
      if (contentType) headers["Content-Type"] = contentType;
      response.writeHead(200, headers);
      response.write(file, "binary");
      response.end();
    });
  });
}).listen(parseInt(port, 10));

console.log("Static file server running atn  => http://localhost:" + port + "/nCTRL + C to shutdown");

Просто сохраните программу в файл: code.js

Теперь создадим веб страницу преобразующую данные из socket.io в картинку 15x15:

<html>
<head>
	<style>
		#wrapper { width:300px; height:300px; }
		div div { width:20px; height:20px; float:left; }
	</style>
	<script type="text/javascript" src="//localhost:8000/socket.io/socket.io.js"></script>
	<script>
		var socket = io.connect('http://localhost:8000');
		socket.on('connect', function () {
			socket.on('message', function (msg) {
				document.getElementById('wrapper').innerHTML = '';
				for (var i = 0; i < 225; i++) {
					pixDraw(Math.round((msg[i])*2.4));
				}
			});
		});	
		function pixDraw(clr) {
			var pixDiv = document.createElement('div');
			pixDiv.style.backgroundColor = "rgb("+clr+","+clr+","+clr+")";
			document.getElementById("wrapper").appendChild(pixDiv);
		}
	</script>
</head>
<body>
	<div id="wrapper"></div>
</body>
</html>

Сохраните как index.html

Запустите программу!

Для windows вы можете скачать архив download.zip по ссылке внизу и запустить runme.bat. В linux наберите команду node code.js в окне терминала.
В поле адрес браузера введите http://localhost:8888/ [2] и увидите изображение поступающее в реальном времени от сенсора мыши:
Веб камера из оптической мыши
Franci Kapel [3]
mousecamera.zip [4]

Автор: xDimus

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/arduino/51654

Ссылки в тексте:

[1] nodejs.org: http://nodejs.org/

[2] http://localhost:8888/: http://localhost:8888/

[3] Franci Kapel: http://frenki.net/2013/12/convert-optical-mouse-into-arduino-web-camera/

[4] mousecamera.zip: http://frenki.net/uploads/mousecamera.zip

[5] Источник: http://habrahabr.ru/post/207484/